<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14779] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14779">14779</a></dd>
<dt>Author</dt> <dd>shahzad</dd>
<dt>Date</dt> <dd>2009-09-07 17:13:09 -0500 (Mon, 07 Sep 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>Initial mod_msn dependency code upload</pre>
<h3>Added Paths</h3>
<ul>
<li><a href="#freeswitchtrunkcontribshahzadREADME1st">freeswitch/trunk/contrib/shahzad/README.1st</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnCMakeListstxt">freeswitch/trunk/contrib/shahzad/libmsn/CMakeLists.txt</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnCOPYING">freeswitch/trunk/contrib/shahzad/libmsn/COPYING</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnREADME">freeswitch/trunk/contrib/shahzad/libmsn/README</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnTHANKS">freeswitch/trunk/contrib/shahzad/libmsn/THANKS</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnTODO">freeswitch/trunk/contrib/shahzad/libmsn/TODO</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/cmake/</li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsncmakemodulesFindLibraryWithDebugcmake">freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindLibraryWithDebug.cmake</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsncmakemodulesFindOpenSSLcmake">freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindOpenSSL.cmake</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/doc/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsndocOVERVIEW">freeswitch/trunk/contrib/shahzad/libmsn/doc/OVERVIEW</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnlibmsnpccmake">freeswitch/trunk/contrib/shahzad/libmsn/libmsn.pc.cmake</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/msn/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnCMakeListstxt">freeswitch/trunk/contrib/shahzad/libmsn/msn/CMakeLists.txt</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnauthdatacpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnauthdatah">freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnbuddycpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnbuddyh">freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnconfighcmake">freeswitch/trunk/contrib/shahzad/libmsn/msn/config.h.cmake</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnconnectioncpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnconnectionh">freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnerrorcodesh">freeswitch/trunk/contrib/shahzad/libmsn/msn/errorcodes.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnexternalsh">freeswitch/trunk/contrib/shahzad/libmsn/msn/externals.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibmsn_exporth">freeswitch/trunk/contrib/shahzad/libmsn/msn/libmsn_export.h</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirencommoncpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirencommonh">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirendct4cpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirendct4h">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirendecodercpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirendecoderh">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenencodercpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenencoderh">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffmancpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffmanh">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffman_constsh">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman_consts.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenrmltcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirenrmlth">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnlibsirensiren7h">freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/siren7.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmd5cpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmd5h">freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmessagecpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/message.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmessageh">freeswitch/trunk/contrib/shahzad/libmsn/msn/message.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmsnh">freeswitch/trunk/contrib/shahzad/libmsn/msn/msn.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmsnobjectcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnmsnobjecth">freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnnotificationservercpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnnotificationserverh">freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnp2pcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnp2ph">freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnpassportcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnpassporth">freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnsoapcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnsoaph">freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnsstream_fixh">freeswitch/trunk/contrib/shahzad/libmsn/msn/sstream_fix.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnswitchboardservercpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnswitchboardserverh">freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnutilcpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/util.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnutilh">freeswitch/trunk/contrib/shahzad/libmsn/msn/util.h</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnxmlParsercpp">freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.cpp</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsnxmlParserh">freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.h</a></li>
<li>freeswitch/trunk/contrib/shahzad/libmsn/msntest/</li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsntestCMakeListstxt">freeswitch/trunk/contrib/shahzad/libmsn/msntest/CMakeLists.txt</a></li>
<li><a href="#freeswitchtrunkcontribshahzadlibmsnmsntestmsntestcpp">freeswitch/trunk/contrib/shahzad/libmsn/msntest/msntest.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribshahzadREADME1st"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/README.1st (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/README.1st         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/README.1st        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+This is work in progress. It is not suitable for any end-user testing right now.
+
+Muhammad Shahzad
+shaheryarkh@gmail.com
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnCMakeListstxt"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/CMakeLists.txt (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/CMakeLists.txt         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/CMakeLists.txt        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+project(libmsn)
+
+# uncomment the following line to enable the inbox feature. This will break the API. Beware.
+#set(LIBMSN_INBOX_URL_ENABLED true)
+
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
+# find directories for openssl
+find_package(OpenSSL REQUIRED)
+
+set (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${OPENSSL_INCLUDE_DIR})
+add_subdirectory(msn)
+
+if(NOT WIN32)
+add_subdirectory(msntest)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libmsn.pc.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/libmsn.pc
+ @ONLY )
+
+install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libmsn.pc
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig
+ COMPONENT Devel )
+endif(NOT WIN32)
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnCOPYING"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/COPYING (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/COPYING         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/COPYING        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,353 @@
</span><ins>+In addition to the license terms of the GNU General Public License,
+as copied below, the developers of libmsn give you permission
+to link the code of this release of libmsn with the OpenSSL project's
+"OpenSSL" library (or with modified versions of it that use the same
+license as the "OpenSSL" library), and distribute the linked executables.
+You must obey the GNU General Public License in all respects for all of the
+code used other than "OpenSSL". If you modify this file, you may
+extend this exception to your version of the file, but you are not
+obligated to do so. If you do not wish to do so, delete this exception
+statement from your version.
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+                 Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                         Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+                 GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                         NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                 END OF TERMS AND CONDITIONS
+
+         How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnREADME"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/README (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/README         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/README        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+libmsn 4.0
+===========
+
+:Author: Mark Rowe
+:Contact: bdash@users.sourceforge.net
+
+:Author: Tiago Salem Herrmann
+:Contact: tiagosalem@users.sourceforge.net
+
+libmsn is a C++ library for Microsoft's MSN Messenger service. It provides a high-level
+interface that allows an application to access instant messaging features with ease.
+
+libmsn is licensed under the terms of the GPL. Please see the file `COPYING' included
+with the distribution for more information.
+
+Whats New?
+----------
+In 4.0: libmsn 4.0 was refactored to support MSNP15 protocol.
+ Many features were added to this version, like offline messaging, file transfer with
+ preview, nugdes, custom emoticons, ink and winks sending and receiving, avatar support,
+ address book management with soap actions, and so on.
+
+In 3.2: With the release of libmsn 3.2 comes support for multiple simultaneous connections. The
+ callback mechanism has been refactored so that it is easy to distinguish between each
+ connection's callbacks. A large number of bug fixes have also been rolled in to this
+ release.
+In 3.1.1: libmsn 3.1.1 is primarily a bug fix release. Changes include fixing up the #include's
+ so that it compiles cleanly on a wider range of platforms, working file transfer
+ support and improved error handling.
+In 3.1: libmsn 3.1 brings support for server-side groups for managing buddies. It also
+ features rewritten network code that should help reduce CPU usage, and the amount
+ of time spent waiting for network data.
+In 3.0b2: 3.0b2 tidies up the external API to be more consistent with the rest of libmsn.
+ The build system has also been adjusted so that the same program, msntest, is
+ built.
+
+Installation
+------------
+You need to use cmake to build libmsn. (http://www.cmake.org/)
+The basic installation procedure is similar to::
+
+ $ cd libmsn; mkdir build; cd build
+ $ cmake ..
+ # make install
+
+See `INSTALL' for more information.
+
+Documentation
+-------------
+Documentation for libmsn is available in the `doc/html' subdirectory. A brief overview of
+the library can be found in the `doc/OVERVIEW' file.
+
+A sample program that uses libmsn can be found in `msntest/msntest.cpp'.
+
+Support
+-------
+For questions about usage of libmsn, please use the libmsn-discuss mailing list. A web
+interface for subscribing to this mailing list is available at
+http://lists.sourceforge.net/lists/listinfo/libmsn-discuss/. If you prefer real-time
+discussion, please look to the #libmsn channel on irc.freenode.net.
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnTHANKS"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/THANKS (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/THANKS         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/THANKS        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+libmsn THANKS File
+==================
+libmsn was originally written by Meredydd Luff, was rewritten by
+Mark Rowe and now is been ported to MSNP15 by Tiago Salem Herrmann
+Several other people have contributed code, submitted bugs or suggested features.
+This file contains a list of those who are known to have contributed
+to the libmsn project.
+
+Mark Rowe <bdash@users.sourceforge.net>
+Meredydd Luff <meredydd@everybuddy.com>
+Tiago Salem Herrmann <tiagosh@gmail.com>
+Edmund Horner <ejrh@paradise.net.nz>
+Adam Palmer <adam@npn.org.uk>
+
+Thanks to msnpiki (msnpiki.msnfanatic.com),
+ZoRoNaX (http://zoronax.spaces.live.com/)
+people from pymsn (http://telepathy.freedesktop.org/wiki/Pymsn).
+Gustavo Pichorim Boiko
+Sascha Wittkowski
+Christian Ehrlicher
+Youness Alaoui (KaKaRoTo) (libsiren)
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnTODO"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/TODO (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/TODO         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/TODO        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+
+TODO
+- improve msnobject support
+
+Switchboard:
+- p2p
+ - voice chat
+ - webcam
+ - ink support (in progress, missing p2p sending support)
+
+done:
+Notification:
+        - SSO login ( MSNP15 )
+        - retrieve lists (Allow, Block, Pending, Reverse)
+        - retrieve Address Book (Forward List)
+        - retrieve Groups and assign contacts
+        - Set user friendlyname
+        - get contacts personal info (media and friendlyname)
+        - get contacts status changes (Online, busy, etc)
+        - set personal info
+        - retrieve, send and delete OIMs (offline messages)
+        - Block/Unblock user
+        - move user to group (del user from group and add to another)
+        - add group
+        - remove group
+        - Add user
+        - del user
+        - get contact capabilities
+
+Switchboard:
+        - multipacket receiving support
+        - send and receive emoticons
+        - send and receive msgs
+        - send and receive nudges
+        - send and receive actions
+        - send msgs while in hidden status
+        - send and receive avatars
+        - send and receive files through Switchboard
+        - send and receive voice clips
+        - send and receive winks
+        - send and receive ink (multipacket support)
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsncmakemodulesFindLibraryWithDebugcmake"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindLibraryWithDebug.cmake (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindLibraryWithDebug.cmake         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindLibraryWithDebug.cmake        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+#
+# FIND_LIBRARY_WITH_DEBUG
+# -> enhanced FIND_LIBRARY to allow the search for an
+# optional debug library with a WIN32_DEBUG_POSTFIX similar
+# to CMAKE_DEBUG_POSTFIX when creating a shared lib
+# it has to be the second and third argument
+
+# Copyright (c) 2007, Christian Ehrlicher, <ch.ehrlicher@gmx.de>
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+MACRO(FIND_LIBRARY_WITH_DEBUG var_name win32_dbg_postfix_name dgb_postfix libname)
+
+ IF(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
+
+ # no WIN32_DEBUG_POSTFIX -> simply pass all arguments to FIND_LIBRARY
+ FIND_LIBRARY(${var_name}
+ ${win32_dbg_postfix_name}
+ ${dgb_postfix}
+ ${libname}
+ ${ARGN}
+ )
+
+ ELSE(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
+
+ IF(NOT WIN32)
+ # on non-win32 we don't need to take care about WIN32_DEBUG_POSTFIX
+
+ FIND_LIBRARY(${var_name} ${libname} ${ARGN})
+
+ ELSE(NOT WIN32)
+
+ # 1. get all possible libnames
+ SET(args ${ARGN})
+ SET(newargs "")
+ SET(libnames_release "")
+ SET(libnames_debug "")
+
+ LIST(LENGTH args listCount)
+
+ IF("${libname}" STREQUAL "NAMES")
+ SET(append_rest 0)
+ LIST(APPEND args " ")
+
+ FOREACH(i RANGE ${listCount})
+ LIST(GET args ${i} val)
+
+ IF(append_rest)
+ LIST(APPEND newargs ${val})
+ ELSE(append_rest)
+ IF("${val}" STREQUAL "PATHS")
+ LIST(APPEND newargs ${val})
+ SET(append_rest 1)
+ ELSE("${val}" STREQUAL "PATHS")
+ LIST(APPEND libnames_release "${val}")
+ LIST(APPEND libnames_debug "${val}${dgb_postfix}")
+ ENDIF("${val}" STREQUAL "PATHS")
+ ENDIF(append_rest)
+
+ ENDFOREACH(i)
+
+ ELSE("${libname}" STREQUAL "NAMES")
+
+ # just one name
+ LIST(APPEND libnames_release "${libname}")
+ LIST(APPEND libnames_debug "${libname}${dgb_postfix}")
+
+ SET(newargs ${args})
+
+ ENDIF("${libname}" STREQUAL "NAMES")
+
+ # search the release lib
+ FIND_LIBRARY(${var_name}_RELEASE
+ NAMES ${libnames_release}
+ ${newargs}
+ )
+
+ # search the debug lib
+ FIND_LIBRARY(${var_name}_DEBUG
+ NAMES ${libnames_debug}
+ ${newargs}
+ )
+
+ IF(${var_name}_RELEASE AND ${var_name}_DEBUG)
+
+ # both libs found
+ SET(${var_name} optimized ${${var_name}_RELEASE}
+ debug ${${var_name}_DEBUG})
+
+ ELSE(${var_name}_RELEASE AND ${var_name}_DEBUG)
+
+ IF(${var_name}_RELEASE)
+
+ # only release found
+ SET(${var_name} ${${var_name}_RELEASE})
+
+ ELSE(${var_name}_RELEASE)
+
+ # only debug (or nothing) found
+ SET(${var_name} ${${var_name}_DEBUG})
+
+ ENDIF(${var_name}_RELEASE)
+
+ ENDIF(${var_name}_RELEASE AND ${var_name}_DEBUG)
+
+ MARK_AS_ADVANCED(${var_name}_RELEASE)
+ MARK_AS_ADVANCED(${var_name}_DEBUG)
+
+ ENDIF(NOT WIN32)
+
+ ENDIF(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
+
+ENDMACRO(FIND_LIBRARY_WITH_DEBUG)
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsncmakemodulesFindOpenSSLcmake"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindOpenSSL.cmake (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindOpenSSL.cmake         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/cmake/modules/FindOpenSSL.cmake        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+# - Try to find the OpenSSL encryption library
+# Once done this will define
+#
+# OPENSSL_FOUND - system has the OpenSSL library
+# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
+# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
+# OPENSSL_EAY_LIBRARIES - The additional libraries needed to use OpenSSL on windows
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+INCLUDE(FindLibraryWithDebug)
+
+# on win32 we additional need to link to libeay32.lib
+MACRO(OPENSSL_ADD_LIB_EAY_LIBS)
+ FIND_LIBRARY_WITH_DEBUG(OPENSSL_EAY_LIBRARIES
+ WIN32_DEBUG_POSTFIX d
+ NAMES eay libeay libeay32 libeay32MD)
+ENDMACRO(OPENSSL_ADD_LIB_EAY_LIBS)
+
+IF(OPENSSL_LIBRARIES)
+ SET(OpenSSL_FIND_QUIETLY TRUE)
+ENDIF(OPENSSL_LIBRARIES)
+
+IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
+ SET(LIB_FOUND 1)
+ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
+
+FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h )
+
+FIND_LIBRARY_WITH_DEBUG(OPENSSL_LIBRARIES
+ WIN32_DEBUG_POSTFIX d
+ NAMES ssl ssleay ssleay32 ssleay32MD)
+
+IF(WIN32)
+ OPENSSL_ADD_LIB_EAY_LIBS()
+ IF(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES AND OPENSSL_EAY_LIBRARIES)
+ SET(OPENSSL_FOUND TRUE)
+ ELSE(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES AND OPENSSL_EAY_LIBRARIES)
+ SET(OPENSSL_FOUND FALSE)
+ ENDIF (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES AND OPENSSL_EAY_LIBRARIES)
+ELSE(WIN32)
+ IF(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
+ SET(OPENSSL_FOUND TRUE)
+ ELSE(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
+ SET(OPENSSL_FOUND FALSE)
+ ENDIF (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
+ENDIF(WIN32)
+
+IF (OPENSSL_FOUND)
+ IF (NOT OpenSSL_FIND_QUIETLY)
+ MESSAGE(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}")
+ ENDIF (NOT OpenSSL_FIND_QUIETLY)
+ELSE (OPENSSL_FOUND)
+ IF (OpenSSL_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could NOT find OpenSSL")
+ ENDIF (OpenSSL_FIND_REQUIRED)
+ENDIF (OPENSSL_FOUND)
+
+MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsndocOVERVIEW"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/doc/OVERVIEW (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/doc/OVERVIEW         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/doc/OVERVIEW        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,194 @@
</span><ins>+libmsn overview
+---------------
+
+To better understand the libmsn architecture it is good to know the names and the jobs of some MSN service entities.
+
+1) Notification Server:
+ This server is the one you will keep connected until the session finishes.
+ Through this server you will:
+ - be able to change your nickname.
+ - receive notifications about the status of contacts present on your contact list.
+ - be notified about users that just added you to their lists
+ - receive the personal message and current song from other contacts and publish yours.
+ - be able to request a new switchboard session to a contact in your contact list.
+ - receive notifications about an user asking you to connect to an existent switchboard.
+ - receive notifications about new offline messages.
+ - receive notifications about emails in your hotmail account
+ - and more..
+
+ (check the doc/ directory for more info)
+
+2) Switchboard Server:
+ This server is a kind of bridge between two or more people.
+ Every time you want to talk to a contact you need to request a switchboard session and
+ then ask to invite the other contacts to the session.
+ Through a switchboard connection you can:
+ - send and receive text messages
+ - send and receive typing notification
+ - send and receive voice clips
+ - send and receive files
+ - send and receive draws (called inks)
+ - send and receive custom emoticons
+ - send and receive nudges
+ - send and receive actions
+ - send and receive winks
+ - send and receive custom backgrounds
+
+ (check the doc/ directory for more info)
+
+3) Lists:
+ There are 5 lists in the server which may contain the passport of your contacts.
+ Each list has a special meaning:
+ - Address Book (Or forward List): Contains all the contacts that you have in your list.
+ - Allow List: Users that you allow to see your status and request switchboard sessions with you.
+ - Block List: Users that won't see you online and cannot request switchboard sessions with you.
+ - Reverse List: Users that currently have you in their Address Book.
+ - Pending List: List of users that have added you and you need to decide if you will add them or not.
+
+-----------------
+
+Libmsn is an asynchronous library, so it provides a set of callbacks that you must implement in your application.
+The list of callbacks can be found in externals.h, and the example how to implement them is in msntest.cpp.
+
+So the first step to connect to the MSN messenger is to implement the Callbacks class in your application and to create an instance of the class NotificationServerConnection, which abstracts the connection to the notification server.
+
+The NotificationServerConnection constructor requires 3 arguments:
+ - The username, the password and the reference to your Callbacks class reimplementation.
+
+"""
+ Callbacks cb;
+ MSN::Passport uname;
+ MSN::NotificationServerConnection mainConnection(uname, pass, cb);
+"""
+
+Now it is time to ask libmsn to connect the MSN messenger service:
+
+"""
+ mainConnection.connect("messenger.hotmail.com", 1863);
+"""
+
+If everything is ok you will receive a gotNewConnection() callback.
+Then you need to call synchronizeContactList().
+
+An example:
+"""
+void Callbacks::gotNewConnection(MSN::Connection * conn)
+{
+ if (dynamic_cast<MSN::NotificationServerConnection *>(conn))
+ dynamic_cast<MSN::NotificationServerConnection *>(conn)->synchronizeContactList();
+}
+"""
+
+This will make libmsn request the contact list to the server.
+Wait a bit and then you will receive the contents of the five lists shown above. This
+will happen through gotBuddyListInfo() callback.
+Next step is to send again the list to the server calling completeConnection().
+(Note: you need to add only members of Allow List, Block List and the Address Book
+to the list you will send through completeConnection().
+Take a look at msntest.cpp to understand how to do it) The reason why libmsn
+does not do that automatically is that in a near future libmsn will support partial
+list fetching, and even if you don't request the whole list in synchronizeContactList(),
+you will need to pass the whole list in completeConnection() anyway.
+
+"""
+ conn->completeConnection(allContacts,info);
+"""
+
+If everything is ok, you will receive a connectionReady(), and then you can
+finally change your status (Invisible, Online, Away, ..) using setState().
+
+Like this:
+
+"""
+ // set your display picture
+ mainConnection.change_DisplayPicture("/tmp/global-photo.png");
+
+ // configure the capabilities of this client
+ uint clientid=0;
+
+ clientid += MSN::MSNC7;
+ clientid += MSN::MSNC6;
+ clientid += MSN::MSNC5;
+ clientid += MSN::MSNC4;
+ clientid += MSN::MSNC3;
+ clientid += MSN::MSNC2;
+ clientid += MSN::MSNC1;
+ clientid += MSN::SupportWinks;
+ clientid += MSN::VoiceClips;
+ clientid += MSN::InkGifSupport;
+ clientid += MSN::SIPInvitations;
+ clientid += MSN::SupportMultiPacketMessaging;
+
+ // set a new state
+ mainConnection.setState(MSN::STATUS_INVISIBLE, clientid);
+"""
+
+This is enough to get your application connected to the MSN messenger service.
+
+
+FAQ
+---
+
+--------------------------------------------------------
+1) How do I talk to a contact?
+
+ - you need to request a switchboard session with the other contact. Create a context
+ so then you can track this request later.
+"""
+ const std::string rcpt_ = "buddy@hisher.passport.net";
+ const std::string msg_ = "Hi! this is libmsn";
+ const std::pair<std::string,std::string> *ctx = new std::pair<std::string,std::string>(rcpt_, msg_);
+
+ // request a new switchboard connection
+ mainConnection->requestSwitchboardConnection (ctx);
+"""
+
+now wait until libmsn raises gotSwitchboard() and invite the other user to the session.
+
+"""
+void Callbacks::gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag)
+{
+ if (tag){
+ const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(tag);
+ conn->inviteUser(ctx->first);
+ }
+}
+"""
+
+when the other user joins the session you can finally send the message.
+It is possible to track this action by the buddyJoinedConversation() callback.
+
+"""
+void Callbacks::buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname, int is_initial)
+{
+ if (conn->auth.tag){
+ const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(conn->auth.tag);
+ int trid = conn->sendMessage(ctx->second);
+ delete ctx;
+ conn->auth.tag = NULL;
+ }
+}
+"""
+--------------------------------------------------------
+
+2) How do I send a custom emoticon?
+
+"""
+ conn->sendEmoticon("(EMOTICON)", filename);
+"""
+
+where `conn' is an active switchboard connection, `(EMOTICON)' is the alias and `filename'
+is the path to the gif file.
+
+--------------------------------------------------------
+
+3) How do I send a nudge?
+
+"""
+ conn->sendNudge();
+"""
+where `conn' is an active switchboard connection.
+
+--------------------------------------------------------
+
+For more examples take a look at msntest.cpp
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnlibmsnpccmake"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/libmsn.pc.cmake (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/libmsn.pc.cmake         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/libmsn.pc.cmake        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_PREFIX@/lib@LIB_SUFFIX@
+includedir=@CMAKE_INSTALL_PREFIX@/include
+
+Name: libmsn
+Description: MSN protocol implementation
+Version: 0.4.0
+
+Requires: libssl
+Libs: -L${libdir} -lmsn
+Cflags: -I${includedir}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnCMakeListstxt"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/CMakeLists.txt (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/CMakeLists.txt         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/CMakeLists.txt        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+########### next target ###############
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR})
+
+set(msn_STAT_SRCS
+ authdata.cpp
+ message.cpp
+ connection.cpp
+ switchboardserver.cpp
+ notificationserver.cpp
+ util.cpp
+ md5.cpp
+ soap.cpp
+ p2p.cpp
+ xmlParser.cpp
+ msnobject.cpp
+ buddy.cpp
+ passport.cpp
+)
+
+if(WIN32)
+set(msn_STAT_SRCS ${msn_STAT_SRCS}
+ ${OPENSSL_INCLUDE_DIR}/openssl/applink.c)
+endif(WIN32)
+
+set(msn_HEADERS
+ authdata.h
+ message.h
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h
+ connection.h
+ switchboardserver.h
+ notificationserver.h
+ util.h
+ externals.h
+ errorcodes.h
+ msn.h
+ buddy.h
+ passport.h
+ sstream_fix.h
+ soap.h
+ p2p.h
+ msnobject.h
+ libmsn_export.h)
+
+set(siren_STAT_SRCS
+ libsiren/common.cpp
+ libsiren/dct4.cpp
+ libsiren/decoder.cpp
+ libsiren/encoder.cpp
+ libsiren/huffman.cpp
+ libsiren/rmlt.cpp
+)
+
+set(siren_HEADERS
+ libsiren/common.h
+ libsiren/dct4.h
+ libsiren/decoder.h
+ libsiren/encoder.h
+ libsiren/huffman_consts.h
+ libsiren/huffman.h
+ libsiren/rmlt.h
+ libsiren/siren7.h
+)
+add_library(msn SHARED ${msn_STAT_SRCS} ${siren_STAT_SRCS})
+set_target_properties(msn PROPERTIES VERSION 0.1.0
+ SOVERSION 0.1
+)
+
+if(NOT WIN32)
+ target_link_libraries(msn crypto)
+else(NOT WIN32)
+ target_link_libraries(msn ${OPENSSL_EAY_LIBRARIES})
+endif(NOT WIN32)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h
+)
+
+########### install files ###############
+install(TARGETS msn RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+install(FILES ${msn_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/msn)
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnauthdatacpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+/*
+ * authdata.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ *
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/authdata.h>
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnauthdatah"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/authdata.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+#ifndef __msn_authdata_h__
+#define __msn_authdata_h__
+
+/*
+ * authdata.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <msn/passport.h>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class LIBMSN_EXPORT AuthData
+ {
+public:
+ Passport username;
+
+ AuthData(Passport username_) : username(username_) {};
+ virtual ~AuthData() {};
+ };
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnbuddycpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+/*
+ * buddy.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Apr 19 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/buddy.h>
+#include <cassert>
+
+namespace MSN
+{
+ std::string buddyStatusToString(BuddyStatus state)
+ {
+ switch (state)
+ {
+ case STATUS_AVAILABLE:
+ return "NLN";
+ case STATUS_BUSY:
+ return "BSY";
+ case STATUS_IDLE:
+ return "IDL";
+ case STATUS_BERIGHTBACK:
+ return "BRB";
+ case STATUS_AWAY:
+ return "AWY";
+ case STATUS_ONTHEPHONE:
+ return "PHN";
+ case STATUS_OUTTOLUNCH:
+ return "LUN";
+ case STATUS_INVISIBLE:
+ return "HDN";
+ default:
+ assert(false);
+ }
+ }
+
+ BuddyStatus buddyStatusFromString(std::string state)
+ {
+ if (state == "NLN")
+ return STATUS_AVAILABLE;
+ else if (state == "BSY")
+ return STATUS_BUSY;
+ else if (state == "IDL")
+ return STATUS_IDLE;
+ else if (state == "BRB")
+ return STATUS_BERIGHTBACK;
+ else if (state == "AWY")
+ return STATUS_AWAY;
+ else if (state == "PHN")
+ return STATUS_ONTHEPHONE;
+ else if (state == "LUN")
+ return STATUS_OUTTOLUNCH;
+ else if (state == "HDN")
+ return STATUS_INVISIBLE;
+ else
+ throw std::runtime_error("Unknown status!");
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnbuddyh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/buddy.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,138 @@
</span><ins>+#ifndef __msn_buddy_h__
+#define __msn_buddy_h__
+
+/*
+ * buddy.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Apr 19 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <msn/passport.h>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ /** The online state of a buddy.
+ */
+
+ enum BuddyStatus
+ {
+ STATUS_AVAILABLE, /**< Contact is available */
+ STATUS_BUSY, /**< Contact is busy */
+ STATUS_IDLE, /**< Contact is idle */
+ STATUS_BERIGHTBACK, /**< Contact will be right back */
+ STATUS_AWAY, /**< Contact is away */
+ STATUS_ONTHEPHONE, /**< Contact is on the phone */
+ STATUS_OUTTOLUNCH, /**< Contact is out to lunch */
+ STATUS_INVISIBLE /**< Contact is invisible */
+ };
+
+ std::string LIBMSN_EXPORT buddyStatusToString(BuddyStatus s);
+ BuddyStatus LIBMSN_EXPORT buddyStatusFromString(std::string s);
+
+ class Group;
+
+ /** The Buddy class contains information about a member of a buddy list.
+ *
+ * Each Buddy is made up of their passport address (@a userName),
+ * user-visible display name (@a friendlyName), a list of properties
+ * (@a properties) and zero or more @a groups on the buddy list that they belong to.
+ *
+ */
+ class LIBMSN_EXPORT Buddy
+ {
+public:
+ /** The PhoneNumbers class contains information about one or more phone numbers
+ * that are retrieved during the buddy list synchronisation process.
+ */
+ class PhoneNumber
+ {
+public:
+ /** The name of this phone number.
+ *
+ * @todo Should this be an enumeration containing the possible
+ * types of phone number?
+ */
+ std::string title;
+
+ std::string number;
+
+ bool enabled;
+
+ PhoneNumber(std::string title_, std::string number_, bool enabled_=true)
+ : title(title_), number(number_), enabled(enabled_) {};
+
+ };
+
+ /** all the properties received at login time */
+ std::map<std::string, std::string> properties;
+
+ /** Their passport address */
+ Passport userName;
+
+ /** Their friendly name */
+ std::string friendlyName;
+
+ /** A list of phone numbers related to this buddy */
+ std::list<Buddy::PhoneNumber> phoneNumbers;
+
+ /** A list of Group's that this buddy is a member of */
+ std::list<Group *> groups;
+
+ /** Lists which this contact belong. Pending, Forward, Block... **/
+ unsigned int lists;
+
+ Buddy(Passport userName_, std::string friendlyName_ = "") :
+ userName(userName_), friendlyName(friendlyName_), lists(0) {};
+ bool operator==(const Buddy &other) { return userName == other.userName; }
+ };
+
+ /** The Group class represents a group of contacts on the buddy list.
+ *
+ * Each group is represented by a @a groupID, a list of buddies @buddies
+ * and has a user-visible @a name.
+ */
+ class LIBMSN_EXPORT Group
+ {
+public:
+
+ /** Id of this group **/
+ std::string groupID;
+
+ /** Name of this group **/
+ std::string name;
+
+ /** List of contacts in this group **/
+ std::list<Buddy *> buddies;
+
+ Group(std::string groupID_, std::string name_)
+ : groupID(groupID_), name(name_) {};
+
+ Group() : name("INVALID") {};
+ };
+}
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnconfighcmake"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/config.h.cmake (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/config.h.cmake         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/config.h.cmake        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+#ifndef LIBMSN_CONFIG_H
+#define LIBMSN_CONFIG_H
+
+#cmakedefine LIBMSN_INBOX_URL_ENABLED
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnconnectioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,240 @@
</span><ins>+/*
+ * connection.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/connection.h>
+#include <msn/errorcodes.h>
+#include <msn/util.h>
+#include <msn/passport.h>
+#include <msn/externals.h>
+#include <msn/notificationserver.h>
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#else
+#include <winsock.h>
+#include <io.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <cerrno>
+#include <time.h>
+#include <cassert>
+
+namespace MSN
+{
+ static std::vector<std::string> errors;
+
+ Connection::Connection()
+ : sock(NULL), connected(false), trID(1)
+ {
+ srand((unsigned int) time(NULL));
+
+ if (errors.size() != 0)
+ {
+ assert(errors.size() == 1000);
+ }
+ else
+ {
+ errors.resize(1000);
+ for (int a = 0; a < 1000; a++)
+ {
+ errors[a] = "Unknown error code";
+ }
+
+ errors[200] = "Syntax error";
+ errors[201] = "Invalid parameter";
+ errors[205] = "Invalid user";
+ errors[206] = "Domain name missing from username";
+ errors[207] = "Already logged in";
+ errors[208] = "Invalid username";
+ errors[209] = "Invalid friendly name";
+ errors[210] = "List full";
+ errors[215] = "This user is already on this list or in this session";
+ errors[216] = "Not on list";
+ errors[218] = "Already in this mode";
+ errors[219] = "This user is already in the opposite list";
+ errors[241] = "Unable to add user";
+ errors[280] = "Switchboard server failed";
+ errors[281] = "Transfer notification failed";
+ errors[300] = "Required fields missing";
+ errors[302] = "Not logged in";
+ errors[500] = "Internal server error";
+ errors[501] = "Database server error";
+ errors[510] = "File operation failed at server";
+ errors[520] = "Memory allocation failed on server";
+ errors[600] = "The server is too busy";
+ errors[601] = "The server is unavailable";
+ errors[602] = "A Peer Notification Server is down";
+ errors[603] = "Database connection failed";
+ errors[604] = "Server going down for maintenance";
+ errors[707] = "Server failed to create connection";
+ errors[711] = "Blocking write failed on server";
+ errors[712] = "Session overload on server";
+ errors[713] = "You have been too active recently. Slow down!";
+ errors[714] = "Too many sessions open";
+ errors[715] = "Email Address Not verified";
+ errors[717] = "Bad friend file on server";
+ errors[911] = "Authentication failed. Check that you typed your username and password correctly.";
+ errors[913] = "This action is not allowed while you are offline";
+ errors[920] = "This server is not accepting new users";
+ errors[921] = "Error synchronizing lists";
+ errors[922] = "Error synchronizing address book";
+ }
+
+ }
+
+ Connection::~Connection() { }
+
+ void Connection::disconnect()
+ {
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+
+ this->myNotificationServer()->externalCallbacks.closeSocket(this->sock);
+
+ this->sock = NULL;
+ this->writeBuffer.erase();
+ this->readBuffer.erase();
+ this->trID = 1;
+ }
+
+ std::vector<std::string> Connection::getLine()
+ {
+ assert(this->isWholeLineAvailable());
+ std::string s = this->readBuffer.substr(0, this->readBuffer.find("\r\n"));
+ this->myNotificationServer()->externalCallbacks.log(0, (s + "\n").c_str());
+ return splitString(s, " ");
+ }
+
+ bool Connection::isWholeLineAvailable()
+ {
+ return this->readBuffer.find("\r\n") != std::string::npos;
+ }
+
+ void Connection::errorOnSocket(int errno_)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, strerror(errno_));
+ this->disconnect();
+ }
+
+ void Connection::socketConnectionCompleted()
+ {
+ this->connected = true;
+
+ if(this->writeBuffer.size())
+ {
+ // We know that we are connected, so this will try writing to the network.
+ size_t writtenLength = this->write(this->writeBuffer, 1);
+ if(writtenLength > 0 && this->writeBuffer.size() > 0)
+ this->writeBuffer = this->writeBuffer.substr(writtenLength);
+ }
+ }
+
+ size_t Connection::write(std::string s, bool log) throw (std::runtime_error)
+ {
+ if(s.size() < 0)
+ return 0;
+
+ if (! this->connected)
+ {
+ this->writeBuffer.append(s);
+ }
+ else
+ {
+ if (log)
+ this->myNotificationServer()->externalCallbacks.log(1, s.c_str());
+
+ char *a = (char*)s.c_str();
+ size_t written = this->myNotificationServer()->
+ externalCallbacks.writeDataToSocket(sock, a, (int) (s.size()));
+ return written;
+ }
+ return s.size();
+ }
+
+ size_t Connection::write(std::ostringstream & ss, bool log) throw (std::runtime_error)
+ {
+ std::string s = ss.str();
+#ifdef DEBUG
+ std::cout << s << std::endl;
+#endif
+ size_t result = write(s, log);
+ return result;
+ }
+
+ void Connection::dataArrivedOnSocket()
+ {
+ char tempReadBuffer[8192];
+ int amountRead = 8192;
+ std::string tempRead;
+ while (amountRead == 8192)
+ {
+ amountRead = this->myNotificationServer()->externalCallbacks.getDataFromSocket(sock, tempReadBuffer, 8192);
+ if(amountRead < 0)
+ break;
+ tempRead+= std::string(tempReadBuffer,amountRead);
+ }
+ if (tempRead.length() < 0)
+ {
+ // We shouldn't be here because dataArrivedOnSocket
+ // is only called when select/poll etc has told us that
+ // the socket is readable.
+ // assert(errno != EAGAIN);
+ this->myNotificationServer()->externalCallbacks.showError(this, "No data to read");
+ this->disconnect();
+ }
+ else if (amountRead == 0)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "Connection closed by remote endpoint.");
+ this->disconnect();
+ }
+ else
+ {
+ this->readBuffer += tempRead;
+#ifdef DEBUG
+ std::cout << tempRead << std::endl;
+#endif
+ try
+ {
+ handleIncomingData();
+ }
+ catch (std::exception & e)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, e.what());
+ }
+ }
+ }
+
+ void Connection::showError(int errorCode)
+ {
+ std::ostringstream buf_;
+ buf_ << "Error code: " << errorCode << " (" << errors[errorCode] << ")";
+ this->myNotificationServer()->externalCallbacks.showError(this, buf_.str());
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnconnectionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/connection.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,153 @@
</span><ins>+#ifndef __msn_connection_h__
+#define __msn_connection_h__
+
+/*
+ * connection.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <stdexcept>
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4290 )
+#endif
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class callback;
+ class Message;
+ class Passport;
+ class NotificationServerConnection;
+
+ /** An abstract base class that represents a connection to another computer.
+ *
+ * Connection provides an interface and some functionality that is common
+ * to notification, switchboard and file transfer connections.
+ *
+ */
+ class LIBMSN_EXPORT Connection
+ {
+public:
+ /** The socket which connects this Connection to another computer
+ *
+ * @deprecated In the future, this member will be made private. Any
+ * functions that access this member should be converted to
+ * member functions of a subclass.
+ */
+ void *sock;
+
+ /** Indicates whether a connection has been established.
+ */
+ bool connected;
+
+
+protected:
+
+ std::string readBuffer;
+public:
+ /** The transaction ID of the next command to be sent.
+ */
+ int trID;
+
+ Connection();
+ virtual ~Connection();
+
+ /** Dispatch a command to its appropriate handler routines based on @a args.
+ *
+ * @param args A vector of strings containing arguments, returned from readLine.
+ */
+ virtual void dispatchCommand(std::vector<std::string> & args) = 0;
+
+ /** Read a line from the network and split it into its components.
+ *
+ * MSN commands and their arguments are separated by white space.
+ */
+ std::vector<std::string> getLine();
+
+ bool isWholeLineAvailable();
+ bool bytesAvailable();
+
+ /** Write a string to the connection.
+ *
+ */
+ virtual size_t write(std::string s, bool log=true) throw (std::runtime_error);
+
+ /** Write the contents of a stringstream to the connection.
+ *
+ * @param s The stringstream to write.
+ * @param log Should we log this output to the console.
+ *
+ * write will buffer the output if a connection has not yet been established.
+ * In this case, the data will be written as soon as a connection is
+ * established.
+ */
+ virtual size_t write(std::ostringstream & s, bool log=true) throw (std::runtime_error);
+
+ /** Connect ourself to @a hostname on @a port.
+ */
+ virtual void connect(const std::string & hostname, unsigned int port) = 0;
+ virtual void disconnect() = 0;
+
+ /** @name External Socket Hooks
+ *
+ * These members should be called whenever an appropriate socket event
+ * occurs.
+ */
+ /** @{ */
+
+ /** New data is available on the connection.
+ */
+ virtual void dataArrivedOnSocket();
+
+ /** The connection has been established.
+ */
+ virtual void socketConnectionCompleted();
+
+ virtual void socketIsWritable() {};
+
+ /** An error has occurred on the socket.
+ */
+ virtual void errorOnSocket(int errno_);
+ /** @} */
+
+ /** Notify the calling library that an error with code @a errorCode has
+ * occured.
+ */
+ void showError(int errorCode);
+
+ /** Is this Connection connected to a remote endpoint?
+ */
+ bool isConnected() { return this->connected; };
+ virtual NotificationServerConnection *myNotificationServer() = 0;
+
+protected:
+ virtual void handleIncomingData() = 0;
+private:
+ std::string writeBuffer;
+ };
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnerrorcodesh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/errorcodes.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/errorcodes.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/errorcodes.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,101 @@
</span><ins>+#ifndef __msn_errorcodes_h__
+#define __msn_errorcodes_h__
+
+/*
+ * errorcodes.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <list>
+#include <msn/switchboardserver.h>
+
+#include "libmsn_export.h"
+
+/** \mainpage libmsn Reference
+ *
+ * <code>libmsn</code> is a C++ library for Microsoft's MSN Messenger service. It
+ * provides a high-level interface that allows an application to access instant
+ * messaging features with ease. For more information, please visit the
+ * <a href='http://libmsn.sourceforge.net'><code>libmsn</code></a> homepage.
+ *
+ */
+
+
+/** Contains all of the functionality provided by <code>libmsn</code>.
+ */
+namespace MSN
+{
+ /** Error codes that the MSN servers may return in response to commands.
+ */
+ typedef enum
+ {
+ ERR_SYNTAX_ERROR = 200,
+ ERR_INVALID_PARAMETER,
+
+ ERR_INVALID_USER = 205,
+ ERR_FQDN_MISSING,
+ ERR_ALREADY_LOGIN,
+ ERR_INVALID_USERNAME,
+ ERR_INVALID_FRIENDLY_NAME,
+ ERR_LIST_FULL,
+
+ ERR_ALREADY_THERE = 215,
+ ERR_NOT_ON_LIST,
+
+ ERR_ALREADY_IN_THE_MODE = 218,
+ ERR_ALREADY_IN_OPPOSITE_LIST,
+
+ ERR_SWITCHBOARD_FAILED = 280,
+ ERR_NOTIFY_XFR_FAILED,
+
+ ERR_REQUIRED_FIELDS_MISSING = 300,
+ ERR_NOT_LOGGED_IN = 302,
+
+ ERR_INTERNAL_SERVER = 500,
+ ERR_DB_SERVER = 501,
+
+ ERR_FILE_OPERATION = 510,
+ ERR_MEMORY_ALLOC = 520,
+
+ ERR_SERVER_BUSY = 600,
+ ERR_SERVER_UNAVAILABLE,
+ ERR_PEER_NS_DOWN,
+ ERR_DB_CONNECT,
+ ERR_SERVER_GOING_DOWN,
+
+ ERR_CREATE_CONNECTION = 707,
+
+ ERR_BLOCKING_WRITE = 711,
+ ERR_SESSION_OVERLOAD,
+ ERR_USER_TOO_ACTIVE,
+ ERR_TOO_MANY_SESSIONS,
+ ERR_NOT_EXPECTED,
+ ERR_BAD_FRIEND_FILE = 717,
+
+ ERR_AUTHENTICATION_FAILED = 911,
+ ERR_NOT_ALLOWED_WHEN_OFFLINE = 913,
+ ERR_NOT_ACCEPTING_NEW_USERS = 920
+ } ErrorCodes;
+}
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnexternalsh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/externals.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/externals.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/externals.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,334 @@
</span><ins>+#ifndef __msn_externals_h__
+#define __msn_externals_h__
+
+/*
+ * externals.h
+ * libmsn
+ *
+ * Created by Meredydd Luff.
+ * Refactored by Tiago Salem Herrmann.
+ * Copyright (c) 2004 Meredydd Luff. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/config.h>
+#include <msn/buddy.h>
+#include <msn/util.h>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class ListSyncInfo;
+ /** The application should implement these callback functions to
+ * be able to receive notifications from the library.
+ */
+ class LIBMSN_EXPORT Callbacks
+ {
+ public:
+
+ /** Asks the application that libmsn only must to be notified when the
+ * socket become readable and/or writable.
+ */
+ virtual void registerSocket(void *sock, int read, int write, bool isSSL) = 0;
+
+ /** Asks the application to never notify libmsn again about events in the socket.
+ */
+ virtual void unregisterSocket(void *sock) = 0;
+
+ /** Asks the application to close the socket
+ */
+ virtual void closeSocket(void *sock) = 0;
+
+ /** Allow your application to be notified about errors on library layer
+ */
+ virtual void showError(MSN::Connection * conn, std::string msg) = 0;
+
+ /** Notifies the application about a buddy status change.
+ * msnobject is the object describing avatar file.
+ * To get it you should call requestDisplayPicture() on a switchboard
+ * connection with this user.
+ */
+ virtual void buddyChangedStatus(MSN::NotificationServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::BuddyStatus state, unsigned int clientID, std::string msnobject) = 0;
+
+ /** Notifies the application about a user who went offline
+ */
+ virtual void buddyOffline(MSN::NotificationServerConnection * conn, MSN::Passport buddy) = 0;
+
+ /** Allow your application to log some network traffic
+ */
+ virtual void log(int writing, const char* buf) = 0;
+
+ /** Notifies the application that your friendly name now is 'friendlyname'.
+ * Probably this is the reply to a previous setFriendlyName() call.
+ */
+ virtual void gotFriendlyName(MSN::NotificationServerConnection * conn, std::string friendlyname) = 0;
+
+ /** Notifies the application that you have received your lists
+ * (Address Book, allow list, block list, reverse list and pending list)
+ * You must call completeConnection on notification server connection to
+ * complete the initial process. An example can be found in msntest.cpp
+ */
+ virtual void gotBuddyListInfo(MSN::NotificationServerConnection * conn, MSN::ListSyncInfo * data) = 0;
+
+ /** Notifies the application that a contact has updated his/her personal info.
+ * Example: Current Song, personal messages..
+ * Check all the possibilities in MSN::personalInfo struct
+ */
+ virtual void buddyChangedPersonalInfo(MSN::NotificationServerConnection * conn, MSN::Passport fromPassport, MSN::personalInfo pInfo) = 0;
+
+ /** Notifies the application that one change was made to your
+ * lists, and the current timestamp is lastChange.
+ * This number should be used on initial process to specify
+ * what version of your lists you already have. If the server
+ * version is not the same, it will provide only the diff between your
+ * version and the current one.
+ * THE PARTIAL LIST FETCH IS NOT WORKING YET.
+ */
+ virtual void gotLatestListSerial(MSN::NotificationServerConnection * conn, std::string lastChange) = 0;
+
+ /** This is a response to a previous sent GTC command.
+ */
+ virtual void gotGTC(MSN::NotificationServerConnection * conn, char c) = 0;
+
+
+ /** This is a response to a previous sent BLP command.
+ */
+ virtual void gotBLP(MSN::NotificationServerConnection * conn, char c) = 0;
+
+ /** Notifies your application that some list was modified by adding
+ * some new contact. If ContactList is MSN::LST_RL, it means someone
+ * added you to its Address Book. So at this point the application should
+ * prompt to the user about adding or blocking this new contact.
+ */
+ virtual void addedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy, std::string friendlyname) = 0;
+
+ /** Notifies your application that some list was modified by removing
+ * some old contact. If ContactList is MSN::LST_RL, it means this contact
+ * has removed you from its Address Book.
+ */
+ virtual void removedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy) = 0;
+
+ /** Notifies your application that a new group was created, or not, depending on
+ * the 'added' boolean variable. The application should track the groupId to permorm
+ * actions with it.
+ */
+ virtual void addedGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupName, std::string groupId) = 0;
+
+ /** Notifies your application that an old group was removed, or not, depending on
+ * the 'removed' boolean variable.
+ */
+ virtual void removedGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId) = 0;
+
+ /** Notifies your application that an old group was renamed.
+ */
+ virtual void renamedGroup(MSN::NotificationServerConnection * conn, bool renamed, std::string newGroupName, std::string groupId) = 0;
+
+ /** Notifies your application that a contact was added to a group, or not, depending on the
+ * 'added' boolean variable.
+ */
+ virtual void addedContactToGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupId, std::string contactId) = 0;
+
+ /** Notifies your application that a contact was removed from a group, or not, depending on the
+ * 'removed' boolean variable.
+ */
+ virtual void removedContactFromGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId, std::string contactId) = 0;
+
+ /** Notifies your application that a contact was added to the Address Book, or not, depending on the
+ * 'added' boolean variable.
+ */
+ virtual void addedContactToAddressBook(MSN::NotificationServerConnection * conn, bool added, std::string passport, std::string displayName, std::string guid) = 0;
+
+ /** Notifies your application that a contact was removed from the Address Book, or not, depending on the
+ * 'removed' boolean variable.
+ */
+ virtual void removedContactFromAddressBook(MSN::NotificationServerConnection * conn, bool removed, std::string contactId, std::string passport) = 0;
+
+ /** Notifies your application that a contact was enabled on Address Book, or not, depending on the
+ * 'enabled' boolean variable.
+ */
+ virtual void enabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool enabled, std::string contactId, std::string passport) = 0;
+
+ /** Notifies your application that a contact was disabled on Address Book, or not, depending on the
+ * 'disabled' boolean variable.
+ */
+ virtual void disabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool disabled, std::string contactId) = 0;
+
+ /** Notifies your application that you got a new switchboard connection
+ */
+ virtual void gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag) = 0;
+
+ /** Notifies your application that a contact joined to a switchboard connection
+ */
+ virtual void buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, int is_initial) = 0;
+
+ /** Notifies your application that a contact left a switchboard connection
+ */
+ virtual void buddyLeftConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy) = 0;
+
+ /** Notifies your application that received an instant message
+ */
+ virtual void gotInstantMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::Message * msg) = 0;
+
+ /** Notifies your application that the "trID" message was received by the other contact
+ */
+ virtual void gotMessageSentACK(MSN::SwitchboardServerConnection * conn, int trID) = 0;
+
+ /** Notifies your application that received an emoticon notification.
+ * To get it you should call requestEmoticon() and pass msnobject to it
+ */
+ virtual void gotEmoticonNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string alias, std::string msnobject) = 0;
+
+ /** Notifies your application that a message could not be delivered
+ */
+ virtual void failedSendingMessage(MSN::Connection * conn) = 0;
+
+ /** Notifies your application that you got a nudge
+ */
+ virtual void gotNudge(MSN::SwitchboardServerConnection * conn, MSN::Passport username) = 0;
+
+ /** Notifies your application that you got a new voice clip.
+ * To get it you should call requestVoiceClip() and pass msnobject to it
+ */
+ virtual void gotVoiceClipNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject) = 0;
+
+ /** Notifies your application that you got a new wink.
+ * To get it you should call requestWink() and pass msnobject to it
+ */
+ virtual void gotWinkNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject) = 0;
+
+ /** Notifies your application that you got a new Ink.
+ */
+ virtual void gotInk(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string image) = 0;
+
+ /** Notifies your application that you got an action.
+ */
+ virtual void gotActionMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string message) = 0;
+
+ /** Notifies your application that a buddy is typing.
+ */
+ virtual void buddyTyping(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname) = 0;
+
+ /** Notifies your application that you got an initial email notification.
+ */
+ virtual void gotInitialEmailNotification(MSN::NotificationServerConnection * conn, int msgs_inbox, int unread_inbox, int msgs_folders, int unread_folders) = 0;
+
+ /** Notifies your application that you got an email notification.
+ */
+ virtual void gotNewEmailNotification(MSN::NotificationServerConnection * conn, std::string from, std::string subject) = 0;
+
+ /** Notifies your application about a progress of a file transfer.
+ */
+ virtual void fileTransferProgress(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, long long unsigned transferred, long long unsigned total) = 0;
+
+ /** Notifies your application that some file transfer has failed
+ */
+ virtual void fileTransferFailed(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, MSN::fileTransferError error) = 0;
+
+ /** Notifies your application that some file transfer has succeeded.
+ */
+ virtual void fileTransferSucceeded(MSN::SwitchboardServerConnection * conn, unsigned int sessionID) = 0;
+
+ /** Notifies your application that the other contact replied a file transfer
+ * invitation. if "response" is true, then the other contact has accepted,
+ * if false, rejected.
+ */
+ virtual void fileTransferInviteResponse(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, bool response) = 0;
+
+ /** Notifies your application that the other contact sent you a voice clip
+ */
+ virtual void gotVoiceClipFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file) = 0;
+
+ /** Notifies your application that the other contact sent you an emoticon
+ */
+ virtual void gotEmoticonFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string alias, std::string file) = 0;
+
+ /** Notifies your application that the other contact sent a wink
+ */
+ virtual void gotWinkFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file) = 0;
+
+ /** Notifies your application that there is a new connection
+ */
+ virtual void gotNewConnection(MSN::Connection * conn) = 0;
+
+ /** Notifies your application that you got a new OIM list.
+ */
+ virtual void gotOIMList(MSN::NotificationServerConnection * conn, std::vector<MSN::eachOIM> OIMs) = 0;
+
+ /** Notifies your application that you got (or not) one previously requested OIM.
+ */
+ virtual void gotOIM(MSN::NotificationServerConnection * conn, bool success, std::string id, std::string message) = 0;
+
+ /** Notifies your application if a previously sent OIM was delivered.
+ */
+ virtual void gotOIMSendConfirmation(MSN::NotificationServerConnection * conn, bool success, int id) = 0;
+
+ /** Notifies your application if a previously request to delete one OIM was successful.
+ */
+ virtual void gotOIMDeleteConfirmation(MSN::NotificationServerConnection * conn, bool success, std::string id) = 0;
+
+ /** Notifies your application that you got a new display picture from "passaport"
+ */
+ virtual void gotContactDisplayPicture(MSN::SwitchboardServerConnection * conn, MSN::Passport passport, std::string filename ) = 0;
+
+ /** Notifies your application that the connection "conn" is ready
+ */
+ virtual void connectionReady(MSN::Connection * conn) = 0;
+
+ /** Notifies your application that the connection "conn" is closed
+ */
+ virtual void closingConnection(MSN::Connection * conn) = 0;
+
+ /** Notifies your application that a contact has changed his/her status
+ * ex: Online, Away, Out to Lunch..
+ */
+ virtual void changedStatus(MSN::NotificationServerConnection * conn, MSN::BuddyStatus state) = 0;
+
+ /** Asks your application to create a socket with "server" at port "port".
+ * This function must return a socket reference that will be used for
+ * getDataFromSocket() and writeDataToSocket()
+ */
+ virtual void * connectToServer(std::string server, int port, bool *connected, bool isSSL = false) = 0;
+
+ /** Notifies your application that someone is trying to send you a file.
+ */
+ virtual void askFileTransfer(MSN::SwitchboardServerConnection *conn, MSN::fileTransferInvite ft) = 0;
+
+ virtual int listenOnPort(int port) = 0;
+
+ virtual std::string getOurIP() = 0;
+
+ virtual std::string getSecureHTTPProxy() = 0;
+
+ virtual int getSocketFileDescriptor (void *sock) = 0;
+
+ /** Asks your application to get @c size bytes of data available in @p sock
+ * and store them in @p data.
+ * It must return the real size written to @p data
+ */
+ virtual size_t getDataFromSocket (void *sock, char *data, size_t size) = 0;
+
+ /** Asks your application to write @c size bytes from @p data to @p sock.
+ * It must return the real size written to *sock
+ */
+ virtual size_t writeDataToSocket (void *sock, char *data, size_t size) = 0;
+#ifdef LIBMSN_INBOX_URL_ENABLED
+ virtual void gotInboxUrl (MSN::NotificationServerConnection *conn, MSN::hotmailInfo info) = 0;
+#endif
+ };
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibmsn_exporth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libmsn_export.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libmsn_export.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libmsn_export.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+#ifndef _LIBMSN_EXPORT_H_
+#define _LIBMSN_EXPORT_H_
+
+/* export classes under windows
+ * visibility can be added later under all other systems
+*/
+#ifdef _MSC_VER
+// we need to include windows.h here to not get compiler errors inside excpt.h (system header)
+#include <windows.h>
+#pragma warning( disable : 4251 )
+#pragma warning( disable : 4996 )
+#endif
+
+#ifdef _WIN32
+# ifdef msn_EXPORTS
+# define LIBMSN_EXPORT __declspec(dllexport)
+# else
+# define LIBMSN_EXPORT __declspec(dllimport)
+#endif
+#else
+# define LIBMSN_EXPORT
+#endif
+
+#endif // _LIBMSN_EXPORT_H_
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirencommoncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,505 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "siren7.h"
+
+int region_size;
+float region_size_inverse;
+
+float standard_deviation[64];
+float deviation_inverse[64];
+float region_power_table_boundary[63];
+
+int expected_bits_table[8] = {52, 47, 43, 37, 29, 22, 16, 0};
+int vector_dimension[8] = {2, 2, 2, 4, 4, 5, 5, 1};
+int number_of_vectors[8] = {10, 10, 10, 5, 5, 4, 4, 20};
+float dead_zone[8] = {0.3f, 0.33f, 0.36f, 0.39f, 0.42f, 0.45f, 0.5f, 0.5f};
+
+int max_bin[8] = {
+ 13,
+ 9,
+ 6,
+ 4,
+ 3,
+ 2,
+ 1,
+ 1};
+
+float step_size[8] = {
+ 0.3536f,
+ 0.5f,
+ 0.70709997f,
+ 1.0f,
+ 1.4141999f,
+ 2.0f,
+ 2.8283999f,
+ 2.8283999f};
+
+float step_size_inverse[8];
+
+static int siren_initialized = 0;
+
+/*
+ STEPSIZE = 2.0 * log(sqrt(2));
+*/
+#define STEPSIZE 0.3010299957
+
+void siren_init() {
+ int i;
+ float region_power;
+
+ if (siren_initialized == 1)
+ return;
+
+ region_size = 20;
+ region_size_inverse = 1.0f/region_size;
+
+ for (i = 0; i < 64; i++) {
+ region_power = (float) pow(10, (i-24) * STEPSIZE);
+ standard_deviation[i] = (float) sqrt(region_power);
+ deviation_inverse[i] = (float) 1.0 / standard_deviation[i];
+ }
+
+ for (i = 0; i < 63; i++)
+ region_power_table_boundary[i] = (float) pow(10, (i-24 + 0.5) * STEPSIZE);
+
+ for (i = 0; i < 8; i++)
+ step_size_inverse[i] = (float) 1.0 / step_size[i];
+
+ siren_dct4_init();
+ siren_rmlt_init();
+
+ siren_initialized = 1;
+}
+
+
+int categorize_regions(int number_of_regions, int number_of_available_bits, int *absolute_region_power_index, int *power_categories, int *category_balance) {
+ int region, delta, i, temp;
+ int expected_number_of_code_bits;
+ int min, max;
+ int offset,
+ num_rate_control_possibilities,
+ raw_value,
+ raw_max_idx = 0,
+ raw_min_idx = 0;
+ int max_rate_categories[28];
+ int min_rate_categories[28];
+ int temp_category_balances[64];
+ int *min_rate_ptr = NULL;
+ int *max_rate_ptr = NULL;
+
+ if (number_of_regions == 14) {
+ num_rate_control_possibilities = 16;
+ if ( number_of_available_bits > 320)
+ number_of_available_bits = ((number_of_available_bits - 320) * 5/8) + 320;
+ } else {
+ num_rate_control_possibilities = 32;
+ if (number_of_regions == 28 && number_of_available_bits > 640)
+ number_of_available_bits = ((number_of_available_bits - 640) * 5/8) + 640;
+ }
+
+ offset = -32;
+ for (delta = 32; number_of_regions > 0 && delta > 0; delta /= 2) {
+ expected_number_of_code_bits = 0;
+ for (region = 0; region < number_of_regions; region++) {
+ i = (delta + offset - absolute_region_power_index[region]) >> 1;
+ if (i > 7)
+ i = 7;
+ else if (i < 0)
+ i = 0;
+
+ power_categories[region] = i;
+ expected_number_of_code_bits += expected_bits_table[i];
+
+ }
+ if (expected_number_of_code_bits >= number_of_available_bits-32)
+ offset += delta;
+ }
+
+ expected_number_of_code_bits = 0;
+ for (region = 0; region < number_of_regions; region++) {
+ i = (offset - absolute_region_power_index[region]) >> 1;
+ if (i > 7)
+ i = 7;
+ else if (i < 0)
+ i = 0;
+ max_rate_categories[region] = min_rate_categories[region] = power_categories[region] = i;
+ expected_number_of_code_bits += expected_bits_table[i];
+ }
+
+
+ min = max = expected_number_of_code_bits;
+ min_rate_ptr = max_rate_ptr = temp_category_balances + num_rate_control_possibilities;
+ for (i = 0; i < num_rate_control_possibilities -1; i++) {
+ if (min + max > number_of_available_bits * 2) {
+ raw_value = -99;
+ for (region = number_of_regions-1; region >= 0; region--) {
+ if (min_rate_categories[region] < 7) {
+ temp = offset - absolute_region_power_index[region] - 2*min_rate_categories[region];
+ if (temp > raw_value) {
+ raw_value = temp;
+ raw_min_idx = region;
+ }
+ }
+ }
+ *min_rate_ptr++ = raw_min_idx;
+ min += expected_bits_table[min_rate_categories[raw_min_idx] + 1] - expected_bits_table[min_rate_categories[raw_min_idx]];
+ min_rate_categories[raw_min_idx]++;
+ } else {
+ raw_value = 99;
+ for (region = 0; region < number_of_regions; region++) {
+ if (max_rate_categories[region] > 0 ) {
+ temp = offset - absolute_region_power_index[region] - 2*max_rate_categories[region];
+ if (temp < raw_value) {
+ raw_value = temp;
+ raw_max_idx = region;
+ }
+ }
+ }
+
+ *--max_rate_ptr = raw_max_idx;
+ max += expected_bits_table[max_rate_categories[raw_max_idx] - 1] - expected_bits_table[max_rate_categories[raw_max_idx]];
+ max_rate_categories[raw_max_idx]--;
+ }
+ }
+
+ for (region = 0; region < number_of_regions; region++)
+ power_categories[region] = max_rate_categories[region];
+
+ for (i = 0; i < num_rate_control_possibilities-1; i++)
+ category_balance[i] = *max_rate_ptr++;
+
+
+ return 0;
+}
+
+
+
+/*
+ Looks like the flag means what kind of encoding is used
+ for now, it looks like :
+ 0 : the sample rate is not encoded in the frame
+ 1 - 2 : the sample rate is fixed in the frame
+ 3 : sample rate is variable and there is one for each frame
+*/
+
+int GetSirenCodecInfo(int flag, int sample_rate, int *number_of_coefs, int *sample_rate_bits, int *rate_control_bits, int *rate_control_possibilities, int *checksum_bits, int *esf_adjustment, int *scale_factor, int *number_of_regions, int *sample_rate_code, int *bits_per_frame ) {
+ switch (flag) {
+ case 0:
+ *number_of_coefs = 320;
+ *sample_rate_bits = 0;
+ *rate_control_bits = 4;
+ *rate_control_possibilities = 16;
+ *checksum_bits = 0;
+ *esf_adjustment = 7;
+ *number_of_regions = 14;
+ *sample_rate_code = 0;
+ *scale_factor = 22;
+ break;
+ case 1:
+ *number_of_coefs = 320;
+ *sample_rate_bits = 2;
+ *rate_control_bits = 4;
+ *rate_control_possibilities = 16;
+ *checksum_bits = 4;
+ *esf_adjustment = -2;
+ *number_of_regions = 14;
+ *scale_factor = 1;
+ if (sample_rate == 16000)
+ *sample_rate_code = 1;
+ else if (sample_rate == 24000)
+ *sample_rate_code = 2;
+ else if (sample_rate == 32000)
+ *sample_rate_code = 3;
+ else
+ return 3;
+ break;
+ case 2:
+ *number_of_coefs = 640;
+ *sample_rate_bits = 2;
+ *rate_control_bits = 5;
+ *rate_control_possibilities = 32;
+ *checksum_bits = 4;
+ *esf_adjustment = 7;
+ *number_of_regions = 28;
+ *scale_factor = 33;
+
+ if (sample_rate == 24000)
+ *sample_rate_code = 1;
+ else if (sample_rate == 24000)
+ *sample_rate_code = 2;
+ else if (sample_rate == 48000)
+ *sample_rate_code = 3;
+ else
+ return 3;
+
+ break;
+ case 3:
+ *number_of_coefs = 640;
+ *sample_rate_bits = 6;
+ *rate_control_bits = 5;
+ *rate_control_possibilities = 32;
+ *checksum_bits = 4;
+ *esf_adjustment = 7;
+ *scale_factor = 33;
+
+ switch (sample_rate) {
+ case 8800:
+ *number_of_regions = 12;
+ *sample_rate_code = 59;
+ break;
+ case 9600:
+ *number_of_regions = 12;
+ *sample_rate_code = 1;
+ break;
+ case 10400:
+ *number_of_regions = 12;
+ *sample_rate_code = 13;
+ break;
+ case 10800:
+ *number_of_regions = 12;
+ *sample_rate_code = 14;
+ break;
+ case 11200:
+ *number_of_regions = 12;
+ *sample_rate_code = 15;
+ break;
+ case 11600:
+ *number_of_regions = 12;
+ *sample_rate_code = 16;
+ break;
+ case 12000:
+ *number_of_regions = 12;
+ *sample_rate_code = 2;
+ break;
+ case 12400:
+ *number_of_regions = 12;
+ *sample_rate_code = 17;
+ break;
+ case 12800:
+ *number_of_regions = 12;
+ *sample_rate_code = 18;
+ break;
+ case 13200:
+ *number_of_regions = 12;
+ *sample_rate_code = 19;
+ break;
+ case 13600:
+ *number_of_regions = 12;
+ *sample_rate_code = 20;
+ break;
+ case 14000:
+ *number_of_regions = 12;
+ *sample_rate_code = 21;
+ break;
+ case 14400:
+ *number_of_regions = 16;
+ *sample_rate_code = 3;
+ break;
+ case 14800:
+ *number_of_regions = 16;
+ *sample_rate_code = 22;
+ break;
+ case 15200:
+ *number_of_regions = 16;
+ *sample_rate_code = 23;
+ break;
+ case 15600:
+ *number_of_regions = 16;
+ *sample_rate_code = 24;
+ break;
+ case 16000:
+ *number_of_regions = 16;
+ *sample_rate_code = 25;
+ break;
+ case 16400:
+ *number_of_regions = 16;
+ *sample_rate_code = 26;
+ break;
+ case 16800:
+ *number_of_regions = 18;
+ *sample_rate_code = 4;
+ break;
+ case 17200:
+ *number_of_regions = 18;
+ *sample_rate_code = 27;
+ break;
+ case 17600:
+ *number_of_regions = 18;
+ *sample_rate_code = 28;
+ break;
+ case 18000:
+ *number_of_regions = 18;
+ *sample_rate_code = 29;
+ break;
+ case 18400:
+ *number_of_regions = 18;
+ *sample_rate_code = 30;
+ break;
+ case 18800:
+ *number_of_regions = 18;
+ *sample_rate_code = 31;
+ break;
+ case 19200:
+ *number_of_regions = 20;
+ *sample_rate_code = 5;
+ break;
+ case 19600:
+ *number_of_regions = 20;
+ *sample_rate_code = 32;
+ break;
+ case 20000:
+ *number_of_regions = 20;
+ *sample_rate_code = 33;
+ break;
+ case 20400:
+ *number_of_regions = 20;
+ *sample_rate_code = 34;
+ break;
+ case 20800:
+ *number_of_regions = 20;
+ *sample_rate_code = 35;
+ break;
+ case 21200:
+ *number_of_regions = 20;
+ *sample_rate_code = 36;
+ break;
+ case 21600:
+ *number_of_regions = 22;
+ *sample_rate_code = 6;
+ break;
+ case 22000:
+ *number_of_regions = 22;
+ *sample_rate_code = 37;
+ break;
+ case 22400:
+ *number_of_regions = 22;
+ *sample_rate_code = 38;
+ break;
+ case 22800:
+ *number_of_regions = 22;
+ *sample_rate_code = 39;
+ break;
+ case 23200:
+ *number_of_regions = 22;
+ *sample_rate_code = 40;
+ break;
+ case 23600:
+ *number_of_regions = 22;
+ *sample_rate_code = 41;
+ break;
+ case 24000:
+ *number_of_regions = 24;
+ *sample_rate_code = 7;
+ break;
+ case 24400:
+ *number_of_regions = 24;
+ *sample_rate_code = 42;
+ break;
+ case 24800:
+ *number_of_regions = 24;
+ *sample_rate_code = 43;
+ break;
+ case 25200:
+ *number_of_regions = 24;
+ *sample_rate_code = 44;
+ break;
+ case 25600:
+ *number_of_regions = 24;
+ *sample_rate_code = 45;
+ break;
+ case 26000:
+ *number_of_regions = 24;
+ *sample_rate_code = 46;
+ break;
+ case 26400:
+ *number_of_regions = 26;
+ *sample_rate_code = 8;
+ break;
+ case 26800:
+ *number_of_regions = 26;
+ *sample_rate_code = 47;
+ break;
+ case 27200:
+ *number_of_regions = 26;
+ *sample_rate_code = 48;
+ break;
+ case 27600:
+ *number_of_regions = 26;
+ *sample_rate_code = 49;
+ break;
+ case 28000:
+ *number_of_regions = 26;
+ *sample_rate_code = 50;
+ break;
+ case 28400:
+ *number_of_regions = 26;
+ *sample_rate_code = 51;
+ break;
+ case 28800:
+ *number_of_regions = 28;
+ *sample_rate_code = 9;
+ break;
+ case 29200:
+ *number_of_regions = 28;
+ *sample_rate_code = 52;
+ break;
+ case 29600:
+ *number_of_regions = 28;
+ *sample_rate_code = 53;
+ break;
+ case 30000:
+ *number_of_regions = 28;
+ *sample_rate_code = 54;
+ break;
+ case 30400:
+ *number_of_regions = 28;
+ *sample_rate_code = 55;
+ break;
+ case 30800:
+ *number_of_regions = 28;
+ *sample_rate_code = 56;
+ break;
+ case 31200:
+ *number_of_regions = 28;
+ *sample_rate_code = 10;
+ break;
+ case 31600:
+ *number_of_regions = 28;
+ *sample_rate_code = 57;
+ break;
+ case 32000:
+ *number_of_regions = 28;
+ *sample_rate_code = 58;
+ break;
+ default:
+ return 3;
+ break;
+ }
+ break;
+ default:
+ return 6;
+ }
+
+ *bits_per_frame = sample_rate / 50;
+ return 0;
+}
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirencommonh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/common.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,146 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN_COMMON_H
+#define _SIREN_COMMON_H
+
+typedef struct {
+ unsigned int RiffId;
+ unsigned int RiffSize;
+} RiffHeader;
+
+typedef struct {
+ unsigned short Format;
+ unsigned short Channels;
+ unsigned int SampleRate;
+ unsigned int ByteRate;
+ unsigned short BlockAlign;
+ unsigned short BitsPerSample;
+} FmtChunk;
+
+
+typedef struct {
+ FmtChunk fmt;
+ unsigned short ExtraSize;
+ unsigned short DctLength;
+} SirenFmtChunk;
+
+typedef struct {
+ RiffHeader riff;
+ unsigned int WaveId;
+
+ unsigned int FmtId;
+ unsigned int FmtSize;
+
+ SirenFmtChunk fmt;
+
+ unsigned int FactId;
+ unsigned int FactSize;
+ unsigned int Samples;
+
+ unsigned int DataId;
+ unsigned int DataSize;
+} SirenWavHeader;
+
+typedef struct {
+ RiffHeader riff;
+ unsigned int WaveId;
+
+ unsigned int FmtId;
+ unsigned int FmtSize;
+
+ FmtChunk fmt;
+
+ unsigned int FactId;
+ unsigned int FactSize;
+ unsigned int Samples;
+
+ unsigned int DataId;
+ unsigned int DataSize;
+} PCMWavHeader;
+
+#define RIFF_ID 0x46464952
+#define WAVE_ID 0x45564157
+#define FMT__ID 0x20746d66
+#define DATA_ID 0x61746164
+#define FACT_ID 0x74636166
+
+
+extern int region_size;
+extern float region_size_inverse;
+extern float standard_deviation[64];
+extern float deviation_inverse[64];
+extern float region_power_table_boundary[63];
+extern int expected_bits_table[8];
+extern int vector_dimension[8];
+extern int number_of_vectors[8];
+extern float dead_zone[8];
+extern int max_bin[8];
+extern float step_size[8];
+extern float step_size_inverse[8];
+
+
+
+extern void siren_init();
+extern int categorize_regions(int number_of_regions, int number_of_available_bits, int *absolute_region_power_index, int *power_categories, int *category_balance);
+extern int GetSirenCodecInfo(int flag, int sample_rate, int *number_of_coefs, int *sample_rate_bits, int *rate_control_bits, int *rate_control_possibilities, int *checksum_bits, int *esf_adjustment, int *scale_factor, int *number_of_regions, int *sample_rate_code, int *bits_per_frame );
+
+
+#ifdef __BIG_ENDIAN__
+
+#define POW_2_8 256
+#define POW_2_16 65536
+#define POW_2_24 16777216
+
+#define IDX(val, i) ((unsigned int) ((unsigned char *) &val)[i])
+
+
+
+#define ME_FROM_LE16(val) ( (unsigned short) ( IDX(val, 0) + IDX(val, 1) * 256 ))
+#define ME_FROM_LE32(val) ( (unsigned int) (IDX(val, 0) + IDX(val, 1) * 256 + \
+ IDX(val, 2) * 65536 + IDX(val, 3) * 16777216))
+
+
+#define ME_TO_LE16(val) ( (unsigned short) ( \
+ (((unsigned short)val % 256) & 0xff) << 8 | \
+ ((((unsigned short)val / POW_2_8) % 256) & 0xff) ))
+
+#define ME_TO_LE32(val) ( (unsigned int) ( \
+ ((((unsigned int) val ) % 256) & 0xff) << 24 | \
+ ((((unsigned int) val / POW_2_8 ) % 256) & 0xff) << 16| \
+ ((((unsigned int) val / POW_2_16) % 256) & 0xff) << 8 | \
+ ((((unsigned int) val / POW_2_24) % 256) & 0xff) ))
+
+#else
+
+#define ME_TO_LE16(val) ( (unsigned short) (val))
+#define ME_TO_LE32(val) ( (unsigned int) (val))
+#define ME_FROM_LE16(val) ( (unsigned short) (val))
+#define ME_FROM_LE32(val) ( (unsigned int) (val))
+
+
+#endif
+
+
+
+#endif /* _SIREN_COMMON_H */
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirendct4cpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,184 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+
+#define PI 3.1415926
+
+typedef struct {
+ float cos;
+ float msin;
+} dct_table_type;
+
+static float dct_core_320[100];
+static float dct_core_640[100];
+static dct_table_type dct_table_5[5];
+static dct_table_type dct_table_10[10];
+static dct_table_type dct_table_20[20];
+static dct_table_type dct_table_40[40];
+static dct_table_type dct_table_80[80];
+static dct_table_type dct_table_160[160];
+static dct_table_type dct_table_320[320];
+static dct_table_type dct_table_640[640];
+static dct_table_type *dct_tables[8] = {dct_table_5,
+ dct_table_10,
+ dct_table_20,
+ dct_table_40,
+ dct_table_80,
+ dct_table_160,
+ dct_table_320,
+ dct_table_640};
+
+static int dct4_initialized = 0;
+
+void siren_dct4_init() {
+ int i, j = 0;
+ double scale_320 = (float) sqrt(2.0/320);
+ double scale_640 = (float) sqrt(2.0/640);
+ double angle;
+ double scale;
+
+ /* set up dct4 tables */
+ for(i = 0; i < 10; i++) {
+ angle = (float) ((i + 0.5) * PI);
+ for (j = 0 ; j < 10; j++) {
+ dct_core_320[(i*10)+j] = (float) (scale_320 * cos((j + 0.5) * angle / 10));
+ dct_core_640[(i*10)+j] = (float) (scale_640 * cos((j + 0.5) * angle / 10));
+ }
+ }
+
+ for(i = 0; i < 8; i++) {
+ scale = (float) (PI / ((5 << i) * 4));
+ for (j = 0 ; j < (5 << i); j++) {
+ angle = (float) (j + 0.5) * scale;
+ dct_tables[i][j].cos = (float) cos(angle);
+ dct_tables[i][j].msin = (float) -sin(angle);
+ }
+ }
+
+ dct4_initialized = 1;
+}
+
+
+void siren_dct4(float *Source, float *Destination, int dct_length) {
+ int log_length = 0;
+ float * dct_core = NULL;
+ dct_table_type ** dct_table_ptr_ptr = NULL;
+ dct_table_type * dct_table_ptr = NULL;
+ float OutBuffer1[640];
+ float OutBuffer2[640];
+ float *Out_ptr;
+ float *NextOut_ptr;
+ float *In_Ptr = NULL;
+ float *In_Ptr_low = NULL;
+ float *In_Ptr_high = NULL;
+ float In_val_low;
+ float In_val_high;
+ float *Out_ptr_low = NULL;
+ float *Out_ptr_high = NULL;
+ float mult1, mult2, mult3, mult4, mult5, mult6, mult7, mult8, mult9, mult10;
+ int i,j;
+
+ if (dct4_initialized == 0)
+ siren_dct4_init();
+
+ if (dct_length == 640) {
+ log_length = 5;
+ dct_core = dct_core_640;
+ } else {
+ log_length = 4;
+ dct_core = dct_core_320;
+ }
+
+ Out_ptr = OutBuffer1;
+ NextOut_ptr = OutBuffer2;
+ In_Ptr = Source;
+ for (i = 0; i <= log_length; i++) {
+ for (j = 0; j < (1 << i); j++) {
+ Out_ptr_low = Out_ptr + (j * (dct_length >> i));
+ Out_ptr_high = Out_ptr + ( (j+1) * (dct_length >> i));
+ do {
+ In_val_low = *In_Ptr++;
+ In_val_high = *In_Ptr++;
+ *Out_ptr_low++ = In_val_low + In_val_high;
+ *--Out_ptr_high = In_val_low - In_val_high;
+ } while (Out_ptr_low < Out_ptr_high);
+ }
+
+ In_Ptr = Out_ptr;
+ Out_ptr = NextOut_ptr;
+ NextOut_ptr = In_Ptr;
+ }
+
+ for (i = 0; i < (2 << log_length); i++) {
+ for (j = 0 ; j < 10 ; j ++) {
+ mult1 = In_Ptr[(i*10)] * dct_core[j*10];
+ mult2 = In_Ptr[(i*10) + 1] * dct_core[(j*10) + 1];
+ mult3 = In_Ptr[(i*10) + 2] * dct_core[(j*10) + 2];
+ mult4 = In_Ptr[(i*10) + 3] * dct_core[(j*10) + 3];
+ mult5 = In_Ptr[(i*10) + 4] * dct_core[(j*10) + 4];
+ mult6 = In_Ptr[(i*10) + 5] * dct_core[(j*10) + 5];
+ mult7 = In_Ptr[(i*10) + 6] * dct_core[(j*10) + 6];
+ mult8 = In_Ptr[(i*10) + 7] * dct_core[(j*10) + 7];
+ mult9 = In_Ptr[(i*10) + 8] * dct_core[(j*10) + 8];
+ mult10 = In_Ptr[(i*10) + 9] * dct_core[(j*10) + 9];
+ Out_ptr[(i*10)+j] = mult1 + mult2 + mult3 + mult4 +
+ mult5 + mult6 + mult7 + mult8 +
+ mult9 + mult10;
+ }
+ }
+
+
+ In_Ptr = Out_ptr;
+ Out_ptr = NextOut_ptr;
+ NextOut_ptr = In_Ptr;
+ dct_table_ptr_ptr = dct_tables;
+ for (i = log_length; i >= 0; i--) {
+ dct_table_ptr_ptr++;
+ for (j = 0; j < (1 << i); j++) {
+ dct_table_ptr = *dct_table_ptr_ptr;
+ if ( i == 0 )
+ Out_ptr_low = Destination + (j * (dct_length >> i));
+ else
+ Out_ptr_low = Out_ptr + (j * (dct_length >> i));
+
+ Out_ptr_high = Out_ptr_low + (dct_length >> i);
+
+ In_Ptr_low = In_Ptr + (j * (dct_length >> i));
+ In_Ptr_high = In_Ptr_low + (dct_length >> (i+1));
+ do {
+ *Out_ptr_low++ = (*In_Ptr_low * (*dct_table_ptr).cos) - (*In_Ptr_high * (*dct_table_ptr).msin);
+ *--Out_ptr_high = (*In_Ptr_high++ * (*dct_table_ptr).cos) + (*In_Ptr_low++ * (*dct_table_ptr).msin);
+ dct_table_ptr++;
+ *Out_ptr_low++ = (*In_Ptr_low * (*dct_table_ptr).cos) + (*In_Ptr_high * (*dct_table_ptr).msin);
+ *--Out_ptr_high = (*In_Ptr_low++ * (*dct_table_ptr).msin) - (*In_Ptr_high++ * (*dct_table_ptr).cos);
+ dct_table_ptr++;
+ } while (Out_ptr_low < Out_ptr_high);
+ }
+
+ In_Ptr = Out_ptr;
+ Out_ptr = NextOut_ptr;
+ NextOut_ptr = In_Ptr;
+ }
+
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirendct4h"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/dct4.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_DCT4_H_
+#define _SIREN7_DCT4_H_
+
+extern void siren_dct4_init();
+extern void siren_dct4(float *Source, float *Destination, int dct_length);
+
+
+#endif /* _SIREN7_DCT4_H_ */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirendecodercpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,234 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+SirenDecoder Siren7_NewDecoder(int sample_rate) {
+ SirenDecoder decoder = (SirenDecoder) malloc(sizeof(struct stSirenDecoder));
+ decoder->sample_rate = sample_rate;
+
+ decoder->WavHeader.riff.RiffId = ME_TO_LE32(RIFF_ID);
+ decoder->WavHeader.riff.RiffSize = sizeof(PCMWavHeader) - 2*sizeof(int);
+ decoder->WavHeader.riff.RiffSize = ME_TO_LE32(decoder->WavHeader.riff.RiffSize);
+ decoder->WavHeader.WaveId = ME_TO_LE32(WAVE_ID);
+
+ decoder->WavHeader.FmtId = ME_TO_LE32(FMT__ID);
+ decoder->WavHeader.FmtSize = ME_TO_LE32(sizeof(FmtChunk));
+
+ decoder->WavHeader.fmt.Format = ME_TO_LE16(0x01);
+ decoder->WavHeader.fmt.Channels = ME_TO_LE16(1);
+ decoder->WavHeader.fmt.SampleRate = ME_TO_LE32(16000);
+ decoder->WavHeader.fmt.ByteRate = ME_TO_LE32(32000);
+ decoder->WavHeader.fmt.BlockAlign = ME_TO_LE16(2);
+ decoder->WavHeader.fmt.BitsPerSample = ME_TO_LE16(16);
+
+ decoder->WavHeader.FactId = ME_TO_LE32(FACT_ID);
+ decoder->WavHeader.FactSize = ME_TO_LE32(sizeof(int));
+ decoder->WavHeader.Samples = ME_TO_LE32(0);
+
+ decoder->WavHeader.DataId = ME_TO_LE32(DATA_ID);
+ decoder->WavHeader.DataSize = ME_TO_LE32(0);
+
+ memset(decoder->context, 0, sizeof(decoder->context));
+ memset(decoder->backup_frame, 0, sizeof(decoder->backup_frame));
+
+ decoder->dw1 = 1;
+ decoder->dw2 = 1;
+ decoder->dw3 = 1;
+ decoder->dw4 = 1;
+
+ siren_init();
+ return decoder;
+}
+
+void Siren7_CloseDecoder(SirenDecoder decoder) {
+ free(decoder);
+}
+
+int Siren7_DecodeFrame(SirenDecoder decoder, unsigned char *DataIn, unsigned char *DataOut) {
+ int number_of_coefs,
+ sample_rate_bits,
+ rate_control_bits,
+ rate_control_possibilities,
+ checksum_bits,
+ esf_adjustment,
+ scale_factor,
+ number_of_regions,
+ sample_rate_code,
+ bits_per_frame;
+ int decoded_sample_rate_code;
+
+ static int absolute_region_power_index[28] = {0};
+ static float decoder_standard_deviation[28] = {0};
+ static int power_categories[28] = {0};
+ static int category_balance[28] = {0};
+ int ChecksumTable[4] = {0x7F80, 0x7878, 0x6666, 0x5555};
+ int i, j;
+
+ int dwRes = 0;
+ int envelope_bits = 0;
+ int rate_control = 0;
+ int number_of_available_bits;
+ int number_of_valid_coefs;
+ int frame_error = 0;
+
+ int In[20];
+ float coefs[320];
+ float BufferOut[320];
+ int sum;
+ int checksum;
+ int calculated_checksum;
+ int idx;
+ int temp1;
+ int temp2;
+
+ for (i = 0; i < 20; i++)
+#ifdef __BIG_ENDIAN__
+ In[i] = ((short *) DataIn)[i];
+#else
+ In[i] = ((((short *) DataIn)[i] << 8) & 0xFF00) | ((((short *) DataIn)[i] >> 8) & 0x00FF);
+#endif
+
+ dwRes = GetSirenCodecInfo(1, decoder->sample_rate, &number_of_coefs, &sample_rate_bits, &rate_control_bits, &rate_control_possibilities, &checksum_bits, &esf_adjustment, &scale_factor, &number_of_regions, &sample_rate_code, &bits_per_frame );
+
+ if (dwRes != 0)
+ return dwRes;
+
+
+ set_bitstream(In);
+
+ decoded_sample_rate_code = 0;
+ for (i = 0; i < sample_rate_bits; i++) {
+ decoded_sample_rate_code <<= 1;
+ decoded_sample_rate_code |= next_bit();
+ }
+
+
+ if (decoded_sample_rate_code != sample_rate_code)
+ return 7;
+
+ number_of_valid_coefs = region_size * number_of_regions;
+ number_of_available_bits = bits_per_frame - sample_rate_bits - checksum_bits ;
+
+
+ envelope_bits = decode_envelope(number_of_regions, decoder_standard_deviation, absolute_region_power_index, esf_adjustment);
+
+ number_of_available_bits -= envelope_bits;
+
+ for (i = 0; i < rate_control_bits; i++) {
+ rate_control <<= 1;
+ rate_control |= next_bit();
+ }
+
+ number_of_available_bits -= rate_control_bits;
+
+ categorize_regions(number_of_regions, number_of_available_bits, absolute_region_power_index, power_categories, category_balance);
+
+ for (i = 0; i < rate_control; i++) {
+ power_categories[category_balance[i]]++;
+ }
+
+ number_of_available_bits = decode_vector(decoder, number_of_regions, number_of_available_bits, decoder_standard_deviation, power_categories, coefs, scale_factor);
+
+
+ frame_error = 0;
+ if (number_of_available_bits > 0) {
+ for (i = 0; i < number_of_available_bits; i++) {
+ if (next_bit() == 0)
+ frame_error = 1;
+ }
+ } else if (number_of_available_bits < 0 && rate_control + 1 < rate_control_possibilities) {
+ frame_error |= 2;
+ }
+
+ for (i = 0; i < number_of_regions; i++) {
+ if (absolute_region_power_index[i] > 33 || absolute_region_power_index[i] < -31)
+ frame_error |= 4;
+ }
+
+ if (checksum_bits > 0) {
+ bits_per_frame >>= 4;
+ checksum = In[bits_per_frame - 1] & ((1 << checksum_bits) - 1);
+ In[bits_per_frame - 1] &= ~checksum;
+ sum = 0;
+ idx = 0;
+ do {
+ sum ^= (In[idx] & 0xFFFF) << (idx % 15);
+ } while (++idx < bits_per_frame);
+
+ sum = (sum >> 15) ^ (sum & 0x7FFF);
+ calculated_checksum = 0;
+ for (i = 0; i < 4; i++) {
+ temp1 = ChecksumTable[i] & sum;
+ for (j = 8; j > 0; j >>= 1) {
+ temp2 = temp1 >> j;
+ temp1 ^= temp2;
+ }
+ calculated_checksum <<= 1;
+ calculated_checksum |= temp1 & 1;
+ }
+
+ if (checksum != calculated_checksum)
+ frame_error |= 8;
+ }
+
+ if (frame_error != 0) {
+ for (i = 0; i < number_of_valid_coefs; i++) {
+ coefs[i] = decoder->backup_frame[i];
+ decoder->backup_frame[i] = 0;
+ }
+ } else {
+ for (i = 0; i < number_of_valid_coefs; i++)
+ decoder->backup_frame[i] = coefs[i];
+ }
+
+
+ for (i = number_of_valid_coefs; i < number_of_coefs; i++)
+ coefs[i] = 0;
+
+
+ dwRes = siren_rmlt_decode_samples(coefs, decoder->context, 320, BufferOut);
+
+
+ for (i = 0; i < 320; i++) {
+ if (BufferOut[i] > 32767.0)
+ ((short *)DataOut)[i] = (short) ME_TO_LE16((short) 32767);
+ else if (BufferOut[i] <= -32768.0)
+ ((short *)DataOut)[i] = (short) ME_TO_LE16((short) 32768);
+ else
+ ((short *)DataOut)[i] = (short) ME_TO_LE16((short) BufferOut[i]);
+ }
+
+ decoder->WavHeader.Samples = ME_FROM_LE32(decoder->WavHeader.Samples);
+ decoder->WavHeader.Samples += 320;
+ decoder->WavHeader.Samples = ME_TO_LE32(decoder->WavHeader.Samples);
+ decoder->WavHeader.DataSize = ME_FROM_LE32(decoder->WavHeader.DataSize);
+ decoder->WavHeader.DataSize += 640;
+ decoder->WavHeader.DataSize = ME_TO_LE32(decoder->WavHeader.DataSize);
+ decoder->WavHeader.riff.RiffSize = ME_FROM_LE32(decoder->WavHeader.riff.RiffSize);
+ decoder->WavHeader.riff.RiffSize += 640;
+ decoder->WavHeader.riff.RiffSize = ME_TO_LE32(decoder->WavHeader.riff.RiffSize);
+
+
+ return 0;
+}
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirendecoderh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/decoder.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN_DECODER_H
+#define _SIREN_DECODER_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dct4.h"
+#include "rmlt.h"
+#include "huffman.h"
+#include "common.h"
+
+
+typedef struct stSirenDecoder {
+        int sample_rate;
+        PCMWavHeader WavHeader;
+        float context[320];
+        float backup_frame[320];
+        int dw1;
+        int dw2;
+        int dw3;
+        int dw4;
+} * SirenDecoder;
+
+
+/* MUST be 16000 to be compatible with MSN Voice clips (I think) */
+extern SirenDecoder Siren7_NewDecoder(int sample_rate);
+extern void Siren7_CloseDecoder(SirenDecoder decoder);
+extern int Siren7_DecodeFrame(SirenDecoder decoder, unsigned char *DataIn, unsigned char *DataOut);
+
+#endif /* _SIREN_DECODER_H */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenencodercpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,234 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+
+#include "siren7.h"
+
+
+SirenEncoder Siren7_NewEncoder(int sample_rate) {
+ SirenEncoder encoder = (SirenEncoder) malloc(sizeof(struct stSirenEncoder));
+ encoder->sample_rate = sample_rate;
+
+ encoder->WavHeader.riff.RiffId = ME_TO_LE32(RIFF_ID);
+ encoder->WavHeader.riff.RiffSize = sizeof(SirenWavHeader) - 2*sizeof(int);
+ encoder->WavHeader.riff.RiffSize = ME_TO_LE32(encoder->WavHeader.riff.RiffSize);
+ encoder->WavHeader.WaveId = ME_TO_LE32(WAVE_ID);
+
+ encoder->WavHeader.FmtId = ME_TO_LE32(FMT__ID);
+ encoder->WavHeader.FmtSize = ME_TO_LE32(sizeof(SirenFmtChunk));
+
+ encoder->WavHeader.fmt.fmt.Format = ME_TO_LE16(0x028E);
+ encoder->WavHeader.fmt.fmt.Channels = ME_TO_LE16(1);
+ encoder->WavHeader.fmt.fmt.SampleRate = ME_TO_LE32(16000);
+ encoder->WavHeader.fmt.fmt.ByteRate = ME_TO_LE32(2000);
+ encoder->WavHeader.fmt.fmt.BlockAlign = ME_TO_LE16(40);
+ encoder->WavHeader.fmt.fmt.BitsPerSample = ME_TO_LE16(0);
+ encoder->WavHeader.fmt.ExtraSize = ME_TO_LE16(2);
+ encoder->WavHeader.fmt.DctLength = ME_TO_LE16(320);
+
+ encoder->WavHeader.FactId = ME_TO_LE32(FACT_ID);
+ encoder->WavHeader.FactSize = ME_TO_LE32(sizeof(int));
+ encoder->WavHeader.Samples = ME_TO_LE32(0);
+
+ encoder->WavHeader.DataId = ME_TO_LE32(DATA_ID);
+ encoder->WavHeader.DataSize = ME_TO_LE32(0);
+
+ memset(encoder->context, 0, sizeof(encoder->context));
+
+ siren_init();
+ return encoder;
+}
+
+void Siren7_CloseEncoder(SirenEncoder encoder) {
+ free(encoder);
+}
+
+
+
+int Siren7_EncodeFrame(SirenEncoder encoder, unsigned char *DataIn, unsigned char *DataOut) {
+ int number_of_coefs,
+ sample_rate_bits,
+ rate_control_bits,
+ rate_control_possibilities,
+ checksum_bits,
+ esf_adjustment,
+ scale_factor,
+ number_of_regions,
+ sample_rate_code,
+ bits_per_frame;
+ int sample_rate = encoder->sample_rate;
+
+ static int absolute_region_power_index[28] = {0};
+ static int power_categories[28] = {0};
+ static int category_balance[28] = {0};
+ static int drp_num_bits[30] = {0};
+ static int drp_code_bits[30] = {0};
+ static int region_mlt_bit_counts[28] = {0};
+ static int region_mlt_bits[112] = {0};
+ int ChecksumTable[4] = {0x7F80, 0x7878, 0x6666, 0x5555};
+ int i, j;
+
+ int dwRes = 0;
+ short out_word;
+ int bits_left;
+ int current_word_bits_left;
+ int region_bit_count;
+ unsigned int current_word;
+ unsigned int sum;
+ unsigned int checksum;
+ int temp1 = 0;
+ int temp2 = 0;
+ int region;
+ int idx = 0;
+ int envelope_bits = 0;
+ int rate_control;
+ int number_of_available_bits;
+
+ float coefs[320];
+ float In[320];
+ short BufferOut[20];
+ float *context = encoder->context;
+
+ for (i = 0; i < 320; i++)
+ In[i] = (float) ((short) ME_FROM_LE16(((short *) DataIn)[i]));
+
+ dwRes = siren_rmlt_encode_samples(In, context, 320, coefs);
+
+
+ if (dwRes != 0)
+ return dwRes;
+
+ dwRes = GetSirenCodecInfo(1, sample_rate, &number_of_coefs, &sample_rate_bits, &rate_control_bits, &rate_control_possibilities, &checksum_bits, &esf_adjustment, &scale_factor, &number_of_regions, &sample_rate_code, &bits_per_frame );
+
+ if (dwRes != 0)
+ return dwRes;
+
+ envelope_bits = compute_region_powers(number_of_regions, coefs, drp_num_bits, drp_code_bits, absolute_region_power_index, esf_adjustment);
+
+ number_of_available_bits = bits_per_frame - rate_control_bits - envelope_bits - sample_rate_bits - checksum_bits ;
+
+ categorize_regions(number_of_regions, number_of_available_bits, absolute_region_power_index, power_categories, category_balance);
+
+ for(region = 0; region < number_of_regions; region++) {
+ absolute_region_power_index[region] += 24;
+ region_mlt_bit_counts[region] = 0;
+ }
+
+ rate_control = quantize_mlt(number_of_regions, rate_control_possibilities, number_of_available_bits, coefs, absolute_region_power_index, power_categories, category_balance, region_mlt_bit_counts, region_mlt_bits);
+
+ idx = 0;
+ bits_left = 16 - sample_rate_bits;
+ out_word = sample_rate_code << (16 - sample_rate_bits);
+ drp_num_bits[number_of_regions] = rate_control_bits;
+ drp_code_bits[number_of_regions] = rate_control;
+ for (region = 0; region <= number_of_regions; region++) {
+ i = drp_num_bits[region] - bits_left;
+ if (i < 0) {
+ out_word += drp_code_bits[region] << -i;
+ bits_left -= drp_num_bits[region];
+ } else {
+ BufferOut[idx++] = out_word + (drp_code_bits[region] >> i);
+ bits_left += 16 - drp_num_bits[region];
+ out_word = drp_code_bits[region] << bits_left;
+ }
+ }
+
+ for (region = 0; region < number_of_regions && (16*idx) < bits_per_frame; region++) {
+ current_word_bits_left = region_bit_count = region_mlt_bit_counts[region];
+ if (current_word_bits_left > 32)
+ current_word_bits_left = 32;
+
+ current_word = region_mlt_bits[region*4];
+ i = 1;
+ while(region_bit_count > 0 && (16*idx) < bits_per_frame) {
+ if (current_word_bits_left < bits_left) {
+ bits_left -= current_word_bits_left;
+ out_word += (current_word >> (32 - current_word_bits_left)) << bits_left;
+ current_word_bits_left = 0;
+ } else {
+ BufferOut[idx++] = (short) (out_word + (current_word >> (32 - bits_left)));
+ current_word_bits_left -= bits_left;
+ current_word <<= bits_left;
+ bits_left = 16;
+ out_word = 0;
+ }
+ if (current_word_bits_left == 0) {
+ region_bit_count -= 32;
+ current_word = region_mlt_bits[(region*4) + i++];
+ current_word_bits_left = region_bit_count;
+ if (current_word_bits_left > 32)
+ current_word_bits_left = 32;
+ }
+ }
+ }
+
+
+ while ( (16*idx) < bits_per_frame) {
+ BufferOut[idx++] = (short) ((0xFFFF >> (16 - bits_left)) + out_word);
+ bits_left = 16;
+ out_word = 0;
+ }
+
+ if (checksum_bits > 0) {
+ BufferOut[idx-1] &= (-1 << checksum_bits);
+ sum = 0;
+ idx = 0;
+ do {
+ sum ^= (BufferOut[idx] & 0xFFFF) << (idx % 15);
+ } while ((16*++idx) < bits_per_frame);
+
+ sum = (sum >> 15) ^ (sum & 0x7FFF);
+ checksum = 0;
+ for (i = 0; i < 4; i++) {
+ temp1 = ChecksumTable[i] & sum;
+ for (j = 8; j > 0; j >>= 1) {
+ temp2 = temp1 >> j;
+ temp1 ^= temp2;
+ }
+ checksum <<= 1;
+ checksum |= temp1 & 1;
+ }
+ BufferOut[idx-1] |= ((1 << checksum_bits) -1) & checksum;
+ }
+
+
+ for (i = 0; i < 20; i++)
+#ifdef __BIG_ENDIAN__
+ ((short *) DataOut)[i] = BufferOut[i];
+#else
+ ((short *) DataOut)[i] = ((BufferOut[i] << 8) & 0xFF00) | ((BufferOut[i] >> 8) & 0x00FF);
+#endif
+
+ encoder->WavHeader.Samples = ME_FROM_LE32(encoder->WavHeader.Samples);
+ encoder->WavHeader.Samples += 320;
+ encoder->WavHeader.Samples = ME_TO_LE32(encoder->WavHeader.Samples);
+ encoder->WavHeader.DataSize = ME_FROM_LE32(encoder->WavHeader.DataSize);
+ encoder->WavHeader.DataSize += 40;
+ encoder->WavHeader.DataSize = ME_TO_LE32(encoder->WavHeader.DataSize);
+ encoder->WavHeader.riff.RiffSize = ME_FROM_LE32(encoder->WavHeader.riff.RiffSize);
+ encoder->WavHeader.riff.RiffSize += 40;
+ encoder->WavHeader.riff.RiffSize = ME_TO_LE32(encoder->WavHeader.riff.RiffSize);
+
+
+ return 0;
+}
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenencoderh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/encoder.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN_ENCODER_H
+#define _SIREN_ENCODER_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dct4.h"
+#include "rmlt.h"
+#include "huffman.h"
+#include "common.h"
+
+
+typedef struct stSirenEncoder {
+        int sample_rate;
+        SirenWavHeader WavHeader;
+        float context[320];
+} * SirenEncoder;
+
+/* sample_rate MUST be 16000 to be compatible with MSN Voice clips (I think) */
+extern SirenEncoder Siren7_NewEncoder(int sample_rate);
+extern void Siren7_CloseEncoder(SirenEncoder encoder);
+extern int Siren7_EncodeFrame(SirenEncoder encoder, unsigned char *DataIn, unsigned char *DataOut);
+
+
+#endif /* _SIREN_ENCODER_H */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffmancpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,382 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+#include "huffman_consts.h"
+
+
+static short current_word = 0;
+static int bit_idx = 0;
+static int *bitstream_ptr = NULL;
+
+int next_bit() {
+ if (bitstream_ptr == NULL)
+ return -1;
+
+ if (bit_idx == 0) {
+ current_word = *bitstream_ptr++;
+ bit_idx = 16;
+ }
+
+ return (current_word >> --bit_idx) & 1;
+}
+
+void set_bitstream(int *stream) {
+ bitstream_ptr = stream;
+ current_word = *bitstream_ptr;
+ bit_idx = 0;
+}
+
+
+int compute_region_powers(int number_of_regions, float *coefs, int *drp_num_bits, int *drp_code_bits, int *absolute_region_power_index, int esf_adjustment) {
+ float region_power = 0;
+ int num_bits;
+ int idx;
+ int max_idx, min_idx;
+ int region, i;
+
+ for (region = 0; region < number_of_regions; region++) {
+ region_power = 0.0f;
+ for (i = 0 ; i < region_size; i++) {
+ region_power += coefs[(region*region_size)+i] * coefs[(region*region_size)+i];
+ }
+ region_power *= region_size_inverse;
+
+ min_idx = 0;
+ max_idx = 64;
+ for (i = 0; i < 6; i++) {
+ idx = (min_idx + max_idx) / 2;
+ if (region_power_table_boundary[idx-1] <= region_power) {
+ min_idx = idx;
+ } else {
+ max_idx = idx;
+ }
+ }
+ absolute_region_power_index[region] = min_idx - 24;
+
+ }
+
+ for (region = number_of_regions-2; region >= 0; region--) {
+ if (absolute_region_power_index[region] < absolute_region_power_index[region+1] - 11)
+ absolute_region_power_index[region] = absolute_region_power_index[region+1] - 11;
+ }
+
+ if (absolute_region_power_index[0] < (1-esf_adjustment))
+ absolute_region_power_index[0] = (1-esf_adjustment);
+
+ if (absolute_region_power_index[0] > (31-esf_adjustment))
+ absolute_region_power_index[0] = (31-esf_adjustment);
+
+ drp_num_bits[0] = 5;
+ drp_code_bits[0] = absolute_region_power_index[0] + esf_adjustment;
+
+
+ for(region = 1; region < number_of_regions; region++) {
+ if (absolute_region_power_index[region] < (-8 - esf_adjustment))
+ absolute_region_power_index[region] = (-8 - esf_adjustment);
+ if (absolute_region_power_index[region] > (31-esf_adjustment))
+ absolute_region_power_index[region] = (31-esf_adjustment);
+ }
+
+ num_bits = 5;
+
+ for(region = 0; region < number_of_regions-1; region++) {
+ idx = absolute_region_power_index[region+1] - absolute_region_power_index[region] + 12;
+ if (idx < 0)
+ idx = 0;
+
+ absolute_region_power_index[region+1] = absolute_region_power_index[region] + idx - 12;
+ drp_num_bits[region+1] = differential_region_power_bits[region][idx];
+ drp_code_bits[region+1] = differential_region_power_codes[region][idx];
+ num_bits += drp_num_bits[region+1];
+ }
+
+ return num_bits;
+}
+
+
+int decode_envelope(int number_of_regions, float *decoder_standard_deviation, int *absolute_region_power_index, int esf_adjustment) {
+ int index;
+ int i;
+ int envelope_bits = 0;
+
+ index = 0;
+ for (i = 0; i < 5; i++)
+ index = (index<<1) | next_bit();
+ envelope_bits = 5;
+
+ absolute_region_power_index[0] = index - esf_adjustment;
+ decoder_standard_deviation[0] = standard_deviation[absolute_region_power_index[0] + 24];
+
+ for (i = 1; i < number_of_regions; i++) {
+ index = 0;
+ do {
+ index = differential_decoder_tree[i-1][index][next_bit()];
+ envelope_bits++;
+ } while (index > 0);
+
+ absolute_region_power_index[i] = absolute_region_power_index[i-1] - index - 12;
+ decoder_standard_deviation[i] = standard_deviation[absolute_region_power_index[i] + 24];
+ }
+
+ return envelope_bits;
+}
+
+
+
+static int huffman_vector(int category, int power_idx, float *mlts, int *out) {
+ int i, j;
+ float temp_value = deviation_inverse[power_idx] * step_size_inverse[category];
+ int sign_idx, idx, non_zeroes, max, bits_available;
+ int current_word = 0;
+ int region_bits = 0;
+
+ bits_available = 32;
+ for (i = 0; i < number_of_vectors[category]; i++) {
+ sign_idx = idx = non_zeroes = 0;
+ for (j = 0; j < vector_dimension[category]; j++) {
+ max = (int) ((fabs(*mlts) * temp_value) + dead_zone[category]);
+ if (max != 0) {
+ sign_idx <<= 1;
+ non_zeroes++;
+ if (*mlts > 0)
+ sign_idx++;
+ if (max > max_bin[category] || max < 0)
+ max = max_bin[category];
+
+ }
+ mlts++;
+ idx = (idx * (max_bin[category] + 1)) + max;
+ }
+
+ region_bits += bitcount_tables[category][idx] + non_zeroes;
+ bits_available -= bitcount_tables[category][idx] + non_zeroes;
+ if (bits_available < 0) {
+ *out++ = current_word + (((code_tables[category][idx] << non_zeroes) + sign_idx) >> -bits_available);
+ bits_available += 32;
+ current_word = ((code_tables[category][idx] << non_zeroes) + sign_idx) << bits_available;
+ } else {
+ current_word += ((code_tables[category][idx] << non_zeroes) + sign_idx) << bits_available;
+ }
+
+ }
+
+ *out = current_word;
+ return region_bits;
+}
+
+int quantize_mlt(int number_of_regions, int rate_control_possibilities, int number_of_available_bits, float *coefs, int *absolute_region_power_index, int *power_categories, int *category_balance, int *region_mlt_bit_counts, int *region_mlt_bits) {
+ int region;
+ int mlt_bits = 0;
+ int rate_control;
+
+ for (rate_control = 0; rate_control < ((rate_control_possibilities >> 1) - 1); rate_control++)
+ power_categories[category_balance[rate_control]]++;
+
+ for (region = 0; region < number_of_regions; region++) {
+ if (power_categories[region] > 6)
+ region_mlt_bit_counts[region] = 0;
+ else
+ region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+ region_mlt_bits + (4*region));
+ mlt_bits += region_mlt_bit_counts[region];
+ }
+
+ while (mlt_bits < number_of_available_bits && rate_control > 0) {
+ rate_control--;
+ region = category_balance[rate_control];
+ power_categories[region]--;
+
+ if (power_categories[region] < 0)
+ power_categories[region] = 0;
+
+ mlt_bits -= region_mlt_bit_counts[region];
+
+ if (power_categories[region] > 6)
+ region_mlt_bit_counts[region] = 0;
+ else
+ region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+ region_mlt_bits + (4*region));
+
+ mlt_bits += region_mlt_bit_counts[region];
+ }
+
+ while(mlt_bits > number_of_available_bits && rate_control < rate_control_possibilities) {
+ region = category_balance[rate_control];
+ power_categories[region]++;
+ mlt_bits -= region_mlt_bit_counts[region];
+
+ if (power_categories[region] > 6)
+ region_mlt_bit_counts[region] = 0;
+ else
+ region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+ region_mlt_bits + (4*region));
+
+ mlt_bits += region_mlt_bit_counts[region];
+
+ rate_control++;
+ }
+
+ return rate_control;
+}
+
+static int get_dw(SirenDecoder decoder) {
+ int ret = decoder->dw1 + decoder->dw4;
+
+ if ((ret & 0x8000) != 0)
+ ret++;
+
+ decoder->dw1 = decoder->dw2;
+ decoder->dw2 = decoder->dw3;
+ decoder->dw3 = decoder->dw4;
+ decoder->dw4 = ret;
+
+ return ret;
+}
+
+
+
+
+int decode_vector(SirenDecoder decoder, int number_of_regions, int number_of_available_bits, float *decoder_standard_deviation, int *power_categories, float *coefs, int scale_factor) {
+ float *coefs_ptr;
+ float decoded_value;
+ float noise;
+ int *decoder_tree;
+
+ int region;
+ int category;
+ int i, j;
+ int index;
+ int error;
+ int dw1;
+ int dw2;
+
+ error = 0;
+ for (region = 0; region < number_of_regions; region++) {
+ category = power_categories[region];
+ coefs_ptr = coefs + (region * region_size);
+
+ if (category < 7) {
+ decoder_tree = decoder_tables[category];
+
+ for (i = 0; i < number_of_vectors[category]; i++) {
+ index = 0;
+ do {
+ if (number_of_available_bits <= 0) {
+ error = 1;
+ break;
+ }
+
+ index = decoder_tree[index + next_bit()];
+ number_of_available_bits--;
+ } while ((index & 1) == 0);
+
+ index >>= 1;
+
+ if (error == 0 && number_of_available_bits >= 0) {
+ for (j = 0; j < vector_dimension[category]; j++) {
+ decoded_value = mlt_quant[category][index & ((1 << index_table[category]) - 1)];
+ index >>= index_table[category];
+
+ if (decoded_value != 0) {
+ if (next_bit() == 0)
+ decoded_value *= -decoder_standard_deviation[region];
+ else
+ decoded_value *= decoder_standard_deviation[region];
+ number_of_available_bits--;
+ }
+
+ *coefs_ptr++ = decoded_value * scale_factor;
+ }
+ } else {
+ error = 1;
+ break;
+ }
+ }
+
+ if (error == 1) {
+ for (j = region + 1; j < number_of_regions; j++)
+ power_categories[j] = 7;
+ category = 7;
+ }
+ }
+
+
+ coefs_ptr = coefs + (region * region_size);
+
+ if (category == 5) {
+ i = 0;
+ for (j = 0; j < region_size; j++) {
+ if (*coefs_ptr != 0) {
+ i++;
+ if (fabs(*coefs_ptr) > 2.0 * decoder_standard_deviation[region]) {
+ i += 3;
+ }
+ }
+ coefs_ptr++;
+ }
+
+ noise = decoder_standard_deviation[region] * noise_category5[i];
+ } else if (category == 6) {
+ i = 0;
+ for (j = 0; j < region_size; j++) {
+ if (*coefs_ptr++ != 0)
+ i++;
+ }
+
+ noise = decoder_standard_deviation[region] * noise_category6[i];
+ } else if (category == 7) {
+ noise = decoder_standard_deviation[region] * noise_category7;
+ } else {
+ noise = 0;
+ }
+
+ coefs_ptr = coefs + (region * region_size);
+
+ if (category == 5 || category == 6 || category == 7) {
+ dw1 = get_dw(decoder);
+ dw2 = get_dw(decoder);
+
+ for (j=0; j<10; j++) {
+ if (category == 7 || *coefs_ptr == 0) {
+ if ((dw1 & 1))
+ *coefs_ptr = noise;
+ else
+ *coefs_ptr = -noise;
+ }
+ coefs_ptr++;
+ dw1 >>= 1;
+
+ if (category == 7 || *coefs_ptr == 0) {
+ if ((dw2 & 1))
+ *coefs_ptr = noise;
+ else
+ *coefs_ptr = -noise;
+ }
+ coefs_ptr++;
+ dw2 >>= 1;
+ }
+ }
+ }
+
+ return error == 1 ? -1 : number_of_available_bits;
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffmanh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SIREN7_HUFFMAN_H_
+#define _SIREN7_HUFFMAN_H_
+
+#include "decoder.h"
+
+extern int compute_region_powers(int number_of_regions, float *coefs, int *drp_num_bits, int *drp_code_bits, int *absolute_region_power_index, int esf_adjustment);
+extern int quantize_mlt(int number_of_regions, int rate_control_possibilities, int number_of_available_bits, float *coefs, int *absolute_region_power_index, int *power_categories, int *category_balance, int *region_mlt_bit_counts, int *region_mlt_bits);
+extern int decode_envelope(int number_of_regions, float *decoder_standard_deviation, int *absolute_region_power_index, int esf_adjustment);
+extern int decode_vector(SirenDecoder decoder, int number_of_regions, int number_of_available_bits, float *decoder_standard_deviation, int *power_categories, float *coefs, int scale_factor);
+
+extern void set_bitstream(int *stream);
+extern int next_bit();
+
+#endif /* _SIREN7_HUFFMAN_H_ */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenhuffman_constsh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman_consts.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman_consts.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/huffman_consts.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,528 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _HUFFMAN_CONSTS_H
+#define _HUFFMAN_CONSTS_H
+
+
+static int differential_region_power_bits[28][24] = {
+ {4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12},
+ {10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16},
+ {12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14},
+ {13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13},
+ {12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14},
+ {12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14},
+ {15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16},
+ {14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15},
+ {9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13},
+ {14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14},
+ {13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14},
+ {16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+ {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14}
+};
+
+
+static int differential_region_power_codes[28][24] = {
+ {8, 38, 18, 10, 7, 6, 3, 2, 0, 1, 7, 6, 5, 4, 11, 78, 158, 318, 1278, 1279, 2552, 2553, 2554, 2555},
+ {36, 8, 3, 5, 0, 1, 7, 6, 4, 3, 2, 5, 3, 4, 5, 19, 74, 150, 302, 1213, 1214, 1215, 2424, 2425},
+ {2582, 644, 160, 41, 5, 11, 7, 5, 4, 1, 0, 6, 4, 7, 3, 6, 4, 21, 81, 323, 1290, 5167, 10332, 10333},
+ {2940, 366, 181, 180, 47, 46, 27, 10, 8, 5, 1, 0, 3, 7, 4, 9, 12, 26, 44, 182, 734, 2941, 2942, 2943},
+ {3982, 7967, 994, 249, 63, 26, 19, 18, 14, 8, 6, 1, 0, 2, 5, 7, 12, 30, 27, 125, 496, 1990, 15932, 15933},
+ {3254, 1626, 407, 206, 202, 100, 30, 14, 3, 5, 3, 0, 2, 4, 2, 13, 24, 31, 102, 207, 812, 6511, 13020, 13021},
+ {1110, 2216, 1111, 139, 35, 9, 3, 20, 11, 4, 2, 1, 3, 3, 1, 0, 21, 5, 16, 68, 276, 2217, 2218, 2219},
+ {1013, 1014, 127, 62, 29, 6, 4, 16, 0, 1, 3, 2, 3, 1, 5, 9, 17, 5, 28, 30, 252, 1015, 2024, 2025},
+ {381, 380, 372, 191, 94, 44, 16, 10, 7, 3, 1, 0, 2, 6, 9, 17, 45, 92, 187, 746, 1494, 2991, 5980, 5981},
+ {3036, 758, 188, 45, 43, 10, 4, 3, 6, 4, 2, 0, 3, 7, 11, 20, 42, 44, 46, 95, 378, 3037, 3038, 3039},
+ {751, 92, 45, 20, 26, 4, 12, 7, 4, 0, 4, 1, 3, 5, 5, 3, 27, 21, 44, 47, 186, 374, 1500, 1501},
+ {45572, 5697, 2849, 1425, 357, 45, 23, 6, 10, 7, 2, 2, 3, 0, 4, 6, 7, 88, 179, 713, 11392, 45573, 45574, 45575},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+ {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021}
+};
+
+
+static int bitcount_table_category0[196] = {
+ 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 11, 11, 4, 5, 6, 7, 7, 8, 8,
+ 9, 9, 9, 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11,
+ 12, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11,
+ 11, 12, 13, 14, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 15, 8,
+ 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 15, 9, 9, 9, 10, 10, 10,
+ 11, 11, 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, 11, 12, 12, 14,
+ 14, 16, 16, 16, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16,
+ 10, 10, 10, 11, 11, 12, 12, 13, 15, 15, 16, 14, 15, 15, 11, 11, 11, 12,
+ 13, 13, 13, 15, 16, 16, 16, 16, 14, 15, 11, 11, 12, 13, 13, 14, 15, 16,
+ 16, 16, 16, 16, 16, 14};
+
+static int code_table_category0[196] = {
+ 1, 2, 1, 24, 14, 51, 9, 68, 110, 26, 218, 54, 154, 761, 3, 10, 22, 8, 58,
+ 22, 71, 16, 30, 50, 213, 75, 94, 632, 15, 18, 52, 23, 107, 5, 54, 63, 239,
+ 46, 276, 271, 851, 252, 28, 10, 12, 1, 22, 133, 191, 55, 105, 278, 317, 554,
+ 310, 276, 32, 50, 94, 20, 187, 219, 13, 268, 473, 445, 145, 849, 1277, 623,
+ 1, 14, 0, 55, 238, 121, 120, 269, 318, 530, 639, 1117, 509, 556, 24, 78, 51,
+ 153, 62, 308, 16, 25, 68, 1058, 428, 277, 2233, 1114, 92, 108, 141, 223, 270,
+ 381, 24, 212, 760, 35, 1063, 279, 1717, 3439, 7, 21, 152, 73, 309, 310, 95, 944,
+ 1890, 2232, 1891, 5107, 10213, 4981, 61, 62, 9, 79, 474, 475, 848, 1059, 1056, 1716,
+ 139, 4978, 4983, 4983, 140, 186, 76, 444, 144, 633, 1057, 838, 2237, 4472, 4473,
+ 10212, 10212, 4983, 74, 78, 311, 213, 850, 1062, 1119, 508, 276, 277, 4982, 4473,
+ 10212, 10212, 208, 70, 555, 418, 68, 510, 2552, 1115, 4980, 4979, 4982, 4982, 4473,
+ 10212, 215, 71, 253, 511, 839, 1718, 2488, 6876, 6877, 4979, 4979, 4982, 4982, 4473};
+
+
+static int bitcount_table_category1[100] = {
+ 1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, 8, 8, 9, 9,
+ 10, 11, 6, 6, 7, 8, 8, 9, 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, 11, 13, 8, 8, 8,
+ 9, 9, 10, 10, 11, 12, 14, 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, 9, 10, 11, 12,
+ 12, 14, 14, 14, 9, 9, 9, 10, 11, 12, 14, 16, 14, 14, 10, 10, 11, 12, 13, 14, 16, 16,
+ 16, 14};
+
+static int code_table_category1[100] = {
+ 1, 2, 11, 27, 31, 9, 120, 31, 275, 310, 1, 0, 12, 5, 33, 54, 102, 111, 246, 448, 10, 14,
+ 31, 39, 59, 100, 114, 202, 485, 969, 24, 26, 36, 52, 103, 30, 120, 242, 69, 1244, 35,
+ 32, 14, 61, 113, 117, 233, 486, 487, 2491, 13, 12, 69, 110, 149, 35, 495, 449, 1978,
+ 7751, 76, 75, 122, 136, 213, 68, 623, 930, 3959, 9961, 115, 16, 107, 225, 424, 850,
+ 1936, 7916, 4981, 4981, 148, 154, 243, 407, 988, 851, 7750, 19920, 7916, 4981, 406, 274,
+ 464, 931, 3874, 7917, 19921, 19920, 19920, 7916};
+
+
+static int bitcount_table_category2[64] = {
+ 1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, 8, 9, 10, 12,
+ 8, 8, 8, 9, 10, 12, 14, 8, 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, 15, 1, 1, 1};
+
+static int code_table_category2[52] = {
+ 1, 0, 10, 11, 28, 62, 363, 3, 2, 9, 8, 24, 53, 352, 7, 8, 13, 25, 89, 74, 355, 10, 23, 24,
+ 29, 55, 354, 1449, 25, 19, 30, 52, 108, 438, 5793, 91, 36, 63, 353, 725, 11584, 23170, 180,
+ 75, 218, 439, 2897, 23171, 11584};
+
+
+static int bitcount_table_category3[625] = {
+ 2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, 16, 5, 6, 8,
+ 10, 11, 5, 6, 8, 10, 12, 7, 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, 16, 16, 7, 9, 10, 12,
+ 15, 7, 8, 10, 12, 13, 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, 14, 16, 14, 9, 11, 12, 16,
+ 16, 9, 10, 13, 15, 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, 16, 15, 16, 16, 11, 13, 16,
+ 16, 15, 11, 13, 15, 16, 16, 13, 13, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 6, 8,
+ 10, 13, 6, 6, 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13,
+ 6, 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, 7, 8,
+ 10, 12, 14, 9, 9, 10, 13, 16, 11, 10, 12, 15, 16, 13, 13, 16, 16, 15, 9, 11, 13, 16, 16, 9, 10,
+ 12, 15, 16, 10, 11, 13, 16, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 16, 11, 13, 16, 16, 16, 11,
+ 13, 16, 16, 16, 12, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 11, 13, 16, 8,
+ 8, 10, 12, 16, 11, 10, 11, 13, 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 15, 6, 8, 10, 13, 16, 8,
+ 8, 10, 12, 16, 10, 10, 11, 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 16, 8, 9, 11, 13, 16, 8,
+ 9, 11, 16, 14, 10, 10, 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, 16, 10, 12, 15, 16, 16,
+ 10, 12, 12, 14, 16, 12, 12, 13, 16, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 12, 15, 15, 16,
+ 16, 13, 13, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15, 16, 16, 16, 8, 10, 13,
+ 15, 16, 10, 11, 13, 16, 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 10,
+ 11, 15, 16, 9, 10, 12, 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 9, 11,
+ 14, 16, 16, 10, 11, 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, 16, 16, 16, 16, 16, 16, 11, 13,
+ 16, 16, 16, 11, 13, 15, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16,
+ 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 13,
+ 16, 16, 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 13,
+ 15, 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 13,
+ 15, 16, 16, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 15, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
+
+static int code_table_category3[625] = {
+ 3, 8, 46, 145, 228, 4, 8, 47, 28, 455, 89, 2, 180, 5, 1335, 250, 12, 644, 1311, 139, 729, 251, 870,
+ 2172, 2211, 5, 23, 112, 334, 1469, 21, 3, 5, 111, 2014, 88, 79, 152, 124, 2685, 297, 48, 110, 1310,
+ 149, 501, 1231, 153, 2267, 2569, 57, 13, 653, 2587, 143, 75, 124, 118, 2611, 5242, 61, 50, 253, 3633,
+ 2216, 476, 39, 57, 1926, 2236, 2586, 1329, 1920, 2566, 1926, 296, 233, 2590, 2240, 2217, 253, 613,
+ 867, 144, 318, 614, 252, 2589, 2242, 2218, 872, 866, 2187, 2296, 2155, 2568, 2227, 150, 2567, 2296,
+ 199, 2686, 2160, 2290, 19145, 232, 2680, 128, 2192, 2212, 2684, 793, 2281, 2223, 2242, 1934, 2165,
+ 2146, 2291, 2296, 2222, 2189, 2187, 2296, 2296, 6, 4, 82, 725, 3632, 15, 21, 56, 599, 148, 3, 162,
+ 42, 411, 2301, 735, 654, 930, 137, 2586, 869, 1334, 1931, 2300, 2213, 9, 22, 146, 1290, 5240, 5, 12,
+ 53, 630, 875, 80, 9, 8, 86, 2002, 210, 117, 56, 2019, 2162, 146, 397, 868, 131, 2151, 77, 160, 365,
+ 2610, 2252, 59, 54, 41, 2591, 1928, 226, 14, 121, 5792, 2295, 1197, 728, 408, 130, 2157, 3635, 155,
+ 2573, 2587, 130, 314, 64, 144, 2173, 2176, 115, 30, 409, 153, 2590, 631, 26, 4787, 2221, 2174, 2683,
+ 1863, 2572, 319, 2150, 2177, 2194, 2571, 2257, 319, 65, 145, 2251, 2156, 2161, 909, 864, 2193, 2197,
+ 2246, 2588, 5797, 156, 2258, 2221, 2158, 2199, 2214, 2152, 319, 2188, 2264, 2572, 319, 319, 30, 117,
+ 219, 865, 2263, 147, 127, 239, 410, 2247, 27, 324, 1468, 2681, 2180, 1328, 5241, 147, 142, 2237, 2241,
+ 2245, 1921, 2262, 142, 41, 11, 505, 2682, 2591, 0, 26, 229, 2015, 2577, 464, 98, 87, 5243, 2166, 149,
+ 2016, 5244, 2190, 2198, 9573, 11598, 11599, 2235, 2190, 144, 298, 1004, 5245, 2277, 156, 104, 254, 2560,
+ 1922, 612, 325, 2017, 129, 2588, 2608, 1330, 871, 2144, 2145, 132, 2147, 2148, 2149, 2144, 119, 1331,
+ 133, 2153, 2154, 211, 58, 2609, 1923, 2159, 510, 163, 5246, 2163, 2164, 1924, 134, 2167, 2168, 2168, 2169,
+ 2170, 2171, 2168, 2168, 1332, 135, 136, 2175, 2153, 150, 873, 2178, 2179, 1923, 1925, 2181, 2182, 2183,
+ 2163, 2184, 2185, 2186, 2168, 2168, 1924, 134, 2167, 2168, 2168, 58, 326, 2687, 138, 2191, 31, 66, 874,
+ 2195, 2196, 151, 152, 1927, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2205, 55,
+ 103, 1230, 140, 2215, 118, 15, 1333, 2219, 2220, 2018, 511, 141, 2224, 2225, 2226, 1929, 2228, 2229, 2230,
+ 2231, 2232, 2233, 2234, 2229, 366, 1005, 1930, 2238, 2239, 12, 1006, 5247, 2243, 2244, 1932, 3634, 1933,
+ 2248, 2249, 2250, 145, 146, 2253, 2253, 2254, 2255, 2256, 2253, 2253, 1291, 5793, 2259, 2260, 2261, 477,
+ 5794, 147, 2265, 2266, 5795, 2268, 2269, 2270, 2270, 2271, 2272, 2273, 2274, 2274, 2275, 2276, 2273, 2274,
+ 2274, 148, 2278, 2279, 2280, 2260, 1935, 2282, 2283, 2284, 2265, 2285, 2286, 2287, 2270, 2270, 2288, 2289,
+ 2273, 2274, 2274, 2271, 2272, 2273, 2274, 2274, 233, 5796, 2292, 2293, 2294, 1292, 3724, 2297, 2298, 2299,
+ 2000, 151, 2302, 2303, 2200, 152, 2561, 2562, 2563, 2205, 2564, 2565, 2204, 2205, 2205, 363, 154, 154, 155,
+ 2570, 59, 3725, 2001, 2574, 2575, 2576, 157, 2578, 2579, 2224, 2580, 2581, 2582, 2583, 2229, 2584, 2585, 2228,
+ 2229, 2229, 654, 5798, 158, 2589, 2238, 2392, 2003, 2592, 2593, 2243, 2594, 2595, 2596, 2597, 2248, 2598, 2599,
+ 2600, 2253, 2253, 2250, 145, 146, 2253, 2253, 2601, 2602, 2603, 2604, 2260, 2605, 2606, 2607, 6336, 2265, 6337,
+ 6338, 6339, 2270, 2270, 6340, 6341, 2273, 2274, 2274, 2271, 2272, 2273, 2274, 2274, 6342, 6343, 2259, 2260,
+ 2260, 38288, 38289, 147, 2265, 2265, 5795, 2268, 2269, 2270, 2270, 2271, 2272, 2273, 2274, 2274, 2271, 2272,
+ 2273, 2274, 2274};
+
+
+static int bitcount_table_category4[256] = {
+ 2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, 11, 11, 15, 15, 4, 5, 9,
+ 12, 5, 5, 8, 12, 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, 8, 8,
+ 12, 15, 10, 10, 13, 15, 14, 14, 15, 13, 11, 13, 15, 15, 11, 13, 15,
+ 15, 14, 15, 15, 13, 15, 15, 13, 13, 4, 5, 9, 13, 5, 6, 9, 13, 9, 9,
+ 11, 15, 14, 13, 15, 15, 4, 6, 9, 12, 5, 6, 9, 13, 9, 8, 11, 15, 13,
+ 12, 15, 15, 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, 14, 15, 15,
+ 14, 10, 12, 15, 15, 11, 13, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14,
+ 6, 9, 13, 14, 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 15, 7, 9, 13,
+ 15, 8, 9, 12, 15, 11, 12, 15, 15, 15, 15, 15, 15, 9, 11, 15, 15, 9,
+ 11, 15, 15, 14, 14, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 14, 15,
+ 15, 15, 15, 15, 15, 15, 14, 14, 15, 15, 9, 12, 15, 15, 12, 13, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 10, 12, 15, 15, 12, 14, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
+ 15, 15, 14, 14, 15, 15};
+
+static int code_table_category4[256] = {
+ 1, 2, 4, 572, 10, 0, 69, 712, 91, 10, 46, 9182, 1426, 1430, 30172, 30194,
+ 9, 28, 22, 2258, 16, 25, 142, 2179, 15, 111, 719, 1521, 1131, 1437, 1520,
+ 30196, 88, 283, 3803, 30193, 13, 236, 2856, 30166, 545, 951, 5709, 1522,
+ 3241, 9180, 30179, 5709, 1088, 4356, 30410, 30175, 1146, 377, 30162, 30163,
+ 8715, 30176, 30165, 5709, 30197, 30184, 5709, 5709, 1, 23, 28, 5710, 26, 14,
+ 29, 7538, 102, 103, 1429, 1524, 3237, 7060, 30401, 30201, 15, 13, 470, 3768,
+ 24, 15, 281, 5747, 24, 181, 1128, 30206, 5711, 3531, 30156, 30158, 116, 100,
+ 2260, 30187, 119, 234, 1764, 30171, 716, 883, 9183, 30164, 3236, 1528, 30180,
+ 9183, 885, 2870, 1532, 30160, 1431, 5708, 30192, 30205, 30402, 30168, 30173,
+ 9183, 30157, 30161, 9183, 9183, 54, 25, 1621, 15211, 180, 287, 2261, 30198, 808,
+ 811, 30411, 30413, 30414, 22986, 22987, 30411, 24, 273, 376, 30159, 137, 280,
+ 2871, 1523, 1768, 2259, 1525, 30167, 1526, 30169, 30170, 1525, 443, 1434, 1527,
+ 30174, 474, 1769, 30177, 30178, 3238, 3239, 30181, 30181, 30182, 30183, 30181,
+ 30181, 3240, 30185, 30186, 1527, 9181, 30188, 30189, 30177, 30190, 30191, 30181,
+ 30181, 3238, 3239, 30181, 30181, 440, 2857, 1529, 30195, 2294, 7061, 1530, 30199,
+ 30200, 1531, 30202, 30411, 30203, 30204, 30411, 30411, 203, 2872, 30207, 30400,
+ 189, 11492, 30403, 30404, 30405, 30406, 30407, 1525, 30408, 30409, 1525, 1525,
+ 8714, 1533, 30412, 1527, 1534, 1535, 30415, 30177, 30416, 30417, 30181, 30181,
+ 3238, 3239, 30181, 30181, 30418, 30419, 1527, 1527, 30420, 30421, 30177, 30177,
+ 3238, 3239, 30181, 30181, 3238, 3239, 30181, 30181};
+
+
+static int bitcount_table_category5[256] = {
+ 2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, 5, 6, 12,10, 11, 15, 9, 11, 15, 10, 13, 15,
+ 14, 15, 6, 4, 6, 12, 6, 7, 12, 12, 12, 15, 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12,
+ 15, 11, 13, 15, 15, 15, 7, 8, 13, 15, 11, 12, 15, 15, 15, 7, 10, 13, 15, 12, 15, 15,
+ 15, 15, 7, 15, 15, 7, 15, 15, 7, 6, 7, 7, 4, 5, 11, 5, 7, 12, 11, 12, 15, 6, 7, 13, 7,
+ 8, 14, 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 8, 5, 6, 13, 7, 8, 15, 12, 14, 15,
+ 6, 8, 14, 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, 15, 15, 8, 9, 13, 15, 12, 13,
+ 15, 15, 15, 8, 11, 13, 15, 13, 13, 15, 15, 15, 8, 14, 15, 8, 15, 15, 8, 7, 8, 8, 8, 10,
+ 15, 11, 12, 15, 15, 15, 7, 10, 12, 15, 12, 13, 15, 15, 15, 8, 14, 15, 7, 15, 15, 8, 7,
+ 8, 8, 8, 12, 15, 12, 13, 15, 15, 15, 8, 11, 13, 15, 13, 15, 15, 15, 15, 8, 15, 15, 8,
+ 15, 15, 8, 7, 8, 8, 14, 15, 6, 15, 15, 8, 7, 8, 8, 15, 15, 8, 15, 15, 8, 7, 8, 8, 6,
+ 8, 8, 7, 8, 8, 7, 8, 8};
+
+static int code_table_category5[243] = {
+ 0, 5, 220, 10, 16, 443, 390, 391, 14333, 11, 26, 1566, 26, 54, 3135, 508, 1558, 28581,
+ 255, 1782, 28599, 885, 6208, 28578, 14335, 28579, 54, 9, 35, 3129, 27, 68, 3537, 1562,
+ 3568, 28610, 25, 62, 4078, 58, 118, 7763, 3107, 7758, 28563, 778, 3131, 28598, 780, 7123,
+ 28630, 28593, 28586, 118, 243, 6210, 28614, 1018, 3567, 28601, 28611, 28570, 68, 388, 6256,
+ 28619, 1559, 28562, 28606, 28565, 28591, 118, 28594, 28571, 62, 28618, 28590, 118, 58,
+ 118, 118, 4, 28, 1781, 31, 60, 3134, 1938, 3882, 28574, 25, 96, 7757, 49, 126, 14244,
+ 3883, 14334, 28613, 1769, 4077, 28602, 3106, 7756, 28582, 28621, 28566, 126, 14, 61, 4079,
+ 61, 138, 28491, 3536, 8153, 28573, 49, 96, 12442, 119, 240, 28490, 12443, 28560, 28561, 3111,
+ 3580, 28564, 3130, 7759, 28567, 28568, 28569, 240, 444, 6209, 28572, 3569, 6211, 28575, 28576,
+ 28577, 138, 778, 7760, 28580, 7761, 7762, 28583, 28584, 28585, 240, 14319, 28587, 96, 28588, 28589,
+ 240, 119, 240, 240, 139, 968, 28592, 1554, 3581, 28595, 28596, 28597, 60, 971, 3560, 28600,3582,
+ 7132, 28603, 28604, 28605, 126, 14332, 28607, 96, 28608, 28609, 126, 49, 126, 126, 241, 1558, 28612,
+ 1563, 6257, 28615, 28616, 28617, 138, 1559, 7133, 28620, 6220, 28622, 28623, 28624, 28625, 240, 28626,
+ 28627, 96, 28628, 28629, 240, 119, 240, 240, 8152, 28631, 61, 28632, 28633, 138, 61, 138, 138, 28634,
+ 28635, 96, 28636, 28637, 240, 119, 240, 240, 49, 96, 96, 119, 240, 240, 119, 240, 240};
+
+
+static int bitcount_table_category6[32] = {1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, 6, 9, 8, 10, 8, 10, 9, 11};
+
+static int code_table_category6[32] = {1, 2, 4, 2, 5, 29, 24, 101, 3, 31, 28, 105, 3, 5, 102, 424, 1, 30, 0, 107, 27, 200, 103, 806, 1, 4, 104, 402, 3, 425, 213, 807};
+
+
+
+static int *bitcount_tables[7] = {
+ bitcount_table_category0,
+ bitcount_table_category1,
+ bitcount_table_category2,
+ bitcount_table_category3,
+ bitcount_table_category4,
+ bitcount_table_category5,
+ bitcount_table_category6};
+
+static int *code_tables[7] = {
+ code_table_category0,
+ code_table_category1,
+ code_table_category2,
+ code_table_category3,
+ code_table_category4,
+ code_table_category5,
+ code_table_category6};
+
+
+
+
+static int differential_decoder_tree[27][24][2] = {
+ {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, -12}, {-11, -10}, {-8, -9}, {-7, -6}, {-13, 12}, {-5, -4}, {0, 13}, {-3, -14}, {-2, 14}, {-1, 15}, {-15, 16}, {-16, 17}, {-17, 18}, {19, 20}, {21, 22}, {-18, -19}, {-20, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {-10, -9}, {-8, -11}, {-7, -6}, {9, -5}, {10, -12}, {-4, 11}, {-13, -3}, {12, -2}, {13, -14}, {-1, 14}, {15, -15}, {0, 16}, {-16, 17}, {-17, 18}, {-18, 19}, {20, 21},{22, -19}, {-20, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {-12, 11}, {-11, -13}, {-10, -9}, {12, -14}, {-8, -7}, {-15, -6}, {13, -5}, {-16, -4}, {14, -17}, {15, -3}, {16, -18}, {-2, 17}, {18, -19}, {-1, 19}, {-20, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {-11, -10}, {7, -12}, {8, -9}, {9, -13}, {-14, 10}, {-8, -15}, {-16, 11}, {-7, 12}, {-17, -6}, {13, 14}, {-18, 15}, {-5, -4}, {16, 17}, {-3, -2}, {-19, 18}, {-1, 19}, {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {-12, -11}, {-13, 7}, {8, -14}, {-10, 9}, {10, -15}, {-9, 11}, {-8, 12}, {-16, 13}, {-7, -6}, {-17, 14}, {-5, -18}, {15, -4}, {16, -19}, {17, -3}, {-20, 18}, {-2, 19}, {-21, 20}, {0, 21}, {22, -1}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-12, -10}, {-13, -9}, {8, 9}, {-14, -8}, {10, -15}, {-7, 11}, {-16, 12}, {-6, -17}, {13, 14}, {-5, 15}, {-18, 16}, {-4, 17}, {-3, -19}, {18, -2}, {-20, 19}, {-1, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, -12}, {6, -11}, {-10, -13}, {-9, 7}, {8, -14}, {9, -8}, {-15, 10}, {-7, -16}, {11, -6}, {12, -17}, {13, -5}, {-18, 14}, {15, -4}, {-19, 16}, {17, -3}, {-20, 18}, {19, 20}, {21, 22}, {0, -2}, {-1, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, -12}, {6, -13}, {-11, -10}, {7, -14}, {8, -9}, {9, -15}, {-8, 10}, {-7, -16}, {11, 12}, {-6, -17}, {-5, 13}, {14, 15}, {-18, -4}, {-19, 16}, {-3, 17}, {18, -2}, {-20, 19}, {20, 21}, {22, 0}, {-1, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {-11, -10}, {-12, -9}, {7, 8}, {-13, -8}, {9, -14}, {-7, 10}, {-6, -15}, {11, 12}, {-5, -16}, {13, 14}, {-17, 15}, {-4, 16}, {17, -18}, {18, -3}, {-2, 19}, {-1, 0}, {-19, 20}, {-20, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-10, -12}, {-9, 8}, {-8, -13}, {9, -7}, {10, -14}, {-6, 11}, {-15, 12}, {-5, 13}, {-16, -4}, {14, 15}, {-17, -3}, {-18, 16}, {17, -19}, {-2, 18}, {-20, 19}, {-1, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, -12}, {6, -11}, {7, 8}, {-10, -13}, {-9, 9}, {-8, -14}, {10, -7}, {11, -15}, {-6, 12}, {-5, 13}, {-4, -16}, {14, 15}, {-3, -17}, {16, 17}, {-18, -2}, {18, -19}, {-1, 19}, {-20, 20}, {-21, 21}, {22, 0}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {5, -12}, {-13, 6}, {-11, 7}, {-14, 8}, {-10, 9}, {-15, -9}, {-8, 10}, {-7, -16}, {11, -6}, {12, -5}, {-17, 13}, {14, -18}, {15, -4}, {16, -19}, {17, -3}, {18, -2}, {19, -1}, {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+ {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}}};
+
+
+
+static float mlt_quant[7][14] = {
+ { 0.0f, 0.392f, 0.761f, 1.120f, 1.477f, 1.832f, 2.183f, 2.541f, 2.893f, 3.245f, 3.598f, 3.942f, 4.288f, 4.724f},
+ { 0.0f, 0.544f, 1.060f, 1.563f, 2.068f, 2.571f, 3.072f, 3.562f, 4.070f, 4.620f, 0.0f, 0.0f, 0.0f, 0.0f},
+ { 0.0f, 0.746f, 1.464f, 2.180f, 2.882f, 3.584f, 4.316f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ { 0.0f, 1.006f, 2.000f, 2.993f, 3.985f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ { 0.0f, 1.321f, 2.703f, 3.983f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ { 0.0f, 1.657f, 3.491f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ { 0.0f, 1.964f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}};
+
+
+static int decoder_tree0[360] = {
+ 2, 1, 4, 6, 8, 10, 12, 14, 16, 18, 33, 3, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 35, 40, 42, 44, 46, 5, 48, 65, 50, 52, 54, 56, 58, 60,
+ 62, 64, 37, 66, 67, 68, 97, 70, 72, 74, 7, 76, 78, 80, 82, 84, 86, 88,
+ 99, 90, 39, 92, 94, 96, 129, 98, 9, 100, 102, 104, 106, 108, 110, 112, 41, 161,
+ 69, 114, 116, 118, 131, 120, 122, 11, 124, 126, 128, 193, 130, 132, 71, 134, 43, 136,
+ 138, 140, 163, 101, 13, 142, 144, 146, 148, 150, 152, 154, 225, 156, 158, 195, 160, 162,
+ 45, 164, 15, 166, 73, 168, 170, 133, 47, 172, 257, 174, 176, 178, 75, 103, 180, 165,
+ 182, 17, 227, 184, 105, 49, 135, 186, 289, 188, 259, 190, 192, 194, 196, 198, 291, 77,
+ 200, 202, 197, 107, 204, 19, 51, 229, 206, 167, 208, 210, 212, 214, 21, 79, 81, 109,
+ 216, 218, 220, 222, 53, 137, 224, 199, 226, 323, 321, 169, 228, 111, 230, 232, 139, 261,
+ 234, 83, 236, 201, 238, 240, 293, 242, 353, 231, 141, 244, 246, 113, 23, 355, 85, 248,
+ 55, 115, 250, 263, 252, 254, 203, 171, 256, 258, 233, 235, 143, 357, 325, 260, 295, 262,
+ 173, 145, 177, 87, 264, 327, 267, 266, 268, 175, 270, 272, 117, 297, 274, 265, 147, 179,
+ 205, 276, 207, 237, 269, 278, 57, 59, 387, 209, 280, 282, 149, 329, 385, 284, 25, 286,
+ 239, 119, 288, 27, 290, 292, 299, 294, 359, 89, 296, 298, 419, 181, 300, 331, 271, 417,
+ 211, 361, 151, 389, 241, 302, 304, 303, 306, 308, 421, 91, 310, 312, 391, 314, 121, 316,
+ 333, 318, 275, 213, 301, 243, 183, 335, 320, 363, 322, 215, 324, 393, 273, 337, 153, 326,
+ 423, 365, 328, 367, 247, 395, 185, 123, 330, 425, 245, 155, 332, 334, 305, 397, 336, 277,
+ 217, 338, 340, 339, 427, 342, 344, 346, 307, 399, 187, 348, 309, 341, 350, 369, 279, 311,
+ 429, 249, 219, 352, 354, 356, 358, 431, 373, 401, 371, 313, 281, 433, 343, 403, 251, 283};
+
+
+static int decoder_tree1[188] = {
+ 2, 1, 4, 6, 8, 10, 12, 14, 16, 3, 33, 18, 20, 22, 24, 26, 35, 28, 30,
+ 32, 34, 36, 5, 65, 38, 40, 37, 42, 44, 46, 67, 48, 50, 52, 54, 56, 58,
+ 60, 7, 62, 39, 97, 64, 69, 66, 99, 68, 70, 72, 74, 76, 78, 80, 129, 41,
+ 131, 82, 9, 71, 84, 86, 101, 88, 90, 92, 94, 96, 161, 43, 11, 73, 98, 103,
+ 100, 163, 102, 104, 106, 108, 133, 110, 105, 112, 75, 114, 45, 13, 116, 165, 118, 195,
+ 135, 193, 120, 77, 122, 47, 124, 167, 225, 126, 79, 107, 227, 128, 137, 197, 15, 130,
+ 169, 199, 132, 109, 134, 17, 139, 49, 136, 229, 138, 140, 81, 259, 142, 144, 171, 146,
+ 141, 148, 111, 150, 201, 231, 152, 51, 257, 289, 154, 19, 113, 156, 261, 158, 203, 173,
+ 263, 143, 160, 291, 235, 83, 162, 233, 265, 164, 205, 166, 293, 145, 168, 175, 177, 237,
+ 115, 295, 170, 207, 172, 267, 174, 176, 297, 147, 178, 180, 269, 182, 271, 209, 299, 239,
+ 179, 184, 301, 241, 211, 0, 0};
+
+static int decoder_tree2[96] = {
+ 2, 1, 4, 6, 8, 10, 12, 3, 17, 14, 19, 16, 18, 20, 22, 24, 26, 5, 21,
+ 35, 33, 28, 30, 32, 34, 36, 38, 37, 40, 23, 51, 42, 7, 49, 44, 46, 48, 50,
+ 39, 53, 52, 54, 56, 25, 67, 9, 58, 60, 65, 55, 41, 62, 64, 69, 66, 11, 27,
+ 68, 57, 83, 70, 71, 81, 43, 72, 74, 13, 76, 85, 29, 73, 78, 99, 59, 87, 101,
+ 80, 97, 45, 82, 84, 75, 89, 61, 86, 103, 88, 77, 90, 105, 91, 92, 107, 93, 0, 0};
+
+static int decoder_tree3[1040] = {
+ 2, 4, 6, 8, 10, 1, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 3, 36,
+ 1025, 38, 40, 42, 44, 46, 48, 50, 129, 17, 52, 54, 1153, 19, 56, 58, 60, 62, 64,
+ 66, 68, 145, 70, 72, 74, 76, 78, 1169, 1027, 147, 80, 82, 1171, 84, 86, 131, 88, 1155,
+ 1043, 1041, 90, 92, 5, 94, 96, 98, 100, 102, 104, 21, 106, 108, 2049, 2177, 110, 112, 114,
+ 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 33, 144, 163, 146, 148,
+ 150, 152, 154, 161, 156, 35, 158, 1297, 160, 162, 273, 257, 164, 166, 149, 168, 1281, 170, 172,
+ 2193, 174, 176, 178, 1299, 180, 1045, 182, 184, 1173, 186, 3201, 188, 190, 192, 194, 2195, 1187, 23,
+ 2179, 196, 7, 198, 275, 200, 2051, 202, 2065, 204, 206, 1029, 1185, 208, 210, 1157, 37, 3073, 2067,
+ 133, 212, 214, 2321, 216, 165, 218, 1059, 220, 1283, 222, 2305, 224, 226, 228, 230, 259, 232, 234,
+ 2323, 236, 1409, 1057, 1315, 238, 240, 242, 244, 246, 1425, 248, 1313, 250, 252, 254, 256, 258, 260,
+ 289, 262, 264, 1189, 266, 268, 179, 151, 270, 272, 274, 276, 278, 291, 280, 282, 9, 385, 284,
+ 286, 177, 49, 401, 1061, 288, 290, 292, 51, 294, 296, 298, 300, 302, 304, 25, 306, 2083, 39,
+ 308, 310, 3329, 167, 312, 314, 1175, 316, 318, 1203, 135, 320, 322, 324, 326, 328, 2211, 2307, 330,
+ 1301, 332, 334, 1047, 336, 338, 2449, 3217, 340, 1427, 2209, 53, 342, 2339, 3345, 344, 346, 348, 403,
+ 181, 4097, 2197, 350, 2181, 1285, 1317, 1031, 352, 354, 356, 3089, 358, 360, 4225, 277, 362, 364, 366,
+ 368, 2069, 370, 3203, 293, 1201, 305, 372, 3219, 307, 2433, 374, 376, 378, 380, 2081, 1411, 382, 384,
+ 3075, 1443, 513, 386, 387, 388, 390, 1331, 261, 392, 394, 396, 398, 400, 1441, 1075, 67, 1159, 402,
+ 404, 406, 408, 410, 412, 414, 3347, 2325, 416, 65, 418, 420, 422, 424, 426, 2053, 193, 1073, 428,
+ 430, 432, 1537, 1329, 2337, 2213, 434, 417, 183, 41, 436, 438, 440, 442, 444, 446, 448, 450, 195,
+ 2435, 452, 2085, 1063, 1191, 454, 456, 458, 460, 419, 2071, 1553, 3091, 55, 137, 462, 464, 466, 468,
+ 470, 472, 474, 476, 478, 2309, 4113, 480, 482, 484, 486, 2451, 2465, 1205, 153, 488, 490, 492, 494,
+ 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 1333, 526, 1555, 2467,
+ 2227, 3205, 3331, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 529, 309, 1303, 3473, 3457,
+ 389, 1569, 1445, 1077, 69, 2199, 1539, 4353, 550, 552, 554, 556, 558, 560, 562, 1459, 4241, 3221, 1429,
+ 2341, 279, 3475, 169, 564, 545, 3105, 323, 2353, 2097, 3235, 421, 2229, 3107, 3233, 566, 568, 570, 572,
+ 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 2099, 1091, 531, 2437, 4227, 405, 197,
+ 263, 1287, 2577, 1049, 1571, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626,
+ 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 1345, 1219, 3077, 1457, 2225, 2579, 515, 2561,
+ 2469, 433, 1221, 2183, 4243, 652, 654, 656, 658, 660, 662, 664, 666, 668, 670, 1217, 3333, 3093, 435, 321,
+ 4369, 1089, 2055, 4099, 3361, 1319, 547, 1161, 1177, 672, 2355, 4115, 1413, 4257, 3349, 2453, 3109, 2357, 2215, 3363,
+ 1079, 1207, 311, 1033, 1347, 1065, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700,
+ 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740,
+ 742, 744, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780,
+ 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 2593, 2565, 4261,
+ 3253, 437, 325, 3489, 2311, 4259, 1431, 2087, 2563, 295, 2343, 449, 199, 265, 2201, 4371, 1193, 816, 533, 1557,
+ 2581, 2241, 3365, 3491, 3603, 549, 2101, 1461, 1093, 2117, 3459, 3079, 4481, 3095, 2327, 3461, 4129, 3249, 1447, 2471,
+ 2231, 71, 4497, 2609, 1289, 393, 3251, 2073, 3097, 2371, 1305, 2089, 818, 820, 822, 824, 826, 828, 830, 832,
+ 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 870, 872,
+ 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912,
+ 914, 916, 918, 920, 922, 924, 926, 928, 930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952,
+ 954, 956, 958, 960, 962, 964, 966, 968, 970, 972, 974, 976, 978, 980, 982, 984, 986, 988, 990, 992,
+ 994, 996, 998, 1000, 1002, 1004, 1006, 1008, 1010, 1012, 1014, 1016, 1018, 1020, 1022, 1024, 1026, 1028, 1030, 1032,
+ 1034, 1036, 4161, 4273, 3507, 3493, 4517, 2497, 1573, 2597, 3621, 4531, 4627, 3523, 3125, 4149, 4529, 3139, 4515, 451,
+ 4277, 2113, 4163, 4499, 3381, 4405, 1473, 4373, 2485, 3509, 565, 1589, 2613, 3585, 3123, 4403, 3141, 4147, 563, 2245,
+ 3269, 4357, 1349, 2373, 3397, 453, 1477, 2501, 2481, 579, 1601, 3477, 4103, 3265, 2243, 1587, 3207, 4231, 3267, 4501,
+ 1475, 3335, 4359, 391, 1415, 2439, 3463, 4487, 519, 1543, 2567, 3591, 4609, 4289, 4611, 2499, 4119, 4385, 4145, 4401,
+ 3223, 4247, 3379, 577, 3393, 3351, 4375, 407, 1585, 2455, 3479, 4503, 535, 1559, 2583, 3607, 3605, 4513, 4485, 3111,
+ 4135, 3121, 517, 3377, 3239, 4263, 1541, 4291, 4229, 3367, 4391, 423, 2115, 4131, 3495, 551, 1575, 2599, 3635, 3395,
+ 2103, 3127, 4151, 3589, 4101, 1603, 3255, 4279, 3601, 1335, 2359, 3383, 439, 1463, 2487, 3511, 567, 1591, 4133, 1095,
+ 2119, 3143, 2369, 1223, 2247, 3271, 327, 1351, 2375, 455, 1479, 3137, 3521, 2057, 3081, 4105, 4387, 3505, 2185, 3209,
+ 4233, 3587, 4355, 2313, 3337, 3237, 1417, 2441, 3465, 521, 1545, 3617, 3633, 561, 4625, 4121, 2611, 2483, 2595, 3225,
+ 4249, 281, 4245, 2329, 3353, 409, 1433, 2457, 3481, 537, 1561, 4483, 3619, 4389, 3113, 4275, 4117, 2217, 3241, 297,
+ 1321, 2345, 3369, 425, 1449, 2473, 57, 1081, 2105, 3129, 185, 1209, 2233, 3257, 313, 1337, 2361, 441, 1465, 73,
+ 1097, 201, 1225, 0, 0};
+
+
+static int decoder_tree4[416] = {
+ 2, 4, 6, 1, 8, 10, 12, 14, 16, 18, 20, 22, 24, 3, 129, 26, 28, 9, 33, 30, 32,
+ 34, 36, 11, 161, 38, 40, 42, 41, 44, 46, 131, 43, 169, 35, 48, 137, 50, 52, 54, 56, 139,
+ 163, 171, 58, 60, 62, 64, 5, 66, 68, 70, 257, 72, 74, 76, 13, 78, 80, 289, 82, 84, 17,
+ 86, 88, 65, 90, 201, 19, 92, 94, 51, 193, 96, 98, 49, 100, 73, 102, 104, 106, 45, 108, 110,
+ 297, 112, 114, 116, 37, 203, 118, 120, 179, 122, 177, 124, 265, 126, 75, 133, 259, 291, 147, 128, 67,
+ 195, 130, 141, 173, 299, 132, 145, 134, 165, 136, 138, 140, 142, 7, 144, 146, 21, 267, 148, 53, 150,
+ 321, 152, 154, 15, 156, 81, 158, 160, 385, 162, 417, 164, 166, 168, 83, 170, 172, 329, 174, 211, 176,
+ 27, 178, 180, 182, 209, 184, 186, 188, 190, 25, 192, 331, 194, 196, 105, 57, 198, 97, 200, 202, 323,
+ 225, 59, 149, 204, 206, 233, 307, 208, 77, 181, 210, 212, 214, 216, 218, 220, 222, 47, 224, 226, 69,
+ 228, 230, 197, 232, 425, 393, 205, 275, 293, 39, 234, 236, 238, 305, 135, 155, 301, 143, 240, 242, 235,
+ 395, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 273, 269, 185, 264, 266, 268, 270, 272, 274, 276,
+ 261, 153, 278, 280, 282, 187, 337, 387, 107, 284, 427, 227, 167, 419, 286, 288, 290, 292, 294, 296, 298,
+ 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 115,
+ 99, 85, 213, 29, 113, 23, 89, 241, 61, 449, 339, 175, 340, 342, 344, 346, 348, 350, 352, 354, 356,
+ 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398,
+ 400, 402, 404, 406, 408, 410, 412, 414, 389, 361, 457, 465, 429, 451, 333, 109, 277, 243, 263, 295, 199,
+ 283, 151, 55, 183, 229, 357, 363, 123, 491, 397, 411, 251, 313, 441, 467, 345, 433, 461, 219, 237, 365,
+ 435, 353, 347, 405, 409, 217, 309, 437, 369, 371, 341, 117, 245, 249, 157, 285, 403, 189, 317, 93, 221,
+ 315, 401, 481, 391, 489, 121, 421, 423, 71, 483, 327, 103, 231, 443, 459, 271, 399, 355, 91, 303, 431,
+ 79, 207, 335, 111, 239, 281, 325, 279, 453, 101, 311, 87, 215, 31, 159, 63, 191};
+
+static int decoder_tree5[384] = {
+ 2, 4, 1, 6, 8, 10, 12, 14, 16, 18, 20, 22, 3, 513, 24, 26, 28, 9, 129, 33, 30,
+ 32, 34, 36, 38, 40, 11, 42, 641, 44, 46, 41, 161, 48, 515, 50, 52, 131, 54, 35, 545, 137,
+ 56, 58, 60, 521, 62, 43, 673, 64, 169, 66, 68, 523, 70, 163, 643, 139, 553, 72, 649, 74, 547,
+ 76, 78, 80, 681, 171, 82, 84, 555, 86, 675, 88, 651, 5, 90, 92, 1025, 94, 96, 98, 683, 13,
+ 100, 17, 102, 104, 106, 65, 108, 110, 257, 112, 114, 1153, 19, 116, 118, 120, 122, 124, 49, 126, 128,
+ 769, 289, 130, 132, 134, 73, 136, 138, 140, 142, 193, 144, 146, 148, 150, 152, 154, 517, 156, 158, 37,
+ 51, 160, 201, 162, 145, 164, 166, 168, 133, 170, 801, 45, 172, 174, 1057, 176, 178, 67, 180, 1027, 577,
+ 182, 184, 186, 188, 190, 192, 194, 196, 198, 259, 200, 202, 204, 525, 177, 265, 141, 206, 208, 210, 212,
+ 195, 297, 214, 75, 216, 1033, 203, 585, 1155, 1185, 267, 1161, 549, 218, 220, 657, 777, 147, 222, 224, 226,
+ 228, 230, 232, 234, 236, 238, 240, 587, 645, 165, 242, 244, 246, 248, 250, 771, 291, 252, 579, 1065, 1035,
+ 705, 531, 529, 659, 173, 254, 561, 653, 256, 713, 677, 557, 258, 260, 262, 264, 266, 268, 270, 272, 274,
+ 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 707, 1059, 809, 715, 563, 179, 691, 1193,
+ 21, 779, 1067, 299, 1187, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332,
+ 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374,
+ 376, 378, 380, 83, 69, 1281, 803, 321, 1195, 1163, 811, 1323, 689, 1321, 1099, 305, 835, 1227, 331, 843, 785,
+ 593, 1043, 1291, 1283, 1171, 275, 787, 1217, 833, 1075, 1313, 1219, 1203, 307, 819, 841, 595, 211, 723, 721, 817,
+ 1029, 329, 81, 1157, 261, 773, 1097, 1089, 1061, 1169, 1091, 1189, 293, 805, 1201, 581, 197, 709, 1289, 273, 1037,
+ 1315, 1041, 1165, 269, 781, 209, 1073, 1069, 323, 685, 1197, 301, 813, 77, 589, 205, 717, 1225, 533, 149, 661,
+ 53, 565, 181, 693, 0, 0};
+
+
+static int decoder_tree6[62] = {
+ 2, 1, 4, 6, 8, 10, 12, 14, 16, 3,
+ 33, 5, 17, 9, 18, 20, 22, 24, 26, 28,
+ 30, 32, 34, 7, 49, 13, 25, 36, 38, 11,
+ 21, 41, 35, 37, 19, 40,         42, 44, 46, 48,
+ 50, 15, 52, 57, 29, 27, 23, 53,         54, 51,
+ 39, 45, 43, 56, 58, 31, 55, 60, 61, 47,
+ 59, 63};
+
+static int *decoder_tables[7] = {
+ decoder_tree0,
+ decoder_tree1,
+ decoder_tree2,
+ decoder_tree3,
+ decoder_tree4,
+ decoder_tree5,
+ decoder_tree6,
+};
+
+static float noise_category5[20] = {0.70711f, 0.6179f, 0.5005f, 0.3220f,
+ 0.17678f, 0.17678f, 0.17678f, 0.17678f,
+ 0.17678f, 0.17678f, 0.17678f, 0.17678f,
+ 0.17678f, 0.17678f, 0.17678f, 0.17678f,
+ 0.17678f, 0.17678f, 0.17678f, 0.17678f};
+
+static float noise_category6[20] = {0.70711f, 0.5686f, 0.3563f, 0.25f,
+ 0.25f, 0.25f, 0.25f, 0.25f,
+ 0.25f, 0.25f, 0.25f, 0.25f,
+ 0.25f, 0.25f, 0.25f, 0.25f,
+ 0.25f, 0.25f, 0.25f, 0.25f};
+
+static float noise_category7 = 0.70711f;
+
+
+static int index_table[8] = {4, 4, 3, 3, 2, 2, 1, 0};
+
+#endif /* _HUFFMAN_CONSTS_H */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenrmltcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,133 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+
+static int rmlt_initialized = 0;
+static float rmlt_window_640[640];
+static float rmlt_window_320[320];
+
+#define PI_2 1.57079632679489661923
+
+void siren_rmlt_init() {
+ int i = 0;
+ float angle;
+
+ for (i = 0; i < 640; i++) {
+ angle = (float) (((i + 0.5) * PI_2) / 640);
+ rmlt_window_640[i] = (float) sin(angle);
+ }
+ for (i = 0; i < 320; i++) {
+ angle = (float) (((i + 0.5) * PI_2) / 320);
+ rmlt_window_320[i] = (float) sin(angle);
+ }
+
+ rmlt_initialized = 1;
+}
+
+int siren_rmlt_encode_samples(float *samples, float *old_samples, int dct_length, float *rmlt_coefs) {
+ int half_dct_length = dct_length / 2;
+ float *old_ptr = old_samples + half_dct_length;
+ float *coef_high = rmlt_coefs + half_dct_length;
+ float *coef_low = rmlt_coefs + half_dct_length;
+ float *samples_low = samples;
+ float *samples_high = samples + dct_length;
+ float *window_low = NULL;
+ float *window_high = NULL;
+ int i = 0;
+
+ if (rmlt_initialized == 0)
+ siren_rmlt_init();
+
+ if (dct_length == 320)
+ window_low = rmlt_window_320;
+ else if (dct_length == 640)
+ window_low = rmlt_window_640;
+ else
+ return 4;
+
+ window_high = window_low + dct_length;
+
+
+ for (i = 0; i < half_dct_length; i++) {
+ *--coef_low = *--old_ptr;
+ *coef_high++ = (*samples_low * *--window_high) - (*--samples_high * *window_low);
+ *old_ptr = (*samples_high * *window_high) + (*samples_low++ * *window_low++);
+ }
+ siren_dct4(rmlt_coefs, rmlt_coefs, dct_length);
+
+ return 0;
+}
+
+
+
+int siren_rmlt_decode_samples(float *coefs, float *old_coefs, int dct_length, float *samples) {
+ int half_dct_length = dct_length / 2;
+ float *old_low = old_coefs;
+ float *old_high = old_coefs + half_dct_length;
+ float *samples_low = samples ;
+ float *samples_high = samples + dct_length;
+ float *samples_middle_low = samples + half_dct_length;
+ float *samples_middle_high = samples + half_dct_length;
+ float *window_low = NULL;
+ float *window_high = NULL;
+ float *window_middle_low = NULL;
+ float *window_middle_high = NULL;
+ float sample_low_val;
+ float sample_high_val;
+ float sample_middle_low_val;
+ float sample_middle_high_val;
+ int i = 0;
+
+ if (rmlt_initialized == 0)
+ siren_rmlt_init();
+
+ if (dct_length == 320)
+ window_low = rmlt_window_320;
+ else if (dct_length == 640)
+ window_low = rmlt_window_640;
+ else
+ return 4;
+
+
+ window_high = window_low + dct_length;
+ window_middle_low = window_low + half_dct_length;
+ window_middle_high = window_low + half_dct_length;
+
+ siren_dct4(coefs, samples, dct_length);
+
+ for (i = 0; i < half_dct_length; i+=2) {
+ sample_low_val = *samples_low;
+ sample_high_val = *--samples_high;
+ sample_middle_low_val = *--samples_middle_low;
+ sample_middle_high_val = *samples_middle_high;
+ *samples_low++ = (*old_low * *--window_high) + (sample_middle_low_val * *window_low);
+ *samples_high = (sample_middle_low_val * *window_high) - (*old_low * *window_low++);
+ *samples_middle_high++ = (sample_low_val * *window_middle_high) - (*--old_high * *--window_middle_low);
+ *samples_middle_low = (*old_high * *window_middle_high++) + (sample_low_val * *window_middle_low);
+ *old_low++ = sample_middle_high_val;
+ *old_high = sample_high_val;
+ }
+
+ return 0;
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirenrmlth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/rmlt.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_RMLT_H_
+#define _SIREN7_RMLT_H_
+
+extern void siren_rmlt_init();
+extern int siren_rmlt_encode_samples(float *samples, float *old_samples, int dct_length, float *rmlt_coefs);
+extern int siren_rmlt_decode_samples(float *coefs, float *old_coefs, int dct_length, float *samples);
+
+#endif /* _SIREN7_RMLT_H_ */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnlibsirensiren7h"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/siren7.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/siren7.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/libsiren/siren7.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_H
+#define _SIREN7_H
+
+#include "encoder.h"
+#include "decoder.h"
+
+
+#endif /* _SIREN7_H */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmd5cpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,392 @@
</span><ins>+/*
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/*$Id: md5.c,v 1.5 2002/10/11 08:04:56 jtownsend Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321.
+ It is derived directly from the text of the RFC and not from the
+ reference implementation.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#ifdef TEST
+/*
+ * Compile with -DTEST to create a self-contained executable test program.
+ * The test program should print out the same values as given in section
+ * A.5 of RFC 1321, reproduced below.
+ */
+main()
+{
+ static const char *const test[7] = {
+ "", /*d41d8cd98f00b204e9800998ecf8427e*/
+ "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/
+ "abc", /*900150983cd24fb0d6963f7d28e17f72*/
+ "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
+ "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ /*d174ab98d277d9f5a5611c2c9f419d9f*/
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
+ };
+ int i;
+
+ for (i = 0; i < 7; ++i) {
+ md5_state_t state;
+ md5_byte_t digest[16];
+ int di;
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
+ md5_finish(&state, digest);
+ printf("MD5 (\"%s\") = ", test[i]);
+ for (di = 0; di < 16; ++di)
+ printf("%02x", digest[di]);
+ printf("\n");
+ }
+ return 0;
+}
+#endif /* TEST */
+
+
+/*
+ * For reference, here is the program that computed the T values.
+ */
+#if 0
+#include <math.h>
+main()
+{
+ int i;
+ for (i = 1; i <= 64; ++i) {
+ unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
+ printf("#define T%d 0x%08lx\n", i, v);
+ }
+ return 0;
+}
+#endif
+/*
+ * End of T computation program.
+ */
+#define T1 0xd76aa478
+#define T2 0xe8c7b756
+#define T3 0x242070db
+#define T4 0xc1bdceee
+#define T5 0xf57c0faf
+#define T6 0x4787c62a
+#define T7 0xa8304613
+#define T8 0xfd469501
+#define T9 0x698098d8
+#define T10 0x8b44f7af
+#define T11 0xffff5bb1
+#define T12 0x895cd7be
+#define T13 0x6b901122
+#define T14 0xfd987193
+#define T15 0xa679438e
+#define T16 0x49b40821
+#define T17 0xf61e2562
+#define T18 0xc040b340
+#define T19 0x265e5a51
+#define T20 0xe9b6c7aa
+#define T21 0xd62f105d
+#define T22 0x02441453
+#define T23 0xd8a1e681
+#define T24 0xe7d3fbc8
+#define T25 0x21e1cde6
+#define T26 0xc33707d6
+#define T27 0xf4d50d87
+#define T28 0x455a14ed
+#define T29 0xa9e3e905
+#define T30 0xfcefa3f8
+#define T31 0x676f02d9
+#define T32 0x8d2a4c8a
+#define T33 0xfffa3942
+#define T34 0x8771f681
+#define T35 0x6d9d6122
+#define T36 0xfde5380c
+#define T37 0xa4beea44
+#define T38 0x4bdecfa9
+#define T39 0xf6bb4b60
+#define T40 0xbebfbc70
+#define T41 0x289b7ec6
+#define T42 0xeaa127fa
+#define T43 0xd4ef3085
+#define T44 0x04881d05
+#define T45 0xd9d4d039
+#define T46 0xe6db99e5
+#define T47 0x1fa27cf8
+#define T48 0xc4ac5665
+#define T49 0xf4292244
+#define T50 0x432aff97
+#define T51 0xab9423a7
+#define T52 0xfc93a039
+#define T53 0x655b59c3
+#define T54 0x8f0ccc92
+#define T55 0xffeff47d
+#define T56 0x85845dd1
+#define T57 0x6fa87e4f
+#define T58 0xfe2ce6e0
+#define T59 0xa3014314
+#define T60 0x4e0811a1
+#define T61 0xf7537e82
+#define T62 0xbd3af235
+#define T63 0x2ad7d2bb
+#define T64 0xeb86d391
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+
+#ifndef ARCH_IS_BIG_ENDIAN
+# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */
+#endif
+#if ARCH_IS_BIG_ENDIAN
+
+ /*
+ * On big-endian machines, we must arrange the bytes in the right
+ * order. (This also works on machines of unknown byte order.)
+ */
+ md5_word_t X[16];
+ const md5_byte_t *xp = data;
+ int i;
+
+ for (i = 0; i < 16; ++i, xp += 4)
+ X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+
+#else /* !ARCH_IS_BIG_ENDIAN */
+
+ /*
+ * On little-endian machines, we can process properly aligned data
+ * without copying it.
+ */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+#endif
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = 0xefcdab89;
+ pms->abcd[2] = 0x98badcfe;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmd5h"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/md5.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,94 @@
</span><ins>+/*
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/*$Id: md5.h,v 1.3 2002/10/11 06:49:22 jtownsend Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321.
+ It is derived directly from the text of the RFC and not from the
+ reference implementation.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This code has some adaptations for the Ghostscript environment, but it
+ * will compile and run correctly in any environment with 8-bit chars and
+ * 32-bit ints. Specifically, it assumes that if the following are
+ * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
+ * ARCH_IS_BIG_ENDIAN.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+#ifdef P1
+void md5_init(P1(md5_state_t *pms));
+#else
+void md5_init(md5_state_t *pms);
+#endif
+
+/* Append a string to the message. */
+#ifdef P3
+void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));
+#else
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+#endif
+
+/* Finish the message and return the digest. */
+#ifdef P2
+void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));
+#else
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+#endif
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmessagecpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/message.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/message.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/message.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,338 @@
</span><ins>+/*
+ * message.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Wed Mar 17 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <msn/message.h>
+#include <msn/errorcodes.h>
+#include <msn/util.h>
+#include <iomanip>
+#include <cassert>
+
+namespace MSN
+{
+ Message::Message(std::string body_, std::string header_)
+ : body(body_), header(header_)
+ {
+ }
+
+ std::string Message::asString() const
+ {
+ return this->header.asString() + this->body;
+ }
+
+ std::string Message::operator[](const std::string header_) const
+ {
+ assert(header_ != "");
+ return this->header[header_];
+ }
+
+ std::string Message::Headers::asString() const
+ {
+ return this->rawContents;
+ }
+
+ std::map<std::string, std::string> Message::getFormatInfo() const throw (std::runtime_error)
+ {
+ std::map<std::string, std::string> formatInfo;
+ std::string formatHeader = (*this)["X-MMS-IM-Format"];
+ if (formatHeader.empty())
+ return formatInfo;
+
+ std::vector<std::string> parameters = splitString(formatHeader, ";");
+ std::vector<std::string>::iterator i = parameters.begin();
+ for (; i != parameters.end(); i++)
+ {
+         if (i->at(0) == ' ')
+         i->erase(0, 1);
+
+ std::vector<std::string> pair = splitString(*i, "=");
+ if (pair.size() == 2)
+ formatInfo[decodeURL(pair[0])] = decodeURL(pair[1]);
+ else if (pair.size() == 1)
+ formatInfo[decodeURL(pair[0])] = "";
+ else
+ throw std::runtime_error("Incorrectly specified message format!");
+ }
+
+ return formatInfo;
+ }
+
+ void Message::setFormatInfo(std::map<std::string, std::string> & info)
+ {
+ std::string value;
+ std::map<std::string, std::string>::iterator i = info.begin();
+
+ if (info.find("FN") != info.end())
+ {
+ value += "FN=";
+ value += encodeURL(info["FN"]);
+ value += "; ";
+ }
+
+ for (; i != info.end(); i++)
+ {
+ if ((*i).first == "FN")
+ continue;
+
+ value += encodeURL((*i).first);
+ value += "=";
+ value += encodeURL((*i).second);
+ value += "; ";
+ }
+ if (value == "")
+ return;
+
+ assert(value.size() >= 2);
+ value = value.substr(0, value.size() - 2);
+ this->header.setHeader("X-MMS-IM-Format", value);
+ }
+
+ std::string Message::getFontName() const
+ {
+ return this->getFormatInfo()["FN"];
+ }
+
+ void Message::setFontName(const std::string & fontName)
+ {
+ std::map<std::string, std::string> info = this->getFormatInfo();
+ info["FN"] = fontName;
+ this->setFormatInfo(info);
+ }
+
+ std::vector<int> Message::getColor() const
+ {
+ std::string color = this->getFormatInfo()["CO"];
+ assert(color.size() <= 6 && color.size() >= 0);
+ color.insert(0U, 6 - color.size(), '0');
+ int r = 0, g = 0, b = 0;
+
+ b = strtol(color.substr(0, 2).c_str(), NULL, 16);
+ g = strtol(color.substr(2, 2).c_str(), NULL, 16);
+ r = strtol(color.substr(4, 2).c_str(), NULL, 16);
+
+ std::vector<int> out;
+ out.push_back(r);
+ out.push_back(g);
+ out.push_back(b);
+ return out;
+ }
+
+ std::string Message::getColorAsHTMLString() const
+ {
+ std::vector<int> color = this->getColor();
+ std::ostringstream s;
+ s << std::hex << std::setfill('0') << std::setw(2) << color[0];
+ s << std::hex << std::setfill('0') << std::setw(2) << color[1];
+ s << std::hex << std::setfill('0') << std::setw(2) << color[2];
+
+ assert(s.str().size() == 6);
+ return s.str();
+ }
+
+ void Message::setColor(std::vector<int> color)
+ {
+ std::map<std::string, std::string> info = this->getFormatInfo();
+ assert(color.size() == 3);
+
+ std::ostringstream s;
+ s << std::hex << std::setfill('0') << std::setw(2) << color[2];
+ s << std::hex << std::setfill('0') << std::setw(2) << color[1];
+ s << std::hex << std::setfill('0') << std::setw(2) << color[0];
+
+ assert(s.str().size() == 6);
+ info["CO"] = s.str();
+ this->setFormatInfo(info);
+ }
+
+ void Message::setColor(std::string color)
+ {
+ color.insert(0U, 6 - color.size(), '0');
+ int r = 0, g = 0, b = 0;
+
+ r = strtol(color.substr(0, 2).c_str(), NULL, 16);
+ g = strtol(color.substr(2, 2).c_str(), NULL, 16);
+ b = strtol(color.substr(4, 2).c_str(), NULL, 16);
+
+ std::vector<int> v;
+ v.push_back(r);
+ v.push_back(g);
+ v.push_back(b);
+ this->setColor(v);
+ }
+
+ void Message::setColor(int red, int green, int blue)
+ {
+ std::vector<int> v;
+ v.push_back(red);
+ v.push_back(green);
+ v.push_back(blue);
+ this->setColor(v);
+ }
+
+
+ int Message::getFontEffects() const
+ {
+ int retVal = 0;
+ std::string fontEffects = this->getFormatInfo()["EF"];
+
+ if (fontEffects.find("B") != std::string::npos)
+ retVal |= BOLD_FONT;
+
+ if (fontEffects.find("I") != std::string::npos)
+ retVal |= ITALIC_FONT;
+
+ if (fontEffects.find("U") != std::string::npos)
+ retVal |= UNDERLINE_FONT;
+
+ if (fontEffects.find("S") != std::string::npos)
+ retVal |= STRIKETHROUGH_FONT;
+
+ return retVal;
+ }
+
+ void Message::setFontEffects(int fontEffects)
+ {
+ std::string effects;
+ std::map<std::string, std::string> info = this->getFormatInfo();
+
+ if (fontEffects & BOLD_FONT)
+ effects += "B";
+
+ if (fontEffects & ITALIC_FONT)
+ effects += "I";
+
+ if (fontEffects & UNDERLINE_FONT)
+ effects += "U";
+
+ if (fontEffects & STRIKETHROUGH_FONT)
+ effects += "S";
+
+ info["EF"] = effects;
+ this->setFormatInfo(info);
+ }
+
+ Message::CharacterSet Message::getFontCharacterSet() const
+ {
+ std::string fontCharacterSet = this->getFormatInfo()["CS"];
+ int c = strtol(fontCharacterSet.c_str(), NULL, 16);
+ return (Message::CharacterSet) c;
+ }
+
+ void Message::setFontCharacterSet(CharacterSet cs)
+ {
+ std::map<std::string, std::string> info = this->getFormatInfo();
+ std::ostringstream s;
+
+ s << std::hex << (int) cs;
+ info["CS"] = s.str();
+
+ this->setFormatInfo(info);
+ }
+
+ Message::FontFamily Message::getFontFamily() const
+ {
+ std::string fontFamily = this->getFormatInfo()["PF"];
+ if (fontFamily.size() < 1)
+ return (Message::FontFamily) 0;
+ int family = decimalFromString(fontFamily.substr(0, 1));
+ return (Message::FontFamily) family;
+ }
+
+ Message::FontPitch Message::getFontPitch() const
+ {
+ std::string fontPitch = this->getFormatInfo()["PF"];
+ if (fontPitch.size() < 2)
+ return (Message::FontPitch) 0;
+ int pitch = decimalFromString(fontPitch.substr(1, 1));
+ return (Message::FontPitch) pitch;
+ }
+
+ void Message::setFontFamilyAndPitch(Message::FontFamily fontFamily, Message::FontPitch fontPitch)
+ {
+ std::map<std::string, std::string> info = this->getFormatInfo();
+ std::ostringstream s;
+
+ s << fontFamily << fontPitch;
+ info["PF"] = s.str();
+
+ this->setFormatInfo(info);
+ }
+
+ bool Message::isRightAligned() const
+ {
+ return this->getFormatInfo()["RL"] == "1";
+ }
+
+ void Message::Headers::setHeader(const std::string header, const std::string value)
+ {
+ if ((*this)[header] == "")
+ {
+ assert(this->rawContents.size() >= 2);
+ this->rawContents.insert(this->rawContents.size() - 2, header + ": " + value + "\r\n");
+ }
+ else
+ {
+ size_t position = this->rawContents.find(header + ": ");
+ assert(position != std::string::npos);
+
+ size_t eol = this->rawContents.find("\r\n", position);
+ if (eol == std::string::npos)
+ eol = this->rawContents.size();
+
+ this->rawContents.erase(position, eol - position + 2);
+ this->rawContents.insert(position, header + ": " + value + "\r\n");
+ }
+ }
+
+ std::string Message::Headers::operator[](const std::string header_) const
+ {
+ std::string retval;
+ std::string::iterator i;
+
+ if (this->rawContents.substr(0U, header_.size()) == header_)
+ {
+ retval = this->rawContents;
+ } else {
+ std::string tmp = "\r\n" + header_;
+ size_t position = this->rawContents.find(tmp);
+ if (position == std::string::npos)
+ return "";
+
+ retval = this->rawContents.substr(position + 2);
+ }
+
+ retval = retval.substr(retval.find(':') + 1);
+ while (isspace(retval[0]))
+ retval.erase(retval.begin());
+
+ for (i = retval.begin(); i != retval.end(); i++)
+ {
+ if (*i == '\r')
+ {
+ return retval.substr(0, std::distance(retval.begin(), i));
+ }
+ }
+ return "";
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmessageh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/message.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/message.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/message.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,211 @@
</span><ins>+#ifndef __msn_message_h__
+#define __msn_message_h__
+
+/*
+ * message.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Wed Mar 17 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <string>
+#include <map>
+#include <vector>
+#include <stdexcept>
+
+#include "libmsn_export.h"
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4290 )
+#endif
+
+namespace MSN
+{
+
+ /** This class represents an MSN message
+ *
+ * It may or may not represent an @e instant @e message.
+ *
+ * @todo Complete read/write support for formatting messages.
+ */
+ class LIBMSN_EXPORT Message
+ {
+public:
+ enum FontEffects
+ {
+ BOLD_FONT = 1,
+ ITALIC_FONT = 2,
+ UNDERLINE_FONT = 4,
+ STRIKETHROUGH_FONT = 8
+ };
+
+#ifdef WIN32
+ typedef int CharacterSet;
+ typedef int FontFamily;
+ typedef int FontPitch;
+#else
+ enum CharacterSet
+ {
+ ANSI_CHARSET = 0x00,
+ DEFAULT_CHARSET = 0x01,
+ SYMBOL_CHARSET = 0x02,
+ MAC_CHARSET = 0x4d,
+ SHIFTJIS_CHARSET = 0x80,
+ HANGEUL_CHARSET = 0x81,
+ JOHAB_CHARSET = 0x82,
+ GB2312_CHARSET = 0x86,
+ CHINESEBIG5_CHARSET = 0x88,
+ GREEK_CHARSET = 0xa1,
+ TURKISH_CHARSET = 0xa2,
+ VIETNAMESE_CHARSET = 0xa3,
+ HEBREW_CHARSET = 0xb1,
+ ARABIC_CHARSET = 0xb2,
+ BALTIC_CHARSET = 0xba,
+ RUSSIAN_CHARSET_DEFAULT = 0xcc,
+ THAI_CHARSET = 0xde,
+ EASTEUROPE_CHARSET = 0xee,
+ OEM_DEFAULT = 0xff
+ };
+
+ enum FontFamily
+ {
+ FF_DONTCARE = 0,
+ FF_ROMAN = 1,
+ FF_SWISS = 2,
+ FF_MODERN = 3,
+ FF_SCRIPT = 4,
+ FF_DECORATIVE = 5
+ };
+
+ enum FontPitch
+ {
+ DEFAULT_PITCH = 0,
+ FIXED_PITCH = 1,
+ VARIABLE_PITCH = 2
+ };
+#endif
+
+ class Headers
+ {
+public:
+ Headers(const std::string & rawContents_) : rawContents(rawContents_) {};
+ Headers() : rawContents("") {};
+ std::string asString() const;
+ std::string operator[](const std::string header) const;
+ void setHeader(const std::string header, const std::string value);
+
+private:
+ std::string rawContents;
+ };
+
+private:
+ std::string body;
+ Message::Headers header;
+
+public:
+ /** Create a message with the specified @a body and @a mimeHeader.
+ */
+ Message(std::string body, std::string mimeHeader="MIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\n");
+
+ /** Convert the Message into a string.
+ *
+ * This returns a string containing the MIME headers separated from the
+ * message body by a blank line.
+ */
+ std::string asString() const;
+
+ /** Return the value of the MIME header named @a header.
+ *
+ * @return The value of the MIME header if present, or "" if not found.
+ */
+ std::string operator[](const std::string header) const;
+ void setHeader(const std::string name, const std::string value) { header.setHeader(name, value); };
+
+ /** Return the body portion of this Message.
+ */
+ std::string getBody() const { return body; };
+
+ /** Return the font name used in this Message.
+ *
+ * @return The font name used for this Message, or "" if none specified.
+ */
+ std::string getFontName() const;
+
+ /** Set font name for use in this Message.
+ */
+ void setFontName(const std::string & fontName);
+
+ /** Get the color used in this Message.
+ */
+ std::vector<int> getColor() const;
+ std::string getColorAsHTMLString() const;
+
+ /** Set the color used in this Message.
+ */
+ void setColor(std::vector<int> color);
+ void setColor(std::string color);
+ void setColor(int red, int green, int blue);
+
+ /** Return the font effects used in this Message.
+ *
+ * @return An integer that is a bitwise-or of Message::FontEffects members.
+ */
+ int getFontEffects() const;
+
+ /** Set the font effects for use in this Message.
+ *
+ * @param fontEffects Bitwise-or of Message::FontEffects members.
+ */
+ void setFontEffects(int fontEffects);
+
+ /** Return the character set that the font uses in this Message.
+ */
+ CharacterSet getFontCharacterSet() const;
+
+ /** Set the character set that the font should use for this Message.
+ */
+ void setFontCharacterSet(CharacterSet cs);
+
+ /** Return the font family used in this Message.
+ */
+ FontFamily getFontFamily() const;
+
+ /** Return the font pitch used in this Message.
+ */
+ FontPitch getFontPitch() const;
+
+ /** Set the font family and pitch to be used for this Message.
+ */
+ void setFontFamilyAndPitch(Message::FontFamily fontFamily, Message::FontPitch fontPitch);
+
+ /** Is the Message to be right-aligned?
+ */
+ bool isRightAligned() const;
+
+private:
+ std::map<std::string, std::string> getFormatInfo() const throw (std::runtime_error);
+ void setFormatInfo(std::map<std::string, std::string> & info);
+ };
+
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmsnh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/msn.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/msn.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/msn.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+#ifndef __msn_h__
+#define __msn_h__
+
+/*
+ * msn.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Apr 17 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/authdata.h>
+#include <msn/connection.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/message.h>
+#include <msn/notificationserver.h>
+#include <msn/switchboardserver.h>
+#include <msn/util.h>
+#include <msn/soap.h>
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmsnobjectcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,185 @@
</span><ins>+/*
+ * msnobject.cpp
+ * libmsn
+ *
+ * Created by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <msn/util.h>
+#include <openssl/sha.h>
+#include <msn/msnobject.h>
+#include <msn/xmlParser.h>
+#include <iostream>
+#include <fstream>
+
+namespace MSN
+{
+ void MSNObject::addMSNObject(std::string filename, int Type)
+ {
+ std::ifstream::pos_type size;
+ char * memblock;
+ SHA_CTX ctx;
+ unsigned char digest[SHA_DIGEST_LENGTH];
+
+ MSNObjectUnit msnobj;
+ msnobj.Creator = this->Creator;
+ msnobj.Size = FileSize(filename.c_str());
+ msnobj.Type = Type;
+
+ if(Type!=11)
+ {
+ msnobj.Location = toStr(++current_id);
+ msnobj.Location += ".tmp";
+ }
+ else
+ {
+ msnobj.Location = "0";
+ // encode wav to siren
+ libmsn_Siren7_EncodeVoiceClip(filename);
+ msnobj.Size = FileSize(filename.c_str());
+ }
+
+ msnobj.realLocation = filename;
+ if(Type!=5 && Type!=8)
+ msnobj.Friendly="AAA=";
+
+ std::ifstream file (filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
+ if (!file.is_open())
+ {
+ return;
+ }
+
+ size = file.tellg();
+ memblock = new char [size];
+ file.seekg (0, std::ios::beg);
+ file.read (memblock, size);
+ file.close();
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, memblock, size);
+ SHA1_Final(digest, &ctx);
+
+ delete[] memblock;
+
+ msnobj.SHA1D = b64_encode((const char*)digest,20);
+ std::string all_fields("Creator" + msnobj.Creator +
+ "Size" + toStr(msnobj.Size) +
+ "Type" + toStr(msnobj.Type) +
+ "Location" + msnobj.Location +
+ "Friendly" + msnobj.Friendly +
+ "SHA1D" + msnobj.SHA1D);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, all_fields.c_str(), all_fields.length());
+ SHA1_Final(digest, &ctx);
+ msnobj.SHA1C = b64_encode((const char*)digest,20);
+ XMLNode msnObject = XMLNode::createXMLTopNode("msnobj");
+ msnObject.addAttribute("Creator", this->Creator.c_str());
+ msnObject.addAttribute("Size", toStr(msnobj.Size).c_str());
+ msnObject.addAttribute("Type", toStr(msnobj.Type).c_str());
+ msnObject.addAttribute("Location", msnobj.Location.c_str());
+ msnObject.addAttribute("Friendly", msnobj.Friendly.c_str());
+ msnObject.addAttribute("SHA1D", msnobj.SHA1D.c_str());
+
+ if(Type!=11) // voice does not have this field
+ msnObject.addAttribute("SHA1C", msnobj.SHA1C.c_str());
+
+ char *xml = msnObject.createXMLString(false);
+ msnobj.XMLString = xml;
+ free(xml);
+ msnObjects.push_front(msnobj);
+ }
+
+ void MSNObject::setCreator(std::string creator)
+ {
+ this->Creator = creator;
+ }
+
+ bool MSNObject::getMSNObjectXML(std::string filename, int Type, std::string & msnobj)
+ {
+ if(msnObjects.empty()) return false;
+
+ std::list<MSNObjectUnit>::iterator i = msnObjects.begin();
+ for(; i!=msnObjects.end();i++)
+ {
+ if((*i).realLocation == filename &&
+ (*i).Type == Type)
+ {
+ msnobj = (*i).XMLString;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool MSNObject::delMSNObjectByType(int Type)
+ {
+ bool deleted=false;
+ if(msnObjects.empty()) return false;
+
+ std::list<MSNObjectUnit>::iterator i = msnObjects.begin();
+ std::list<MSNObjectUnit>::iterator d;
+ for(;i!=msnObjects.end();i++)
+ {
+ if((*i).Type == Type)
+ {
+ d=i;
+ deleted=true;
+ }
+ }
+ if(deleted)
+ msnObjects.erase(d);
+ return deleted;
+ }
+
+ bool MSNObject::getMSNObjectXMLByType(int Type, std::string & xml)
+ {
+ if(msnObjects.empty()) return false;
+ std::list<MSNObjectUnit>::iterator i = msnObjects.begin();
+
+ for( ; i!=msnObjects.end();i++)
+ {
+ if((*i).Type == Type)
+ {
+ xml = (*i).XMLString;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool MSNObject::getMSNObjectRealPath(std::string xml, std::string & realpath)
+ {
+ if(msnObjects.empty()) return false;
+ XMLNode msnObject = XMLNode::parseString(xml.c_str());
+ std::string SHA1D = msnObject.getAttribute("SHA1D",0);
+
+ std::list<MSNObjectUnit>::iterator i = msnObjects.begin();
+
+ for( ; i!=msnObjects.end();i++)
+ {
+ // using SHA1D to ensure if we have this file, even if the name is different
+ if((*i).SHA1D == SHA1D)
+ {
+ realpath = (*i).realLocation;
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnmsnobjecth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/msnobject.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+#ifndef __msn_msnobj_h__
+#define __msn_msnobj_h__
+
+/*
+ * msnobject.h
+ * libmsn
+ *
+ * Created by Tiago Salem Herrmann on Mon Ago 22 2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <list>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class LIBMSN_EXPORT MSNObject
+ {
+private:
+ unsigned int current_id;
+ std::string Creator;
+ typedef struct
+ {
+ std::string Creator;
+ unsigned long long Size;
+ int Type;
+ std::string Location;
+ std::string realLocation;
+ std::string Friendly;
+ std::string SHA1D;
+ std::string SHA1C;
+ std::string XMLString;
+ } MSNObjectUnit;
+
+ std::list<MSNObjectUnit> msnObjects;
+public:
+ MSNObject() : current_id(0) {};
+ ~MSNObject() {};
+ void setCreator(std::string creator);
+ void addMSNObject(std::string filename, int Type);
+ bool getMSNObjectXML(std::string filename, int Type, std::string & msnobj);
+ bool getMSNObject(std::string filename, int Type, MSNObjectUnit & msnobj);
+ bool delMSNObjectByType(int Type);
+ bool getMSNObjectXMLByType(int Type, std::string & xml);
+ bool getMSNObjectRealPath(std::string xml, std::string & realpath);
+ };
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnnotificationservercpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,1782 @@
</span><ins>+/*
+ * notificationserver.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/config.h>
+#include <msn/notificationserver.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/md5.h>
+#include <msn/util.h>
+#include <msn/soap.h>
+#include <algorithm>
+#include <cctype>
+#include <cassert>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#else
+#include <io.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <map>
+
+#include "xmlParser.h"
+
+namespace MSN
+{
+ std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &)> NotificationServerConnection::commandHandlers;
+ std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &, std::string, std::string)> NotificationServerConnection::messageHandlers;
+
+ NotificationServerConnection::NotificationServerConnection(Passport username_, std::string password_, Callbacks & cb_)
+ : Connection(), auth(username_, password_), myPassport(username_), m_clientId(0), externalCallbacks(cb_), _connectionState(NS_DISCONNECTED), generatingLockkey(false), removingOIM(false), bplSetting('B')
+ {
+ msnobj.setCreator(username_);
+ registerHandlers();
+ }
+
+ NotificationServerConnection::~NotificationServerConnection()
+ {
+ if (this->connectionState() != NS_DISCONNECTED)
+ this->disconnect();
+ }
+
+ Connection *NotificationServerConnection::connectionWithSocket(void *sock)
+ {
+ this->assertConnectionStateIsNot(NS_DISCONNECTED);
+
+ if (this->sock == sock)
+ return this;
+
+ std::vector<SwitchboardServerConnection *> & list = _switchboardConnections;
+ std::vector<SwitchboardServerConnection *>::iterator i = list.begin();
+
+ for (; i != list.end(); i++)
+ {
+ Connection *c = (*i)->connectionWithSocket(sock);
+ if (c)
+ return c;
+ }
+
+ std::vector<Soap *> & list2 = _SoapConnections;
+ std::vector<Soap *>::iterator d = list2.begin();
+
+ for (; d != list2.end(); d++)
+ {
+ if((*d)->sock == sock )
+ return (*d);
+ }
+
+
+ return NULL;
+ }
+
+ SwitchboardServerConnection *NotificationServerConnection::switchboardWithOnlyUser(Passport username)
+ {
+ if (this->connectionState() >= NS_CONNECTED)
+ {
+ std::vector<SwitchboardServerConnection *> & list = _switchboardConnections;
+ std::vector<SwitchboardServerConnection *>::iterator i = list.begin();
+
+ for (; i != list.end(); i++)
+ {
+ if ((*i)->users.size() == 1 &&
+ *((*i)->users.begin()) == username)
+ return *i;
+ }
+ }
+ return NULL;
+ }
+
+ const std::vector<SwitchboardServerConnection *> & NotificationServerConnection::switchboardConnections()
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ return _switchboardConnections;
+ }
+
+ void NotificationServerConnection::addSwitchboardConnection(SwitchboardServerConnection *c)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ _switchboardConnections.push_back(c);
+ }
+
+ void NotificationServerConnection::addSoapConnection(Soap *s)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ _SoapConnections.push_back(s);
+ }
+
+ void NotificationServerConnection::removeSwitchboardConnection(SwitchboardServerConnection *c)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::vector<SwitchboardServerConnection *>::iterator it;
+ for(it = _switchboardConnections.begin(); it != _switchboardConnections.end(); it++)
+ {
+ if((*it) == c)
+ {
+ _switchboardConnections.erase(it);
+ return;
+ }
+ }
+ }
+
+ void NotificationServerConnection::removeSoapConnection(Soap *s)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::vector<Soap *>::iterator it;
+ for(it = _SoapConnections.begin(); it != _SoapConnections.end(); it++)
+ {
+ if((*it) == s)
+ {
+ _SoapConnections.erase(it);
+ return;
+ }
+ }
+ }
+
+ void NotificationServerConnection::addCallback(NotificationServerCallback callback,
+ int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTING);
+ this->callbacks[trid] = std::make_pair(callback, data);
+ }
+
+ void NotificationServerConnection::removeCallback(int trid)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTING);
+ this->callbacks.erase(trid);
+ }
+
+ void NotificationServerConnection::registerHandlers()
+ {
+ if (commandHandlers.size() == 0)
+ {
+ commandHandlers["OUT"] = &NotificationServerConnection::handle_OUT;
+ commandHandlers["RML"] = &NotificationServerConnection::handle_RML;
+ commandHandlers["BLP"] = &NotificationServerConnection::handle_BLP;
+ commandHandlers["CHG"] = &NotificationServerConnection::handle_CHG;
+ commandHandlers["CHL"] = &NotificationServerConnection::handle_CHL;
+ commandHandlers["ILN"] = &NotificationServerConnection::handle_ILN;
+ commandHandlers["NLN"] = &NotificationServerConnection::handle_NLN;
+ commandHandlers["FLN"] = &NotificationServerConnection::handle_FLN;
+ commandHandlers["MSG"] = &NotificationServerConnection::handle_MSG;
+ commandHandlers["PRP"] = &NotificationServerConnection::handle_PRP;
+ commandHandlers["UBX"] = &NotificationServerConnection::handle_UBX;
+ commandHandlers["GCF"] = &NotificationServerConnection::handle_GCF;
+ commandHandlers["ADL"] = &NotificationServerConnection::handle_ADL;
+ commandHandlers["UBN"] = &NotificationServerConnection::handle_UBN;
+ commandHandlers["FQY"] = &NotificationServerConnection::handle_FQY;
+ }
+
+ if (messageHandlers.size() == 0)
+ {
+ messageHandlers["text/x-msmsgsinitialemailnotification"] = &NotificationServerConnection::message_initial_email_notification;
+ messageHandlers["text/x-msmsgsinitialmdatanotification"] = &NotificationServerConnection::message_initialmdatanotification;
+ messageHandlers["text/x-msmsgsemailnotification"] = &NotificationServerConnection::message_email_notification;
+ messageHandlers["text/x-msmsgsprofile"] = &NotificationServerConnection::message_msmsgsprofile;
+ messageHandlers["text/x-msmsgsoimnotification"] = &NotificationServerConnection::message_oimnotification;
+ }
+ }
+
+ void NotificationServerConnection::dispatchCommand(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &)>::iterator i = commandHandlers.find(args[0]);
+ if (i != commandHandlers.end())
+ (this->*commandHandlers[args[0]])(args);
+ }
+
+ void NotificationServerConnection::disconnectNS()
+ {
+ std::ostringstream buf_;
+ buf_ << "OUT\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+ disconnect();
+ }
+
+ void NotificationServerConnection::handle_OUT(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ if (args.size() > 1)
+ {
+ if (args[1] == "OTH")
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "You have logged onto MSN twice at once. Your MSN session will now terminate.");
+ }
+ else if (args[1] == "SSD")
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "This MSN server is going down for maintenance. Your MSN session will now terminate.");
+ } else {
+ this->myNotificationServer()->externalCallbacks.showError(this, (std::string("The MSN server has terminated the connection with an unknown reason code. Please report this code: ") +
+ args[1]).c_str());
+ }
+ }
+ this->disconnect();
+ }
+
+ void NotificationServerConnection::handle_RML(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ int msglen;
+ std::string msg;
+
+ if(args[2] != "OK" && args[2] != "OK")
+ return; // TODO - raise an error
+
+ msglen = decimalFromString(args[2]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+
+ XMLNode rml_data = XMLNode::parseString( msg.c_str() );
+
+ int nDomains = rml_data.nChildNode("d");
+ for(int i=0; i<nDomains; i++)
+ {
+ XMLNode domain = rml_data.getChildNode("d", i);
+ std::string domain_name = domain.getAttribute("n",0);
+ int nContacts = domain.nChildNode("c");
+ for(int j=0; j< nContacts; j++)
+ {
+ XMLNode contact = domain.getChildNode("c",j);
+ std::string contact_name = contact.getAttribute("n",0);
+ MSN::ContactList list_number = (MSN::ContactList) decimalFromString(contact.getAttribute("l",0));
+ // type is 1 for normal contact, 4 for mobile phone
+ // TODO - use this value
+ //int type = decimalFromString(contact.getAttribute("t",0));
+
+ MSN::Passport passport(contact_name+"@"+domain_name);
+
+ this->myNotificationServer()->externalCallbacks.removedListEntry(this, list_number, passport);
+ }
+ }
+ }
+
+ void NotificationServerConnection::handle_BLP(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ this->myNotificationServer()->externalCallbacks.gotBLP(this, args[3][0]);
+ }
+
+ void NotificationServerConnection::handle_CHG(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ this->myNotificationServer()->externalCallbacks.changedStatus(this, buddyStatusFromString(args[2]));
+ }
+
+ void NotificationServerConnection::handle_CHL(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ std::ostringstream buf_;
+ buf_ << "QRY " << this->trID++ << " " << szClientID << " 32\r\n";
+ if (write(buf_) != buf_.str().size())
+ return;
+
+ char b[33];
+ memset(&b,0,33);
+ DoMSNP11Challenge(args[2].c_str(),b);
+ // send the md5
+ std::string a(b);
+ write(a, false);
+ }
+
+ void NotificationServerConnection::handle_ILN(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIs(NS_CONNECTED);
+ if(args.size() > 7)
+ this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[3], decodeURL(args[5]), buddyStatusFromString(args[2]), decimalFromString(args[6]), decodeURL(args[7]));
+ else
+ this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[3], decodeURL(args[5]), buddyStatusFromString(args[2]), decimalFromString(args[6]), "");
+ }
+
+ void NotificationServerConnection::handle_NLN(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ if(args.size() > 6)
+ this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[2], decodeURL(args[4]), buddyStatusFromString(args[1]), decimalFromString(args[5]), decodeURL(args[6]));
+ else
+ this->myNotificationServer()->externalCallbacks.buddyChangedStatus(this, args[2], decodeURL(args[4]), buddyStatusFromString(args[1]), decimalFromString(args[5]), "");
+ }
+
+ void NotificationServerConnection::handle_FLN(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ this->myNotificationServer()->externalCallbacks.buddyOffline(this, args[1]);
+ }
+
+ void NotificationServerConnection::handle_UBN(std::vector<std::string> & args)
+ {
+ // TODO - UBN is a way to exchange data through notification server
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+        switch(decimalFromString(args[2])) {
+                case 1:
+                        // XML Data. Don't know what to do..
+                        break;
+                case 2:
+                        // SIP INVITE
+                        break;
+                case 3:
+                        // MSNP2P SLP data..
+                        break;
+                case 5:
+                        // Closed a Chat Window?
+                        break;
+                case 6:
+                        // Resynchronize..
+                        // <Service type="ab/membership">
+                        // reason 1 : added/deleted/blocked/whatever
+                        // reason 3 : added to favorites
+                        break;
+                case 11:
+                        // Unknown "1 1 5 134546710 0" prior to SIP invite...
+                        // Unknown "1 3 5 234889074 0 3 0" after sending a 'busy' response
+                        // Unknown "2 3 5 234889074 0 3 0" before a tunneled SIP invite that never got through
+                        // WLM sends UUN 11 : "4 1 $callid $email 3"
+                        // to itself followed by UUN 11 : "2 3 5 234889074 0 3 0"
+                        // send to the peer after it receives the ACK for
+                        // a decline it did on an inbound invite.
+                        //
+                        // the 134546710 or 234889074 seems to be the value of "AppVersion" from the registry..
+                        // WLM sends UUN 11 : "5 1 1" after acking the 200 OK... it apparently means
+                        // "Supports VGA resolution" or something like that...
+                        break;
+                case 12:
+                        // Tunneled SIP INVITE
+                        break;
+        }
+
+        std::cout << this->readBuffer << std::endl;
+
+ int msglen;
+ std::string msg;
+
+ msglen = decimalFromString(args[3]);
+        msg = this->readBuffer.substr(0, msglen);
+        this->readBuffer = this->readBuffer.substr(msglen);
+ }
+
+ void NotificationServerConnection::handle_FQY(std::vector<std::string> & args)
+ {
+ // TODO - I dont know what it means yet
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ int msglen;
+ std::string msg;
+ msglen = decimalFromString(args[2]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+ }
+
+ void NotificationServerConnection::callback_URL(std::vector<std::string> & args, int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ char b[33];
+ MSN::hotmailInfo info;
+ info.rru = args[2];
+ info.url = args[3];
+ info.id = args[4];
+ info.sl = toStr(time(NULL) - decimalFromString(login_time));
+ info.MSPAuth = MSPAuth;
+ info.sid = sid;
+ info.kv = kv;
+
+ // calculate creds
+ std::string creds_tmp = MSPAuth + info.sl + this->auth.password;
+ memset(&b,0,33);
+
+ md5_state_t state;
+ md5_byte_t digest[16];
+ int di;
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)creds_tmp.c_str(), creds_tmp.size());
+ md5_finish(&state, digest);
+ // convert to string
+ for (di = 0; di < 16; ++di)
+ sprintf(&b[2*di], "%02x", digest[di]);
+
+ std::string creds(b);
+ info.creds = creds;
+
+#ifdef LIBMSN_INBOX_URL_ENABLED
+ this->myNotificationServer()->externalCallbacks.gotInboxUrl(this, info);
+#endif
+ }
+
+ void NotificationServerConnection::handle_MSG(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ int msglen;
+ std::string msg;
+ std::string mime;
+ std::string body;
+ size_t tmp;
+
+ msglen = decimalFromString(args[3]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+
+ body = msg.substr(msg.find("\r\n\r\n") + 4);
+ mime = msg.substr(0, msg.size() - body.size());
+
+ std::string contentType;
+ Message::Headers headers = Message::Headers(mime);
+ contentType = headers["Content-Type"];
+
+ if ((tmp = contentType.find("; charset")) != std::string::npos)
+ contentType = contentType.substr(0, tmp);
+
+ std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &, std::string, std::string)>::iterator i = messageHandlers.find(contentType);
+ if (i != messageHandlers.end())
+ (this->*(messageHandlers[contentType]))(args, mime, body);
+ }
+
+ void NotificationServerConnection::message_initial_email_notification(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ std::string unreadInbox;
+ std::string unreadFolder;
+ int unreadInboxCount = 0, unreadFolderCount = 0;
+
+ // Initial email notifications body is a set of MIME headers
+ Message::Headers headers = Message::Headers(body);
+
+ unreadInbox = headers["Inbox-Unread"];
+ unreadFolder = headers["Folders-Unread"];
+ if (! unreadInbox.empty())
+ unreadInboxCount = decimalFromString(unreadInbox);
+
+ if (! unreadFolder.empty())
+ unreadFolderCount = decimalFromString(unreadFolder);
+
+// this->myNotificationServer()->externalCallbacks.gotInitialEmailNotification(this, unreadInboxCount, unreadFolderCount);
+ }
+
+ void NotificationServerConnection::message_email_notification(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ // New email notifications body is a set of MIME headers
+ Message::Headers headers = Message::Headers(body);
+
+ std::string from = headers["From-Addr"];
+ std::string subject = headers["Subject"];
+
+ this->myNotificationServer()->externalCallbacks.gotNewEmailNotification(this, from, subject);
+ }
+
+ void NotificationServerConnection::message_msmsgsprofile(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ direct_connection=false;
+ Message::Headers headers = Message::Headers(mime);
+ server_reported_ip = headers["ClientIP"];
+ server_reported_port = headers["ClientPort"];
+ login_time = headers["LoginTime"];
+ MSPAuth = headers["MSPAuth"];
+ sid = headers["sid"];
+ kv = headers["kv"];
+
+ if (login_time.empty()) //IN MSNP9 there is no logintime it seems, so set it manualy
+ {
+ time_t actualTime;
+ std::stringstream os;
+ time(&actualTime);
+ os << actualTime;
+ login_time = os.str();
+ }
+
+ this->myNotificationServer()->externalCallbacks.gotNewConnection(this);
+ // TODO - test portability to windows and mac, probably solved by ifdefs,
+ // or with an external callback to user application
+
+ // search on local machine the ip reported by the server
+ /* int s = socket (PF_INET, SOCK_STREAM, 0);
+ for (int i=1;;i++)
+ {
+ struct ifreq ifr;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
+ char *ip;
+
+ ifr.ifr_ifindex = i;
+ if (ioctl (s, SIOCGIFNAME, &ifr) < 0)
+ break;
+
+ if (ioctl (s, SIOCGIFADDR, &ifr) < 0)
+ continue;
+
+ ip = inet_ntoa (sin->sin_addr);
+ std::string ip2(ip);
+ if(ip2==server_reported_ip)
+ direct_connection=true;
+ }
+ close (s);
+ */
+ }
+
+ void NotificationServerConnection::message_initialmdatanotification(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ Message::Headers headers = Message::Headers(body);
+
+ std::string maildata = headers["Mail-Data"];
+ XMLNode domTree = XMLNode::parseString( maildata.c_str() );
+
+ //Mail-Data: <MD><E><I>2</I><IU>1</IU><O>1</O><OU>0</OU></E><Q><QTM>409600</QTM><QNM>204800</QNM></Q></MD>
+ //Mail-Data: <MD><E><I>3</I><IU>2</IU><O>2</O><OU>0</OU></E><Q><QTM>409600</QTM><QNM>204800</QNM></Q></MD>
+ //Mail-Data: <MD><E><I>3</I><IU>1</IU><O>2</O><OU>0</OU></E><Q><QTM>409600</QTM><QNM>204800</QNM></Q></MD>
+ //empty inbox
+ //Mail-Data: <MD><E><I>0</I><IU>0</IU><O>5</O><OU>0</OU></E><Q><QTM>409600</QTM><QNM>204800</QNM></Q></MD>
+ int emails = domTree.nChildNode("E");
+
+ if (emails)
+ {
+ XMLNode curr_element = domTree.getChildNode("E",0);
+ int inbox_msgs = decimalFromString(curr_element.getChildNode("I").getText());
+ int inbox_unread = decimalFromString(curr_element.getChildNode("IU").getText());
+ int other_folders = decimalFromString(curr_element.getChildNode("O").getText());
+ int other_folders_unread = decimalFromString(curr_element.getChildNode("OU").getText());
+
+ this->myNotificationServer()->externalCallbacks. gotInitialEmailNotification(this, inbox_msgs, inbox_unread, other_folders, other_folders_unread);
+ }
+ // try to get OIM information
+ message_oimnotification(args, mime, body);
+ }
+
+ void NotificationServerConnection::message_oimnotification(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ Message::Headers headers = Message::Headers(body);
+
+ std::string maildata = headers["Mail-Data"];
+
+ if(maildata == "too-large")
+ {
+ // more than 25 OIM's
+ // request OIM list through soap
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->getMailData();
+ return;
+ }
+ // process maildata
+ gotMailData(maildata);
+ }
+
+ void NotificationServerConnection::gotSoapMailData(Soap & soapConnection, std::string maildata)
+ {
+ gotMailData(maildata);
+ }
+
+ void NotificationServerConnection::gotMailData(std::string maildata)
+ {
+ std::vector<eachOIM> messages;
+ XMLNode domTree = XMLNode::parseString( maildata.c_str() );
+
+ int oims = domTree.nChildNode("M");
+
+ if (oims)
+ {
+ for(int i=0;i<oims;i++)
+ {
+ eachOIM temp_oim;
+ XMLNode curr_element = domTree.getChildNode("M",i);
+ temp_oim.from = curr_element.getChildNode("E").getText();
+ temp_oim.id = curr_element.getChildNode("I").getText();
+ temp_oim.fromFN = curr_element.getChildNode("N").getText();
+
+ std::vector<std::string> friendlyName;
+ // if we do not have '?', it is just the email
+ if(temp_oim.fromFN.find("?") != std::string::npos)
+ {
+ friendlyName=splitString(temp_oim.fromFN,"?");
+ // TODO - handle the encoding (friendlyName[1])
+ if(friendlyName[2]=="B")
+ {
+ temp_oim.fromFN=b64_decode(friendlyName[3].c_str());
+ }
+ if(friendlyName[2]=="Q")
+ {
+ // Quoted-Printable, is similar to URL encoding,
+ // but uses "=" instead of "%".
+ std::string change = friendlyName[3];
+ // changes the = by %
+ for(unsigned int a=0;a<change.length();a++)
+ if(change[a]=='=') change[a]='%';
+
+ temp_oim.fromFN=decodeURL(change);
+ }
+ }
+ messages.push_back(temp_oim);
+ }
+ this->myNotificationServer()->externalCallbacks.gotOIMList(this, messages);
+ }
+ domTree.deleteNodeContent('Y');
+ }
+
+ void NotificationServerConnection::handle_RNG(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ SwitchboardServerConnection::AuthData auth = SwitchboardServerConnection::AuthData(this->auth.username,
+ args[1],
+ args[4]);
+ SwitchboardServerConnection *newSBconn = new SwitchboardServerConnection(auth, *this);
+ this->addSwitchboardConnection(newSBconn);
+ std::pair<std::string, int> server_address = splitServerAddress(args[2]);
+ newSBconn->connect(server_address.first, server_address.second);
+ }
+
+ void NotificationServerConnection::handle_PRP(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ if(this->_connectionState == NS_SYNCHRONISING)
+ {
+ this->myNotificationServer()->externalCallbacks.gotFriendlyName(this, decodeURL(args[3]));
+ this->myDisplayName = decodeURL(args[3]);
+ this->myNotificationServer()->externalCallbacks.connectionReady(this);
+ // the initial process ends here
+ this->setConnectionState(NS_CONNECTED);
+ return;
+ }
+ if ( args[2] == "MFN") //when you set manually your FriendlyName
+ {
+ this->myNotificationServer()->externalCallbacks.gotFriendlyName(this, decodeURL(args[3]));
+ this->myDisplayName = decodeURL(args[3]);
+
+ }// TODO - Implement other PRP commands: MBE WWE
+ }
+
+ void NotificationServerConnection::handle_GCF(std::vector<std::string> & args)
+ {
+ int msglen;
+ std::string msg;
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ // we do not use it so far. throw it away
+ msglen = decimalFromString(args[2]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+ }
+
+ void NotificationServerConnection::handle_ADL(std::vector<std::string> & args)
+ {
+ int msglen;
+ std::string msg;
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ if(args[2] =="OK" && (this->_connectionState == NS_SYNCHRONISING))
+ {
+ if(adl_packets.empty())
+ {
+ // no more adl packets to send!
+ // now you need the change the nickname and set the status
+ // to complete the initial connection process
+ // it is not possible to use setFriendlyName
+ // because we cannot send soap requests at this time
+ std::ostringstream buf_;
+ if(this->myDisplayName.empty())
+ this->myDisplayName = myPassport;
+ if(server_email_verified != "0")
+ {
+ // our email is verified
+ buf_ << "PRP " << this->trID++ << " MFN " << encodeURL(this->myDisplayName) << "\r\n";
+ write(buf_);
+ }
+ else
+ {
+ // not verified, so we cant change our displayName
+ this->myNotificationServer()->externalCallbacks.connectionReady(this);
+ // the initial process ends here
+ this->setConnectionState(NS_CONNECTED);
+ }
+ return;
+ }
+ else
+ {
+ // send each adl packet at a time
+ std::string adl_payload = adl_packets.front();
+ adl_packets.pop_front();
+ std::ostringstream buf_;
+ buf_ << "ADL " << this->trID++ << " " << adl_payload.length() << "\r\n";
+ buf_ << adl_payload;
+ if (write(buf_) != buf_.str().size())
+ return;
+ }
+ }
+ // I reach here when ADL has payload
+ msglen = decimalFromString(args[2]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+ // ADL 0 70
+ // <ml><d n="domain.com"><c n="foo.bar" t="1" l="8" f="fName" /></d></ml>
+ //
+
+ XMLNode adl_data = XMLNode::parseString( msg.c_str() );
+
+ int nDomains = adl_data.nChildNode("d");
+ for(int i=0; i<nDomains; i++)
+ {
+ XMLNode domain = adl_data.getChildNode("d",i);
+ std::string domain_name = domain.getAttribute("n",0);
+ int nContacts = domain.nChildNode("c");
+ for(int j=0; j< nContacts; j++)
+ {
+ XMLNode contact = domain.getChildNode("c",j);
+ std::string contact_name = contact.getAttribute("n",0);
+ std::string fname = contact.getAttribute("f",0);
+ MSN::ContactList list_number = (MSN::ContactList) decimalFromString(contact.getAttribute("l",0));
+ // type is 1 for wlm contacts, 4 for mobile phone, 32 for yahoo? (or any kind of email contact)
+ int type = decimalFromString(contact.getAttribute("t",0));
+ if(type == 32)
+ return;
+
+ MSN::Passport passport(contact_name+"@"+domain_name);
+
+ this->myNotificationServer()->externalCallbacks.addedListEntry(this, list_number, passport, fname);
+ }
+ }
+ }
+
+ void NotificationServerConnection::handle_UBX(std::vector<std::string> & args)
+ {
+ int msglen;
+ personalInfo pInfo;
+ std::string msg,media,psm;
+ MSN::Passport fromPassport = args[1];
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ msglen = decimalFromString(args[3]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+
+ // some buggy clients send no data in UBX command
+ if( msg.length() < 10 ) return;
+
+ XMLNode ubx_data = XMLNode::parseString( msg.c_str() );
+
+ const char *a = ubx_data.getChildNode("PSM").getText();
+ if(a)
+ {
+ psm = a;
+ pInfo.PSM = psm;
+ }
+
+ const char *m = ubx_data.getChildNode("CurrentMedia").getText();
+ if(m)
+ {
+ media = m;
+ // the splitString will drop the first NULL position.
+ // we need it to keep the order of the following fields.
+ std::vector<std::string> media1 = splitString(media, "\\0");
+ if(media1.size()>=4) // at least 4 fields. Type, Enabled, format, data
+ { // if we have some field, so ...
+ int i=0;
+ if (media.find("\\0")==0)
+ { // if starts with \0 there is no
+ // App field. It is optional.
+ pInfo.mediaApp = "";
+ }
+ else
+ {
+ pInfo.mediaApp = media1[i++];
+ }
+ pInfo.mediaType = media1[i++];
+ pInfo.mediaIsEnabled = decimalFromString(media1[i++]);
+
+ if(pInfo.mediaIsEnabled)
+ {
+ pInfo.mediaFormat = media1[i++];
+ for(unsigned int b=i; b < media1.size(); b++)
+ {
+ pInfo.mediaLines.push_back(media1[i++]);
+ }
+ }
+ }
+ }
+ this->myNotificationServer()->externalCallbacks.buddyChangedPersonalInfo(this, fromPassport, pInfo);
+ }
+
+ void NotificationServerConnection::setState(BuddyStatus state, uint clientID)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::ostringstream buf_;
+ std::string xml;
+
+ if(msnobj.getMSNObjectXMLByType(3,xml))
+ buf_ << "CHG " << this->trID++ << " " <<
+ buddyStatusToString(state) << " "<< unsignedToStr(clientID) << " " << encodeURL(xml) << "\r\n";
+ else
+ buf_ << "CHG " << this->trID++ << " " << buddyStatusToString(state) << " " << unsignedToStr(clientID) << "\r\n";
+ write(buf_);
+ }
+
+ void NotificationServerConnection::setBLP(char setting)
+ {
+ if (setting != 'A' || setting != 'B')
+ return;
+
+ if(this->_connectionState == NS_CONNECTED)
+ {
+ std::ostringstream buf_;
+ this->bplSetting = setting;
+ buf_ << "BLP " << this->trID++ << " " << setting << "L\r\n";
+ write(buf_);
+ }
+ else
+ {
+ this->bplSetting = setting;
+ }
+ }
+
+ void NotificationServerConnection::setFriendlyName(std::string friendlyName, bool updateServer) throw (std::runtime_error)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ if(friendlyName.empty())
+ return;
+ if (friendlyName.size() > 387)
+ throw std::runtime_error("Friendly name too long!");
+
+ if(updateServer)
+ {
+ // update nickname on server
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->changeDisplayName(friendlyName);
+ }
+ else
+ {
+ this->myDisplayName = friendlyName;
+ std::ostringstream buf_;
+ buf_ << "PRP " << this->trID++ << " MFN " << encodeURL(friendlyName) << "\r\n";
+ write(buf_);
+ }
+ }
+
+ void NotificationServerConnection::setPersonalStatus(personalInfo pInfo)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::string tempMedia;
+ XMLNode data = XMLNode::createXMLTopNode("Data");
+ XMLNode PSM = XMLNode::createXMLTopNode("PSM");
+ XMLNode CurrentMedia = XMLNode::createXMLTopNode("CurrentMedia");
+ XMLNode MachineGuid = XMLNode::createXMLTopNode("MachineGuid");
+
+ PSM.addText( pInfo.PSM.c_str() );
+ if(pInfo.mediaIsEnabled)
+ {
+ tempMedia = pInfo.mediaApp +"\\0"+
+ pInfo.mediaType+"\\0"+
+ toStr(pInfo.mediaIsEnabled)+"\\0"+
+ pInfo.mediaFormat +"\\0";
+
+ std::vector<std::string>::iterator i = pInfo.mediaLines.begin();
+ for(;i!=pInfo.mediaLines.end();i++)
+ {
+ tempMedia+=(*i);
+ tempMedia+="\\0";
+ }
+ }
+ CurrentMedia.addText( tempMedia.c_str() );
+
+ data.addChild(PSM);
+ data.addChild(CurrentMedia);
+
+ char *payload1=data.createXMLString(false);
+
+ std::string payload(payload1);
+ free(payload1);
+ std::ostringstream buf_;
+ buf_ << "UUX " << this->trID++ << " " << payload.length() << "\r\n";
+ buf_ << payload;
+ write(buf_);
+ }
+
+ void NotificationServerConnection::blockContact(Passport buddyName)
+ {
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->removeContactFromList(buddyName,LST_AL);
+
+ soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->addContactToList(buddyName,LST_BL);
+ }
+
+ void NotificationServerConnection::unblockContact(Passport buddyName)
+ {
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->removeContactFromList(buddyName,LST_BL);
+
+ soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->addContactToList(buddyName,LST_AL);
+ }
+
+ void NotificationServerConnection::addToAddressBook(Passport buddyName, std::string displayName)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->addContactToAddressBook(buddyName, displayName);
+ }
+
+ void NotificationServerConnection::enableContactOnAddressBook(std::string contactId, std::string passport)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->enableContactOnAddressBook(contactId, passport, this->myDisplayName);
+ }
+
+ void NotificationServerConnection::disableContactOnAddressBook(std::string contactId, std::string passport)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->disableContactFromAddressBook(contactId,passport);
+ }
+
+ void NotificationServerConnection::delFromAddressBook(std::string contactId, std::string passport)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->delContactFromAddressBook(contactId,passport);
+ }
+
+ void NotificationServerConnection::addToList(MSN::ContactList list, Passport buddyName)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->addContactToList(buddyName,list);
+ }
+
+ void NotificationServerConnection::removeFromList(MSN::ContactList list, Passport buddyName)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->removeContactFromList(buddyName,list);
+ }
+
+ void NotificationServerConnection::addToGroup(std::string groupId, std::string contactId)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->addContactToGroup(groupId, contactId);
+ }
+
+ void NotificationServerConnection::removeFromGroup(std::string groupId, std::string contactId)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->delContactFromGroup(groupId, contactId);
+ }
+
+ void NotificationServerConnection::addGroup(std::string groupName)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->addGroup(groupName);
+ }
+
+ void NotificationServerConnection::removeGroup(std::string groupID)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->delGroup(groupID);
+ }
+
+ void NotificationServerConnection::renameGroup(std::string groupID, std::string newGroupName)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->renameGroup(groupID, newGroupName);
+ }
+
+ void NotificationServerConnection::synchronizeContactList(std::string lastChange)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ this->assertConnectionStateIsNot(NS_SYNCHRONISING);
+
+ // we are synchronizing through soap requests now
+ this->setConnectionState(NS_SYNCHRONISING);
+
+ listInfo = new ListSyncInfo(lastChange);
+ if(!listInfo)
+ return; // TODO - raise an error
+
+ if(!lastChange.length()) lastChange = "0";
+
+ listInfo->lastChange = lastChange;
+
+ Soap *soapConnection;
+ soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->getLists(listInfo);
+ }
+
+ void NotificationServerConnection::gotLists(Soap &soapConnection)
+ {
+ if(!listInfo)
+ return; // TODO - raise an error
+
+ Soap *soapConnection1;
+ soapConnection1 = new Soap(*this, this->sitesToAuthList);
+
+ // ask for Address book
+ soapConnection1->getAddressBook(this->listInfo);
+ }
+
+ void NotificationServerConnection::gotAddressBook(Soap &soapConnection)
+ {
+ // TODO - sorry, I dont have choice. I need this here because the initial setFriendlyName
+ // is called by handle_ADL(), which does not have access to info variable.
+ this->myDisplayName = listInfo->myDisplayName;
+
+ std::ostringstream buf_;
+
+ // TODO - see what is the user choice: BL or AL
+ // A value of 'AL' indicates that users that are neither on the client's Allow List or Buddy List will be allowed to see the client's online status and open a switchboard session with the client. A value of 'BL' indicates that these users will see the client as offline and will not be allowed to open a switchboard session.
+ // http://msnpiki.msnfanatic.com/index.php/Command:BLP
+
+ buf_ << "BLP " << this->trID << " " << this->bplSetting << "L\r\n";
+ if (write(buf_) != buf_.str().size())
+ return;
+
+ this->addCallback(&NotificationServerConnection::callback_initialBPL, this->trID++, (void *)NULL);
+ }
+
+ void NotificationServerConnection::callback_initialBPL(std::vector<std::string> & args, int trid, void *data)
+ {
+ this->assertConnectionStateIs(NS_SYNCHRONISING);
+ this->removeCallback(trid);
+
+ this->myNotificationServer()->externalCallbacks.gotBuddyListInfo(this, this->listInfo);
+ delete this->listInfo;
+ }
+
+ void NotificationServerConnection::completeConnection(std::map<std::string, int > & allContacts, void *info)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+
+ // FIXME - handle the errors
+ std::map<std::string, std::vector<std::string> > domains;
+
+ std::string tempADL;
+
+ // contains which number is. (i.e. 1 for FL, 2 for AL, 4 for BL) or the sum
+ std::map<std::string, int> tempList;
+
+ std::map<std::string,int>::iterator i;
+ for (i = allContacts.begin(); i != allContacts.end(); i++)
+ {
+ std::vector<std::string> parts = splitString((*i).first,"@");
+ if(tempList[(*i).first]==0)
+ domains[parts[1]].push_back(parts[0]);
+
+ // it does not allow LST_AL and LST_BL, as the server will refuse with a 241 error
+ int privacyListMask = MSN::LST_AL | MSN::LST_BL;
+ if ( ((*i).second & privacyListMask) == privacyListMask )
+ tempList[(*i).first] = (*i).second & ~MSN::LST_AL;
+ else
+ tempList[(*i).first] = (*i).second;
+ }
+
+ // deleting buddy information
+ std::map<std::string, MSN::Buddy *>::iterator d = listInfo->contactList.begin();
+ for(d; d != listInfo->contactList.end(); d++)
+ {
+ delete (*d).second;
+ }
+
+ // adding domains and users to xml:
+ // The max payload of ADL command is about 7500 bytes.
+ // so the code below should do that.
+ // not using xmlParser due to the complex algorithm
+ // TODO - What to do when there are no contacts?
+ std::map<std::string, std::vector<std::string> >::iterator cur = domains.begin();
+
+ tempADL+= "<ml l=\"1\">";
+ // for each domain
+ for(; cur != domains.end(); cur++)
+ {
+ tempADL += "<d n=\"" + (*cur).first + "\">";
+ // for each user
+ while(domains[(*cur).first].size()!=0)
+ {
+ std::string a((*cur).second[0]+"@"+(*cur).first);
+ tempADL += "<c n=\"" + (*cur).second[0] + "\" l=\""+toStr(tempList[a]) +"\" t=\"1\"/>";
+ (*cur).second.erase((*cur).second.begin());
+ if(tempADL.length()>7400)
+ {
+ // it means that there are more contacts from this domain
+ if(domains[(*cur).first].size()!=0)
+ {
+ tempADL += "</d></ml>";
+ adl_packets.push_back(tempADL);
+ tempADL="";
+ tempADL += "<ml l=\"1\">";
+ tempADL += "<d n=\"" + (*cur).first + "\">";
+ continue;
+ }
+ }
+ }
+ tempADL += "</d>";
+ }
+ tempADL += "</ml>";
+ adl_packets.push_back(tempADL);
+
+ // send the first one
+ std::string adl_payload = adl_packets.front();
+ adl_packets.pop_front();
+
+ std::ostringstream buf_;
+ buf_ << "ADL " << this->trID++ << " " << adl_payload.length() << "\r\n";
+ buf_ << adl_payload;
+ if (write(buf_) != buf_.str().size())
+ return;
+ }
+
+
+ void NotificationServerConnection::sendPing()
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::string a("PNG\r\n");
+ write(a);
+ }
+
+ void NotificationServerConnection::requestSwitchboardConnection(const void *tag)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ SwitchboardServerConnection::AuthData *auth = new SwitchboardServerConnection::AuthData(this->auth.username, tag);
+ std::ostringstream buf_;
+ buf_ << "XFR " << this->trID << " SB\r\n";
+ if (write(buf_) != buf_.str().size())
+ return;
+
+ this->addCallback(&NotificationServerConnection::callback_TransferToSwitchboard, this->trID++, (void *)auth);
+ }
+
+ template <class _Tp>
+ class _sameUserName
+ {
+ Buddy buddy;
+public:
+ _sameUserName(const _Tp &__u) : buddy(__u) {};
+ bool operator()(const _Tp &__x) { return __x.userName == buddy.userName; }
+ };
+
+ void NotificationServerConnection::socketConnectionCompleted()
+ {
+ this->assertConnectionStateIs(NS_CONNECTING);
+ this->setConnectionState(NS_CONNECTED);
+
+ Connection::socketConnectionCompleted();
+
+ // If an error occurs in Connection::socketConnectionCompleted, we
+ // will be disconnected before we get here.
+ if (this->connectionState() != NS_DISCONNECTED)
+ {
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1, 0, false);
+ }
+ }
+
+ void NotificationServerConnection::connect(const std::string & hostname, unsigned int port)
+ {
+ this->assertConnectionStateIs(NS_DISCONNECTED);
+ connectinfo *info = new connectinfo(this->auth.username, this->auth.password);
+ this->info = info;
+
+ if ((this->sock = this->myNotificationServer()->externalCallbacks.connectToServer(hostname, port, &this->connected)) == NULL)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "Could not connect to MSN server");
+ this->myNotificationServer()->externalCallbacks.closingConnection(this);
+ return;
+ }
+ this->setConnectionState(NS_CONNECTING);
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0, 1, false);
+ if (this->connected)
+ this->socketConnectionCompleted();
+
+ std::ostringstream buf_;
+ buf_ << "VER " << this->trID << " MSNP15 CVR0\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+
+ this->addCallback(&NotificationServerConnection::callback_NegotiateCVR, this->trID++, (void *)info);
+ }
+
+ void NotificationServerConnection::connect(const std::string & hostname, unsigned int port, const Passport & username, const std::string & password)
+ {
+ this->auth.username = username;
+ this->auth.password = password;
+ this->connect(hostname, port);
+ }
+
+ void NotificationServerConnection::disconnect()
+ {
+ this->assertConnectionStateIsNot(NS_DISCONNECTED);
+
+ std::vector<SwitchboardServerConnection *> list = _switchboardConnections;
+ std::vector<SwitchboardServerConnection *>::iterator i = list.begin();
+ for (; i != list.end(); ++i)
+ {
+ delete *i;
+ }
+ std::vector<Soap *> list2 = _SoapConnections;
+ std::vector<Soap *>::iterator d = list2.begin();
+
+ for (; d != list2.end(); ++d)
+ {
+ delete *d;
+ }
+
+ this->callbacks.clear();
+ this->sitesToAuthList.erase(sitesToAuthList.begin(), sitesToAuthList.end());
+ SentQueuedOIMs.erase(SentQueuedOIMs.begin(), SentQueuedOIMs.end());
+ this->setConnectionState(NS_DISCONNECTED);
+ this->myNotificationServer()->externalCallbacks.closingConnection(this);
+ Connection::disconnect();
+ }
+
+ void NotificationServerConnection::disconnectForTransfer()
+ {
+ this->assertConnectionStateIsNot(NS_DISCONNECTED);
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ this->myNotificationServer()->externalCallbacks.closeSocket(this->sock);
+ this->setConnectionState(NS_DISCONNECTED);
+ }
+
+ void NotificationServerConnection::handleIncomingData()
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ while (this->isWholeLineAvailable())
+ {
+ std::vector<std::string> args = this->getLine();
+ if(!args.size()) continue;
+ if (args[0] == "MSG" || args[0] == "NOT" ||
+ args[0] == "IPG" || args[0] == "GCF" ||
+ args[0] == "UBX" || args[0] == "ADL" ||
+ args[0] == "RML")
+ {
+ int dataLength;
+ if (args[0] == "MSG" || args[0] == "UBX")
+ dataLength = decimalFromString(args[3]);
+ else if(args[0] == "GCF" || args[0] == "ADL" || args[0] == "RML")
+ dataLength = decimalFromString(args[2]);
+ else
+ dataLength = decimalFromString(args[1]);
+
+ if (this->readBuffer.find("\r\n") + 2 + dataLength > this->readBuffer.size())
+ return;
+ }
+ this->readBuffer = this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
+ int trid = 0;
+
+ if (args.size() >= 6 && args[0] == "XFR" && args[2] == "NS")
+ {
+ // XFR TrID NS NotificationServerIP:Port 0 ThisServerIP:Port
+ // 0 1 2 3 4 5
+ this->callbacks.clear(); // delete the callback data
+
+ this->disconnectForTransfer();
+
+ std::pair<std::string, int> server_address = splitServerAddress(args[3]);
+ this->connect(server_address.first, server_address.second);
+ return;
+ }
+
+ if (args.size() >= 7 && args[0] == "RNG")
+ {
+ // RNG SessionID SwitchboardServerIP:Port CKI AuthString InvitingUser InvitingDisplayName
+ // 0 1 2 3 4 5 6
+ this->handle_RNG(args);
+ return;
+ }
+
+ if (args.size() >= 2 && args[0] == "QNG")
+ {
+ // QNG seconds
+ // 0 1
+
+ // ping response, ignore
+ return;
+ }
+
+ if ((args.size() >= 3 && args[0] == "LST" ) ||
+ (args.size() >= 2 && (args[0] == "GTC" )) ||
+ (args.size() >= 3 && (args[0] == "BPR" || args[0] == "LSG" ))
+ )
+ {
+ // LST N=UserName F=FriendlyName C=GUID param groupID
+ // 0 1 2 3 4 5
+ //
+ // or
+ // (GTC|BLP) [TrID] [ListVersion] Setting
+ // 0 1 2 4
+
+ if (this->synctrid)
+ {
+ trid = this->synctrid;
+ }
+ else
+ {
+ trid = decimalFromString(args[1]);
+ }
+ }
+ else if (args.size() > 1)
+ {
+ try
+ {
+ trid = decimalFromString(args[1]);
+ }
+ catch (...)
+ {
+ }
+ }
+
+ if (!this->callbacks.empty() && trid >= 0)
+ {
+ if (this->callbacks.find(trid) != this->callbacks.end())
+ {
+ (this->*(this->callbacks[trid].first))(args, trid, this->callbacks[trid].second);
+ continue;
+ }
+ }
+
+ if (isdigit(args[0][0]))
+ this->showError(decimalFromString(args[0]));
+ else
+ this->dispatchCommand(args);
+ }
+ }
+
+ void NotificationServerConnection::callback_NegotiateCVR(std::vector<std::string> & args, int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ connectinfo * info = (connectinfo *) data;
+ this->removeCallback(trid);
+ if (args.size() >= 3 && args[0] != "VER" || args[2] != "MSNP15") // if either *differs*...
+ {
+ this->myNotificationServer()->externalCallbacks.showError(NULL, "Protocol negotiation failed");
+ this->disconnect();
+ return;
+ }
+
+ std::ostringstream buf_;
+ buf_ << "CVR " << this->trID << " 0x0409 winnt 5.1 i386 MSG80BETA 8.1.0178.00 MSMSGS " << info->username << "\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+ this->addCallback(&NotificationServerConnection::callback_RequestUSR, this->trID++, (void *) data);
+ }
+
+ void NotificationServerConnection::callback_TransferToSwitchboard(std::vector<std::string> & args, int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ SwitchboardServerConnection::AuthData *auth = static_cast<SwitchboardServerConnection::AuthData *>(data);
+ this->removeCallback(trid);
+
+ if (args[0] != "XFR")
+ {
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ delete auth;
+ return;
+ }
+
+ auth->cookie = args[5];
+ auth->sessionID = "";
+
+ SwitchboardServerConnection *newconn = new SwitchboardServerConnection(*auth, *this);
+
+ this->addSwitchboardConnection(newconn);
+ std::pair<std::string, int> server_address = splitServerAddress(args[3]);
+ newconn->connect(server_address.first, server_address.second);
+
+ delete auth;
+ }
+
+ void NotificationServerConnection::callback_RequestUSR(std::vector<std::string> & args, int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ connectinfo *info = (connectinfo *)data;
+ this->removeCallback(trid);
+
+ if (args.size() > 1 && args[0] != "CVR") // if*differs*...
+ {
+ this->myNotificationServer()->externalCallbacks.showError(NULL, "Protocol negotiation failed");
+ this->disconnect();
+ return;
+ }
+
+ std::ostringstream buf_;
+ buf_ << "USR " << this->trID << " SSO I " << info->username << "\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+
+ this->addCallback(&NotificationServerConnection::callback_PassportAuthentication, this->trID++, (void *) data);
+ }
+
+ void NotificationServerConnection::callback_PassportAuthentication(std::vector<std::string> & args, int trid, void * data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ connectinfo * info;
+
+ info=(connectinfo *)data;
+ this->removeCallback(trid);
+
+ if (isdigit(args[0][0]))
+ {
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ return;
+ }
+
+ if (args.size() >= 4 && args[4].empty()) {
+ this->disconnect();
+ return;
+ }
+
+ this->myNotificationServer()->externalCallbacks.getSecureHTTPProxy();
+
+ Soap *soapConnection = new Soap(*this);
+
+ this->mdi = args[5];
+ soapConnection->setMBI(args[4]);
+ soapConnection->getTickets(info->username,info->password,args[4]);
+ delete info;
+ info=NULL;
+ }
+
+ void NotificationServerConnection::gotTickets(Soap & soapConnection, std::vector<MSN::Soap::sitesToAuth> sitesToAuthList)
+ {
+ std::ostringstream buf_;
+ this->sitesToAuthList = sitesToAuthList;
+ std::string token = sitesToAuthList[1].BinarySecurityToken;
+ std::string binarysecret = sitesToAuthList[1].BinarySecret;
+ this->token = token;
+
+ buf_ << "USR " << this->trID << " SSO S " << token << " " << mdi_encrypt(binarysecret, mdi) << "\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+ this->addCallback(&NotificationServerConnection::callback_AuthenticationComplete, this->trID++, NULL);
+ }
+
+ void NotificationServerConnection::callback_AuthenticationComplete(std::vector<std::string> & args, int trid, void * data)
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ this->removeCallback(trid);
+
+ if (isdigit(args[0][0]))
+ {
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ return;
+ }
+ server_email_verified = args[4];
+ }
+
+ void NotificationServerConnection::get_oim(std::string id, bool markAsRead)
+ {
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->getOIM(id,markAsRead);
+ }
+
+ void NotificationServerConnection::delete_oim(std::string id)
+ {
+ if(this->removingOIM)
+ {
+ DeletedQueuedOIMs.push_back(id);
+ return;
+ }
+ this->removingOIM = true;
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->deleteOIM(id);
+ }
+
+ void NotificationServerConnection::send_oim(Soap::OIM oim)
+ {
+ // do not generate two lockkeys at the same time
+ if(this->generatingLockkey)
+ {
+ SentQueuedOIMs.push_back(oim);
+ return;
+ }
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ SentQueuedOIMs.push_back(oim);
+ this->generatingLockkey=true;
+ soapConnection->generateLockkey(oim);
+ }
+
+ void NotificationServerConnection::gotOIM(Soap & soapConnection, bool success, std::string id, std::string message)
+ {
+ this->myNotificationServer()->externalCallbacks.gotOIM(this, success, id, message);
+ }
+
+ void NotificationServerConnection::gotOIMLockkey(Soap & soapConnection, std::string lockkey)
+ {
+ this->lockkey = lockkey;
+ this->generatingLockkey = false;
+ if(this->lockkey.empty())
+ {
+ std::vector<Soap::OIM>::iterator i = SentQueuedOIMs.begin();
+ for(; i != SentQueuedOIMs.end(); i++)
+ {
+ this->myNotificationServer()->externalCallbacks.gotOIMSendConfirmation(this, false, (*i).id);
+ }
+ SentQueuedOIMs.erase(SentQueuedOIMs.begin(), SentQueuedOIMs.end());
+ return;
+ }
+ sendQueuedOIMs();
+ }
+
+ void NotificationServerConnection::gotOIMDeleteConfirmation(Soap & soapConnection, std::string id, bool deleted)
+ {
+ this->myNotificationServer()->externalCallbacks.gotOIMDeleteConfirmation(this, deleted, id);
+ if(this->DeletedQueuedOIMs.empty())
+ {
+ removingOIM = false;
+ return;
+ }
+ else
+ {
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+ soapConnection->deleteOIM(DeletedQueuedOIMs.back());
+ DeletedQueuedOIMs.pop_back();
+ }
+ }
+
+ void NotificationServerConnection::gotOIMSendConfirmation(Soap & soapConnection, int id, bool sent)
+ {
+ if(!sent)
+ this->lockkey.clear();
+
+ this->myNotificationServer()->externalCallbacks.gotOIMSendConfirmation(this, sent, id);
+ }
+
+ void NotificationServerConnection::sendQueuedOIMs()
+ {
+ std::vector<Soap::OIM>::iterator i = SentQueuedOIMs.begin();
+ for(; i != SentQueuedOIMs.end(); i++)
+ {
+ Soap *soapConnection = new Soap(*this, this->sitesToAuthList);
+
+ soapConnection->sendOIM((*i), this->lockkey);
+ }
+ SentQueuedOIMs.erase(SentQueuedOIMs.begin(), SentQueuedOIMs.end());
+ }
+
+ bool NotificationServerConnection::change_DisplayPicture(std::string filename)
+ {
+ msnobj.delMSNObjectByType(3);
+ if(!filename.empty())
+ msnobj.addMSNObject(filename,3);
+
+ return true;
+ }
+
+ void NotificationServerConnection::gotChangeDisplayNameConfirmation(Soap & soapConnection, std::string displayName, bool changed)
+ {
+ if(changed)
+ {
+ this->myDisplayName = displayName;
+ // server update OK, now change to the current session
+ std::ostringstream buf_;
+ buf_ << "PRP " << this->trID++ << " MFN " << encodeURL(displayName) << "\r\n";
+ write(buf_);
+ }
+ // TODO - raise an error if not changed
+ }
+
+ void NotificationServerConnection::gotAddContactToGroupConfirmation(Soap & soapConnection, bool added, std::string newVersion, std::string groupId, std::string contactId)
+ {
+ this->myNotificationServer()->externalCallbacks.addedContactToGroup(this, added, groupId, contactId);
+ }
+
+ void NotificationServerConnection::gotDelContactFromGroupConfirmation(Soap & soapConnection, bool removed, std::string newVersion, std::string groupId, std::string contactId)
+ {
+ this->myNotificationServer()->externalCallbacks.removedContactFromGroup(this, removed, groupId, contactId);
+ }
+
+ void NotificationServerConnection::gotAddGroupConfirmation(Soap & soapConnection, bool added, std::string newVersion, std::string groupName, std::string groupId)
+ {
+ this->myNotificationServer()->externalCallbacks.addedGroup(this, added, groupName, groupId);
+ }
+
+ void NotificationServerConnection::gotDelGroupConfirmation(Soap & soapConnection, bool removed, std::string newVersion, std::string groupId)
+ {
+ this->myNotificationServer()->externalCallbacks.removedGroup(this, removed, groupId);
+ }
+ void NotificationServerConnection::gotRenameGroupConfirmation(Soap & soapConnection, bool renamed, std::string newVersion, std::string newGroupName, std::string groupId)
+ {
+ this->myNotificationServer()->externalCallbacks.renamedGroup(this, renamed, newGroupName, groupId);
+ }
+
+ void NotificationServerConnection::gotAddContactToAddressBookConfirmation(Soap & soapConnection, bool added, std::string newVersion, std::string passport, std::string displayName, std::string guid)
+ {
+ this->myNotificationServer()->externalCallbacks.addedContactToAddressBook(this, added, passport, displayName, guid);
+ if(added)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ // TODO - use xmlParser
+ std::string payload3("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\"2\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_3;
+ buf_3 << "ADL " << this->trID++ << " " << payload3.length() << "\r\n";
+ buf_3 << payload3;
+ write(buf_3);
+
+ std::string payload2("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\"1\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_2;
+ buf_2 << "ADL " << this->trID++ << " " << payload2.length() << "\r\n";
+ buf_2 << payload2;
+ write(buf_2);
+
+ // the official client sends FQY
+ std::string payload4("<ml l=\"2\"><d n=\"" + domain + "\"><c n=\"" + user+ "\"/></d></ml>");
+ std::ostringstream buf_4;
+ buf_4 << "FQY " << this->trID++ << " " << payload4.length() << "\r\n";
+ buf_4 << payload4;
+ write(buf_4);
+ }
+ }
+
+ void NotificationServerConnection::gotDelContactFromAddressBookConfirmation(Soap & soapConnection, bool removed, std::string newVersion, std::string contactId, std::string passport)
+ {
+ this->myNotificationServer()->externalCallbacks.removedContactFromAddressBook(this, removed, contactId, passport);
+ if(removed)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ // TODO - use xmlParser
+ std::string payload2("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\"1\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_2;
+ buf_2 << "RML " << this->trID++ << " " << payload2.length() << "\r\n";
+ buf_2 << payload2;
+ write(buf_2);
+
+ }
+ }
+
+ void NotificationServerConnection::gotEnableContactOnAddressBookConfirmation(Soap & soapConnection, bool disabled, std::string newVersion, std::string contactId, std::string passport)
+ {
+ this->myNotificationServer()->externalCallbacks.enabledContactOnAddressBook(this, disabled, contactId, passport);
+ if(disabled)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ // TODO - use xmlParser
+ std::string payload3("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\"1\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_3;
+ buf_3 << "ADL " << this->trID++ << " " << payload3.length() << "\r\n";
+ buf_3 << payload3;
+ write(buf_3);
+ }
+ }
+
+ void NotificationServerConnection::gotDisableContactOnAddressBookConfirmation(Soap & soapConnection, bool disabled, std::string newVersion, std::string contactId, std::string passport)
+ {
+ this->myNotificationServer()->externalCallbacks.disabledContactOnAddressBook(this, disabled, contactId);
+ if(disabled)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ // TODO - use xmlParser
+ std::string payload2("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\"1\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_2;
+ buf_2 << "RML " << this->trID++ << " " << payload2.length() << "\r\n";
+ buf_2 << payload2;
+ write(buf_2);
+ }
+ }
+
+ void NotificationServerConnection::gotAddContactToListConfirmation(Soap & soapConnection, bool added, std::string newVersion, std::string passport, MSN::ContactList list)
+ {
+ if(added)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+
+ // TODO - use xmlParser
+ std::string payload2("<ml><d n=\"" + domain + "\"><c n=\"" + user+ "\" l=\""+toStr(list)+"\" t=\"1\"/></d></ml>");
+ std::ostringstream buf_2;
+ buf_2 << "ADL " << this->trID++ << " " << payload2.length() << "\r\n";
+ buf_2 << payload2;
+ write(buf_2);
+ this->myNotificationServer()->externalCallbacks.addedListEntry(this, list, passport, "");
+ }
+ }
+ void NotificationServerConnection::gotDelContactFromListConfirmation(Soap & soapConnection, bool deleted, std::string newVersion, std::string passport, MSN::ContactList list)
+ {
+ if(deleted)
+ {
+ std::vector<std::string> passport2 = splitString(passport, "@");
+ std::string user = passport2[0];
+ std::string domain = passport2[1];
+ // TODO - use XMLParser
+ std::string payload("<ml><d n=\""+ domain + "\"><c n=\"" + user + "\" l=\""+toStr(list)+"\" t=\"1\"/></d></ml>");
+
+ std::ostringstream buf_;
+ buf_ << "RML " << this->trID++ << " " << payload.length() << "\r\n";
+ buf_ << payload;
+ write(buf_);
+ this->myNotificationServer()->externalCallbacks.removedListEntry(this, list, passport);
+ }
+ }
+
+ void NotificationServerConnection::setCapabilities(uint m_clientId)
+ {
+ this->m_clientId = m_clientId;
+ }
+
+ void NotificationServerConnection::getInboxUrl()
+ {
+ this->assertConnectionStateIsAtLeast(NS_CONNECTED);
+ std::ostringstream buf_;
+ buf_ << "URL " << this->trID << " INBOX\r\n";
+ write(buf_);
+ this->addCallback(&NotificationServerConnection::callback_URL, this->trID++, NULL);
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnnotificationserverh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/notificationserver.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,549 @@
</span><ins>+#ifndef __msn_notificationserver_h__
+#define __msn_notificationserver_h__
+
+/*
+ * notificationserver.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/connection.h>
+#include <msn/authdata.h>
+#include <msn/errorcodes.h>
+#include <msn/buddy.h>
+#include <msn/passport.h>
+#include <stdexcept>
+#include <msn/externals.h>
+#include <msn/msnobject.h>
+#include <msn/soap.h>
+#include <cassert>
+#include <sys/types.h>
+
+#include "libmsn_export.h"
+
+#ifdef _WIN32
+typedef unsigned uint;
+#endif
+
+namespace MSN
+{
+ class SwitchboardServerConnection;
+
+ /** Contains information about synchronising the contact list with the server.
+ */
+ class LIBMSN_EXPORT ListSyncInfo
+ {
+public:
+ /** Constants specifying the status of the list synchronisation.
+ */
+ enum SyncProgress
+ {
+ LST_AB = 1, /**< Address book has been received. */
+ LST_AL = 2, /**< Allow list has been received. */
+ LST_BL = 4, /**< Block list has been received. */
+ LST_RL = 8, /**< Reverse list has been received. */
+ LST_PL = 16, /**< Pending list has been received. */
+ COMPLETE_BLP = 32 /**< @c BLP has been received. */
+ };
+
+
+ /** Treat unknown users as if appearing on this list when they attempt
+ * to initiate a switchboard session.
+ */
+ enum PrivacySetting
+ {
+ ALLOW = 'A', /**< Any user can see our status, except those in Block List. */
+ BLOCK = 'B' /**< Nobody can see our status, except those in Allow List. */
+ };
+
+ /** Action to take when a new user appears on our reverse list.
+ */
+ enum NewReverseListEntryAction
+ {
+ PROMPT = 'A',
+ DONT_PROMPT = 'N'
+ };
+
+
+ /** A list of people who's statuses we are wish to be notified about.
+ */
+ std::map<std::string, Buddy *> contactList;
+
+ std::string myDisplayName;
+
+ std::map<std::string, Group> groups;
+
+ /** The progress of the sync operation.
+ */
+ unsigned int progress;
+
+ unsigned int usersRemaining, groupsRemaining;
+
+ /** Last change on Address Book and lists timestamp
+ */
+ std::string lastChange;
+
+ /** Specifies the default list for non-buddies to be treated as
+ * appearing in when attempting to invite you into a switchboard setting.
+ *
+ * This corresponds to the @c BLP command in the MSN protocol.
+ */
+ char privacySetting;
+
+ /** Specifies whether the user should be prompted when a new buddy
+ * appears on their reverse list.
+ *
+ * This corresponds to the @c GTC command in the MSN protocol.
+ */
+ char reverseListPrompting;
+
+ ListSyncInfo(std::string lastChange_) :
+ progress(0), lastChange(lastChange_),
+ privacySetting(ListSyncInfo::ALLOW), reverseListPrompting(ListSyncInfo::PROMPT) {};
+ };
+
+ // Intermediate steps in connection:
+ class LIBMSN_EXPORT connectinfo
+ {
+public:
+ Passport username;
+ std::string password;
+ std::string cookie;
+
+ connectinfo(const Passport & username_, const std::string & password_) : username(username_), password(password_), cookie("") {};
+ };
+
+ /** Represents a connection to a MSN notification server.
+ *
+ * The MSN notification server is responsible for dealing with the contact
+ * list, online status, and dispatching message requests or invitations to
+ * or from switchboard servers.
+ */
+ class LIBMSN_EXPORT NotificationServerConnection : public Connection
+ {
+private:
+ typedef void (NotificationServerConnection::*NotificationServerCallback)(std::vector<std::string> & args, int trid, void *);
+
+ std::string token;
+ class AuthData : public ::MSN::AuthData
+ {
+public:
+ std::string password;
+
+ AuthData(const Passport & passport_,
+ const std::string & password_) :
+ ::MSN::AuthData(passport_), password(password_) {} ;
+ };
+ NotificationServerConnection::AuthData auth;
+ int synctrid;
+
+public:
+ MSNObject msnobj;
+
+ /** Create a NotificationServerConnection with the specified @a username and
+ * @a password.
+ */
+ NotificationServerConnection(Passport username, std::string password, Callbacks & cb);
+
+ virtual ~NotificationServerConnection();
+ virtual void dispatchCommand(std::vector<std::string> & args);
+
+ /** Return a list of SwitchboardServerConnection's that have been started
+ * from this NotificationServerConnection.
+ */
+ const std::vector<SwitchboardServerConnection *> & switchboardConnections();
+
+ /* Add a SwitchboardServerConnection to the list of connections that have
+ * been started from this connection.
+ */
+ void addSwitchboardConnection(SwitchboardServerConnection *);
+
+ /* Add the @p Soap object to the list of connections that have
+ * been started from this connection.
+ */
+ void addSoapConnection(Soap *);
+
+ /* Remove a SwitchboardServerConnection from the list of connections that have
+ * been started from this connection.
+ */
+ void removeSwitchboardConnection(SwitchboardServerConnection *);
+
+ /* Remove the @p Soap object from the list of connections that have
+ * been started from this connection.
+ */
+ void removeSoapConnection(Soap *);
+
+ /** Return a connection that is associated with @a fd.
+ *
+ * If @a fd is equal to @p sock, @c this is returned. Otherwise
+ * connectionWithSocket is sent to each SwitchboardServerConnection
+ * or Soap connections until a match is found.
+ *
+ * @return The matching connection, if found. Otherwise, @c NULL.
+ */
+ Connection *connectionWithSocket(void *sock);
+
+ /** Return a SwitchboardServerConnection that has exactly one user whose
+ * username is @a username.
+ *
+ * @return The matching SwitchboardServerConnection, or @c NULL.
+ */
+ SwitchboardServerConnection *switchboardWithOnlyUser(Passport username);
+
+ /** @name Action Methods
+ *
+ * These methods all perform actions on the notification server.
+ */
+ /** @{ */
+
+ /** Set our capabilities. This is the sum of MSNClientInformationFields enum fields
+ */
+ void setCapabilities(uint m_clientId);
+
+ void disconnectNS();
+
+ /** Set our online state to @a state and our capabilites to @a clientID.
+ */
+ void setState(BuddyStatus state, uint clientID);
+
+ /** Set Black List policy
+ */
+ void setBLP(char setting);
+
+ /** It must be called to complete the connection. Add all your contacts
+ * to allContacts, (both Forward, allow and block lists). The integer value
+ * of allContacts is the sum of all lists this contact is present. For example:
+ * If the contact is both on your allow and forward list, the number must be
+ * 3 (2+1).
+ */
+ void completeConnection(std::map<std::string,int > & allContacts, void *data);
+
+ /** Set our friendly name to @a friendlyName.
+ *
+ * @param friendlyName Maximum allowed length is 387 characters after URL-encoding.
+ */
+ void setFriendlyName(std::string friendlyName, bool updateServer = false) throw (std::runtime_error);
+
+ /** Points to our display picture. It must be a png file, size: 96x96.
+ * @param filename Path to the PNG file to be sent as avatar of this contact
+ */
+ bool change_DisplayPicture(std::string filename);
+
+ /** Sets our personal info. Current media, personal message...
+ */
+ void setPersonalStatus(personalInfo pInfo);
+
+ /** Add buddy named @a buddyName to the list named @a list.
+ */
+ void addToList(MSN::ContactList list, Passport buddyName);
+
+ /** Remove buddy named @a buddyName from the list named @a list.
+ */
+ void removeFromList(MSN::ContactList list, Passport buddyName);
+
+ /** Add contact @a buddyName to address book with @a displayName
+ * Automatically adds to allow list too.
+ */
+ void addToAddressBook(Passport buddyName, std::string displayName);
+
+ /** Delete contact @a passport with @a contactId from address book.
+ */
+ void delFromAddressBook(std::string contactId, std::string passport);
+
+ /** Enable a contact on address book. You will use it when you have disabled
+ * a contact before. This contact is still on your Address Book, but it is not
+ * a messenger contact. This function will turn this contact into a messenger
+ * contact again.
+ */
+ void enableContactOnAddressBook(std::string contactId, std::string passport);
+
+ /** Do not delete the contact, just disable it.
+ */
+ void disableContactOnAddressBook(std::string contactId, std::string passport);
+
+ /** Block a contact. This user won't be able to see your status anymore.
+ */
+ void blockContact(Passport buddyName);
+
+ /** Unblock a contact. This user will be able to see your status again.
+ */
+ void unblockContact(Passport buddyName);
+
+ /** Add a contact @a contactId to the group @a groupId .
+ */
+ void addToGroup(std::string groupId, std::string contactId);
+
+ /** Remove a contact from a group.
+ */
+ void removeFromGroup(std::string groupId, std::string contactId);
+
+ /** Add a new group.
+ */
+ void addGroup(std::string groupName);
+
+ /** Remove a group.
+ */
+ void removeGroup(std::string groupId);
+
+ /** Rename a group.
+ */
+ void renameGroup(std::string groupId, std::string newGroupName);
+
+ /** Request the server side buddy list.
+ *
+ * @param lastChange if @a version is specified the server will respond with
+ * the changes necessary to update the list to the latest
+ * version. Otherwise the entire list will be sent.
+ */
+ void synchronizeContactList(std::string lastChange="0");
+
+ /** Send a 'keep-alive' ping to the server.
+ */
+ void sendPing();
+
+ /** Request a switchboard connection.
+ */
+ void requestSwitchboardConnection(const void *tag);
+
+ /** Retrieve the Offline Instant Message identified by id
+ */
+ void get_oim(std::string id, bool markAsRead);
+
+ /** Erase the Offline Instant Message identified by id
+ */
+ void delete_oim(std::string id);
+
+ /** Send an Offline Instant Message
+ */
+ void send_oim(Soap::OIM oim);
+
+ void getInboxUrl();
+
+ /* when we have to send more than 1 ADL command, we need to keep this here to track */
+ std::list<std::string> adl_packets;
+
+ /* Our current Display Name */
+ std::string myDisplayName;
+
+ /* Our passport */
+ std::string myPassport;
+
+ /* Sum of capabilities of the user */
+ uint m_clientId;
+
+ char bplSetting;
+
+ /* Our IP number reported by notification server */
+ std::string server_reported_ip;
+
+ /* Our TCP source port reported by notification server */
+ std::string server_reported_port;
+
+ std::string login_time;
+
+ std::string MSPAuth;
+
+ std::string sid;
+
+ std::string kv;
+
+ /* 1 if our email is verified, 0 if not */
+ std::string server_email_verified;
+
+ /* Says if we are direct connected based on server's report */
+ bool direct_connection;
+
+ virtual void connect(const std::string & hostname, unsigned int port);
+
+ virtual void connect(const std::string & hostname, unsigned int port,
+ const Passport & username,
+ const std::string & password);
+
+ virtual void disconnect();
+
+ virtual void addCallback(NotificationServerCallback cb, int trid, void *data);
+
+ virtual void removeCallback(int trid);
+
+ virtual void socketConnectionCompleted();
+
+ enum NotificationServerState
+ {
+ NS_DISCONNECTED,
+ NS_CONNECTING,
+ NS_CONNECTED,
+ NS_SYNCHRONISING,
+ NS_ONLINE
+ };
+
+ connectinfo *info;
+ NotificationServerState connectionState() const { return this->_connectionState; };
+ Callbacks & externalCallbacks;
+ virtual NotificationServerConnection *myNotificationServer() { return this; };
+ void gotTickets(Soap & soapConnection, std::vector<MSN::Soap::sitesToAuth> sitesToAuthList);
+ void gotLists(Soap &soapConnection);
+ void gotAddressBook(Soap &soapConnection);
+ void gotOIM(Soap & soapConnection, bool success, std::string id, std::string message);
+ void gotOIMLockkey(Soap & soapConnection, std::string lockkey);
+ void gotOIMSendConfirmation(Soap & soapConnection, int id, bool sent);
+ void gotOIMDeleteConfirmation(Soap & soapConnection, std::string id, bool deleted);
+ void gotSoapMailData(Soap & soapConnection, std::string maildata);
+ void gotChangeDisplayNameConfirmation(Soap & soapConnection, std::string displayName, bool changed);
+ void gotDelContactFromGroupConfirmation(Soap & soapConnection,
+ bool deleted,
+ std::string newVersion,
+ std::string groupId,
+ std::string contactId);
+
+ void gotAddContactToGroupConfirmation(Soap & soapConnection,
+ bool added,
+ std::string newVersion,
+ std::string groupId,
+ std::string contactId);
+
+ void gotAddGroupConfirmation(Soap & soapConnection,
+ bool added,
+ std::string newVersion,
+ std::string groupName,
+ std::string groupId);
+
+ void gotDelGroupConfirmation(Soap & soapConnection,
+ bool removed,
+ std::string newVersion,
+ std::string groupId);
+
+ void gotRenameGroupConfirmation(Soap & soapConnection,
+ bool renamed,
+ std::string newVersion,
+ std::string newGroupName,
+ std::string groupId);
+
+ void gotAddContactToAddressBookConfirmation(Soap & soapConnection,
+ bool added,
+ std::string newVersion,
+ std::string passport,
+ std::string displayName,
+ std::string guid);
+
+ void gotDelContactFromAddressBookConfirmation(Soap & soapConnection,
+ bool removed,
+ std::string newVersion,
+ std::string contactId,
+ std::string passport);
+
+ void gotEnableContactOnAddressBookConfirmation(Soap & soapConnection,
+ bool enabled,
+ std::string newVersion,
+ std::string contactId,
+ std::string passport);
+
+ void gotDisableContactOnAddressBookConfirmation(Soap & soapConnection,
+ bool disabled,
+ std::string newVersion,
+ std::string contactId,
+ std::string passport);
+
+ void gotAddContactToListConfirmation(Soap & soapConnection,
+ bool added,
+ std::string newVersion,
+ std::string passport,
+ MSN::ContactList list);
+
+ void gotDelContactFromListConfirmation(Soap & soapConnection,
+ bool deleted,
+ std::string newVersion,
+ std::string passport,
+ MSN::ContactList list);
+
+protected:
+ virtual void handleIncomingData();
+ NotificationServerState _connectionState;
+
+ void setConnectionState(NotificationServerState s) { this->_connectionState = s; };
+ void assertConnectionStateIs(NotificationServerState s) { assert(this->_connectionState == s); };
+ void assertConnectionStateIsNot(NotificationServerState s) { assert(this->_connectionState != s); };
+ void assertConnectionStateIsAtLeast(NotificationServerState s) { assert(this->_connectionState >= s); };
+private:
+ std::vector<SwitchboardServerConnection *> _switchboardConnections;
+ std::vector<Soap *> _SoapConnections;
+ std::map<int, std::pair<NotificationServerCallback, void *> > callbacks;
+
+ ListSyncInfo *listInfo;
+
+ std::vector<MSN::Soap::sitesToAuth> sitesToAuthList;
+ std::vector<MSN::Soap::OIM> SentQueuedOIMs;
+ std::vector<std::string> DeletedQueuedOIMs;
+
+ std::string lockkey;
+ bool generatingLockkey;
+ bool removingOIM;
+
+ void sendQueuedOIMs();
+
+ // mdi value got by tweener
+ std::string mdi;
+
+ virtual void disconnectForTransfer();
+
+ static std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &)> commandHandlers;
+ static std::map<std::string, void (NotificationServerConnection::*)(std::vector<std::string> &, std::string, std::string)> messageHandlers;
+
+ void registerHandlers();
+ void handle_OUT(std::vector<std::string> & args);
+ void handle_RML(std::vector<std::string> & args);
+ void handle_BLP(std::vector<std::string> & args);
+ void handle_CHG(std::vector<std::string> & args);
+ void handle_CHL(std::vector<std::string> & args);
+ void handle_ILN(std::vector<std::string> & args);
+ void handle_NLN(std::vector<std::string> & args);
+ void handle_FLN(std::vector<std::string> & args);
+ void handle_MSG(std::vector<std::string> & args);
+ void handle_RNG(std::vector<std::string> & args);
+ void handle_PRP(std::vector<std::string> & args);
+ void handle_UBX(std::vector<std::string> & args);
+ void handle_GCF(std::vector<std::string> & args);
+ void handle_ADL(std::vector<std::string> & args);
+ void handle_UBN(std::vector<std::string> & args);
+ void handle_FQY(std::vector<std::string> & args);
+
+ void callback_NegotiateCVR(std::vector<std::string> & args, int trid, void *data);
+ void callback_TransferToSwitchboard(std::vector<std::string> & args, int trid, void *data);
+ void callback_RequestUSR(std::vector<std::string> & args, int trid, void *data);
+ void callback_PassportAuthentication(std::vector<std::string> & args, int trid, void * data);
+ void callback_AuthenticationComplete(std::vector<std::string> & args, int trid, void * data);
+ void callback_initialBPL(std::vector<std::string> & args, int trid, void *data);
+ void callback_URL(std::vector<std::string> & args, int trid, void *data);
+
+
+ void message_initial_email_notification(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_email_notification(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_msmsgsprofile(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_initialmdatanotification(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_oimnotification(std::vector<std::string> & args, std::string mime, std::string body);
+
+ void gotMailData(std::string maildata);
+
+ };
+
+}
+
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnp2pcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,1406 @@
</span><ins>+/*
+ * p2p.cpp
+ * libmsn
+ *
+ * Created by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/notificationserver.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/util.h>
+#include <msn/p2p.h>
+#include <msn/xmlParser.h>
+
+#include <cctype>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#include <string.h>
+
+namespace MSN {
+
+ P2P::P2P()
+ {
+ rand_helper = 1;
+ }
+ P2P::~P2P()
+ {
+ }
+
+
+ void P2P::handleP2Pmessage(MSN::SwitchboardServerConnection &conn, std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ Message::Headers headers = Message::Headers(mime);
+ p2pPacket packet;
+ // not for me, ignore it
+ if(headers["P2P-Dest"] != conn.myNotificationServer()->myPassport)
+ return;
+
+ std::istringstream header(body,std::ios::binary);
+
+ header.read((char*)&packet.p2pHeader.sessionID, sizeof(packet.p2pHeader.sessionID));
+ header.read((char*)&packet.p2pHeader.identifier, sizeof(packet.p2pHeader.identifier));
+ header.read((char*)&packet.p2pHeader.dataOffset, sizeof(packet.p2pHeader.dataOffset));
+ header.read((char*)&packet.p2pHeader.totalDataSize, sizeof(packet.p2pHeader.totalDataSize));
+ header.read((char*)&packet.p2pHeader.messageLength, sizeof(packet.p2pHeader.messageLength));
+ header.read((char*)&packet.p2pHeader.flag, sizeof(packet.p2pHeader.flag));
+ header.read((char*)&packet.p2pHeader.ackID, sizeof(packet.p2pHeader.ackID));
+ header.read((char*)&packet.p2pHeader.ackUID, sizeof(packet.p2pHeader.ackUID));
+ header.read((char*)&packet.p2pHeader.ackDataSize, sizeof(packet.p2pHeader.ackDataSize));
+ char *c = new char[packet.p2pHeader.messageLength];
+ header.read(c, packet.p2pHeader.messageLength);
+ std::string content(c, packet.p2pHeader.messageLength);
+ packet.body = content;
+ free(c);
+ header.read((char*)&packet.p2pFooter.appID, sizeof(packet.p2pFooter.appID));
+
+ if(packet.p2pHeader.flag==FLAG_ACK)
+ {
+ handle_p2pACK(conn, packet);
+ return;
+ }
+
+ if(packet.p2pHeader.sessionID == 0x40 &&
+ little2big_endian(packet.p2pFooter.appID)==3) // INK, oh god!
+ {
+ p2pSession session;
+ session.to = args[1];
+ if(!packet.p2pHeader.dataOffset) // first packet
+ {
+ session.ink = packet.body;
+ startedSessions[packet.p2pHeader.sessionID] = session;
+ return;
+ }
+ else
+ {
+ if (packet.p2pHeader.dataOffset+packet.p2pHeader.messageLength
+ == packet.p2pHeader.totalDataSize)
+ {
+ session = startedSessions[packet.p2pHeader.sessionID];
+ session.ink += packet.body;
+ sendACK(conn, packet, session);
+ startedSessions.erase(packet.p2pHeader.sessionID);
+ // TODO - THIS IS UGLY!
+ U8 *d1 = new U8[packet.p2pHeader.totalDataSize];
+ U8 *a = new U8[packet.p2pHeader.totalDataSize];
+ a[0]='\0';
+ a++;
+ const char *f = session.ink.c_str();
+ memcpy(a,f,session.ink.size());
+ a--;
+ _ucs2_utf8(d1, a, session.ink.size());
+ char *c = new char[packet.p2pHeader.totalDataSize+2];
+ char *g = new char[packet.p2pHeader.totalDataSize+2];
+ sprintf(c,"%s",(char*)d1);
+ sprintf(g,"%s",(char*)(d1+strlen((char*)d1)+1));
+
+ std::string d2(c);
+ std::string d3(g);
+ free(a);
+ free(c);
+ free(d1);
+ free(g);
+
+ conn.message_ink(args, d2, d3);
+ return;
+ }
+ if (packet.p2pHeader.dataOffset+packet.p2pHeader.messageLength
+ < packet.p2pHeader.totalDataSize)
+ {
+ session = startedSessions[packet.p2pHeader.sessionID];
+ session.ink += packet.body;
+ startedSessions[packet.p2pHeader.sessionID] = session;
+ return;
+ }
+ }
+ return;
+ }
+
+ // in these conditions, the packet is data, receive it to a file
+ if(packet.p2pHeader.sessionID &&
+ (packet.p2pHeader.flag == FLAG_FILE_DATA ||
+ packet.p2pHeader.flag == FLAG_FILE_DATA2 ||
+ packet.p2pHeader.flag == FLAG_DATA_EMOTICONS))
+ {
+ // we need to ensure we have a started session
+ if(!startedSessions.count(packet.p2pHeader.sessionID))
+ return;
+
+ startedSessions[packet.p2pHeader.sessionID].step = STEP_RECEIVING;
+ receiveP2PData(conn,packet);
+ return;
+ }
+
+ if(packet.p2pHeader.sessionID && packet.p2pFooter.appID)
+ {
+ // we need to ensure we have a started session
+ if(!startedSessions.count(packet.p2pHeader.sessionID))
+ return;
+
+ // data preparation, always?
+ p2pSession session = startedSessions[packet.p2pHeader.sessionID];
+ sendACK(conn, packet, session);
+ return;
+ }
+
+ if(packet.p2pFooter.appID==APP_NONE) // when 0, assembly all the data before processing
+ {
+ // reassembly the packet
+ if(packet.p2pHeader.messageLength < packet.p2pHeader.totalDataSize) // just part of the packet
+ {
+ if(pendingP2PMsg.count(packet.p2pHeader.identifier)==0) // it is the first part
+ {
+ pendingP2PMsg[packet.p2pHeader.identifier]=packet;
+ return;
+ }
+ p2pPacket pkt_part = pendingP2PMsg[packet.p2pHeader.identifier];
+
+ // not the first part
+ pkt_part.body+=packet.body;
+
+ if(packet.p2pHeader.messageLength+packet.p2pHeader.dataOffset <
+ packet.p2pHeader.totalDataSize)
+ {
+ pendingP2PMsg[packet.p2pHeader.identifier]=pkt_part;
+ // this is not the last part, wait for the last one
+ return;
+ }
+
+ // shouldn't be reached
+ if(packet.p2pHeader.messageLength+packet.p2pHeader.dataOffset >
+ packet.p2pHeader.totalDataSize)
+ {
+ pendingP2PMsg.erase(packet.p2pHeader.identifier);
+ return;
+ }
+ if(packet.p2pHeader.messageLength+packet.p2pHeader.dataOffset ==
+ packet.p2pHeader.totalDataSize)
+ {
+ packet=pkt_part;
+ pendingP2PMsg.erase(packet.p2pHeader.identifier);
+ }
+ }
+ }
+
+ if(!packet.body.find("INVITE"))
+ {
+ handle_INVITE(conn,packet);
+ }
+ else if (!packet.body.find("MSNSLP/1.0 200 OK"))
+ {
+ handle_200OK(conn,packet);
+ }
+ else if (!packet.body.find("BYE"))
+ {
+ handle_BYE(conn,packet);
+ }
+ else if(!packet.body.find("MSNSLP/1.0 603 Decline") || !packet.body.find("MSNSLP/1.0 603 DECLINE"))
+ {
+ handle_603Decline(conn,packet);
+ }
+/* std::cout << "session id: " << packet.p2pHeader.sessionID << std::endl;
+ std::cout << "identifier: " << packet.p2pHeader.identifier << std::endl;
+ std::cout << "dataOffset: " << packet.p2pHeader.dataOffset << std::endl;
+ std::cout << "totalDataSize: " << packet.p2pHeader.totalDataSize << std::endl;
+ std::cout << "messageLength: " << packet.p2pHeader.messageLength << std::endl;
+ std::cout << "flag: " << packet.p2pHeader.flag << std::endl;
+ std::cout << "ackID: " << packet.p2pHeader.ackID << std::endl;
+ std::cout << "ackUID: " << packet.p2pHeader.ackUID << std::endl;
+ std::cout << "ackDataSize: " << packet.p2pHeader.ackDataSize << std::endl;
+ std::cout << "footer: " << packet.p2pFooter.appID << std::endl << std::endl;
+*/
+ }
+
+ void P2P::sendACK(MSN::SwitchboardServerConnection &conn, p2pPacket &packet, p2pSession &session)
+ {
+ p2pPacket ack_pkt;
+
+ std::ostringstream msghdr;
+ std::ostringstream footer;
+ std::ostringstream header;
+ std::ostringstream full_msg;
+
+ session.currentIdentifier++;
+ if(session.currentIdentifier == session.baseIdentifier) // skip the original identifier
+ session.currentIdentifier++;
+
+ // assembly the ack packet
+ ack_pkt.p2pHeader.sessionID = packet.p2pHeader.sessionID;
+ ack_pkt.p2pHeader.identifier = session.currentIdentifier;
+ ack_pkt.p2pHeader.dataOffset = 0;
+ ack_pkt.p2pHeader.totalDataSize = packet.p2pHeader.totalDataSize;
+ ack_pkt.p2pHeader.messageLength = 0;
+ ack_pkt.p2pHeader.flag = FLAG_ACK;
+ ack_pkt.p2pHeader.ackID = packet.p2pHeader.identifier;
+ ack_pkt.p2pHeader.ackUID = packet.p2pHeader.ackID;
+ ack_pkt.p2pHeader.ackDataSize = packet.p2pHeader.totalDataSize;
+
+ ack_pkt.p2pFooter.appID = APP_NONE;
+
+ msghdr <<"MIME-Version: 1.0\r\n"
+ "Content-Type: application/x-msnmsgrp2p\r\n"
+ "P2P-Dest: " << conn.users.front() << "\r\n\r\n";
+
+ header.write((char*)&ack_pkt.p2pHeader.sessionID, sizeof(ack_pkt.p2pHeader.sessionID));
+ header.write((char*)&ack_pkt.p2pHeader.identifier, sizeof(ack_pkt.p2pHeader.identifier));
+ header.write((char*)&ack_pkt.p2pHeader.dataOffset, sizeof(ack_pkt.p2pHeader.dataOffset));
+ header.write((char*)&ack_pkt.p2pHeader.totalDataSize, sizeof(ack_pkt.p2pHeader.totalDataSize));
+ header.write((char*)&ack_pkt.p2pHeader.messageLength, sizeof(ack_pkt.p2pHeader.messageLength));
+ header.write((char*)&ack_pkt.p2pHeader.flag, sizeof(ack_pkt.p2pHeader.flag));
+ header.write((char*)&ack_pkt.p2pHeader.ackID, sizeof(ack_pkt.p2pHeader.ackID));
+ header.write((char*)&ack_pkt.p2pHeader.ackUID, sizeof(ack_pkt.p2pHeader.ackUID));
+ header.write((char*)&ack_pkt.p2pHeader.ackDataSize, sizeof(ack_pkt.p2pHeader.ackDataSize));
+
+ footer.write((char*)&ack_pkt.p2pFooter.appID,sizeof(ack_pkt.p2pFooter.appID));
+
+ full_msg << msghdr.str() << header.str() << footer.str();
+
+ std::ostringstream buf_;
+ buf_ << "MSG " << conn.trID++ << " D " << full_msg.str().size() << "\r\n";
+ buf_ << full_msg.str();
+
+ if (conn.write(buf_) != buf_.str().size())
+ return;
+/* std::cout << "session id: " << ack_pkt.p2pHeader.sessionID << std::endl;
+ std::cout << "identifier: " << ack_pkt.p2pHeader.identifier << std::endl;
+ std::cout << "dataOffset: " << ack_pkt.p2pHeader.dataOffset << std::endl;
+ std::cout << "totalDataSize: " << ack_pkt.p2pHeader.totalDataSize << std::endl;
+ std::cout << "messageLength: " << ack_pkt.p2pHeader.messageLength << std::endl;
+ std::cout << "flag: " << ack_pkt.p2pHeader.flag << std::endl;
+ std::cout << "ackID: " << ack_pkt.p2pHeader.ackID << std::endl;
+ std::cout << "ackUID: " << ack_pkt.p2pHeader.ackUID << std::endl;
+ std::cout << "ackDataSize: " << ack_pkt.p2pHeader.ackDataSize << std::endl;
+ std::cout << "footer: " << ack_pkt.p2pFooter.appID << std::endl << std::endl;
+*/
+
+ }
+
+ void P2P::receiveP2PData(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+ // check if there is no session
+ if(!startedSessions.count(packet.p2pHeader.sessionID))
+ return;
+
+ p2pSession session = startedSessions[packet.p2pHeader.sessionID];
+ if(!session.in_stream && STEP_RECEIVING_FINISHED)
+ return;
+
+ if(!session.in_stream->is_open())
+ {
+ startedSessions[packet.p2pHeader.sessionID].totalDataSize = packet.p2pHeader.totalDataSize;
+ session.in_stream->open(session.filename.c_str(), std::ios::binary);
+ }
+
+ if(packet.body.length())
+ session.in_stream->write(packet.body.c_str(), packet.body.length());
+
+ // notify upper layer the current progress
+ if(session.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferProgress(&conn, session.sessionID,session.in_stream->tellp(), packet.p2pHeader.totalDataSize);
+
+ if((unsigned int)packet.p2pHeader.totalDataSize <= session.in_stream->tellp())
+ {
+ session.in_stream->close();
+ session.step = STEP_RECEIVING_FINISHED;
+ delete session.in_stream; // end of line
+ session.in_stream=NULL;
+ sendACK(conn, packet, session);
+ startedSessions[packet.p2pHeader.sessionID]=session;
+
+ if(session.appID == APP_DISPLAY_PICTURE ||
+ session.appID == APP_DISPLAY_PICTURE2)
+ {
+ conn.myNotificationServer()->externalCallbacks.gotContactDisplayPicture(&conn, conn.users.front(), session.filename );
+ }
+ else
+ {
+ switch(session.typeTransfer)
+ {
+ case APP_VOICE_CLIP:
+ libmsn_Siren7_DecodeVoiceClip(session.filename);
+ conn.myNotificationServer()->externalCallbacks.gotVoiceClipFile(&conn, session.sessionID, session.filename);
+ break;
+ case APP_EMOTICON:
+ conn.myNotificationServer()->externalCallbacks.gotEmoticonFile(&conn, session.sessionID, session.emoticonAlias, session.filename);
+ break;
+ case APP_WINK:
+ conn.myNotificationServer()->externalCallbacks.gotWinkFile(&conn, session.sessionID, session.filename);
+ break;
+ }
+ if(session.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferSucceeded(&conn, session.sessionID);
+ }
+
+ if(session.appID != APP_FILE_TRANSFER)
+ {
+ send_BYE(conn, packet, session);
+ this->addCallback(&P2P::handle_BYEACK, session.sessionID, packet.p2pHeader.ackID);
+ }
+ }
+ }
+
+ void P2P::sendP2PData(MSN::SwitchboardServerConnection &conn, p2pSession &session, p2pPacket &packet)
+ {
+ p2pPacket pkt_part = session.tempPacket;
+ char part[1202];
+ std::ostringstream msghdr;
+ std::ostringstream footer;
+ std::ostringstream header;
+ std::ostringstream full_msg;
+
+ msghdr <<"MIME-Version: 1.0\r\n"
+ "Content-Type: application/x-msnmsgrp2p\r\n"
+ "P2P-Dest: " << conn.users.front() << "\r\n\r\n";
+ if(session.tempPacket.p2pHeader.ackID==0) // it means.. first packet
+ {
+ session.currentIdentifier++;
+ if(session.currentIdentifier == session.baseIdentifier) // skip the original identifier
+ session.currentIdentifier++;
+
+ session.tempPacket.p2pHeader.sessionID = session.sessionID;
+ session.tempPacket.p2pHeader.identifier = session.currentIdentifier;
+
+ if(session.appID == APP_FILE_TRANSFER)
+ session.tempPacket.p2pHeader.flag = FLAG_FILE_DATA;
+ else
+ session.tempPacket.p2pHeader.flag = FLAG_DATA_PICTURE;
+
+ session.tempPacket.p2pHeader.dataOffset = 0;
+ session.tempPacket.p2pHeader.totalDataSize = FileSize(session.filename.c_str());
+ session.tempPacket.p2pHeader.messageLength = 0;
+ session.tempPacket.p2pHeader.ackUID = 0;
+ session.tempPacket.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ session.tempPacket.p2pHeader.ackDataSize=0;
+ // swap to big endian
+ session.tempPacket.p2pFooter.appID = little2big_endian(session.appID);
+ // scheduling the action to do when it is finished
+ this->addCallback(&P2P::handle_DataACK, session.sessionID, session.tempPacket.p2pHeader.ackID);
+ }
+
+ pkt_part = session.tempPacket;
+ if(!session.out_stream)
+ return;
+
+ if(!session.out_stream->is_open())
+ session.out_stream->open(session.filename.c_str(), std::ios::binary);
+
+ pkt_part.p2pHeader.dataOffset = session.out_stream->tellg();
+ session.out_stream->read(part, 1100);
+
+ if(!session.out_stream->gcount())// nothing to read, go away
+ {
+ session.out_stream->close();
+ delete session.out_stream;
+ session.out_stream = NULL;
+ startedSessions[session.sessionID]=session;
+ if(session.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferSucceeded(&conn, session.sessionID);
+ return;
+ }
+
+ pkt_part.p2pHeader.messageLength = session.out_stream->gcount();
+
+ if(session.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferProgress(&conn, session.sessionID, pkt_part.p2pHeader.dataOffset, pkt_part.p2pHeader.totalDataSize);
+
+ std::string a(part, pkt_part.p2pHeader.messageLength);
+ std::istringstream temp_msg(a);
+
+ header.write((char*)&pkt_part.p2pHeader.sessionID, sizeof(pkt_part.p2pHeader.sessionID));
+ header.write((char*)&pkt_part.p2pHeader.identifier, sizeof(pkt_part.p2pHeader.identifier));
+ header.write((char*)&pkt_part.p2pHeader.dataOffset, sizeof(pkt_part.p2pHeader.dataOffset));
+ header.write((char*)&pkt_part.p2pHeader.totalDataSize, sizeof(pkt_part.p2pHeader.totalDataSize));
+ header.write((char*)&pkt_part.p2pHeader.messageLength, sizeof(pkt_part.p2pHeader.messageLength));
+ header.write((char*)&pkt_part.p2pHeader.flag, sizeof(pkt_part.p2pHeader.flag));
+ header.write((char*)&pkt_part.p2pHeader.ackID, sizeof(pkt_part.p2pHeader.ackID));
+ header.write((char*)&pkt_part.p2pHeader.ackUID, sizeof(pkt_part.p2pHeader.ackUID));
+ header.write((char*)&pkt_part.p2pHeader.ackDataSize, sizeof(pkt_part.p2pHeader.ackDataSize));
+
+ footer.write((char*)&pkt_part.p2pFooter.appID,sizeof(pkt_part.p2pFooter.appID));
+
+ full_msg << msghdr.str() << header.str() << temp_msg.str() << footer.str();
+
+ std::ostringstream buf_;
+ buf_ << "MSG " << conn.trID << " D " << full_msg.str().size() << "\r\n";
+ buf_ << full_msg.str();
+
+ if (conn.write(buf_) != buf_.str().size())
+ return;
+
+ session.tempPacket = pkt_part;
+
+ startedSessions[session.sessionID]=session;
+ // call callback_continueTransfer when ack for this packet is received
+ conn.addP2PCallback(&SwitchboardServerConnection::callback_continueTransfer, conn.trID++, session.sessionID);
+ }
+
+ void P2P::sendP2PPacket(MSN::SwitchboardServerConnection &conn, p2pPacket &packet, p2pSession &session)
+ {
+ std::ostringstream msghdr;
+ std::istringstream msg(packet.body);
+ std::ostringstream footer;
+
+ if(session.to.empty())
+ session.to = conn.users.front();
+
+ msghdr <<"MIME-Version: 1.0\r\n"
+ "Content-Type: application/x-msnmsgrp2p\r\n"
+ "P2P-Dest: " << conn.users.front() << "\r\n\r\n";
+
+ footer.write((char*)&packet.p2pFooter.appID,sizeof(packet.p2pFooter.appID));
+
+ session.currentIdentifier++;
+ if(session.currentIdentifier == session.baseIdentifier) // skip the original identifier
+ session.currentIdentifier++;
+
+ packet.p2pHeader.identifier = session.currentIdentifier;
+
+ // split big messages in many packets
+ char temp_buf[1201];
+ while(!msg.eof())
+ {
+ std::ostringstream header;
+ std::ostringstream full_msg;
+ packet.p2pHeader.dataOffset = msg.tellg();
+ msg.read(temp_buf,1200);
+
+ if(msg.gcount()==0)// nothing to read, go away
+ break;
+
+ packet.p2pHeader.totalDataSize = msg.str().size();
+ packet.p2pHeader.messageLength = msg.gcount();
+
+ std::string a(temp_buf, msg.gcount());
+ std::istringstream temp_msg(a);
+
+ header.write((char*)&packet.p2pHeader.sessionID, sizeof(packet.p2pHeader.sessionID));
+ header.write((char*)&packet.p2pHeader.identifier, sizeof(packet.p2pHeader.identifier));
+ header.write((char*)&packet.p2pHeader.dataOffset, sizeof(packet.p2pHeader.dataOffset));
+ header.write((char*)&packet.p2pHeader.totalDataSize, sizeof(packet.p2pHeader.totalDataSize));
+ header.write((char*)&packet.p2pHeader.messageLength, sizeof(packet.p2pHeader.messageLength));
+ header.write((char*)&packet.p2pHeader.flag, sizeof(packet.p2pHeader.flag));
+ header.write((char*)&packet.p2pHeader.ackID, sizeof(packet.p2pHeader.ackID));
+ header.write((char*)&packet.p2pHeader.ackUID, sizeof(packet.p2pHeader.ackUID));
+ header.write((char*)&packet.p2pHeader.ackDataSize, sizeof(packet.p2pHeader.ackDataSize));
+
+ full_msg << msghdr.str() << header.str() << temp_msg.str() << footer.str();
+
+ std::ostringstream buf_;
+ buf_ << "MSG " << conn.trID++ << " D " << full_msg.str().size() << "\r\n";
+ buf_ << full_msg.str();
+
+ if (conn.write(buf_) != buf_.str().size())
+ return;
+ }
+ }
+
+ void P2P::handle_session_changes(MSN::SwitchboardServerConnection &conn, p2pPacket &packet, p2pSession &session)
+ {
+ std::string body;
+ std::vector<std::string> msg = splitString(packet.body, "\r\n\r\n");
+ msg[1]+="\r\n"; // it is really needed :(
+ Message::Headers header_slp = Message::Headers(msg[0]);
+ Message::Headers header_app = Message::Headers(msg[1]);
+ switch(session.appID)
+ {
+ case APP_FILE_TRANSFER:
+ {
+ session.CSeq = decimalFromString(header_slp["CSeq"]);
+ session.Bridges = header_app["Bridges"];
+ session.NetID = decimalFromString(header_app["NetID"]);
+ session.ConnType = header_app["Conn-Type"];
+ session.ICF = header_app["ICF"];
+ session.UPnPNat = header_app["UPnPNat"];
+ session.Listening = header_app["Listening"];
+
+ session.IPv4InternalAddrs = header_app["IPv4Internal-Addrs"];
+ session.IPv4InternalPort = header_app["IPv4Internal-Port"];
+ session.IPv4ExternalAddrs = header_app["IPv4External-Addrs"];
+ session.IPv4ExternalPort = header_app["IPv4External-Port"];
+
+ if(session.step == STEP_RECEIVING)
+ {
+ return;
+ }
+
+ // direct connection, sending client is waiting connection.
+ if(session.Listening == "true")
+ {
+/* // TODO - implement this part
+ bool a;
+ unsigned int port = decimalFromString(session.IPv4ExternalPort);
+ session.fileTransfer = new FileTransferConnectionP2P(conn, session);
+ if(!session.fileTransfer)
+ return;
+
+ session.fileTransfer->setDirection(FileTransferConnectionP2P::MSNFTP_RECV);
+ session.fileTransfer->setPerspective(FileTransferConnectionP2P::MSNFTP_CLIENT);
+ session.fileTransfer->sock = conn.myNotificationServer()->externalCallbacks.connectToServer(session.IPv4ExternalAddrs, port, &a);
+ conn.addFileTransferConnectionP2P(session.fileTransfer);
+
+ if (session.fileTransfer->sock < 0)
+ {
+ // if not possible to connect, stop
+ return;
+ }
+ std::ostringstream body2;
+ char b=4;
+ body2.write(&b,1);
+ body2.write("foo\0",4);
+
+ conn.myNotificationServer()->externalCallbacks.registerSocket(session.fileTransfer->sock,1,1);
+ session.fileTransfer->write(body2.str());*/
+ }
+ else if (conn.myNotificationServer()->direct_connection)
+ {
+ // direct connection, we are waiting connection.
+ // direct_connection means we are directly connected
+ // to the internet
+ body= "Bridge: TCPv1\r\n"
+ "Listening: true\r\n"
+ "Nonce: {00000000-0000-0000-0000-000000000000}\r\n";
+ }
+ else
+ {
+ // switchboard file transfer, the slowest mode
+ body= "Bridge: TCPv1\r\n"
+ "Listening: false\r\n"
+ "Nonce: {00000000-0000-0000-0000-000000000000}\r\n";
+ }
+
+ send_200OK(conn, session, body);
+ }
+ }
+ }
+
+ void P2P::handle_INVITE(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+ p2pSession session;
+ std::vector<std::string> msg = splitString(packet.body, "\r\n\r\n");
+ msg[1]+="\r\n"; // this is really needed :(
+ Message::Headers header_slp = Message::Headers(msg[0]);
+ Message::Headers header_app = Message::Headers(msg[1]);
+
+ session.to = header_slp["From"];
+ session.to = splitString(header_slp["From"], ":")[1];
+ session.to = splitString(session.to, ">")[0];
+ session.from = header_slp["To"];
+ session.from = splitString(header_slp["To"], ":")[1];
+ session.from = splitString(session.from, ">")[0];
+
+ session.Via = header_slp["Via"];
+ session.CSeq = decimalFromString(header_slp["CSeq"]);
+ session.CallID = header_slp["Call-ID"];
+ session.ContentType = header_slp["Content-Type"];
+
+ std::map<unsigned int, p2pSession>::iterator i = startedSessions.begin();
+ for(; i != startedSessions.end(); i++)
+ {
+ if((*i).second.CallID == session.CallID)
+ {
+ // this isn't a new session, since I already have this callid
+ p2pSession old_session = (*i).second;
+ sendACK(conn, packet, session);
+ old_session.Via = session.Via;
+ old_session.CSeq = session.CSeq;
+ old_session.ContentType = session.ContentType;
+ // handle the changes received in this invitation packet
+ handle_session_changes(conn, packet, old_session);
+ return;
+ }
+ }
+ //session.fromPassport = packet.fromPassport;
+ session.sessionID = decimalFromString(header_app["SessionID"]);
+ session.appID = decimalFromString(header_app["AppID"]);
+ session.Context = header_app["Context"];
+
+ // new connection goes below
+ session.out_stream = new std::ifstream;
+ session.tempPacket.p2pHeader.ackID=0;
+ session.in_stream = NULL;
+ session.currentIdentifier = rand()%0x8FFFFFF0 + rand_helper++;
+ session.baseIdentifier = session.currentIdentifier; // we need to keep this one
+ sendACK(conn, packet, session);
+ session.baseIdentifier++;
+ session.step = STEP_ACK_INVITATION_SENT;
+
+ switch(session.appID)
+ {
+ case APP_WEBCAM:
+ {
+ if(header_app["EUF-GUID"] == "{4BD96FC0-AB17-4425-A14A-439185962DC8}")
+ {
+ //conn.myNotificationServer()->externalCallbacks.askWebCam(&conn, session.sessionID);
+ std::string body("SessionID: "+ toStr(session.sessionID) +"\r\n");
+ send_200OK(conn, session, body);
+ }
+ if(header_app["EUF-GUID"] == "{1C9AA97E-9C05-4583-A3BD-908A196F1E92}")
+ {
+ //conn.myNotificationServer()->externalCallbacks.askWebCam(&conn, session.sessionID);
+ }
+ break;
+ }
+ case APP_EMOTICON:
+ case APP_DISPLAY_PICTURE:
+ case APP_DISPLAY_PICTURE2:
+ case APP_VOICE_CLIP:
+ {
+ // I dont know why, just following the rules.
+ // I think this is the better place to do this
+ session.currentIdentifier-=4;
+
+ std::string body("SessionID: "+ toStr(session.sessionID) +"\r\n");
+ send_200OK(conn,session,body); // always accept display picture
+ break;
+ }
+ case APP_FILE_TRANSFER:
+ {
+ session.currentIdentifier-=1;
+ session.sending=false;
+ startedSessions[session.sessionID]=session;
+ std::istringstream context(b64_decode(session.Context.c_str()), std::ios::binary);
+
+ std::string preview;
+ unsigned int header_size;
+ unsigned int type;
+ bool has_preview =true;
+
+ context.read((char*)&header_size, sizeof(unsigned int));
+
+ context.seekg(0, std::ios::beg);
+ context.seekg(16);
+ context.read((char*)&type, sizeof(unsigned int));
+
+ context.seekg(0, std::ios::end);
+ // type == 1 means no preview
+ if(header_size != context.tellg() && type != 1)
+ has_preview=true;
+
+ context.seekg(0, std::ios::beg);
+ context.seekg(19);
+
+ U8 *filenameutf16 = new U8[520];
+ U8 *filenameutf8 = new U8[520];
+ context.read((char*)filenameutf16, 520);
+ _ucs2_utf8(filenameutf8, filenameutf16, 520);
+ std::string filename((char*)filenameutf8);
+ free(filenameutf16);
+ free(filenameutf8);
+
+ unsigned long long filesize;
+ context.seekg(8);
+ context.read((char*)&filesize, sizeof(unsigned long long));
+
+ if(has_preview)
+ {
+ context.seekg(header_size);
+ int size2 = b64_decode(session.Context.c_str()).size() - header_size;
+ char *a = new char[size2];
+ context.read((char*)a, size2);
+ preview = b64_encode(a,size2);
+ free(a);
+ }
+ fileTransferInvite ft;
+ ft.type = type;
+ ft.sessionId = session.sessionID;
+ ft.userPassport = conn. users.front();
+ ft.filename = filename;
+ ft.filesize = filesize;
+ ft.preview = preview;
+
+ conn.myNotificationServer()->externalCallbacks.askFileTransfer(&conn, ft);
+ return;
+ }
+ }
+ }
+
+ void P2P::handle_200OK(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+ p2pSession session;
+ std::vector<std::string> msg = splitString(packet.body, "\r\n\r\n");
+ msg[1]+="\r\n"; // this is really needed :(
+ Message::Headers header_slp = Message::Headers(msg[0]);
+ Message::Headers header_app = Message::Headers(msg[1]);
+
+ unsigned int tmp_session = decimalFromString(header_app["SessionID"]);
+
+ if(!tmp_session)
+ return;
+
+ // we need to ensure we have a started session
+ if(!startedSessions.count(tmp_session))
+ return;
+
+ session = startedSessions[tmp_session];
+
+ sendACK(conn, packet, session);
+ if(session.appID == APP_FILE_TRANSFER)
+ {
+ sendP2PData(conn, session, packet);
+ conn.myNotificationServer()->externalCallbacks.fileTransferInviteResponse(&conn, tmp_session, true);
+ }
+ }
+
+ void P2P::handle_603Decline(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+ p2pSession session;
+ std::vector<std::string> msg = splitString(packet.body, "\r\n\r\n");
+ msg[1]+="\r\n"; // this is really needed :(
+ Message::Headers header_slp = Message::Headers(msg[0]);
+ Message::Headers header_app = Message::Headers(msg[1]);
+
+ unsigned int tmp_session = decimalFromString(header_app["SessionID"]);
+
+ if(!tmp_session)
+ return;
+
+ // we need to ensure we have a started session
+ if(!startedSessions.count(tmp_session))
+ return;
+
+ session = startedSessions[tmp_session];
+
+ conn.myNotificationServer()->externalCallbacks.fileTransferInviteResponse(&conn, tmp_session, false);
+ }
+
+ void P2P::handle_BYE(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+ p2pSession session;
+ std::vector<std::string> msg = splitString(packet.body, "\r\n\r\n");
+ msg[1]+="\r\n"; // this is really needed :(
+ Message::Headers header_slp = Message::Headers(msg[0]);
+ Message::Headers header_app = Message::Headers(msg[1]);
+
+ session.to = header_slp["From"];
+ session.to = splitString(header_slp["From"], ":")[1];
+ session.to = splitString(session.to, ">")[0];
+ session.from = header_slp["To"];
+ session.from = splitString(header_slp["To"], ":")[1];
+ session.from = splitString(session.from, ">")[0];
+
+ session.CSeq = decimalFromString(header_slp["CSeq"]);
+ session.CallID = header_slp["Call-ID"];
+ session.Via = header_slp["Via"];
+
+ session.sessionID = decimalFromString(header_app["SessionID"]);
+ session.appID = decimalFromString(header_app["AppID"]);
+ session.Context = header_app["Context"];
+
+ std::map<unsigned int, p2pSession>::iterator i = startedSessions.begin();
+ for(; i != startedSessions.end(); i++)
+ {
+ if((*i).second.CallID == session.CallID)
+ {
+ sendACK(conn, packet, (*i).second);
+ if((*i).second.in_stream &&
+ (unsigned int)(*i).second.totalDataSize > (*i).second.in_stream->tellp())
+ {
+ if((*i).second.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferFailed(&conn, (*i).second.sessionID, MSN::FILE_TRANSFER_ERROR_USER_CANCELED);
+ }
+ if(!(*i).second.in_stream && (*i).second.appID == APP_FILE_TRANSFER)
+ {
+ if((*i).second.appID == APP_FILE_TRANSFER)
+ conn.myNotificationServer()->externalCallbacks.fileTransferFailed(&conn, (*i).second.sessionID, MSN::FILE_TRANSFER_ERROR_USER_CANCELED);
+ }
+ if((*i).second.in_stream)
+ {
+ if((*i).second.in_stream->is_open())
+ (*i).second.in_stream->close();
+
+ delete (*i).second.in_stream;
+ (*i).second.in_stream = NULL;
+ }
+ startedSessions.erase((*i).second.sessionID);
+ return;
+ }
+ }
+ }
+
+ void P2P::handle_p2pACK(MSN::SwitchboardServerConnection &conn, p2pPacket &packet)
+ {
+
+ if (!this->callbacks.empty() && packet.p2pHeader.ackUID > 0)
+ {
+ if (this->callbacks.find(packet.p2pHeader.ackUID) != this->callbacks.end())
+ {
+ (this->*(this->callbacks[packet.p2pHeader.ackUID].first))(conn,this->callbacks[packet.p2pHeader.ackUID].second, packet);
+ }
+ }
+ }
+
+ void P2P::send_200OK(MSN::SwitchboardServerConnection &conn, p2pSession &session, std::string body)
+ {
+ p2pPacket packet;
+
+ std::ostringstream body2;
+ body2.write("\0",1);
+ std::string body_final("\r\n"+body+body2.str());
+
+ if(session.ContentType == "application/x-msnmsgr-transreqbody")
+ session.ContentType="application/x-msnmsgr-transrespbody";
+
+ std::string content("MSNSLP/1.0 200 OK\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: "+ toStr(++session.CSeq) + "\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: "+session.ContentType +"\r\n"
+ "Content-Length: "+ toStr(body_final.length())+ "\r\n"
+ +body_final);
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+
+ sendP2PPacket(conn, packet, session);
+
+ session.step = STEP_200OK_SENT;
+
+ startedSessions[session.sessionID]=session;
+
+ this->addCallback(&P2P::handle_200OKACK, session.sessionID, packet.p2pHeader.ackID);
+ }
+
+ void P2P::send_BYE(MSN::SwitchboardServerConnection &conn, p2pPacket &packet, p2pSession &session)
+ {
+ std::ostringstream body;
+ body.write("\r\n\0",3);
+ std::string content("BYE MSNMSGR:"+session.to+" MSNSLP/1.0\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: 0\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionclosebody\r\n"
+ "Content-Length: "+ toStr(body.str().size())+ "\r\n"
+ +body.str());
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+
+ sendP2PPacket(conn, packet, session);
+
+ session.step = STEP_BYE_SENT;
+
+ startedSessions[session.sessionID]=session;
+
+// this->addCallback(&P2P::handle_200OKACK, session.sessionID, packet.p2pHeader.ackID);
+ }
+
+
+ void P2P::send_603Decline(MSN::SwitchboardServerConnection &conn, p2pSession &session)
+ {
+ p2pPacket packet;
+
+ std::ostringstream body2;
+ body2.write("\0",1);
+ std::string body("\r\nSessionID: "+ toStr(session.sessionID)+"\r\n"+body2.str());
+ std::string content("MSNSLP/1.0 603 Decline\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: "+ toStr(++session.CSeq) + "\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
+ "Content-Length: "+ toStr(body.length())+ "\r\n"
+ +body);
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+
+ sendP2PPacket(conn, packet, session);
+
+ session.step = STEP_603DECLINE_SENT;
+
+ startedSessions[session.sessionID]=session;
+
+ this->addCallback(&P2P::handle_603DeclineACK, session.sessionID, packet.p2pHeader.ackID);
+ }
+
+
+ void P2P::addCallback(P2PCallbacks callback, unsigned int sessionID, unsigned int ackID)
+ {
+ this->callbacks[ackID] = std::make_pair(callback,sessionID);
+ }
+
+ void P2P::removeCallback(unsigned int ackID)
+ {
+ this->callbacks.erase(ackID);
+ }
+
+ void P2P::handle_603DeclineACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ this->removeCallback(packet.p2pHeader.ackUID);
+ startedSessions.erase(sessionID);
+ }
+
+ void P2P::handle_200OKACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ p2pPacket pkt_prep;
+
+ this->removeCallback(packet.p2pHeader.ackUID);
+ if (startedSessions.find(sessionID) == startedSessions.end())
+ {
+ return;
+ }
+ p2pSession session = startedSessions[sessionID];
+ session.step = STEP_200OK_ACK_SENT;
+
+ switch(session.appID)
+ {
+ case APP_EMOTICON:
+ case APP_WEBCAM:
+ case APP_DISPLAY_PICTURE:
+ case APP_DISPLAY_PICTURE2:
+ case APP_VOICE_CLIP:
+ {
+ pkt_prep.p2pHeader.sessionID = sessionID;
+ pkt_prep.p2pHeader.flag = FLAG_NOP;
+ pkt_prep.p2pHeader.identifier = session.currentIdentifier;
+ pkt_prep.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ pkt_prep.p2pHeader.ackUID = 0;
+ pkt_prep.p2pHeader.ackDataSize = 0;
+ // big endian
+ pkt_prep.p2pFooter.appID = little2big_endian(session.appID);
+
+ std::ostringstream content;
+ content.write("\0\0\0\0",4);
+ pkt_prep.body = content.str();
+
+ sendP2PPacket(conn, pkt_prep, session);
+ session.step = STEP_DATA_PREPARATION_SENT;
+ session.typeTransfer = (p2pTransferObj)session.appID;
+
+ startedSessions[sessionID]=session;
+
+ this->addCallback(&P2P::handle_DataPreparationACK, session.sessionID, pkt_prep.p2pHeader.ackID);
+ break;
+ }
+ case APP_FILE_TRANSFER:
+ {
+ // great, on 200OK from file transfer the packet does not
+ // have appID
+ // We should wait now an inviting for direct connection
+ }
+ }
+ }
+
+ void P2P::handle_DataPreparationACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ this->removeCallback(packet.p2pHeader.ackUID);
+ p2pSession session = startedSessions[sessionID];
+ session.step = STEP_SENDING;
+ std::string filepath;
+ filepath += b64_decode(session.Context.c_str()); // prevents empty context
+ if(filepath.length())
+ {
+ if(!conn.myNotificationServer()->msnobj.getMSNObjectRealPath(b64_decode(session.Context.c_str()), session.filename))
+ {
+ send_603Decline(conn,session);
+ return;
+ }
+ }
+ else
+ {
+ send_603Decline(conn,session);
+ return;
+ }
+ sendP2PData(conn, session, packet);
+ }
+
+ void P2P::handle_MSGACKReceived(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string fromPassport)
+ {
+ p2pPacket packet;
+ if(startedSessions.find(sessionID) == startedSessions.end())
+ return;
+
+ p2pSession session = startedSessions[sessionID];
+ sendP2PData(conn, session, packet);
+ }
+
+ void P2P::handle_fileTransferResponse(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, bool response)
+ {
+ p2pSession session = startedSessions[sessionID];
+ session.filename = filename;
+ if(response) // user accepted
+ {
+ session.in_stream = new std::ofstream;
+ std::string body("SessionID: "+ toStr(session.sessionID) +"\r\n");
+ send_200OK(conn, session, body);
+ }
+ else // user rejected
+ {
+ // I dont want to receive your file, blergh
+ send_603Decline(conn,session);
+ }
+ }
+
+ void P2P::handle_DataACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ this->removeCallback(packet.p2pHeader.ackUID);
+
+ p2pPacket pkt_bye;
+
+ std::string branch = new_branch();
+
+ p2pSession session = startedSessions[sessionID];
+ session.step = STEP_DATA_TRANSFER_ACK;
+
+ std::ostringstream body;
+ body.write("\r\n\0",3);
+ std::string content("BYE MSNMSGR:"+session.to+" MSNSLP/1.0\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: MSNSLP/1.0/TLP ;branch="+branch+"\r\n"
+ "CSeq: 0\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionclosebody\r\n"
+ "Content-Length: "+ toStr(body.str().length())+ "\r\n"
+ +body.str());
+
+ pkt_bye.p2pHeader.sessionID = 0;
+ pkt_bye.p2pHeader.identifier = session.currentIdentifier;
+ pkt_bye.p2pHeader.flag = FLAG_NOP;
+ pkt_bye.p2pHeader.dataOffset = 0;
+ pkt_bye.p2pHeader.totalDataSize = content.length();
+ pkt_bye.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ pkt_bye.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ pkt_bye.p2pHeader.ackUID = 0;
+ pkt_bye.p2pHeader.ackDataSize=0;
+
+ pkt_bye.body = content;
+
+ pkt_bye.p2pFooter.appID = APP_NONE;
+
+ sendP2PPacket(conn, pkt_bye, session);
+
+ session.step = STEP_BYE_SENT;
+
+ startedSessions[session.sessionID]=session;
+
+ this->addCallback(&P2P::handle_BYEACK, session.sessionID, pkt_bye.p2pHeader.ackID);
+ }
+
+ void P2P::handle_BYEACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ this->removeCallback(packet.p2pHeader.ackUID);
+ }
+
+ void P2P::requestDisplayPicture(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, std::string msnobject)
+ {
+ p2pSession session;
+ session.Context = b64_encode(msnobject.c_str(), msnobject.size());
+ session.CSeq = 0;
+ session.sessionID = sessionID;
+ session.filename = filename;
+ session.CallID = new_branch();
+ session.to = conn.users.front() ;
+ session.from = conn.myNotificationServer()->myPassport;
+ session.currentIdentifier = rand()%0x8FFFFFF0 + rand_helper++;
+ session.baseIdentifier = session.currentIdentifier;
+ session.Via = "MSNSLP/1.0/TLP ;branch=";
+ session.Via+= new_branch();
+ session.appID = APP_DISPLAY_PICTURE2;
+ p2pPacket packet;
+ std::ostringstream body2;
+ body2.write("\0",1);
+ std::string body("\r\n"
+ "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6}\r\n"
+ "SessionID: "+ toStr(session.sessionID)+"\r\n"
+ "AppID: 1\r\n"
+ "Context: " + session.Context + "\r\n"+body2.str());
+ std::string content("INVITE MSNMSGR:"+ session.to +" MSNSLP/1.0\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: "+ toStr(session.CSeq++) + "\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
+ "Content-Length: "+ toStr(body.length())+ "\r\n"
+ +body);
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+
+ session.in_stream = new std::ofstream;
+
+ sendP2PPacket(conn, packet, session);
+
+ session.currentIdentifier = session.currentIdentifier - 3;
+
+ startedSessions[session.sessionID]=session;
+ }
+
+ void P2P::requestFile(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, std::string msnobject, p2pTransferObj obj)
+ {
+ p2pSession session;
+ if(startedSessions.find(sessionID) != startedSessions.end())
+ session = startedSessions[sessionID];
+
+ session.Context = b64_encode(msnobject.c_str(), msnobject.size());
+ session.CSeq = 0;
+ session.sessionID = sessionID;
+ session.filename = filename;
+ session.CallID = new_branch();
+ session.to = conn.users.front() ;
+ session.from = conn.myNotificationServer()->myPassport;
+ session.currentIdentifier = rand()%0x8FFFFFF0 + rand_helper++;
+ session.baseIdentifier = session.currentIdentifier;
+ session.Via = "MSNSLP/1.0/TLP ;branch=";
+ session.Via+= new_branch();
+ session.typeTransfer = obj;
+
+ p2pPacket packet;
+ std::ostringstream body2;
+ body2.write("\0",1);
+ std::string body("\r\n"
+ "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6}\r\n"
+ "SessionID: "+ toStr(session.sessionID)+"\r\n"
+ "AppID: 1\r\n"
+ "Context: " + session.Context + "\r\n"+body2.str());
+ std::string content("INVITE MSNMSGR:"+ session.to +" MSNSLP/1.0\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: "+ toStr(session.CSeq++) + "\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
+ "Content-Length: "+ toStr(body.length())+ "\r\n"
+ +body);
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+
+ session.in_stream = new std::ofstream;
+
+ sendP2PPacket(conn, packet, session);
+
+ session.currentIdentifier = session.currentIdentifier - 3;
+
+ startedSessions[session.sessionID]=session;
+ }
+
+ void P2P::requestEmoticon(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, std::string msnobject, std::string alias)
+ {
+ p2pSession session;
+ session.emoticonAlias = alias;
+ startedSessions[sessionID]=session;
+ requestFile(conn, sessionID, filename, msnobject, APP_EMOTICON);
+ }
+
+ void P2P::requestVoiceClip(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, std::string msnobject)
+ {
+ requestFile(conn, sessionID, filename, msnobject, APP_VOICE_CLIP);
+ }
+
+ void P2P::requestWink(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, std::string filename, std::string msnobject)
+ {
+ requestFile(conn, sessionID, filename, msnobject, APP_WINK);
+ }
+
+ void P2P::handle_INVITE_ACK(MSN::SwitchboardServerConnection &conn, unsigned int sessionID, p2pPacket &packet)
+ {
+ }
+
+ std::string build_file_transfer_context(MSN::fileTransferInvite ft)
+ {
+ std::ostringstream context;
+ unsigned int hlength=0x27E;
+ unsigned int msnversion=0x03;
+ unsigned long long filesize = FileSize(ft.filename.c_str());
+ unsigned int type = ft.type;
+ char filename[520];
+ char unknown1[30];
+ unsigned int unknown2 = (ft.type == FILE_TRANSFER_BACKGROUND_SHARING) ||
+ (ft.type == FILE_TRANSFER_BACKGROUND_SHARING_CUSTOM) ? 0xFFFFFE : 0xFFFFFF ;
+ char unknown3[64];
+
+ memset(&filename,0,520);
+ memset(&unknown1,0,30);
+ memset(&unknown3,0,64);
+
+ // TODO - convert filename to ucs2
+ U8 *filenameutf8 = new U8[520];
+ U8 *filenameutf16 = new U8[521];
+ memset(filenameutf8, 0, 520);
+ memset(filenameutf16, 0, 521);
+ memcpy(filenameutf8, ft.friendlyname.c_str(), ft.friendlyname.size());
+ _utf8_ucs2(filenameutf16, filenameutf8);
+ filenameutf16++;
+
+ context.write((char*)&hlength, sizeof(unsigned int));
+ context.write((char*)&msnversion, sizeof(unsigned int));
+ context.write((char*)&filesize, sizeof(unsigned long long));
+ context.write((char*)&type, sizeof(unsigned int));
+ context.write((char*)filenameutf16, 520);
+ context.write((char*)&unknown1, 30);
+ context.write((char*)&unknown2, sizeof(unsigned int));
+ context.write((char*)&unknown3, 64);
+
+ free(--filenameutf16);
+ free(filenameutf8);
+
+ if(ft.type == FILE_TRANSFER_WITH_PREVIEW && ft.preview.size())
+ context.write((char*)b64_decode(ft.preview.c_str()).c_str(), b64_decode(ft.preview.c_str()).size());
+
+ return b64_encode(context.str().c_str(), context.str().size());
+ }
+
+ void P2P::sendFile(MSN::SwitchboardServerConnection &conn, MSN::fileTransferInvite ft)
+ {
+ p2pSession session;
+ session.Context = build_file_transfer_context(ft);
+ session.CSeq = 0;
+ session.sessionID = ft.sessionId;
+ session.filename = ft.filename;
+ session.CallID = new_branch();
+ session.to = conn.users.front();
+ session.from = conn.myNotificationServer()->myPassport;
+ session.currentIdentifier = rand()%0x8FFFFFF0 + rand_helper++;
+ session.baseIdentifier = session.currentIdentifier;
+ session.Via = "MSNSLP/1.0/TLP ;branch=";
+ session.Via+= new_branch();
+ session.tempPacket.p2pHeader.ackID=0;
+ session.in_stream = NULL;
+
+ p2pPacket packet;
+ std::ostringstream body2;
+ body2.write("\0",1);
+ std::string other_passport = conn.users.front();
+ std::string body("\r\n"
+ "EUF-GUID: {5D3E02AB-6190-11D3-BBBB-00C04F795683}\r\n"
+ "SessionID: "+ toStr(session.sessionID)+"\r\n"
+ "SChannelState: 0\r\n"
+ "Capabilities-Flags: 1\r\n"
+ "AppID: 2\r\n"
+ "Context: " + session.Context + "\r\n"+body2.str());
+ std::string content("INVITE MSNMSGR:"+ other_passport +" MSNSLP/1.0\r\n"
+ "To: <msnmsgr:"+session.to+">\r\n"
+ "From: <msnmsgr:"+session.from+">\r\n"
+ "Via: "+session.Via+"\r\n"
+ "CSeq: "+ toStr(session.CSeq++) + "\r\n"
+ "Call-ID: "+session.CallID+"\r\n"
+ "Max-Forwards: 0\r\n"
+ "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
+ "Content-Length: "+ toStr(body.length())+ "\r\n"
+ +body);
+
+ packet.p2pHeader.sessionID = 0;
+ packet.p2pHeader.identifier = session.currentIdentifier;
+ packet.p2pHeader.flag = FLAG_NOP;
+ packet.p2pHeader.dataOffset = 0;
+ packet.p2pHeader.totalDataSize = content.length();
+ packet.p2pHeader.messageLength = 0; // filled inside sendP2PPacket()
+ packet.p2pHeader.ackID = rand()%0x8FFFFFF0 + rand_helper++;
+ packet.p2pHeader.ackUID = 0;
+ packet.p2pHeader.ackDataSize=0;
+
+ packet.body = content;
+
+ packet.p2pFooter.appID = APP_NONE;
+ session.appID = APP_FILE_TRANSFER;
+
+ session.out_stream = new std::ifstream;
+
+ sendP2PPacket(conn, packet, session);
+
+ startedSessions[session.sessionID]=session;
+ }
+
+ void P2P::sendInk(MSN::SwitchboardServerConnection &conn, std::string image)
+ {
+ std::list<Passport>::iterator i = conn.users.begin();
+ // for each user
+
+ }
+ void P2P::cancelTransfer(MSN::SwitchboardServerConnection &conn, unsigned int sessionID)
+ {
+ p2pSession session;
+ p2pPacket packet;
+ if(startedSessions.find(sessionID) == startedSessions.end())
+ return;
+
+ session = startedSessions[sessionID];
+ send_BYE(conn, packet, session);
+ startedSessions.erase(sessionID);
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnp2ph"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/p2p.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,322 @@
</span><ins>+#ifndef __msn_p2p_h__
+#define __msn_p2p_h__
+/*
+ * p2p.h
+ * libmsn
+ *
+ * Crated by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <msn/connection.h>
+#include <msn/authdata.h>
+#include <msn/errorcodes.h>
+#include <msn/buddy.h>
+#include <msn/passport.h>
+#include <msn/util.h>
+#include <stdexcept>
+
+#include <vector>
+#include <fstream>
+#include <iostream>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class SwitchboardServerConnection;
+ class FileTransferConnectionP2P;
+
+ /** Manages all p2p communication.
+ */
+ class LIBMSN_EXPORT P2P
+ {
+ public:
+ P2P();
+ virtual ~P2P();
+ unsigned int rand_helper;
+ enum {
+ DIRECTION_SENDING = 0,
+ DIRECTION_RECEIVING = 1
+ };
+ enum {
+ STEP_INVITATION_SENT,
+ STEP_ACK_INVITATION_SENT,
+ STEP_200OK_SENT,
+ STEP_200OK_ACK_SENT,
+ STEP_603DECLINE_SENT,
+ STEP_603DECLINE_ACK_SENT,
+ STEP_DC_INVITE_SENT, // direct connection
+ STEP_DC_INVITE_ACK_SENT, // direct connection
+ STEP_DC_200OK_SENT,
+ STEP_DC_200OKACK_SENT,
+ STEP_DATA_PREPARATION_SENT,
+ STEP_DATA_PREPARATION_ACK,
+ STEP_SENDING,
+ STEP_RECEIVING,
+ STEP_RECEIVING_FINISHED,
+ STEP_DATA_TRANSFER_ACK,
+ STEP_BYE_SENT,
+ STEP_BYE_ACK
+ };
+ typedef enum {
+ APP_NONE = 0,
+ APP_WEBCAM = 4,
+ APP_FILE_TRANSFER = 2,
+ APP_DISPLAY_PICTURE = 1,
+ APP_EMOTICON = 11,
+ APP_DISPLAY_PICTURE2 = 12, // MSNP15 uses 12 instead 1
+ APP_VOICE_CLIP = 20, // MSNP15 uses 12 instead 1
+ APP_WINK = 98, // non standard
+ APP_INK = 99 // non standard
+ } p2pTransferObj;
+ enum {
+ FLAG_NOP = 0x0,
+ FLAG_ACK = 0x2,
+ FLAG_ERROR = 0x8,
+ FLAG_DATA_EMOTICONS = 0x20,
+ FLAG_DATA_PICTURE = 0x20,
+ FLAG_FILE_DATA = 0x01000030,
+ FLAG_FILE_DATA2 = 0x01000020
+ };
+
+ struct p2pPacket {
+ struct {
+ unsigned int sessionID;
+ unsigned int identifier;
+ unsigned long long dataOffset;
+ unsigned long long totalDataSize;
+ unsigned int messageLength;
+ unsigned int flag;
+ unsigned int ackID;
+ unsigned int ackUID;
+ unsigned long long ackDataSize;
+ }p2pHeader;
+ std::string body;
+ struct {
+ unsigned int appID;
+ }p2pFooter;
+
+ p2pPacket() {
+ p2pHeader.sessionID = 0;
+ p2pHeader.identifier = 0;
+ p2pHeader.dataOffset = 0;
+ p2pHeader.totalDataSize = 0;
+ p2pHeader.messageLength = 0;
+ p2pHeader.flag = 0;
+ p2pHeader.ackID = 0;
+ p2pHeader.ackUID = 0;
+ p2pHeader.ackDataSize = 0;
+ p2pFooter.appID = 0;
+ }
+ };
+
+ struct p2pSession {
+ bool sending; // sending or receiving, if sending, so true
+ unsigned long long totalDataSize;
+ unsigned int step; // step at the moment
+ unsigned int currentIdentifier;
+ unsigned int baseIdentifier; // baseIdentifier
+ unsigned int CSeq;
+ unsigned int sessionID;
+ unsigned int appID;
+ MSN::FileTransferConnectionP2P *fileTransfer;
+ std::string from;
+ std::string to;
+ std::string CallID;
+ std::string Via;
+ std::string ContentType;
+ std::string Context; // can be the file preview or msnobject
+ std::string filename; // filename to transfer
+ std::ifstream *out_stream; // file to send
+ std::ofstream *in_stream; // file to receive
+ std::string ConnType;
+ std::string Bridges;
+ std::string NetID;
+ std::string UPnPNat;
+ std::string Listening;
+ std::string ICF;
+ std::string IPv4InternalAddrs;
+ std::string IPv4InternalPort;
+ std::string IPv4ExternalAddrs;
+ std::string IPv4ExternalPort;
+ p2pTransferObj typeTransfer;
+ std::string emoticonAlias;
+
+ p2pPacket tempPacket; // this is used for general purposes
+ std::string ink;
+
+ p2pSession() {
+ sending = false;
+ totalDataSize = 0;
+ step = 0;
+ currentIdentifier = 0;
+ baseIdentifier = 0;
+ CSeq = 0;
+ sessionID = 0;
+ appID = 0;
+ fileTransfer = 0;
+ out_stream = 0;
+ in_stream = 0;
+ typeTransfer = APP_NONE;
+ }
+ };
+
+ typedef void (P2P::*P2PCallbacks)(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ std::map<unsigned int, std::pair<P2PCallbacks, unsigned int> > callbacks;
+
+ virtual void addCallback(P2PCallbacks, unsigned int sessionID,
+ unsigned int ackID);
+
+ virtual void removeCallback(unsigned int ackID);
+
+ std::map<unsigned int, p2pPacket> pendingP2PMsg;
+ std::map<unsigned int, p2pSession> startedSessions;
+
+ void sendFile(MSN::SwitchboardServerConnection &conn,
+ MSN::fileTransferInvite ft);
+
+ void handleP2Pmessage(MSN::SwitchboardServerConnection &conn,
+ std::vector<std::string> & args,
+ std::string mime, std::string body);
+
+ void sendACK(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet,
+ p2pSession &session);
+
+ void sendP2PPacket(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet,
+ p2pSession &session);
+
+ void sendP2PData(MSN::SwitchboardServerConnection &conn,
+ p2pSession &session,
+ p2pPacket &packet);
+
+ void receiveP2PData(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_negotiation(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_INVITE(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_603Decline(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_INVITE_ACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_200OK(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_BYE(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void send_200OK(MSN::SwitchboardServerConnection &conn,
+ p2pSession &session,
+ std::string body);
+
+ void send_BYE(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet,
+ p2pSession &session);
+
+ void send_603Decline(MSN::SwitchboardServerConnection &conn,
+ p2pSession &session);
+
+ void handle_p2pACK(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet);
+
+ void handle_200OKACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_603DeclineACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_DataPreparationACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_DataACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_BYEACK(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ p2pPacket &packet);
+
+ void handle_MSGACKReceived(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string fromPassport);
+
+ void handle_fileTransferResponse(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ bool response);
+
+ void handle_session_changes(MSN::SwitchboardServerConnection &conn,
+ p2pPacket &packet,
+ p2pSession &session);
+
+ void requestFile(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject,
+ p2pTransferObj obj);
+
+ void requestDisplayPicture(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject);
+
+ void sendInk(MSN::SwitchboardServerConnection &conn,
+ std::string image);
+
+ void cancelTransfer(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID);
+
+ void requestEmoticon(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject,
+ std::string alias);
+
+ void requestVoiceClip(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject);
+
+ void requestWink(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject);
+
+ void requestInk(MSN::SwitchboardServerConnection &conn,
+ unsigned int sessionID,
+ std::string filename,
+ std::string msnobject);
+ };
+}
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnpassportcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+/*
+ * passport.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Thu May 20 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/passport.h>
+#include <stdio.h>
+
+namespace MSN
+{
+ void Passport::validate()
+ {
+ if (email.find(" ") != std::string::npos)
+ throw InvalidPassport("Passport must not contain any spaces!");
+
+ if (email.find("@") == std::string::npos || email.find("@") != email.rfind("@"))
+ throw InvalidPassport("Passport must contain exactly one '@' character!");
+
+ if (email.find("@") == 0)
+ throw InvalidPassport("Passport must have at least one character before the '@'!");
+
+ if (email.find(".", email.find("@")) == std::string::npos)
+ throw InvalidPassport("Passport must have at least one '.' after the '@'!");
+
+ if (email.find(".", email.find("@")) - email.find("@") < 2)
+ throw InvalidPassport("Passport must have at least one character between the '@' and the '.'!");
+
+ if (email[email.size() - 1] == '.')
+ throw InvalidPassport("Passport must not end with a '.' character!");
+
+ if (email.size() < 5)
+ throw InvalidPassport("Passport must contain at least 5 characters!");
+ }
+
+ Passport::operator std::string() const
+ {
+ return email;
+ }
+
+ const char *Passport::c_str() const
+ {
+ return email.c_str();
+ }
+}
+
+std::ostream & operator <<(std::ostream & os, const MSN::Passport & passport)
+{
+ return os << std::string(passport);
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnpassporth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/passport.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+#ifndef __msn_passport_h__
+#define __msn_passport_h__
+
+/*
+ * passport.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Thu May 20 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <stdexcept>
+#include <iostream>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ /** An InvalidPassport exception will be thrown whenever
+ * a malformed passport is passed to a function that requires
+ * a valid address.
+ */
+ class InvalidPassport : public std::runtime_error
+ {
+public:
+ InvalidPassport(std::string err) : std::runtime_error(err) {};
+ };
+
+ /** A Passport represents a passport address. It is used to
+ * validate these addresses for functions that require it.
+ *
+ * @todo Document validation rules.
+ * @todo Investigate subclassing std::string to reduce code duplication.
+ */
+ class LIBMSN_EXPORT Passport
+ {
+public:
+ Passport(std::string email_) : email(email_) { validate(); };
+ Passport(const char *email_) : email(std::string(email_)) { validate(); };
+ Passport() : email("") {};
+
+ operator std::string() const;
+ const char *c_str() const;
+ bool operator ==(const Passport & other) const { return this->email == other.email; };
+
+ friend bool operator ==(const Passport & p, const std::string & other) { return p.email == other; };
+ friend bool operator ==(const std::string & other, const Passport & p) { return p.email == other; };
+ friend std::istream& operator >>(std::istream & is, Passport & p) { is >> p.email; p.validate(); return is; }
+ friend std::ostream& operator <<(std::ostream & os, Passport & p) { os << p.email; p.validate(); return os; }
+private:
+ void validate();
+ std::string email;
+ };
+}
+
+std::ostream & operator << (std::ostream & os, const MSN::Passport& passport);
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnsoapcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,2696 @@
</span><ins>+/*
+ * soap.cpp
+ * libmsn
+ *
+ * Crated by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+
+#include <msn/notificationserver.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/md5.h>
+#include <msn/util.h>
+#include <msn/soap.h>
+
+#include <cctype>
+#include <iostream>
+#include <algorithm>
+#include <string.h>
+
+#include "xmlParser.h"
+
+namespace MSN {
+ std::map<int,std::string> Soap::actionDomains;
+ std::map<int,std::string> Soap::actionPOSTURLs;
+ std::map<int,std::string> Soap::actionURLs;
+
+ Soap::Soap(NotificationServerConnection & _myNotificationServer) :
+ Connection(),
+ notificationServer(_myNotificationServer)
+ {
+ fillURLs();
+ }
+
+ Soap::Soap(NotificationServerConnection & _myNotificationServer, std::vector<sitesToAuth> _sitesToAuthList) :
+ Connection(),
+ notificationServer(_myNotificationServer),
+ sitesToAuthList(_sitesToAuthList)
+ {
+ fillURLs();
+ }
+
+ void Soap::requestSoapAction(soapAction action,std::string xml_body, std::string &xml_response)
+ {
+ this->action = action;
+
+ std::string full_msg;
+
+ full_msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+
+ full_msg.append(this->request_body);
+
+ std::string http_header("POST "+actionPOSTURLs[action]+" HTTP/1.1\r\n");
+ if(action != AUTH)
+ {
+ http_header.append("SOAPAction: "+actionURLs[action]+"\r\n");
+ }
+ http_header.append(
+ "Accept: */*\r\n"
+ "Content-Type: text/xml; charset=utf-8\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Proxy-Connection: Keep-Alive\r\n"
+ "Connection: Keep-Alive\r\n"
+ "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Windows Live Messenger 8.1.0178)\r\n"
+ "Host: "+actionDomains[action]+"\r\n"
+ "Content-Length: " +toStr(full_msg.length()) +"\r\n\r\n"
+ );
+
+ if ((this->sock = this->myNotificationServer()->externalCallbacks.connectToServer(actionDomains[action], 443, &this->connected, true)) == NULL)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "Could not connect to server");
+ return;
+ }
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0, 1, true);
+
+ if (this->connected)
+ this->socketConnectionCompleted();
+
+ std::ostringstream buf_;
+ buf_ << http_header << full_msg;
+ if(this->write(buf_) != buf_.str().size())
+ return;
+
+ this->myNotificationServer()->addSoapConnection(this);
+
+ }
+
+ void Soap::setMBI(std::string MBI)
+ {
+ this->mbi = MBI;
+ for(unsigned int d=0; d< sitesToAuthList.size(); d++)
+ {
+ // we just receive this MBI at connection time
+ if(sitesToAuthList[d].url=="messengerclear.live.com")
+ sitesToAuthList[d].URI=MBI;
+ }
+ }
+
+ void Soap::fillURLs()
+ {
+ sitesToAuth sta;
+
+ actionDomains[AUTH] = "login.live.com";
+ actionDomains[GET_LISTS] = "by5.omega.contacts.msn.com";
+ actionDomains[GET_ADDRESS_BOOK] = "by5.omega.contacts.msn.com";
+ actionDomains[ADD_CONTACT_TO_LIST] = "by5.omega.contacts.msn.com";
+ actionDomains[DEL_CONTACT_FROM_LIST] = "by5.omega.contacts.msn.com";
+ actionDomains[DEL_CONTACT_FROM_ADDRESSBOOK] = "by5.omega.contacts.msn.com";
+ actionDomains[ADD_CONTACT_TO_ADDRESSBOOK] = "by5.omega.contacts.msn.com";
+ actionDomains[DISABLE_CONTACT_ON_ADDRESSBOOK] = "by5.omega.contacts.msn.com";
+ actionDomains[ENABLE_CONTACT_ON_ADDRESSBOOK] = "by5.omega.contacts.msn.com";
+ actionDomains[ADD_GROUP] = "by5.omega.contacts.msn.com";
+ actionDomains[DEL_GROUP] = "by5.omega.contacts.msn.com";
+ actionDomains[RENAME_GROUP] = "by5.omega.contacts.msn.com";
+ actionDomains[BLOCK_CONTACT] = "";
+ actionDomains[UNBLOCK_CONTACT] = "";
+ actionDomains[ADD_CONTACT_TO_GROUP] = "by5.omega.contacts.msn.com";
+ actionDomains[DEL_CONTACT_FROM_GROUP] ="by5.omega.contacts.msn.com";
+ actionDomains[UPDATE_GROUP] = "";
+ actionDomains[GENERATE_LOCKKEY] = "ows.messenger.msn.com";
+ actionDomains[RETRIEVE_OIM_MAIL_DATA] = "rsi.hotmail.com";
+ actionDomains[RETRIEVE_OIM] = "rsi.hotmail.com";
+ actionDomains[DELETE_OIM] = "rsi.hotmail.com";
+ actionDomains[SEND_OIM] = "ows.messenger.msn.com";
+ actionDomains[CHANGE_DISPLAYNAME] = "by5.omega.contacts.msn.com";
+
+ actionPOSTURLs[AUTH] = "/RST.srf";
+ actionPOSTURLs[GET_LISTS] = "/abservice/SharingService.asmx";
+ actionPOSTURLs[GET_ADDRESS_BOOK] = "/abservice/abservice.asmx";
+ actionPOSTURLs[ADD_CONTACT_TO_LIST] = "/abservice/SharingService.asmx";
+ actionPOSTURLs[DEL_CONTACT_FROM_LIST] = "/abservice/SharingService.asmx";
+ actionPOSTURLs[DEL_CONTACT_FROM_ADDRESSBOOK] = "/abservice/abservice.asmx";
+ actionPOSTURLs[ADD_CONTACT_TO_ADDRESSBOOK] = "/abservice/abservice.asmx";
+ actionPOSTURLs[DISABLE_CONTACT_ON_ADDRESSBOOK] = "/abservice/abservice.asmx";
+ actionPOSTURLs[ENABLE_CONTACT_ON_ADDRESSBOOK] = "/abservice/abservice.asmx";
+ actionPOSTURLs[ADD_GROUP] = "/abservice/abservice.asmx";
+ actionPOSTURLs[DEL_GROUP] = "/abservice/abservice.asmx";
+ actionPOSTURLs[RENAME_GROUP] = "/abservice/abservice.asmx";
+ actionPOSTURLs[BLOCK_CONTACT] = "";
+ actionPOSTURLs[UNBLOCK_CONTACT] = "";
+ actionPOSTURLs[ADD_CONTACT_TO_GROUP] = "/abservice/abservice.asmx";
+ actionPOSTURLs[DEL_CONTACT_FROM_GROUP] ="/abservice/abservice.asmx";
+ actionPOSTURLs[UPDATE_GROUP] = "";
+ actionPOSTURLs[GENERATE_LOCKKEY] = "/OimWS/oim.asmx";
+ actionPOSTURLs[RETRIEVE_OIM_MAIL_DATA] = "/rsi/rsi.asmx";
+ actionPOSTURLs[RETRIEVE_OIM] = "/rsi/rsi.asmx";
+ actionPOSTURLs[DELETE_OIM] = "/rsi/rsi.asmx";
+ actionPOSTURLs[SEND_OIM] = "/OimWS/oim.asmx";
+ actionPOSTURLs[CHANGE_DISPLAYNAME] = "/abservice/abservice.asmx";
+
+ actionURLs[AUTH] = '\0';
+ actionURLs[GET_LISTS] = "http://www.msn.com/webservices/AddressBook/FindMembership";
+ actionURLs[GET_ADDRESS_BOOK] = "http://www.msn.com/webservices/AddressBook/ABFindAll";
+ actionURLs[ADD_CONTACT_TO_LIST] = "http://www.msn.com/webservices/AddressBook/AddMember";
+ actionURLs[DEL_CONTACT_FROM_LIST] = "http://www.msn.com/webservices/AddressBook/DeleteMember";
+ actionURLs[DEL_CONTACT_FROM_ADDRESSBOOK] = "http://www.msn.com/webservices/AddressBook/ABContactDelete";
+ actionURLs[ADD_CONTACT_TO_ADDRESSBOOK] = "http://www.msn.com/webservices/AddressBook/ABContactAdd";
+ actionURLs[DISABLE_CONTACT_ON_ADDRESSBOOK] = "http://www.msn.com/webservices/AddressBook/ABContactUpdate";
+ actionURLs[ENABLE_CONTACT_ON_ADDRESSBOOK] = "http://www.msn.com/webservices/AddressBook/ABContactUpdate";
+ actionURLs[DEL_CONTACT_FROM_LIST] = "http://www.msn.com/webservices/AddressBook/DeleteMember";
+ actionURLs[ADD_GROUP] = "http://www.msn.com/webservices/AddressBook/ABGroupAdd";
+ actionURLs[DEL_GROUP] = "http://www.msn.com/webservices/AddressBook/ABGroupDelete";
+ actionURLs[RENAME_GROUP] = "http://www.msn.com/webservices/AddressBook/ABGroupUpdate";
+ actionURLs[BLOCK_CONTACT] = "";
+ actionURLs[UNBLOCK_CONTACT] = "";
+ actionURLs[ADD_CONTACT_TO_GROUP] = "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd";
+ actionURLs[DEL_CONTACT_FROM_GROUP] ="http://www.msn.com/webservices/AddressBook/ABGroupContactDelete";
+ actionURLs[UPDATE_GROUP] = "";
+ actionURLs[GENERATE_LOCKKEY] = "http://messenger.live.com/ws/2006/09/oim/Store2";
+ actionURLs[RETRIEVE_OIM_MAIL_DATA] = "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata";
+ actionURLs[RETRIEVE_OIM] = "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage";
+ actionURLs[DELETE_OIM] = "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages";
+ actionURLs[SEND_OIM] = "http://messenger.live.com/ws/2006/09/oim/Store2";
+ actionURLs[CHANGE_DISPLAYNAME] = "http://www.msn.com/webservices/AddressBook/ABContactUpdate";
+
+ sta.url = "http://Passport.NET/tb";
+ sitesToAuthList.push_back(sta);
+ sta.url = "messengerclear.live.com";
+ sta.URI = ""; // this is filled later.
+ sitesToAuthList.push_back(sta);
+ sta.url = "messenger.msn.com";
+ sta.URI = "?id=507";
+ sitesToAuthList.push_back(sta);
+ sta.url = "contacts.msn.com";
+ sta.URI = "MBI";
+ sitesToAuthList.push_back(sta);
+ sta.url = "messengersecure.live.com";
+ sta.URI = "MBI_SSL";
+ sitesToAuthList.push_back(sta);
+ sta.url = "spaces.live.com";
+ sta.URI = "MBI";
+ sitesToAuthList.push_back(sta);
+ sta.url = "storage.msn.com";
+ sta.URI = "MBI";
+ sitesToAuthList.push_back(sta);
+
+ }
+
+ void Soap::getTickets(std::string Passport, std::string password, std::string policy)
+ {
+ this->passport = Passport;
+ this->password = password;
+ this->policy = policy;
+ XMLNode temp; //to general use
+ XMLNode envelope = XMLNode::createXMLTopNode("Envelope");
+ envelope.addAttribute("xmlns", "http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:wsse", "http://schemas.xmlsoap.org/ws/2003/06/secext");
+ envelope.addAttribute("xmlns:saml", "urn:oasis:names:tc:SAML:1.0:assertion");
+ envelope.addAttribute("xmlns:wsp", "http://schemas.xmlsoap.org/ws/2002/12/policy");
+ envelope.addAttribute("xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
+ envelope.addAttribute("xmlns:wsa", "http://schemas.xmlsoap.org/ws/2004/03/addressing");
+ envelope.addAttribute("xmlns:wssc","http://schemas.xmlsoap.org/ws/2004/04/sc");
+ envelope.addAttribute("xmlns:wst","http://schemas.xmlsoap.org/ws/2004/04/trust");
+ XMLNode header = XMLNode::createXMLTopNode("Header");
+ XMLNode authinfo = XMLNode::createXMLTopNode("ps:AuthInfo");
+ authinfo.addAttribute("xmlns:ps","http://schemas.microsoft.com/Passport/SoapServices/PPCRL");
+ authinfo.addAttribute("Id","PPAuthInfo");
+ temp = XMLNode::createXMLTopNode("ps:HostingApp");
+ temp.addText("{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}");
+ authinfo.addChild(temp);
+ temp = XMLNode::createXMLTopNode("ps:BinaryVersion");
+ temp.addText("4");
+ authinfo.addChild(temp);
+ temp = XMLNode::createXMLTopNode("ps:UIVersion");
+ temp.addText("1");
+ authinfo.addChild(temp);
+ temp = XMLNode::createXMLTopNode("ps:Cookies");
+ temp.addText("");
+ authinfo.addChild(temp);
+ temp = XMLNode::createXMLTopNode("ps:RequestParams");
+ temp.addText("AQAAAAIAAABsYwQAAAAxMDMz");
+ authinfo.addChild(temp);
+ header.addChild(authinfo);
+
+ XMLNode security = XMLNode::createXMLTopNode("wsse:Security");
+ XMLNode username = XMLNode::createXMLTopNode("wsse:UsernameToken");
+ username.addAttribute("Id","user");
+ temp = XMLNode::createXMLTopNode("wsse:Username");
+ temp.addText( Passport.c_str() );
+ username.addChild(temp);
+ temp = XMLNode::createXMLTopNode( "wsse:Password" );
+ temp.addText( password.c_str() );
+ username.addChild(temp);
+ security.addChild(username);
+ header.addChild(security);
+ envelope.addChild( header );
+
+ // BODY
+ XMLNode body = XMLNode::createXMLTopNode( "Body" );
+ XMLNode multipletokens = XMLNode::createXMLTopNode( "ps:RequestMultipleSecurityTokens" );
+ multipletokens.addAttribute("xmlns:ps","http://schemas.microsoft.com/Passport/SoapServices/PPCRL");
+ multipletokens.addAttribute("Id","RSTS");
+ XMLNode securitytoken;
+ XMLNode endpr;
+ XMLNode address;
+
+ // request tokens for each site
+ for (unsigned int i=0; i<sitesToAuthList.size(); i++)
+ {
+ securitytoken = XMLNode::createXMLTopNode("wst:RequestSecurityToken");
+ std::string RST = "RST";
+ RST=RST+toStr(i);
+ securitytoken.addAttribute("Id", RST.c_str() );
+ temp = XMLNode::createXMLTopNode( "wst:RequestType" );
+ temp.addText( "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue" );
+ securitytoken.addChild(temp);
+
+ temp = XMLNode::createXMLTopNode( "wsp:AppliesTo" );
+ endpr = XMLNode::createXMLTopNode("wsa:EndpointReference");
+ address = XMLNode::createXMLTopNode("wsa:Address");
+ address.addText( sitesToAuthList[i].url.c_str() );
+ endpr.addChild(address);
+ temp.addChild(endpr);
+ securitytoken.addChild(temp);
+ if(!sitesToAuthList[i].URI.empty())
+ {
+ XMLNode policyref = XMLNode::createXMLTopNode("wsse:PolicyReference");
+ policyref.addAttribute("URI", sitesToAuthList[i].URI.c_str());
+ policyref.addText( "" );
+ securitytoken.addChild(policyref);
+ }
+ multipletokens.addChild(securitytoken);
+ }
+
+ body.addChild(multipletokens);
+ envelope.addChild( body );
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(AUTH, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGetTicketsResponse(std::string response)
+ {
+ XMLNode domTree = XMLNode::parseString( response.c_str() );
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = domTree.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[AUTH] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->getTickets(this->passport, this->password, this->policy);
+ }
+ return;
+ }
+
+ // get the header information from the DOM
+ XMLNode tokens = domTree.getChildNode("S:Envelope").getChildNode("S:Body").getChildNode("wst:RequestSecurityTokenResponseCollection");
+ const char *reason = domTree.getChildNode("S:Envelope").getChildNode("S:Fault").getChildNode("faultcode").getText();
+ if(reason)
+ {
+ std::string reason1(reason);
+ if(reason1 == "wsse:FailedAuthentication")
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "Wrong Password");
+ this->myNotificationServer()->removeSoapConnection(this);
+ this->myNotificationServer()->disconnect();
+ return;
+ }
+ if(reason1 == "psf:Redirect")
+ {
+ const char *newurl = domTree.getChildNode("S:Envelope").getChildNode("S:Fault").getChildNode("psf:redirectUrl").getText();
+ Soap *soapConnection = new Soap(notificationServer);
+
+ std::string newurl1(newurl);
+ std::vector<std::string> a = splitString(newurl1, "/");
+ std::string newdomain = splitString(a[1], "/")[0];
+ soapConnection->actionDomains[AUTH] = newdomain;
+ std::vector<std::string> postpath = splitString(newurl1, newdomain);
+ soapConnection->actionPOSTURLs[AUTH] = postpath[1];
+ soapConnection->setMBI(mbi);
+
+ soapConnection->getTickets(passport,password,policy);
+ return;
+ }
+ }
+ int nItems = tokens.nChildNode("wst:RequestSecurityTokenResponse");
+
+ // fill sitesToAuthList the strucutre with tokens and binary secrets
+ for(int site=0; site< nItems; site++)
+ {
+ XMLNode a = tokens.getChildNode("wst:RequestSecurityTokenResponse",site);
+ const char *token1 = a.getChildNode("wst:RequestedProofToken").getChildNode("wst:BinarySecret").getText();
+ if(token1)
+ {
+ std::string c(token1);
+ sitesToAuthList[site].BinarySecret = c;
+ }
+ const char *token2 = a.getChildNode("wst:RequestedSecurityToken").getChildNode("wsse:BinarySecurityToken").getText();
+ if(token2)
+ {
+ std::string b(token2);
+ sitesToAuthList[site].BinarySecurityToken = b;
+ }
+ }
+ this->myNotificationServer()->gotTickets(*this, sitesToAuthList);
+ }
+
+ void Soap::enableContactOnAddressBook(std::string contactId, std::string passport, std::string myDisplayName)
+ {
+ this->contactId = contactId;
+ this->tempPassport = passport;
+ this->myDisplayName = myDisplayName;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("ContactSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABContactUpdate = XMLNode::createXMLTopNode( "ABContactUpdate" );
+ ABContactUpdate.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABContactUpdate.addChild(abId);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ Contact.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode contactId1 = XMLNode::createXMLTopNode( "contactId" );
+ contactId1.addText(contactId.c_str());
+ XMLNode contactInfo = XMLNode::createXMLTopNode( "contactInfo" );
+ XMLNode displayName = XMLNode::createXMLTopNode( "displayName" );
+ displayName.addText(passport.c_str());
+ XMLNode isMessengerUser = XMLNode::createXMLTopNode( "isMessengerUser" );
+ isMessengerUser.addText("true");
+ XMLNode MessengerMemberInfo = XMLNode::createXMLTopNode( "MessengerMemberInfo" );
+ XMLNode DisplayName = XMLNode::createXMLTopNode( "DisplayName" );
+ DisplayName.addText(myDisplayName.c_str());
+ MessengerMemberInfo.addChild(DisplayName);
+ contactInfo.addChild(displayName);
+ contactInfo.addChild(isMessengerUser);
+ contactInfo.addChild(MessengerMemberInfo);
+ XMLNode propertiesChanged = XMLNode::createXMLTopNode( "propertiesChanged" );
+ propertiesChanged.addText("DisplayName IsMessengerUser MessengerMemberInfo");
+ Contact.addChild(contactId1);
+ Contact.addChild(contactInfo);
+ Contact.addChild(propertiesChanged);
+ contacts.addChild(Contact);
+ ABContactUpdate.addChild(contacts);
+ body.addChild(ABContactUpdate);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(ENABLE_CONTACT_ON_ADDRESSBOOK, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseEnableContactOnAddressBookResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[ENABLE_CONTACT_ON_ADDRESSBOOK] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->enableContactOnAddressBook(this->contactId, this->tempPassport, this->myDisplayName);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotEnableContactOnAddressBookConfirmation(*this, true, newVersion, this->contactId, this->tempPassport);
+ }
+ else
+ {
+ this->myNotificationServer()->gotEnableContactOnAddressBookConfirmation(*this, false, "", this->contactId, this->tempPassport);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::delContactFromAddressBook(std::string contactId, std::string passport)
+ {
+ this->contactId = contactId;
+ this->tempPassport = passport;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("Timer");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABContactDelete = XMLNode::createXMLTopNode( "ABContactDelete" );
+ ABContactDelete.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABContactDelete.addChild(abId);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ XMLNode contactId1 = XMLNode::createXMLTopNode( "contactId" );
+ contactId1.addText(contactId.c_str());
+ Contact.addChild(contactId1);
+ contacts.addChild(Contact);
+ ABContactDelete.addChild(contacts);
+ body.addChild(ABContactDelete);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DEL_CONTACT_FROM_ADDRESSBOOK, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+
+ }
+
+ void Soap::parseDelContactFromAddressBookResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DEL_CONTACT_FROM_ADDRESSBOOK] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->delContactFromAddressBook(this->contactId, this->tempPassport);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotDelContactFromAddressBookConfirmation(*this, true, newVersion, this->contactId, this->tempPassport);
+ }
+ else
+ {
+ this->myNotificationServer()->gotDelContactFromAddressBookConfirmation(*this, false, "", this->contactId, this->tempPassport);
+ }
+ response1.deleteNodeContent();
+
+ }
+
+ void Soap::disableContactFromAddressBook(std::string contactId, std::string passport)
+ {
+ this->contactId = contactId;
+ this->tempPassport = passport;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("Timer");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABContactUpdate = XMLNode::createXMLTopNode( "ABContactUpdate" );
+ ABContactUpdate.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABContactUpdate.addChild(abId);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ Contact.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode contactId1 = XMLNode::createXMLTopNode( "contactId" );
+ contactId1.addText(contactId.c_str());
+ XMLNode contactInfo = XMLNode::createXMLTopNode( "contactInfo" );
+ XMLNode displayName = XMLNode::createXMLTopNode( "displayName" );
+ XMLNode isMessengerUser = XMLNode::createXMLTopNode( "isMessengerUser" );
+ isMessengerUser.addText("false");
+ contactInfo.addChild(displayName);
+ contactInfo.addChild(isMessengerUser);
+ XMLNode propertiesChanged = XMLNode::createXMLTopNode( "propertiesChanged" );
+ propertiesChanged.addText("DisplayName IsMessengerUser");
+ Contact.addChild(contactId1);
+ Contact.addChild(contactInfo);
+ Contact.addChild(propertiesChanged);
+ contacts.addChild(Contact);
+ ABContactUpdate.addChild(contacts);
+ body.addChild(ABContactUpdate);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DISABLE_CONTACT_ON_ADDRESSBOOK, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseDisableContactFromAddressBookResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DISABLE_CONTACT_ON_ADDRESSBOOK] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->disableContactFromAddressBook(this->contactId, this->tempPassport);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotDisableContactOnAddressBookConfirmation(*this, true, newVersion, this->contactId, this->tempPassport);
+ }
+ else
+ {
+ this->myNotificationServer()->gotDisableContactOnAddressBookConfirmation(*this, false, "", this->contactId, this->tempPassport);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::addContactToAddressBook(std::string passport, std::string displayName)
+ {
+ this->tempPassport = passport;
+ this->tempDisplayName = displayName;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("ContactSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABContactAdd = XMLNode::createXMLTopNode( "ABContactAdd" );
+ ABContactAdd.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABContactAdd.addChild(abId);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ Contact.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode contactInfo = XMLNode::createXMLTopNode( "contactInfo" );
+ XMLNode contactType = XMLNode::createXMLTopNode( "contactType" );
+ contactType.addText("Regular");
+ XMLNode passportName = XMLNode::createXMLTopNode( "passportName" );
+ passportName.addText(passport.c_str());
+ XMLNode isMessengerUser = XMLNode::createXMLTopNode( "isMessengerUser" );
+ isMessengerUser.addText("true");
+ XMLNode MessengerMemberInfo = XMLNode::createXMLTopNode( "MessengerMemberInfo" );
+ XMLNode DisplayName = XMLNode::createXMLTopNode( "DisplayName" );
+ DisplayName.addText(displayName.c_str());
+ MessengerMemberInfo.addChild(DisplayName);
+ contactInfo.addChild(contactType);
+ contactInfo.addChild(passportName);
+ contactInfo.addChild(isMessengerUser);
+ contactInfo.addChild(MessengerMemberInfo);
+ Contact.addChild(contactInfo);
+ contacts.addChild(Contact);
+ ABContactAdd.addChild(contacts);
+ XMLNode options = XMLNode::createXMLTopNode( "options" );
+ XMLNode EnableAllowListManagement = XMLNode::createXMLTopNode( "EnableAllowListManagement" );
+ EnableAllowListManagement.addText("true");
+ options.addChild(EnableAllowListManagement);
+ ABContactAdd.addChild(options);
+ body.addChild(ABContactAdd);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(ADD_CONTACT_TO_ADDRESSBOOK, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseAddContactToAddressBookResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[ADD_CONTACT_TO_ADDRESSBOOK] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->addContactToAddressBook(this->tempPassport, this->tempDisplayName);
+ }
+ return;
+ }
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ const char *guid = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("ABContactAddResponse").getChildNode("ABContactAddResult").getChildNode("guid").getText();
+ if(guid)
+ {
+ std::string newVersion(ver);
+ std::string newGuid(guid);
+ this->myNotificationServer()->gotAddContactToAddressBookConfirmation(*this, true, newVersion, this->tempPassport, this->tempDisplayName, newGuid);
+ }
+ }
+ else
+ {
+ this->myNotificationServer()->gotAddContactToAddressBookConfirmation(*this, false, "", this->tempPassport, this->tempDisplayName, "");
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::addContactToGroup(std::string groupId, std::string contactId)
+ {
+ this->groupId = groupId;
+ this->contactId = contactId;
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("GroupSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABGroupContactAdd = XMLNode::createXMLTopNode( "ABGroupContactAdd" );
+ ABGroupContactAdd.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABGroupContactAdd.addChild(abId);
+ XMLNode groupFilter = XMLNode::createXMLTopNode( "groupFilter" );
+ XMLNode groupIds = XMLNode::createXMLTopNode( "groupIds" );
+ XMLNode guid = XMLNode::createXMLTopNode( "guid" );
+ guid.addText(groupId.c_str());
+ groupIds.addChild(guid);
+ groupFilter.addChild(groupIds);
+ ABGroupContactAdd.addChild(groupFilter);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ XMLNode contactId1 = XMLNode::createXMLTopNode( "contactId" );
+ contactId1.addText(contactId.c_str());
+ Contact.addChild(contactId1);
+ contacts.addChild(Contact);
+ ABGroupContactAdd.addChild(contacts);
+ body.addChild(ABGroupContactAdd);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(ADD_CONTACT_TO_GROUP, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseAddContactToGroupResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[ADD_CONTACT_TO_GROUP] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->addContactToGroup(this->groupId, this->contactId);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotAddContactToGroupConfirmation(*this, true, newVersion, this->groupId, this->contactId);
+ }
+ else
+ {
+ this->myNotificationServer()->gotAddContactToGroupConfirmation(*this, false, "", this->groupId, this->contactId);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::addGroup(std::string groupName)
+ {
+ this->groupName = groupName;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("GroupSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABGroupAdd = XMLNode::createXMLTopNode( "ABGroupAdd" );
+ ABGroupAdd.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABGroupAdd.addChild(abId);
+ XMLNode groupAddOptions = XMLNode::createXMLTopNode( "groupAddOptions" );
+ XMLNode fRenameOnMsgrConflict = XMLNode::createXMLTopNode( "fRenameOnMsgrConflict" );
+ fRenameOnMsgrConflict.addText("false");
+ groupAddOptions.addChild(fRenameOnMsgrConflict);
+ ABGroupAdd.addChild(groupAddOptions);
+ XMLNode groupInfo = XMLNode::createXMLTopNode( "groupInfo" );
+ XMLNode GroupInfo = XMLNode::createXMLTopNode( "GroupInfo" );
+ XMLNode name = XMLNode::createXMLTopNode( "name" );
+ name.addText(groupName.c_str());
+ GroupInfo.addChild(name);
+ XMLNode groupType = XMLNode::createXMLTopNode( "groupType" );
+ groupType.addText("C8529CE2-6EAD-434d-881F-341E17DB3FF8");
+ GroupInfo.addChild(groupType);
+ XMLNode fMessenger = XMLNode::createXMLTopNode( "fMessenger" );
+ fMessenger.addText("false");
+ GroupInfo.addChild(fMessenger);
+ XMLNode annotations = XMLNode::createXMLTopNode( "annotations" );
+ XMLNode Annotation = XMLNode::createXMLTopNode( "Annotation" );
+ XMLNode Name = XMLNode::createXMLTopNode( "Name" );
+ Name.addText("MSN.IM.Display");
+ XMLNode Value = XMLNode::createXMLTopNode( "Value" );
+ Value.addText("1");
+ Annotation.addChild(Name);
+ Annotation.addChild(Value);
+ annotations.addChild(Annotation);
+ GroupInfo.addChild(annotations);
+ groupInfo.addChild(GroupInfo);
+ ABGroupAdd.addChild(groupInfo);
+ body.addChild(ABGroupAdd);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(ADD_GROUP, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseAddGroupResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[ADD_GROUP] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->addGroup(this->groupName);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ const char *guid = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("ABGroupAddResponse").getChildNode("ABGroupAddResult").getChildNode("guid").getText();
+ if(guid)
+ {
+ std::string newVersion(ver);
+ std::string newGuid(guid);
+ this->myNotificationServer()->gotAddGroupConfirmation(*this, true, newVersion, this->groupName, newGuid);
+ }
+ }
+ else
+ {
+ this->myNotificationServer()->gotAddGroupConfirmation(*this, false, "", this->groupName, "");
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::delGroup(std::string groupId)
+ {
+ this->groupId = groupId;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("GroupSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABGroupDelete = XMLNode::createXMLTopNode( "ABGroupDelete" );
+ ABGroupDelete.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABGroupDelete.addChild(abId);
+ XMLNode groupFilter = XMLNode::createXMLTopNode( "groupFilter" );
+ XMLNode groupIds = XMLNode::createXMLTopNode( "groupIds" );
+ XMLNode guid = XMLNode::createXMLTopNode( "guid" );
+ guid.addText(groupId.c_str());
+ groupIds.addChild(guid);
+ groupFilter.addChild(groupIds);
+ ABGroupDelete.addChild(groupFilter);
+ body.addChild(ABGroupDelete);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DEL_GROUP, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseDelGroupResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DEL_GROUP] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->delGroup(this->groupId);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotDelGroupConfirmation(*this, true, newVersion, this->groupId);
+ }
+ else
+ {
+ this->myNotificationServer()->gotDelGroupConfirmation(*this, false, "", this->groupId);
+ }
+
+ response1.deleteNodeContent();
+ }
+
+ void Soap::renameGroup(std::string groupId, std::string newGroupName)
+ {
+ this->groupId = groupId;
+ this->groupName = newGroupName;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("GroupSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABGroupUpdate = XMLNode::createXMLTopNode( "ABGroupUpdate" );
+ ABGroupUpdate.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABGroupUpdate.addChild(abId);
+ XMLNode groups = XMLNode::createXMLTopNode( "groups" );
+ XMLNode Group = XMLNode::createXMLTopNode( "Group" );
+ XMLNode groupId1 = XMLNode::createXMLTopNode( "groupId" );
+ groupId1.addText(groupId.c_str());
+ XMLNode groupInfo = XMLNode::createXMLTopNode( "groupInfo" );
+ XMLNode name = XMLNode::createXMLTopNode( "name" );
+ name.addText(newGroupName.c_str());
+ groupInfo.addChild(name);
+ XMLNode propertiesChanged = XMLNode::createXMLTopNode( "propertiesChanged" );
+ propertiesChanged.addText("GroupName");
+ Group.addChild(groupId1);
+ Group.addChild(groupInfo);
+ Group.addChild(propertiesChanged);
+ groups.addChild(Group);
+ ABGroupUpdate.addChild(groups);
+ body.addChild(ABGroupUpdate);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(RENAME_GROUP, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseRenameGroupResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[RENAME_GROUP] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->renameGroup(this->groupId, this->groupName);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotRenameGroupConfirmation(*this, true, newVersion, this->groupName, this->groupId);
+ }
+ else
+ {
+ this->myNotificationServer()->gotRenameGroupConfirmation(*this, false, "", this->groupName, this->groupId);
+ }
+ response1.deleteNodeContent();
+ }
+
+
+ void Soap::delContactFromGroup(std::string groupId, std::string contactId)
+ {
+ this->groupId = groupId;
+ this->contactId = contactId;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("GroupSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABGroupContactDelete = XMLNode::createXMLTopNode( "ABGroupContactDelete" );
+ ABGroupContactDelete.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText( "00000000-0000-0000-0000-000000000000" );
+ ABGroupContactDelete.addChild(abId);
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ XMLNode contactId1 = XMLNode::createXMLTopNode( "contactId" );
+ contactId1.addText(contactId.c_str());
+ Contact.addChild(contactId1);
+ contacts.addChild(Contact);
+ ABGroupContactDelete.addChild(contacts);
+ XMLNode groupFilter = XMLNode::createXMLTopNode( "groupFilter" );
+ XMLNode groupIds = XMLNode::createXMLTopNode( "groupIds" );
+ XMLNode guid = XMLNode::createXMLTopNode( "guid" );
+ guid.addText(groupId.c_str());
+ groupIds.addChild(guid);
+ groupFilter.addChild(groupIds);
+ ABGroupContactDelete.addChild(groupFilter);
+ body.addChild(ABGroupContactDelete);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DEL_CONTACT_FROM_GROUP, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseDelContactFromGroupResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DEL_CONTACT_FROM_GROUP] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->delContactFromGroup(this->groupId, this->contactId);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotDelContactFromGroupConfirmation(*this, true, newVersion, this->groupId, this->contactId);
+ }
+ else
+ {
+ this->myNotificationServer()->gotDelContactFromGroupConfirmation(*this, false, "", this->groupId, this->contactId);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::addContactToList(MSN::Passport passport, MSN::ContactList list)
+ {
+ this->tempPassport = passport;
+ this->tempList = list;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("ContactSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode AddMember = XMLNode::createXMLTopNode( "AddMember" );
+ AddMember.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode serviceHandle = XMLNode::createXMLTopNode( "serviceHandle" );
+ XMLNode Id = XMLNode::createXMLTopNode( "Id" );
+ Id.addText( "0" );
+ XMLNode Type = XMLNode::createXMLTopNode( "Type" );
+ Type.addText( "Messenger" );
+ XMLNode ForeignId = XMLNode::createXMLTopNode( "ForeignId" );
+ ForeignId.addText( "" );
+ serviceHandle.addChild(Id);
+ serviceHandle.addChild(Type);
+ serviceHandle.addChild(ForeignId);
+ AddMember.addChild(serviceHandle);
+ XMLNode memberships = XMLNode::createXMLTopNode( "memberships" );
+ XMLNode Membership = XMLNode::createXMLTopNode( "Membership" );
+ XMLNode MemberRole = XMLNode::createXMLTopNode( "MemberRole" );
+ switch(list)
+ {
+ case LST_AL:
+ MemberRole.addText("Allow");
+ break;
+ case LST_BL:
+ MemberRole.addText("Block");
+ break;
+ case LST_RL:
+ MemberRole.addText("Reverse");
+ break;
+ default:
+ return; // TODO - raise an error
+ }
+ XMLNode Members = XMLNode::createXMLTopNode( "Members" );
+ XMLNode Member = XMLNode::createXMLTopNode( "Member" );
+ Member.addAttribute("xsi:type","PassportMember");
+ Member.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ XMLNode Type2 = XMLNode::createXMLTopNode("Type");
+ Type2.addText("Passport");
+ XMLNode State = XMLNode::createXMLTopNode("State");
+ State.addText("Accepted");
+ XMLNode PassportName = XMLNode::createXMLTopNode("PassportName");
+ PassportName.addText(passport.c_str());
+ Member.addChild(Type2);
+ Member.addChild(State);
+ Member.addChild(PassportName);
+ Members.addChild(Member);
+ Membership.addChild(MemberRole);
+ Membership.addChild(Members);
+ memberships.addChild(Membership);
+ AddMember.addChild(memberships);
+ body.addChild(AddMember);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(ADD_CONTACT_TO_LIST, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseAddContactToListResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[ADD_CONTACT_TO_LIST] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->addContactToList(this->tempPassport, this->tempList);
+ }
+ return;
+ }
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotAddContactToListConfirmation(*this, true, newVersion, this->tempPassport, this->tempList);
+ }
+ else
+ {
+ this->myNotificationServer()->gotAddContactToListConfirmation(*this, false, "", this->tempPassport, this->tempList);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::removeContactFromList(MSN::Passport passport, MSN::ContactList list)
+ {
+ this->tempPassport = passport;
+ this->tempList = list;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false") ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText ("ContactSave");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode DeleteMember = XMLNode::createXMLTopNode( "DeleteMember" );
+ DeleteMember.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode serviceHandle = XMLNode::createXMLTopNode( "serviceHandle" );
+ XMLNode Id = XMLNode::createXMLTopNode( "Id" );
+ Id.addText( "0" );
+ XMLNode Type = XMLNode::createXMLTopNode( "Type" );
+ Type.addText( "Messenger" );
+ XMLNode ForeignId = XMLNode::createXMLTopNode( "ForeignId" );
+ Type.addText( "" );
+ serviceHandle.addChild(Id);
+ serviceHandle.addChild(Type);
+ serviceHandle.addChild(ForeignId);
+ DeleteMember.addChild(serviceHandle);
+ XMLNode memberships = XMLNode::createXMLTopNode( "memberships" );
+ XMLNode Membership = XMLNode::createXMLTopNode( "Membership" );
+ XMLNode MemberRole = XMLNode::createXMLTopNode( "MemberRole" );
+ switch(list)
+ {
+ case LST_AL:
+ MemberRole.addText("Allow");
+ break;
+ case LST_BL:
+ MemberRole.addText("Block");
+ break;
+ case LST_PL:
+ MemberRole.addText("Pending");
+ break;
+ default:
+ return; // TODO - raise an error
+ }
+ XMLNode Members = XMLNode::createXMLTopNode( "Members" );
+ XMLNode Member = XMLNode::createXMLTopNode( "Member" );
+ Member.addAttribute("xsi:type","PassportMember");
+ Member.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ XMLNode Type2 = XMLNode::createXMLTopNode("Type");
+ Type2.addText("Passport");
+ XMLNode State = XMLNode::createXMLTopNode("State");
+ State.addText("Accepted");
+ XMLNode PassportName = XMLNode::createXMLTopNode("PassportName");
+ PassportName.addText(passport.c_str());
+ Member.addChild(Type2);
+ Member.addChild(State);
+ Member.addChild(PassportName);
+ Members.addChild(Member);
+ Membership.addChild(MemberRole);
+ Membership.addChild(Members);
+ memberships.addChild(Membership);
+ DeleteMember.addChild(memberships);
+ body.addChild(DeleteMember);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DEL_CONTACT_FROM_LIST, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+
+ }
+
+ void Soap::parseRemoveContactFromListResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DEL_CONTACT_FROM_LIST] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->removeContactFromList(this->tempPassport, this->tempList);
+ }
+ return;
+ }
+
+
+ XMLNode version = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("Version");
+ const char *ver = version.getText();
+ if(ver)
+ {
+ std::string newVersion(ver);
+ this->myNotificationServer()->gotDelContactFromListConfirmation(*this, true, newVersion, this->tempPassport, this->tempList);
+ }
+ else
+ {
+ this->myNotificationServer()->gotDelContactFromListConfirmation(*this, false, "", this->tempPassport, this->tempList);
+ }
+ response1.deleteNodeContent();
+ }
+
+ void Soap::getLists(ListSyncInfo *data)
+ {
+ // info is used to to fill the lists with memebers
+ this->listInfo = data;
+
+ XMLNode envelope = XMLNode::createXMLTopNode( "soap:Envelope" );
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode( "soap:Header" );
+ header.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode abapphdr = XMLNode::createXMLTopNode( "ABApplicationHeader" );
+ abapphdr.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode( "ApplicationId" );
+ appid.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ appid.addText( "996CDE1E-AA53-4477-B943-2BE802EA6166" );
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode( "IsMigration" );
+ ismigration.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ ismigration.addText( "false" ) ;
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode( "PartnerScenario" );
+ scenario.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ scenario.addText ("Initial" );
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode( "ABAuthHeader" );
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode( "ManagedGroupRequest" );
+ ManagedGroupRequest.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ ManagedGroupRequest.addText( "false" );
+ XMLNode TicketToken = XMLNode::createXMLTopNode( "TicketToken" );
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ body.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode FindMembership = XMLNode::createXMLTopNode( "FindMembership" );
+ FindMembership.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode serviceFilter = XMLNode::createXMLTopNode( "serviceFilter" );
+ XMLNode Types = XMLNode::createXMLTopNode( "Types" );
+ XMLNode ServiceType = XMLNode::createXMLTopNode( "ServiceType" );
+ ServiceType.addText( "Messenger" );
+ Types.addChild(ServiceType);
+ ServiceType = XMLNode::createXMLTopNode( "ServiceType" );
+ ServiceType.addText( "Invitation" );
+ Types.addChild(ServiceType);
+ ServiceType = XMLNode::createXMLTopNode( "ServiceType" );
+ ServiceType.addText( "SocialNetwork" );
+ Types.addChild(ServiceType);
+ ServiceType = XMLNode::createXMLTopNode( "ServiceType" );
+ ServiceType.addText( "Space" );
+ Types.addChild(ServiceType);
+ ServiceType = XMLNode::createXMLTopNode( "ServiceType" );
+ ServiceType.addText( "Profile" );
+ Types.addChild(ServiceType);
+ serviceFilter.addChild(Types);
+ if(data->lastChange != "0")
+ {
+ XMLNode View = XMLNode::createXMLTopNode( "View" );
+ View.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ View.addText("Full");
+ XMLNode deltasOnly = XMLNode::createXMLTopNode( "deltasOnly" );
+ deltasOnly.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ deltasOnly.addText("true");
+ XMLNode lastChange = XMLNode::createXMLTopNode( "lastChange" );
+ lastChange.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ lastChange.addText(data->lastChange.c_str());
+ FindMembership.addChild(View);
+ FindMembership.addChild(deltasOnly);
+ FindMembership.addChild(lastChange);
+ }
+ FindMembership.addChild(serviceFilter);
+ body.addChild(FindMembership);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(GET_LISTS, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGetListsResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[GET_LISTS] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->getLists(this->listInfo);
+ }
+ return;
+ }
+
+
+ XMLNode Services = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("FindMembershipResponse").getChildNode("FindMembershipResult").getChildNode("Services");
+
+ int nServices = Services.nChildNode("Service");
+ for(int d=0;d<nServices;d++)
+ {
+ XMLNode Service = Services.getChildNode("Service", d);
+
+ XMLNode Memberships = Service.getChildNode("Memberships");
+ int nItems = Memberships.nChildNode("Membership");
+
+ for(int i=0;i<nItems;i++)
+ {
+ XMLNode Membership = Memberships.getChildNode("Membership", i);
+ std::string MemberRole = Membership.getChildNode("MemberRole").getText();
+ XMLNode Members = Membership.getChildNode("Members");
+
+ int nItems2 = Members.nChildNode("Member");
+ for(int j=0; j<nItems2;j++)
+ {
+ XMLNode Member = Members.getChildNode("Member", j);
+ // Email type is another network than WLM. Not supported yet
+ if(Member.nChildNode("Type") &&
+ Member.getChildNode("Type").getText() == "Email")
+ continue;
+
+ // TODO- verify if xsi:type == "PassportMember" instead
+ // of presence of PassportName
+ if(!Member.nChildNode("PassportName"))
+ continue;
+ std::string a = Member.getChildNode("PassportName").getText();
+ transform (a.begin(),a.end(), a.begin(), tolower);
+
+ // we cant add this contact or we will receive a 205 error
+ // see http://trac.adiumx.com/ticket/11126
+ if(a == "messenger@microsoft.com")
+ continue;
+
+ if(!listInfo->contactList[a])
+ listInfo->contactList[a]=new Buddy(a);
+
+ if(MemberRole == "Allow")
+ {
+ listInfo->contactList[a]->lists |= MSN::LST_AL;
+ }
+ else if(MemberRole == "Block")
+ {
+ listInfo->contactList[a]->lists |= MSN::LST_BL;
+ }
+ else if(MemberRole == "Reverse")
+ {
+ listInfo->contactList[a]->lists |= MSN::LST_RL;
+ }
+ else if(MemberRole == "Pending")
+ {
+ listInfo->contactList[a]->lists |= MSN::LST_PL;
+ }
+
+ }
+ }
+ }
+ listInfo->progress |= ListSyncInfo::LST_RL | ListSyncInfo::LST_AL | ListSyncInfo::LST_BL | ListSyncInfo::LST_PL;
+ response1.deleteNodeContent();
+ this->myNotificationServer()->gotLists(*this);
+ }
+
+ void Soap::getAddressBook(ListSyncInfo *info)
+ {
+ this->listInfo = info;
+ // info is used to to fill the lists with memebers
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode abapphdr = XMLNode::createXMLTopNode("ABApplicationHeader");
+ abapphdr.addAttribute("xmlns", "http://www.msn.com/webservices/AddressBook");
+ XMLNode appid = XMLNode::createXMLTopNode("ApplicationId");
+ appid.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ abapphdr.addChild(appid);
+ XMLNode ismigration = XMLNode::createXMLTopNode("IsMigration");
+ ismigration.addText("false");
+ abapphdr.addChild(ismigration);
+ XMLNode scenario = XMLNode::createXMLTopNode("PartnerScenario");
+ scenario.addText("Initial");
+ abapphdr.addChild(scenario);
+ header.addChild(abapphdr);
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns", "http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode("ManagedGroupRequest");
+ ManagedGroupRequest.addText("false");
+ XMLNode TicketToken = XMLNode::createXMLTopNode("TicketToken");
+ // TODO - change this - maybe one day the position can be changed
+ TicketToken.addText( sitesToAuthList[3].BinarySecurityToken.c_str() );
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+
+ XMLNode body = XMLNode::createXMLTopNode("soap:Body");
+ XMLNode ABFindAll = XMLNode::createXMLTopNode("FindMembership");
+ ABFindAll.addAttribute("xmlns", "http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode("abId");
+ abId.addText("00000000-0000-0000-0000-000000000000");
+ ABFindAll.addChild(abId);
+ XMLNode abView = XMLNode::createXMLTopNode("abView");
+ abView.addText("Full");
+ ABFindAll.addChild(abView);
+ XMLNode deltasOnly = XMLNode::createXMLTopNode("deltasOnly");
+ if(info->lastChange != "0")
+ {
+ // receive all the list
+ deltasOnly.addText("true");
+ }
+ else
+ {
+ // receive only the changes since lastChange
+ deltasOnly.addText("false");
+ }
+ ABFindAll.addChild(deltasOnly);
+ XMLNode lastChange_ = XMLNode::createXMLTopNode("lastChange");
+ if(info->lastChange == "0")
+ {
+ lastChange_.addText("0001-01-01T00:00:00.0000000-08:00");
+ }
+ else
+ {
+ lastChange_.addText( info->lastChange.c_str() );
+ }
+ ABFindAll.addChild(lastChange_);
+ body.addChild(ABFindAll);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(GET_ADDRESS_BOOK, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGetAddressBookResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[GET_ADDRESS_BOOK] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->getAddressBook(this->listInfo);
+ }
+ return;
+ }
+
+ XMLNode groups = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("ABFindAllResponse").getChildNode("ABFindAllResult").getChildNode("groups");
+ int nItems = groups.nChildNode("Group");
+
+ for(int i=0;i<nItems;i++)
+ {
+ XMLNode thisGroup = groups.getChildNode("Group", i);
+ std::string groupId = thisGroup.getChildNode("groupId").getText();
+ std::string groupName = thisGroup.getChildNode("groupInfo").getChildNode("name").getText();
+ Group g(groupId, groupName);
+ listInfo->groups[groupId] = g;
+ }
+ XMLNode contacts = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("ABFindAllResponse").getChildNode("ABFindAllResult").getChildNode("contacts");
+
+ nItems = contacts.nChildNode("Contact");
+
+ for(int a=0;a<nItems;a++)
+ {
+ XMLNode thisContact = contacts.getChildNode("Contact", a).getChildNode("contactInfo");
+ std::string contactType(thisContact.getChildNode("contactType").getText());
+
+ if(contactType=="Me"){
+ // Just grab the current Friendly name
+ std::string displayName;
+ const char *displayn = thisContact.getChildNode("displayName").getText();
+ if (displayn)
+ displayName = displayn;
+
+ listInfo->myDisplayName = displayName;
+ continue;
+ }
+ // TODO - grab all the fields
+ // passportName isn't ever present
+ std::string passportName;
+ std::string contactId;
+ const char *passportName_cstr = thisContact.getChildNode("passportName").getText();
+ const char *contactId_cstr = contacts.getChildNode("Contact", a).getChildNode("contactId").getText();
+
+ if(passportName_cstr)
+ passportName = passportName_cstr;
+ else
+ continue;
+
+ if(contactId_cstr)
+ contactId = contactId_cstr;
+ else
+ continue;
+
+ if(passportName.empty())
+ continue;
+
+ //
+ // FIXED 20090823 by José AgustÃn Terol Sanchis (agus3985@gmail.com):
+ //
+ // These attributes couldn't be founded at the server response and
+ // the method "getText()" will return NULL. This NULL value will
+ // throw a exception at the std::string constructor that will
+ // abort the address book parsing and, by the way, the connection
+ // to the service.
+ std::string displayName;
+ const char *displayName_cstr = thisContact.getChildNode("displayName").getText();
+ if (displayName_cstr)
+ {
+ displayName = displayName_cstr;
+ }
+ else
+ {
+ // We can use the passport name if we haven't received the
+ // displayName of the current contact instead of ignore it
+ displayName = passportName;
+// continue;
+ }
+
+ std::string isMobileIMEnabled;
+ const char *isMobileIMEnabled_cstr = thisContact.getChildNode("isMobileIMEnabled").getText();
+ if (isMobileIMEnabled_cstr)
+ isMobileIMEnabled = isMobileIMEnabled_cstr;
+ else
+ continue; // We could use here a default string such as "false"
+
+ std::string isMessengerUser;
+ const char *isMessengerUser_cstr = thisContact.getChildNode("isMessengerUser").getText();
+ if (isMessengerUser_cstr)
+ isMessengerUser = isMessengerUser_cstr;
+ else
+ continue; // We could use here a default string such as "true"
+
+ std::string contactType1;
+ const char *contactType1_cstr = thisContact.getChildNode("contactType").getText();
+ if (contactType1_cstr)
+ contactType1 = contactType1_cstr;
+ else
+ continue; // We could use here a default string such as "Regular"
+
+ transform (passportName.begin(), passportName.end(), passportName.begin(), tolower);
+
+ // we cant add this contact or we will receive a 205 error
+ // see http://trac.adiumx.com/ticket/11126
+ if( passportName == "messenger@microsoft.com")
+ continue;
+
+ if(!listInfo->contactList[passportName])
+ listInfo->contactList[passportName]=new Buddy(passportName,displayName);
+ MSN::Buddy *contact = listInfo->contactList[passportName];
+
+ contact->properties["contactId"] = contactId;
+ contact->properties["passportName"] = passportName;
+ contact->properties["displayName"] = displayName;
+ contact->properties["isMobileIMEnabled"] = isMobileIMEnabled;
+ contact->properties["isMessengerUser"] = isMessengerUser;
+ contact->properties["contactType"] = contactType1;
+ contact->userName = contact->properties["passportName"];
+ contact->friendlyName = contact->properties["displayName"];
+ contact->lists |= MSN::LST_AB;
+
+ XMLNode groupIds = thisContact.getChildNode("groupIds");
+ int nItems2 = groupIds.nChildNode("guid");
+ for(int b=0;b<nItems2;b++)
+ {
+ XMLNode guid = groupIds.getChildNode("guid", b);
+ std::string groupID(guid.getText());
+ listInfo->groups[groupID].buddies.push_back(contact);
+ listInfo->contactList[contact->userName]->groups.push_back(&listInfo->groups[groupID]);
+ }
+ }
+ listInfo->progress |= ListSyncInfo::LST_AB;
+ std::string lastChange;
+ const char *clastChange = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("ABFindAllResponse").getChildNode("ABFindAllResult").getChildNode("ab").getChildNode("lastChange").getText();
+ if(clastChange)
+ lastChange = clastChange;
+ else
+ lastChange = "0";
+
+ this->myNotificationServer()->externalCallbacks.gotLatestListSerial(this->myNotificationServer(), lastChange);
+
+ response1.deleteNodeContent();
+ this->myNotificationServer()->gotAddressBook(*this);
+ }
+
+ void Soap::getOIM(std::string id, bool markAsRead)
+ {
+ this->oim_id = id;
+ this->markAsRead = markAsRead;
+ // index 2 is messenger.msn.com
+ std::string token = sitesToAuthList[2].BinarySecurityToken;
+ std::string t = token.substr(token.find("t=") + 2, token.find("&p=")-2);
+ std::string p = token.substr(token.find("&p=") + 3, -1);
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode PassportCookie = XMLNode::createXMLTopNode("PassportCookie");
+ PassportCookie.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ XMLNode t1 = XMLNode::createXMLTopNode("t");
+ t1.addText(t.c_str());
+ XMLNode p1 = XMLNode::createXMLTopNode("p");
+ p1.addText(p.c_str());
+ PassportCookie.addChild(t1);
+ PassportCookie.addChild(p1);
+ header.addChild(PassportCookie);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode("soap:Body");
+ XMLNode GetMessage = XMLNode::createXMLTopNode("GetMessage");
+ GetMessage.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ XMLNode messageId = XMLNode::createXMLTopNode("messageId");
+ messageId.addText(id.c_str());
+ XMLNode alsoMarkAsRead = XMLNode::createXMLTopNode("alsoMarkAsRead");
+ if(markAsRead)
+ alsoMarkAsRead.addText("true");
+ else
+ alsoMarkAsRead.addText("false");
+ GetMessage.addChild(messageId);
+ GetMessage.addChild(alsoMarkAsRead);
+ body.addChild(GetMessage);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(RETRIEVE_OIM, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGetOIMResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[RETRIEVE_OIM] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->getOIM(this->oim_id, this->markAsRead);
+ }
+ return;
+ }
+
+
+ const char* msg = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("GetMessageResponse").getChildNode("GetMessageResult").getText();
+ if(msg)
+ {
+ std::string message1(msg);
+ // TODO - extract all the fields. create a struct to carry this data
+ message1 = message1.substr(message1.find("\r\n\r\n")+4,-1).c_str();
+ std::vector<std::string> a = splitString(message1, "\r\n");
+ message1="";
+ std::vector<std::string>::iterator i = a.begin();
+ for(;i!=a.end(); i++)
+ {
+ message1+=(*i);
+ }
+ message1 = b64_decode(message1.c_str());
+ response1.deleteNodeContent();
+ // yes, new oim
+ this->myNotificationServer()->gotOIM(*this, true, this->oim_id, message1);
+ return;
+ }
+ // no oim with this id
+ this->myNotificationServer()->gotOIM(*this, false, this->oim_id, "");
+ }
+
+ void Soap::deleteOIM(std::string id)
+ {
+ this->oim_id=id;
+ // index 2 is messenger.msn.com
+ std::string token = sitesToAuthList[2].BinarySecurityToken;
+ std::string t = token.substr(token.find("t=") + 2, token.find("&p=")-2);
+ std::string p = token.substr(token.find("&p=") + 3, -1);
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode PassportCookie = XMLNode::createXMLTopNode("PassportCookie");
+ PassportCookie.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ XMLNode t1 = XMLNode::createXMLTopNode("t");
+ t1.addText(t.c_str());
+ XMLNode p1 = XMLNode::createXMLTopNode("p");
+ p1.addText(p.c_str());
+ PassportCookie.addChild(t1);
+ PassportCookie.addChild(p1);
+ header.addChild(PassportCookie);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode("soap:Body");
+ XMLNode DeleteMessages = XMLNode::createXMLTopNode("DeleteMessages");
+ DeleteMessages.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ XMLNode messageIds = XMLNode::createXMLTopNode("messageIds");
+ XMLNode messageId = XMLNode::createXMLTopNode("messageId");
+ messageId.addText(id.c_str());
+ messageIds.addChild(messageId);
+ DeleteMessages.addChild(messageIds);
+ body.addChild(DeleteMessages);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(DELETE_OIM, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseDeleteOIMResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[DELETE_OIM] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->deleteOIM(this->oim_id);
+ }
+ return;
+ }
+
+ if(http_response_code == "200" )
+ {
+ this->myNotificationServer()->gotOIMDeleteConfirmation(*this, oim_id, true);
+ return;
+ }
+ this->myNotificationServer()->gotOIMDeleteConfirmation(*this, oim_id, false);
+ }
+
+ void Soap::getMailData()
+ {
+ // index 2 is messenger.msn.com
+ std::string token = sitesToAuthList[2].BinarySecurityToken;
+ std::string t = token.substr(token.find("t=") + 2, token.find("&p=")-2);
+ std::string p = token.substr(token.find("&p=") + 3, -1);
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode PassportCookie = XMLNode::createXMLTopNode("PassportCookie");
+ PassportCookie.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ XMLNode t1 = XMLNode::createXMLTopNode("t");
+ t1.addText(t.c_str());
+ XMLNode p1 = XMLNode::createXMLTopNode("p");
+ p1.addText(p.c_str());
+ PassportCookie.addChild(t1);
+ PassportCookie.addChild(p1);
+ header.addChild(PassportCookie);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode("soap:Body");
+ XMLNode GetMetadata = XMLNode::createXMLTopNode("GetMetadata");
+ GetMetadata.addAttribute("xmlns", "http://www.hotmail.msn.com/ws/2004/09/oim/rsi");
+ body.addChild(GetMetadata);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(RETRIEVE_OIM_MAIL_DATA, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGetMailDataResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[RETRIEVE_OIM_MAIL_DATA] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->getMailData();
+ }
+ return;
+ }
+
+
+ // oh my god! xml text as a field of a xml node! I cant believe it!
+ std::string maildata = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("GetMetadataResponse").getChildNode("MD").createXMLString(false);
+ if(maildata.empty())
+ return; // TODO - raise an error
+
+ response1.deleteNodeContent();
+ this->myNotificationServer()->gotSoapMailData(*this, maildata);
+ }
+
+
+ void Soap::generateLockkey(OIM oim)
+ {
+ //almost equal to send oim
+
+ this->oim = oim;
+ // index 4 is messengersecure.live.com
+ std::string token = sitesToAuthList[4].BinarySecurityToken;
+
+ // encoding to the required form
+ oim.myFname = "=?utf-8?B?" + b64_encode(oim.myFname.c_str(), oim.myFname.length()) + "?=";
+
+ // TODO - find an email library to handle this part
+ std::string b64_message = b64_encode(oim.message.c_str(), oim.message.length());
+ oim.message="";
+ for(unsigned int i=0; i<b64_message.length();i++)
+ {
+ if( (i%72) == 0 && i != 0 )
+ {
+ oim.message.append("\r\n");
+ oim.message+=b64_message.at(i);
+ }
+ else
+ {
+ oim.message += b64_message.at(i);
+ }
+ }
+ std::string msg_body("MIME-Version: 1.0\r\n"
+ "Content-Type: text/plain; charset=UTF-8\r\n"
+ "Content-Transfer-Encoding: base64\r\n"
+ "X-OIM-Message-Type: OfflineMessage\r\n"
+ "X-OIM-Run-Id: "+new_branch()+"\r\n"
+ "X-OIM-Sequence-Num: 1\r\n\r\n"+
+ oim.message);
+ oim.full_msg = msg_body;
+ this->oim.full_msg = oim.full_msg;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode From = XMLNode::createXMLTopNode("From");
+ From.addAttribute("memberName", oim.myUsername.c_str());
+ From.addAttribute("friendlyName", oim.myFname.c_str());
+ From.addAttribute("xml:lang", "pt-BR");
+ From.addAttribute("proxy", "MSNMSGR");
+ From.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ From.addAttribute("msnpVer", "MSNP15");
+ From.addAttribute("buildVer", "8.1.0178");
+ XMLNode To = XMLNode::createXMLTopNode("To");
+ To.addAttribute("memberName", oim.toUsername.c_str());
+ To.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ XMLNode Ticket = XMLNode::createXMLTopNode("Ticket");
+ Ticket.addAttribute("passport", decodeURL(token).c_str());
+ Ticket.addAttribute("appid", szClientID);
+ Ticket.addAttribute("lockkey", "");
+ Ticket.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ XMLNode Sequence = XMLNode::createXMLTopNode("Sequence");
+ Sequence.addAttribute("xmlns", "http://schemas.xmlsoap.org/ws/2003/03/rm");
+ XMLNode Identifier = XMLNode::createXMLTopNode( "Identifier" );
+ Identifier.addAttribute("xmlns", "http://schemas.xmlsoap.org/ws/2002/07/utility");
+ Identifier.addText("http://messenger.msn.com");
+ XMLNode MessageNumber = XMLNode::createXMLTopNode("MessageNumber");
+ MessageNumber.addText("1");
+ Sequence.addChild(Identifier);
+ Sequence.addChild(MessageNumber);
+ header.addChild(From);
+ header.addChild(To);
+ header.addChild(Ticket);
+ header.addChild(Sequence);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode MessageType = XMLNode::createXMLTopNode( "MessageType" );
+ MessageType.addAttribute("xmlns","http://messenger.msn.com/ws/2004/09/oim/");
+ MessageType.addText("text");
+ XMLNode Content = XMLNode::createXMLTopNode( "Content" );
+ Content.addAttribute("xmlns","http://messenger.msn.com/ws/2004/09/oim/");
+ Content.addText(oim.full_msg.c_str());
+ body.addChild(MessageType);
+ body.addChild(Content);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(GENERATE_LOCKKEY, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseGenerateLockkeyResponse(std::string response)
+ {
+ OIM oim = this->oim;
+ // probably we need to generate a new lockkey
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[GENERATE_LOCKKEY] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->generateLockkey(this->oim);
+ }
+ return;
+ }
+
+ XMLNode LockKeyChallenge = response1.getChildNode("soap:Envelope").getChildNode("soap:Body").getChildNode("soap:Fault").getChildNode("detail").getChildNode("LockKeyChallenge");
+
+ const char * lockkey1 = LockKeyChallenge.getText();
+ if(!lockkey1)
+ {
+ this->myNotificationServer()->gotOIMLockkey(*this, "");
+ return;
+ }
+ std::string lockkey = lockkey1;
+ char b[33];
+ memset(&b,0,33);
+ DoMSNP11Challenge(lockkey.c_str(),b);
+ std::string new_lockkey(b);
+ this->lockkey = new_lockkey;
+
+ this->myNotificationServer()->gotOIMLockkey(*this, this->lockkey);
+ }
+
+ void Soap::sendOIM(OIM oim, std::string lockkey)
+ {
+ this->oim = oim;
+ this->lockkey = lockkey;
+ // index 4 is messengersecure.live.com
+ std::string token = sitesToAuthList[4].BinarySecurityToken;
+
+ // encoding to the required form
+ oim.myFname = "=?utf-8?B?" + b64_encode(oim.myFname.c_str(), oim.myFname.length()) + "?=";
+
+ // TODO - find an email library to handle this part
+ std::string b64_message = b64_encode(oim.message.c_str(), oim.message.length());
+ oim.message="";
+ for(unsigned int i=0; i<b64_message.length();i++)
+ {
+ if( (i%72) == 0 && i != 0 )
+ {
+ oim.message.append("\r\n");
+ oim.message+=b64_message.at(i);
+ }
+ else
+ {
+ oim.message += b64_message.at(i);
+ }
+ }
+ std::string msg_body("MIME-Version: 1.0\r\n"
+ "Content-Type: text/plain; charset=UTF-8\r\n"
+ "Content-Transfer-Encoding: base64\r\n"
+ "X-OIM-Message-Type: OfflineMessage\r\n"
+ "X-OIM-Run-Id: "+new_branch()+"\r\n"
+ "X-OIM-Sequence-Num: 1\r\n\r\n"+
+ oim.message);
+ oim.full_msg = msg_body;
+ this->oim.full_msg = oim.full_msg;
+
+ XMLNode envelope = XMLNode::createXMLTopNode("soap:Envelope");
+ envelope.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode From = XMLNode::createXMLTopNode("From");
+ From.addAttribute("memberName", oim.myUsername.c_str());
+ From.addAttribute("friendlyName", oim.myFname.c_str());
+ From.addAttribute("xml:lang", "pt-BR");
+ From.addAttribute("proxy", "MSNMSGR");
+ From.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ From.addAttribute("msnpVer", "MSNP15");
+ From.addAttribute("buildVer", "8.1.0178");
+ XMLNode To = XMLNode::createXMLTopNode("To");
+ To.addAttribute("memberName", oim.toUsername.c_str());
+ To.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ XMLNode Ticket = XMLNode::createXMLTopNode("Ticket");
+ Ticket.addAttribute("passport", decodeURL(token).c_str());
+ Ticket.addAttribute("appid", szClientID);
+ Ticket.addAttribute("lockkey", lockkey.c_str());
+ Ticket.addAttribute("xmlns", "http://messenger.msn.com/ws/2004/09/oim/");
+ XMLNode Sequence = XMLNode::createXMLTopNode("Sequence");
+ Sequence.addAttribute("xmlns", "http://schemas.xmlsoap.org/ws/2003/03/rm");
+ XMLNode Identifier = XMLNode::createXMLTopNode( "Identifier" );
+ Identifier.addAttribute("xmlns", "http://schemas.xmlsoap.org/ws/2002/07/utility");
+ Identifier.addText("http://messenger.msn.com");
+ XMLNode MessageNumber = XMLNode::createXMLTopNode("MessageNumber");
+ MessageNumber.addText("1");
+ Sequence.addChild(Identifier);
+ Sequence.addChild(MessageNumber);
+ header.addChild(From);
+ header.addChild(To);
+ header.addChild(Ticket);
+ header.addChild(Sequence);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode MessageType = XMLNode::createXMLTopNode( "MessageType" );
+ MessageType.addAttribute("xmlns","http://messenger.msn.com/ws/2004/09/oim/");
+ MessageType.addText("text");
+ XMLNode Content = XMLNode::createXMLTopNode( "Content" );
+ Content.addAttribute("xmlns","http://messenger.msn.com/ws/2004/09/oim/");
+ Content.addText(oim.full_msg.c_str());
+ body.addChild(MessageType);
+ body.addChild(Content);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(SEND_OIM, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+ }
+
+ void Soap::parseSendOIMResponse(std::string response)
+ {
+ OIM oim = this->oim;
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[SEND_OIM] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->sendOIM(this->oim, this->lockkey);
+ }
+ return;
+ }
+
+ if(http_response_code == "200" )
+ {
+ this->myNotificationServer()->gotOIMSendConfirmation(*this, oim.id, true);
+ return;
+ }
+ this->myNotificationServer()->gotOIMSendConfirmation(*this, oim.id, false);
+ }
+
+ void Soap::changeDisplayName(std::string newDisplayName)
+ {
+ this->tempDisplayName = newDisplayName;
+ XMLNode envelope = XMLNode::createXMLTopNode( "soap:Envelope" );
+ envelope.addAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/");
+ envelope.addAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ envelope.addAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
+ envelope.addAttribute("xmlns:soapenc","http://schemas.xmlsoap.org/soap/encoding/");
+ XMLNode header = XMLNode::createXMLTopNode("soap:Header");
+ XMLNode ABApplicationHeader = XMLNode::createXMLTopNode( "ABApplicationHeader" );
+ ABApplicationHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ApplicationId = XMLNode::createXMLTopNode( "ApplicationId" );
+ ApplicationId.addText("996CDE1E-AA53-4477-B943-2BE802EA6166");
+ XMLNode IsMigration = XMLNode::createXMLTopNode("IsMigration");
+ IsMigration.addText("false");
+ XMLNode PartnerScenario = XMLNode::createXMLTopNode("PartnerScenario");
+ PartnerScenario.addText("Timer");
+ ABApplicationHeader.addChild(ApplicationId);
+ ABApplicationHeader.addChild(IsMigration);
+ ABApplicationHeader.addChild(PartnerScenario);
+
+ XMLNode ABAuthHeader = XMLNode::createXMLTopNode("ABAuthHeader");
+ ABAuthHeader.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode ManagedGroupRequest = XMLNode::createXMLTopNode("ManagedGroupRequest");
+ ManagedGroupRequest.addText("false");
+ XMLNode TicketToken = XMLNode::createXMLTopNode("TicketToken");
+ TicketToken.addText(sitesToAuthList[3].BinarySecurityToken.c_str());
+ ABAuthHeader.addChild(ManagedGroupRequest);
+ ABAuthHeader.addChild(TicketToken);
+
+ header.addChild(ABApplicationHeader);
+ header.addChild(ABAuthHeader);
+ envelope.addChild(header);
+ XMLNode body = XMLNode::createXMLTopNode( "soap:Body" );
+ XMLNode ABContactUpdate = XMLNode::createXMLTopNode( "ABContactUpdate" );
+ ABContactUpdate.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode abId = XMLNode::createXMLTopNode( "abId" );
+ abId.addText("00000000-0000-0000-0000-000000000000");
+ XMLNode contacts = XMLNode::createXMLTopNode( "contacts" );
+ XMLNode Contact = XMLNode::createXMLTopNode( "Contact" );
+ Contact.addAttribute("xmlns","http://www.msn.com/webservices/AddressBook");
+ XMLNode contactInfo = XMLNode::createXMLTopNode( "contactInfo" );
+ XMLNode contactType = XMLNode::createXMLTopNode( "contactType" );
+ contactType.addText("Me");
+ XMLNode displayName = XMLNode::createXMLTopNode( "displayName" );
+ displayName.addText(newDisplayName.c_str());
+ contactInfo.addChild(contactType);
+ contactInfo.addChild(displayName);
+ XMLNode propertiesChanged = XMLNode::createXMLTopNode( "propertiesChanged" );
+ propertiesChanged.addText("DisplayName");
+ Contact.addChild(contactInfo);
+ Contact.addChild(propertiesChanged);
+ contacts.addChild(Contact);
+ ABContactUpdate.addChild(abId);
+ ABContactUpdate.addChild(contacts);
+ body.addChild(ABContactUpdate);
+ envelope.addChild(body);
+
+ std::string xml_response;
+ char *xml_request = envelope.createXMLString(false);
+ std::string temp2 = xml_request;
+ this->request_body = temp2;
+
+ requestSoapAction(CHANGE_DISPLAYNAME, xml_request, xml_response);
+
+ free(xml_request);
+ envelope.deleteNodeContent();
+
+ }
+
+ void Soap::parseChangeDisplayNameResponse(std::string response)
+ {
+ XMLNode response1 = XMLNode::parseString(response.c_str());
+ if(http_response_code == "301" )
+ {
+ const char *preferredHostName = response1.getChildNode("soap:Envelope").getChildNode("soap:Header").getChildNode("ServiceHeader").getChildNode("PreferredHostName").getText();
+ if(preferredHostName)
+ {
+ Soap *soapConnection = new Soap(notificationServer, sitesToAuthList);
+
+ std::string newdomain(preferredHostName);
+ soapConnection->actionDomains[CHANGE_DISPLAYNAME] = newdomain;
+ soapConnection->setMBI(mbi);
+ soapConnection->changeDisplayName(this->tempDisplayName);
+ }
+ return;
+ }
+
+ if(http_response_code == "200" )
+ {
+ this->myNotificationServer()->gotChangeDisplayNameConfirmation(*this, this->tempDisplayName, true);
+ return;
+ }
+ this->myNotificationServer()->gotChangeDisplayNameConfirmation(*this, this->tempDisplayName, false);
+ }
+
+ void Soap::socketConnectionCompleted()
+ {
+ Connection::socketConnectionCompleted();
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1, 0, true);
+ }
+
+ void Soap::handleIncomingData()
+ {
+ // grab http header
+ if(this->http_header_response.empty())
+ {
+ if (this->readBuffer.find("\r\n\r\n") == std::string::npos )
+ return;
+
+ http_header_response = this->readBuffer.substr(0,this->readBuffer.find("\r\n\r\n") + 4);
+ Message::Headers headers = Message::Headers(http_header_response);
+ this->response_length = decimalFromString(headers["Content-Length"]);
+
+ this->http_response_code = splitString(http_header_response.substr(0,http_header_response.find("\r\n"))," ")[1];
+
+ // drop http from buffer
+ this->readBuffer = this->readBuffer.substr(this->readBuffer.find("\r\n\r\n") + 4);
+ }
+
+ if(this->readBuffer.length() < this->response_length)
+ return; // wait for the full response
+
+ this->response_body = this->readBuffer;
+
+ this->readBuffer.clear();
+
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+
+ switch(this->action)
+ {
+ case AUTH:
+ parseGetTicketsResponse(this->response_body);
+ break;
+ case GET_LISTS:
+ parseGetListsResponse(this->response_body);
+ break;
+ case GET_ADDRESS_BOOK:
+ parseGetAddressBookResponse(this->response_body);
+ break;
+ case SEND_OIM:
+ parseSendOIMResponse(this->response_body);
+ break;
+ case GENERATE_LOCKKEY:
+ parseGenerateLockkeyResponse(this->response_body);
+ break;
+ case RETRIEVE_OIM:
+ parseGetOIMResponse(this->response_body);
+ break;
+ case DELETE_OIM:
+ parseDeleteOIMResponse(this->response_body);
+ break;
+ case RETRIEVE_OIM_MAIL_DATA:
+ parseGetMailDataResponse(this->response_body);
+ break;
+ case ADD_CONTACT_TO_LIST:
+ parseAddContactToListResponse(this->response_body);
+ break;
+ case DEL_CONTACT_FROM_LIST:
+ parseRemoveContactFromListResponse(this->response_body);
+ break;
+ case CHANGE_DISPLAYNAME:
+ parseChangeDisplayNameResponse(this->response_body);
+ break;
+ case ADD_CONTACT_TO_GROUP:
+ parseAddContactToGroupResponse(this->response_body);
+ break;
+ case DEL_CONTACT_FROM_GROUP:
+ parseDelContactFromGroupResponse(this->response_body);
+ break;
+ case ADD_GROUP:
+ parseAddGroupResponse(this->response_body);
+ break;
+ case DEL_GROUP:
+ parseDelGroupResponse(this->response_body);
+ break;
+ case RENAME_GROUP:
+ parseRenameGroupResponse(this->response_body);
+ break;
+ case DISABLE_CONTACT_ON_ADDRESSBOOK:
+ parseDisableContactFromAddressBookResponse(this->response_body);
+ break;
+ case ENABLE_CONTACT_ON_ADDRESSBOOK:
+ parseEnableContactOnAddressBookResponse(this->response_body);
+ break;
+ case ADD_CONTACT_TO_ADDRESSBOOK:
+ parseAddContactToAddressBookResponse(this->response_body);
+ break;
+ case DEL_CONTACT_FROM_ADDRESSBOOK:
+ parseDelContactFromAddressBookResponse(this->response_body);
+ break;
+
+ }
+ delete this;
+ }
+
+ void Soap::disconnect()
+ {
+ }
+
+ Soap::~Soap()
+ {
+ Connection::disconnect();
+ if(this->myNotificationServer()->connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED)
+ this->myNotificationServer()->removeSoapConnection(this);
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnsoaph"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/soap.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,221 @@
</span><ins>+#ifndef __msn_soap_h__
+#define __msn_soap_h__
+/*
+ * soap.h
+ * libmsn
+ *
+ * Crated by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <msn/connection.h>
+#include <msn/authdata.h>
+#include <msn/errorcodes.h>
+#include <msn/buddy.h>
+#include <msn/passport.h>
+#include <stdexcept>
+#include <msn/externals.h>
+
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class NotificationServerConnection;
+
+ /** Represents a Soap Connection made by NotificationServerConnection
+ */
+ class LIBMSN_EXPORT Soap : public Connection
+ {
+private:
+ NotificationServerConnection & notificationServer;
+ std::string request_body;
+ std::string http_header_response;
+ std::string response_body;
+ int action;
+ unsigned int response_length;
+ ListSyncInfo *listInfo;
+ std::string oim_id;
+ std::string http_response_code;
+ std::string tempDisplayName;
+ std::string tempPassport;
+ std::string contactId;
+ std::string groupId;
+ std::string groupName;
+ MSN::ContactList tempList;
+ std::string passport;
+ std::string password;
+ std::string policy;
+ std::string mbi;
+ std::string myDisplayName;
+ bool markAsRead;
+
+public:
+ struct sitesToAuthTAG
+ {
+ std::string url;
+ std::string URI;
+ std::string BinarySecurityToken;
+ std::string BinarySecret;
+ };
+
+ typedef sitesToAuthTAG sitesToAuth;
+
+ struct OIMTAG
+ {
+ int id;
+ std::string toUsername;
+ std::string myUsername;
+ std::string myFname;
+ std::string message;
+ std::string full_msg; // includes b64 body
+ };
+
+ typedef OIMTAG OIM;
+
+ MSN::Soap::OIM oim;
+ Soap(NotificationServerConnection & _myNotificationServer);
+ Soap(NotificationServerConnection & _myNotificationServer, std::vector<sitesToAuth> sitesToAuthList);
+ ~Soap();
+ std::string body;
+ std::string ticket_token;
+ std::string lockkey;
+
+ enum memberRoles { // the lists
+ ALLOW_LIST = 2,
+ BLOCK_LIST = 4,
+ REVERSE_LIST = 8,
+ PENDING_LIST = 16
+ };
+
+ typedef enum {
+ AUTH,
+ GET_LISTS,
+ GET_ADDRESS_BOOK,
+ ADD_CONTACT_TO_LIST,
+ DEL_CONTACT_FROM_LIST,
+ ADD_CONTACT_TO_ADDRESSBOOK,
+ DEL_CONTACT_FROM_ADDRESSBOOK,
+ ENABLE_CONTACT_ON_ADDRESSBOOK,
+ DISABLE_CONTACT_ON_ADDRESSBOOK,
+ ADD_GROUP,
+ DEL_GROUP,
+ RENAME_GROUP,
+ BLOCK_CONTACT,
+ UNBLOCK_CONTACT,
+ ADD_CONTACT_TO_GROUP,
+ DEL_CONTACT_FROM_GROUP,
+ UPDATE_GROUP,
+ GENERATE_LOCKKEY,
+ RETRIEVE_OIM_MAIL_DATA,
+ RETRIEVE_OIM,
+ DELETE_OIM,
+ SEND_OIM,
+ CHANGE_DISPLAYNAME
+ } soapAction;
+
+ static std::map<int,std::string> actionDomains;
+ static std::map<int,std::string> actionPOSTURLs;
+ static std::map<int,std::string> actionURLs;
+ std::vector<sitesToAuth> sitesToAuthList;
+
+ void fillURLs();
+ void setMBI(std::string MBI);
+ void requestSoapAction(soapAction action, std::string xml_body, std::string & xml_response);
+
+ void getTickets(std::string Passport,
+ std::string password,
+ std::string policy);
+ void parseGetTicketsResponse(std::string response);
+
+ void getLists(ListSyncInfo* data);
+ void parseGetListsResponse(std::string response);
+
+ void getAddressBook(ListSyncInfo *info);
+ void parseGetAddressBookResponse(std::string response);
+
+ void getOIM(std::string id, bool markAsRead);
+ void parseGetOIMResponse(std::string response);
+
+ void deleteOIM(std::string id);
+ void parseDeleteOIMResponse(std::string response);
+
+ void getMailData();
+ void parseGetMailDataResponse(std::string response);
+
+ void sendOIM(OIM oim, std::string lockkey);
+ void parseSendOIMResponse(std::string response);
+
+ void addContactToList(MSN::Passport passport, MSN::ContactList list);
+ void parseAddContactToListResponse(std::string response);
+
+ void addContactToAddressBook(std::string passport, std::string displayName);
+ void parseAddContactToAddressBookResponse(std::string response);
+
+ void delContactFromAddressBook(std::string contactId, std::string passport);
+ void parseDelContactFromAddressBookResponse(std::string response);
+
+ void enableContactOnAddressBook(std::string contactId,
+ std::string passport,
+ std::string myDisplayName);
+
+ void parseEnableContactOnAddressBookResponse(std::string response);
+
+ void disableContactFromAddressBook(std::string contactId, std::string passport);
+ void parseDisableContactFromAddressBookResponse(std::string response);
+
+ void addContactToGroup(std::string groupId, std::string contactId);
+ void parseAddContactToGroupResponse(std::string response);
+
+ void delContactFromGroup(std::string groupId, std::string contactId);
+ void parseDelContactFromGroupResponse(std::string response);
+
+ void removeContactFromList(MSN::Passport passport, MSN::ContactList list);
+ void parseRemoveContactFromListResponse(std::string response);
+
+ void addGroup(std::string groupName);
+ void parseAddGroupResponse(std::string response);
+
+ void delGroup(std::string groupId);
+ void parseDelGroupResponse(std::string response);
+
+ void renameGroup(std::string groupId, std::string newGroupName);
+ void parseRenameGroupResponse(std::string response);
+
+ void generateLockkey(OIM oim);
+ void parseGenerateLockkeyResponse(std::string response);
+
+ void changeDisplayName(std::string newDisplayName);
+ void parseChangeDisplayNameResponse(std::string);
+
+ virtual void dispatchCommand(std::vector<std::string> &) {};
+ virtual void connect(const std::string &, unsigned int) {};
+ virtual void disconnect();
+ virtual void sendMessage(const Message *) {};
+ virtual void sendMessage(const std::string &) {};
+ virtual void socketConnectionCompleted();
+ virtual void handleIncomingData();
+ virtual NotificationServerConnection *myNotificationServer() { return &notificationServer; };
+
+ };
+
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnsstream_fixh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/sstream_fix.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/sstream_fix.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/sstream_fix.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+/*
+ * This file is one big nasty kludge because the older
+ * libstdc++ libraries (before v3) have the old strstream
+ * but I want to use the new, and much improved sstream.
+ * - Barnaby
+ *
+ * Copyright (C) 2001 Barnaby Gray <barnaby@beedesign.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_SSTREAM
+# include <sstream>
+#elif HAVE_STRSTREAM
+# define USE_STRSTREAM_WRAPPERS
+#else
+# error "No sstream/strstream implementation"
+#endif
+
+#if defined(USE_STRSTREAM_WRAPPERS) && !defined(SSTREAM_FIX_H)
+#define SSTREAM_FIX_H
+
+#include <string>
+#include <strstream>
+
+#include "libmsn_export.h"
+
+namespace std
+{
+
+ /*
+ * Only limited functionality from ostringstream
+ * is implemented
+ */
+ class ostringstream : public ostrstream {
+ public:
+ string str() {
+ char *cstr = ostrstream::str();
+ freeze(0);
+ if (cstr == 0) return string();
+ return string(cstr,pcount());
+ }
+ };
+
+ /*
+ * Only limited functionality from istringstream
+ * is implemented
+ */
+ class istringstream : public istrstream {
+ public:
+ istringstream(const string& str)
+ : istrstream(str.c_str()) { }
+ };
+
+}
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnswitchboardservercpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,749 @@
</span><ins>+/*
+ * switchboardserver.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/switchboardserver.h>
+#include <msn/notificationserver.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/util.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <algorithm>
+#include <cassert>
+#include <sstream>
+
+namespace MSN
+{
+ std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &)> SwitchboardServerConnection::commandHandlers;
+ std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &, std::string, std::string)> SwitchboardServerConnection::messageHandlers;
+
+ SwitchboardServerConnection::SwitchboardServerConnection(AuthData & auth_, NotificationServerConnection & n)
+ : Connection(), auth(auth_), _connectionState(SB_DISCONNECTED), notificationServer(n)
+ {
+ registerCommandHandlers();
+ registerMessageHandlers();
+ }
+
+ SwitchboardServerConnection::~SwitchboardServerConnection()
+ {
+ if (this->connectionState() != SB_DISCONNECTED)
+ this->disconnect();
+ }
+
+ Connection *SwitchboardServerConnection::connectionWithSocket(void * sock)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTING);
+
+ if (this->sock == sock)
+ return this;
+
+/* std::list<FileTransferConnectionP2P *> & list2 = _fileTransferConnectionsP2P;
+ std::list<FileTransferConnectionP2P *>::iterator j = list2.begin();
+
+ for (; j != list2.end(); j++)
+ {
+ if ((*j)->sock == fd)
+ return *i;
+ }
+ */
+ return NULL;
+ }
+
+ void SwitchboardServerConnection::sendEmoticon(std::string alias, std::string file)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+
+ myNotificationServer()->msnobj.addMSNObject(file,2);
+ std::string msnobject;
+ myNotificationServer()->msnobj.getMSNObjectXML(file, 2, msnobject);
+
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-mms-emoticon\r\n\r\n";
+ msg_ << alias << "\t" << msnobject << "\t";
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " N " << (int) msg_length << "\r\n" << msg_.str();
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::sendFile(MSN::fileTransferInvite ft)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ p2p.sendFile(*this,ft);
+ }
+
+ void SwitchboardServerConnection::addFileTransferConnectionP2P(FileTransferConnectionP2P *c)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ _fileTransferConnectionsP2P.push_back(c);
+ }
+
+ void SwitchboardServerConnection::removeFileTransferConnectionP2P(FileTransferConnectionP2P *c)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ _fileTransferConnectionsP2P.remove(c);
+ }
+
+ template <class _Tp>
+ class hasCookieOf
+ {
+ const std::string & cookie;
+public:
+ hasCookieOf(const std::string & __i) : cookie(__i) {};
+ bool operator()(const _Tp &__x) { return __x->cookie == cookie; }
+ };
+
+ void SwitchboardServerConnection::addCallback(SwitchboardServerCallback callback,
+ int trid, void *data)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTING);
+ this->callbacks[trid] = std::make_pair(callback, data);
+ }
+
+ void SwitchboardServerConnection::removeCallback(int trid)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTING);
+ this->callbacks.erase(trid);
+ }
+
+ void SwitchboardServerConnection::addP2PCallback(SwitchboardServerCallback2 callback,
+ int trid, unsigned int sessionID)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTING);
+ this->callbacks2[trid] = std::make_pair(callback, sessionID);
+ }
+
+ void SwitchboardServerConnection::removeP2PCallback(int trid)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTING);
+ this->callbacks2.erase(trid);
+ }
+
+ void SwitchboardServerConnection::registerMessageHandlers()
+ {
+ if (messageHandlers.size() == 0)
+ {
+ messageHandlers["text/plain"] = &SwitchboardServerConnection::message_plain;
+ messageHandlers["text/x-msmsgsinvite"] = &SwitchboardServerConnection::message_invitation;
+ messageHandlers["text/x-msmsgscontrol"] = &SwitchboardServerConnection::message_typing_user;
+ messageHandlers["application/x-msnmsgrp2p"] = &SwitchboardServerConnection::message_p2p;
+ messageHandlers["text/x-msnmsgr-datacast"] = &SwitchboardServerConnection::message_datacast;
+ messageHandlers["text/x-mms-emoticon"] = &SwitchboardServerConnection::message_emoticon;
+ messageHandlers["text/x-mms-animemoticon"] = &SwitchboardServerConnection::message_emoticon;
+ messageHandlers["image/gif"] = &SwitchboardServerConnection::message_ink;
+ messageHandlers["application/x-ms-ink"] = &SwitchboardServerConnection::message_ink;
+ }
+ }
+
+ void SwitchboardServerConnection::registerCommandHandlers()
+ {
+ if (commandHandlers.size() == 0)
+ {
+ commandHandlers["BYE"] = &SwitchboardServerConnection::handle_BYE;
+ commandHandlers["JOI"] = &SwitchboardServerConnection::handle_JOI;
+ commandHandlers["NAK"] = &SwitchboardServerConnection::handle_NAK;
+ commandHandlers["MSG"] = &SwitchboardServerConnection::handle_MSG;
+ }
+ }
+
+ void SwitchboardServerConnection::message_plain(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ Message msg = Message(body, mime);
+
+ this->myNotificationServer()->externalCallbacks.gotInstantMessage(this,args[1], decodeURL(args[2]), &msg);
+ }
+
+ void SwitchboardServerConnection::message_emoticon(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ std::vector<std::string> emoticons = splitString(body,"\t");
+ for(unsigned int i=0; i < emoticons.size(); )
+ {
+ // avoid errors with clients which do not respect the protocol
+ if(i+2 > emoticons.size()) return;
+ this->myNotificationServer()->externalCallbacks.gotEmoticonNotification(this,args[1], emoticons[i] , emoticons[i+1]);
+ i+=2; // move to the next one
+ }
+ }
+
+ void SwitchboardServerConnection::message_invitation(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ }
+
+ void SwitchboardServerConnection::message_typing_user(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ this->myNotificationServer()->externalCallbacks.buddyTyping(this, args[1], decodeURL(args[2]));
+ }
+
+ void SwitchboardServerConnection::message_ink(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ std::string image = body.substr(body.find("base64:")+7);
+ this->myNotificationServer()->externalCallbacks.gotInk(this, args[1], image);
+ }
+
+ void SwitchboardServerConnection::message_p2p(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ p2p.handleP2Pmessage(*this,args,mime,body);
+ }
+ void SwitchboardServerConnection::message_datacast(std::vector<std::string> & args, std::string mime, std::string body)
+ {
+ Message::Headers headers = Message::Headers(body);
+ int id = decimalFromString(headers["ID"]);
+ switch(id)
+ {
+ case 1:
+ this->myNotificationServer()->externalCallbacks.gotNudge(this, args[1]);
+ break;
+ case 2:
+ this->myNotificationServer()->externalCallbacks.gotWinkNotification(this, args[1], headers["Data"]);
+ break;
+ case 3:
+ this->myNotificationServer()->externalCallbacks.gotVoiceClipNotification(this, args[1], headers["Data"]);
+ break;
+ case 4:
+ this->myNotificationServer()->externalCallbacks.gotActionMessage(this, args[1], headers["Data"]);
+ break;
+ }
+ }
+
+ void SwitchboardServerConnection::dispatchCommand(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &)>::iterator i = commandHandlers.find(args[0]);
+ if (i != commandHandlers.end())
+ (this->*commandHandlers[args[0]])(args);
+ }
+
+ int SwitchboardServerConnection::sendMessage(const Message *msg)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::string s = msg->asString();
+
+ std::ostringstream buf_;
+ buf_ << "MSG " << this->trID << " A " << (int) s.size() << "\r\n" << s;
+ this->write(buf_);
+ this->addCallback(&SwitchboardServerConnection::callback_messageACK, this->trID, NULL);
+ return this->trID++;
+ }
+
+ int SwitchboardServerConnection::sendMessage(const std::string & body)
+ {
+ Message msg(body, "MIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\n");
+ return this->sendMessage(&msg);
+ }
+
+ void SwitchboardServerConnection::sendKeepAlive()
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::string s("MIME-Version: 1.0\r\nContent-Type: text/x-keepalive\r\n\r\n");
+ std::ostringstream buf_;
+ buf_ << "MSG " << this->trID++ << " U " << (int) s.size() << "\r\n" << s;
+ this->write(buf_);
+ }
+
+ void SwitchboardServerConnection::handle_BYE(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ std::list<Passport> & list = this->users;
+ std::list<Passport>::iterator i;
+
+ this->myNotificationServer()->externalCallbacks.buddyLeftConversation(this, args[1]);
+
+ for (i = list.begin(); i != list.end(); i++)
+ {
+ if (*i == args[1])
+ {
+ list.remove(*i);
+ break;
+ }
+ }
+
+ if (this->users.empty() || (args.size() > 3 && args[3] == "1"))
+ {
+ this->disconnect();
+ }
+ }
+
+ void SwitchboardServerConnection::handle_JOI(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ if (args[1] == this->auth.username)
+ return;
+
+ if (this->auth.sessionID.empty() && this->connectionState() == SB_WAITING_FOR_USERS)
+ this->setConnectionState(SB_READY);
+
+ this->users.push_back(args[1]);
+ this->myNotificationServer()->externalCallbacks.buddyJoinedConversation(this, args[1], decodeURL(args[2]), 0);
+ }
+
+ void SwitchboardServerConnection::handle_NAK(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ this->myNotificationServer()->externalCallbacks.failedSendingMessage(this);
+ }
+
+ void SwitchboardServerConnection::handle_MSG(std::vector<std::string> & args)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ int msglen;
+ std::string msg;
+ std::string mime;
+ std::string body;
+ size_t tmp;
+
+ msglen = decimalFromString(args[3]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+
+ body = msg.substr(msg.find("\r\n\r\n") + 4);
+ mime = msg.substr(0, msg.size() - body.size());
+
+ std::string contentType;
+ Message::Headers headers = Message::Headers(mime);
+
+ std::string chunks = headers["Chunks"];
+ if(!chunks.empty())
+ {
+ // First packet of MultiPacket Data;
+ MultiPacketSession session;
+ std::string messageID = headers["Message-ID"];
+ session.chunks = decimalFromString(chunks);
+ session.mime = mime;
+ session.receivedChunks = 1;
+ session.body += body;
+ if(session.chunks != 1)
+ {
+ MultiPacketSessions[messageID] = session;
+ return;
+ }
+
+ }
+ else
+ {
+ std::string chunk = headers["Chunk"];
+ if(!chunk.empty())
+ {
+ // part of multipacket data
+ std::string messageID = headers["Message-ID"];
+ MultiPacketSession session = MultiPacketSessions[messageID];
+ session.body += body;
+ session.receivedChunks++;
+ if(session.chunks != session.receivedChunks)
+ {
+ MultiPacketSessions[messageID] = session;
+ return;
+ }
+ else
+ {
+ MultiPacketSessions.erase(messageID);
+ body = session.body;
+ mime = session.mime;
+ headers = Message::Headers(mime);
+ }
+ }
+ }
+ contentType = headers["Content-Type"];
+
+ if ((tmp = contentType.find("; charset")) != std::string::npos)
+ contentType = contentType.substr(0, tmp);
+
+ std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &, std::string, std::string)>::iterator i = messageHandlers.find(contentType);
+ if (i != messageHandlers.end())
+ (this->*(messageHandlers[contentType]))(args, mime, body);
+ }
+
+ void SwitchboardServerConnection::sendAction(std::string action)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-msnmsgr-datacast\r\n\r\n";
+ msg_ << "ID: 4\r\n";
+ msg_ << "Data: " << action << "\r\n" ;
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " U " << (int) msg_length << "\r\n" << msg_.str();
+
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::sendVoiceClip(std::string msnobject)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-msnmsgr-datacast\r\n\r\n";
+ msg_ << "ID: 3\r\n";
+ msg_ << "Data: " << msnobject << "\r\n\r\n";
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " N " << (int) msg_length << "\r\n" << msg_.str();
+
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::sendWink(std::string msnobject)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-msnmsgr-datacast\r\n\r\n";
+ msg_ << "ID: 2\r\n";
+ msg_ << "Data: " << msnobject << "\r\n\r\n";
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " N " << (int) msg_length << "\r\n" << msg_.str();
+
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::sendNudge()
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-msnmsgr-datacast\r\n\r\n";
+ msg_ << "ID: 1\r\n";
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " U " << (int) msg_length << "\r\n" << msg_.str();
+
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::sendInk(std::string image)
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+
+ if(users.size() == 1)
+ {
+ p2p.sendInk(*this, image);
+// return;
+ }
+
+ std::string body("base64:"+image);
+ bool one_packet = false;
+
+ if(body.size() <= 1202) // if we need more than 1 packet, then use multipacket
+ one_packet = true ;
+
+ if(one_packet)
+ {
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: image/gif\r\n\r\n";
+ msg_ << body;
+
+ size_t msg_length = msg_.str().size();
+ buf_ << "MSG " << this->trID++ << " N " << (int) msg_length << "\r\n" << msg_.str();
+ write(buf_);
+ return;
+ }
+ else
+ {
+ std::istringstream body_stream(body);
+ std::string messageid = new_branch();
+ std::vector<std::string> chunks;
+ // spliting the message
+ while(!body_stream.eof())
+ {
+ char *part = new char[1203];
+ memset(part,0,1203);
+ body_stream.read((char*)part, 1202);
+ std::string part1(part);
+ chunks.push_back(part1);
+ free(part);
+ }
+
+ // sending the first one
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: image/gif\r\n";
+ msg_ << "Message-ID: " << messageid << "\r\n";
+ msg_ << "Chunks: " << chunks.size() << "\r\n\r\n";
+ msg_ << chunks.front();
+
+ size_t msg_length = msg_.str().size();
+ buf_ << "MSG " << this->trID++ << " N " << (int) msg_length << "\r\n" << msg_.str();
+ write(buf_);
+
+ std::vector<std::string>::iterator i = chunks.begin();
+
+ for(int num=0; i!=chunks.end(); i++, num++)
+ {
+ if(i == chunks.begin())
+ continue;
+
+ std::ostringstream buf2_, msg2_;
+ msg2_ << "Message-ID: " << messageid << "\r\n";
+ msg2_ << "Chunk: " << num << "\r\n\r\n";
+ msg2_ << (*i);
+
+ size_t msg_length2 = msg2_.str().size();
+ buf2_ << "MSG " << this->trID++ << " N " << (int) msg_length2 << "\r\n" << msg2_.str();
+ write(buf2_);
+ }
+ }
+ }
+
+ void SwitchboardServerConnection::sendTypingNotification()
+ {
+ this->assertConnectionStateIsAtLeast(SB_READY);
+ std::ostringstream buf_, msg_;
+ msg_ << "MIME-Version: 1.0\r\n";
+ msg_ << "Content-Type: text/x-msmsgscontrol\r\n";
+ msg_ << "TypingUser: " << this->auth.username << "\r\n";
+ msg_ << "\r\n";
+ msg_ << "\r\n";
+ size_t msg_length = msg_.str().size();
+
+ buf_ << "MSG " << this->trID++ << " U " << (int) msg_length << "\r\n" << msg_.str();
+
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::inviteUser(Passport userName)
+ {
+ this->assertConnectionStateIsAtLeast(SB_WAITING_FOR_USERS);
+ std::ostringstream buf_;
+ buf_ << "CAL " << this->trID++ << " " << userName << "\r\n";
+ write(buf_);
+ }
+
+ void SwitchboardServerConnection::connect(const std::string & hostname, unsigned int port)
+ {
+ this->assertConnectionStateIs(SB_DISCONNECTED);
+
+ if ((this->sock = this->myNotificationServer()->externalCallbacks.connectToServer(hostname, port, &this->connected)) == NULL)
+ {
+ this->myNotificationServer()->externalCallbacks.showError(this, "Could not connect to switchboard server");
+ return;
+ }
+
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0, 1, false);
+ this->setConnectionState(SB_CONNECTING);
+
+ if (this->connected)
+ this->socketConnectionCompleted();
+
+ std::ostringstream buf_;
+ if (this->auth.sessionID.empty())
+ {
+ buf_ << "USR " << this->trID << " " << this->auth.username << " " << this->auth.cookie << "\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+ this->addCallback(&SwitchboardServerConnection::callback_InviteUsers, this->trID, NULL);
+ }
+ else
+ {
+ buf_ << "ANS " << this->trID << " " << this->auth.username << " " << this->auth.cookie << " " << this->auth.sessionID << "\r\n";
+ if (this->write(buf_) != buf_.str().size())
+ return;
+ this->myNotificationServer()->externalCallbacks.gotNewConnection(this);
+ this->addCallback(&SwitchboardServerConnection::callback_AnsweredCall, this->trID, NULL);
+ }
+
+ this->trID++;
+ }
+
+ void SwitchboardServerConnection::disconnect()
+ {
+ this->assertConnectionStateIsNot(SB_DISCONNECTED);
+ notificationServer.removeSwitchboardConnection(this);
+ this->myNotificationServer()->externalCallbacks.closingConnection(this);
+
+ std::list<FileTransferConnectionP2P *> list2 = _fileTransferConnectionsP2P;
+ std::list<FileTransferConnectionP2P *>::iterator j = list2.begin();
+ for (; j != list2.end(); j++)
+ {
+ removeFileTransferConnectionP2P(*j);
+ }
+
+ this->callbacks.clear();
+ Connection::disconnect();
+ this->setConnectionState(SB_DISCONNECTED);
+ }
+
+ void SwitchboardServerConnection::socketConnectionCompleted()
+ {
+ this->assertConnectionStateIs(SB_CONNECTING);
+ Connection::socketConnectionCompleted();
+ this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1, 0, false);
+ this->setConnectionState(SB_WAITING_FOR_USERS);
+ }
+
+ void SwitchboardServerConnection::handleIncomingData()
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ while (this->isWholeLineAvailable())
+ {
+ std::vector<std::string> args = this->getLine();
+ if (args[0] == "MSG" || args[0] == "NOT")
+ {
+ int dataLength = decimalFromString(args[3]);
+ if (this->readBuffer.find("\r\n") + 2 + dataLength > this->readBuffer.size())
+ return;
+ }
+ this->readBuffer = this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
+
+ int trid = 0;
+
+ if (args.size() > 1)
+ {
+ try
+ {
+ trid = decimalFromString(args[1]);
+ }
+ catch (...)
+ {
+ }
+ }
+
+ if (!this->callbacks.empty() && trid > 0)
+ {
+ if (this->callbacks.find(trid) != this->callbacks.end())
+ {
+ (this->*(this->callbacks[trid].first))(args, trid, this->callbacks[trid].second);
+ continue;
+ }
+ }
+ if (!this->callbacks2.empty() && trid > 0)
+ {
+ if (this->callbacks2.find(trid) != this->callbacks2.end())
+ {
+ (this->*(this->callbacks2[trid].first))(args, trid, this->callbacks2[trid].second);
+ continue;
+ }
+ }
+
+ if (isdigit(args[0][0]))
+ this->showError(decimalFromString(args[0]));
+ else
+ this->dispatchCommand(args);
+ }
+ }
+
+ void SwitchboardServerConnection::callback_messageACK(std::vector<std::string> & args, int trid, void *)
+ {
+ this->removeCallback(trid);
+ this->myNotificationServer()->externalCallbacks.gotMessageSentACK(this, trid);
+ }
+
+ void SwitchboardServerConnection::callback_InviteUsers(std::vector<std::string> & args, int trid, void *)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ this->removeCallback(trid);
+
+ if (args.size() < 3)
+ {
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ return;
+ }
+
+ if(args[2] != "OK")
+ {
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ return;
+ }
+
+ this->myNotificationServer()->externalCallbacks.gotSwitchboard(this, this->auth.tag);
+ this->myNotificationServer()->externalCallbacks.gotNewConnection(this);
+ }
+
+ void SwitchboardServerConnection::callback_continueTransfer(std::vector<std::string> & args, int trid, unsigned int sessionID)
+ {
+ this->removeP2PCallback(trid);
+ p2p.handle_MSGACKReceived(*this,sessionID, args[1]);
+ }
+
+ void SwitchboardServerConnection::fileTransferResponse(unsigned int sessionID, std::string filename, bool response)
+ {
+ p2p.handle_fileTransferResponse(*this,sessionID, filename, response);
+ }
+
+ void SwitchboardServerConnection::callback_AnsweredCall(std::vector<std::string> & args, int trid, void * data)
+ {
+ this->assertConnectionStateIs(SB_WAITING_FOR_USERS);
+ if (args.size() >= 3 && args[0] == "ANS" && args[2] == "OK")
+ return;
+
+ if (isdigit(args[0][0]))
+ {
+ this->removeCallback(trid);
+ this->showError(decimalFromString(args[0]));
+ this->disconnect();
+ return;
+ }
+
+ if (args.size() >= 6 && args[0] == "IRO")
+ {
+ if (args[4] == this->auth.username)
+ return;
+
+ this->users.push_back(args[4]);
+ this->myNotificationServer()->externalCallbacks.buddyJoinedConversation(this, args[4], decodeURL(args[5]), 1);
+ if (args[2] == args[3])
+ {
+ this->removeCallback(trid);
+ this->setConnectionState(SB_READY);
+ }
+ }
+ }
+
+ void SwitchboardServerConnection::requestEmoticon(unsigned int id, std::string filename, std::string msnobject, std::string alias)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ p2p.requestEmoticon(*this,id, filename, msnobject, alias);
+ }
+
+ void SwitchboardServerConnection::requestWink(unsigned int id, std::string filename, std::string msnobject)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ p2p.requestWink(*this,id, filename, msnobject);
+ }
+
+ void SwitchboardServerConnection::requestVoiceClip(unsigned int id, std::string filename, std::string msnobject)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ p2p.requestVoiceClip(*this,id, filename, msnobject);
+ }
+
+ void SwitchboardServerConnection::requestDisplayPicture(unsigned int id, std::string filename, std::string msnobject)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ p2p.requestDisplayPicture(*this,id, filename, msnobject);
+ }
+
+ void SwitchboardServerConnection::cancelFileTransfer(unsigned int id)
+ {
+ this->assertConnectionStateIsAtLeast(SB_CONNECTED);
+ p2p.cancelTransfer(*this,id);
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnswitchboardserverh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/switchboardserver.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,253 @@
</span><ins>+#ifndef __msn_switchboardserver_h__
+#define __msn_switchboardserver_h__
+
+/*
+ * switchboardserver.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <msn/message.h>
+#include <msn/authdata.h>
+#include <msn/connection.h>
+#include <msn/passport.h>
+#include <msn/p2p.h>
+#include <string>
+#include <cassert>
+
+#include "libmsn_export.h"
+
+namespace MSN
+{
+ class NotificationServerConnection;
+ class FileTransferConnectionP2P;
+
+ /** Represents a connection to a MSN switchboard.
+ */
+ class LIBMSN_EXPORT SwitchboardServerConnection : public Connection
+ {
+private:
+ typedef void (SwitchboardServerConnection::*SwitchboardServerCallback)(std::vector<std::string> & args, int trid, void *);
+ typedef void (SwitchboardServerConnection::*SwitchboardServerCallback2)(std::vector<std::string> & args, int trid, unsigned int sessionID);
+
+ typedef struct
+ {
+ int chunks;
+ int receivedChunks;
+ std::string mime;
+ std::string body;
+ } MultiPacketSession;
+
+public:
+ class AuthData : public ::MSN::AuthData
+ {
+public:
+ std::string sessionID;
+ bool direct_connection;
+ std::string cookie;
+ const void *tag;
+
+ AuthData(Passport & username_, const std::string & sessionID_,
+ const std::string & cookie_, const void *tag_=NULL) :
+ ::MSN::AuthData(username_), sessionID(sessionID_), cookie(cookie_), tag(tag_) {};
+
+ AuthData(Passport & username_, const void *tag_=NULL) :
+ ::MSN::AuthData(username_), sessionID(""), cookie(""), tag(tag_) {};
+ };
+
+ SwitchboardServerConnection::AuthData auth;
+
+ /** A list of the users in this switchboard session.
+ */
+ std::list<Passport> users;
+
+ P2P p2p;
+
+ SwitchboardServerConnection(AuthData & auth_, NotificationServerConnection &);
+ virtual ~SwitchboardServerConnection();
+ virtual void dispatchCommand(std::vector<std::string> & args);
+
+ /** Return a connection that is associated with @a fd.
+ *
+ * If @a fd is equal to @p sock, @c this is returned. Otherwise
+ * connectionWithSocket is sent to each FileTransferConnection
+ * until a match is found.
+ *
+ * @return The matching connection, if found. Otherwise, @c NULL.
+ */
+ Connection *connectionWithSocket(void *sock);
+
+ std::map<std::string, MultiPacketSession> MultiPacketSessions;
+
+ /** Add a FileTransferConnection to the list of associated connections.
+ */
+ void addFileTransferConnectionP2P(FileTransferConnectionP2P *);
+
+ /** Remove a FileTransferConnection from the list of associated connections.
+ */
+ void removeFileTransferConnectionP2P(FileTransferConnectionP2P *);
+
+ /** Send a typing notification to the switchboard server.
+ */
+ void sendTypingNotification();
+
+ /** Send a text action
+ */
+ void sendAction(std::string action);
+
+ /** Send a Voice Clip
+ */
+ void sendVoiceClip(std::string msnobject);
+
+ /** Send a Wink
+ */
+ void sendWink(std::string msnobject);
+
+ /** Send Ink
+ */
+ void sendInk(std::string image);
+
+ /** Send an emoticon
+ */
+ void sendEmoticon(std::string alias, std::string file);
+
+ /** Send a nudge
+ */
+ void sendNudge();
+
+ /** Send a keep alive message
+ */
+ void sendKeepAlive();
+
+ /** Send a file
+ */
+ void sendFile(MSN::fileTransferInvite ft);
+
+ /** Invite @a userName into this conversation.
+ */
+ void inviteUser(Passport userName);
+
+ /** Response to a file transfer invitation
+ */
+ void fileTransferResponse(unsigned int sessionID, std::string filename, bool response);
+
+ /** Cancel a file transfer in progress
+ */
+ void cancelFileTransfer(unsigned int sessionID);
+
+ virtual void connect(const std::string & hostname, unsigned int port);
+ virtual void disconnect();
+
+ /** Send formatted message, returns the trID
+ */
+ virtual int sendMessage(const Message *msg);
+
+ /** Send plain text message, returns the trID
+ */
+ virtual int sendMessage(const std::string & s);
+
+ /** Add @a cb as a callback that will be called when a response is received
+ * a transaction ID of @a trid.
+ */
+ virtual void addCallback(SwitchboardServerCallback, int trid, void *data);
+
+ // callback of msg acks
+ virtual void addP2PCallback(SwitchboardServerCallback2, int trid, unsigned int sessionID);
+
+ /** Remove callbacks for transaction ID @a trid.
+ */
+ virtual void removeCallback(int trid);
+
+ virtual void removeP2PCallback(int trid);
+
+ virtual void socketConnectionCompleted();
+
+ enum SwitchboardServerState
+ {
+ SB_DISCONNECTED,
+ SB_CONNECTING,
+ SB_CONNECTED,
+ SB_WAITING_FOR_USERS,
+ SB_READY
+ };
+
+ SwitchboardServerState connectionState() const { return this->_connectionState; };
+ virtual NotificationServerConnection *myNotificationServer() { return &notificationServer; };
+ void callback_continueTransfer(std::vector<std::string> & args, int trid, unsigned int sessionID);
+
+ /** Request an emoticon
+ */
+ void requestEmoticon(unsigned int id, std::string filename, std::string msnobject, std::string alias);
+
+ /** Request a voice clip
+ */
+ void requestVoiceClip(unsigned int id, std::string filename, std::string msnobject);
+
+ /** Request a wink
+ */
+ void requestWink(unsigned int id, std::string filename, std::string msnobject);
+
+ /** Request a display picture
+ */
+ void requestDisplayPicture(unsigned int id, std::string filename, std::string msnobject);
+protected:
+ virtual void handleIncomingData();
+ SwitchboardServerState _connectionState;
+
+ void setConnectionState(SwitchboardServerState s) { this->_connectionState = s; };
+ void assertConnectionStateIs(SwitchboardServerState s) { assert(this->_connectionState == s); };
+ void assertConnectionStateIsNot(SwitchboardServerState s) { assert(this->_connectionState != s); };
+ void assertConnectionStateIsAtLeast(SwitchboardServerState s) { assert(this->_connectionState >= s); };
+private:
+ NotificationServerConnection & notificationServer;
+ std::list<FileTransferConnectionP2P *> _fileTransferConnectionsP2P;
+
+ std::map<int, std::pair<SwitchboardServerCallback, void *> > callbacks;
+ std::map<int, std::pair<SwitchboardServerCallback2, unsigned int> > callbacks2;
+
+ static std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &)> commandHandlers;
+ static std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &, std::string, std::string)> messageHandlers;
+ void registerCommandHandlers();
+ void registerMessageHandlers();
+ void handle_BYE(std::vector<std::string> & args);
+ void handle_JOI(std::vector<std::string> & args);
+ void handle_NAK(std::vector<std::string> & args);
+ void handle_MSG(std::vector<std::string> & args);
+
+ void callback_InviteUsers(std::vector<std::string> & args, int trid, void * data);
+ void callback_AnsweredCall(std::vector<std::string> & args, int trid, void * data);
+ void callback_messageACK(std::vector<std::string> & args, int trid, void * data);
+
+ void handleInvite(Passport from, const std::string & friendly, const std::string & mime, const std::string & body);
+ void handleNewInvite(Passport & from, const std::string & friendly, const std::string & mime, const std::string & body);
+ void message_plain(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_invitation(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_typing_user(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_p2p(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_datacast(std::vector<std::string> & args, std::string mime, std::string body);
+ void message_emoticon(std::vector<std::string> & args, std::string mime, std::string body);
+public:
+ void message_ink(std::vector<std::string> & args, std::string mime, std::string body);
+
+ friend class Connection;
+ };
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnutilcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/util.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/util.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/util.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,623 @@
</span><ins>+/*
+ * util.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <iostream>
+#include <msn/util.h>
+#include <sstream>
+#include <errno.h>
+#include <cctype>
+#include <fstream>
+#include <openssl/rand.h>
+#include <cstring>
+#include <sys/timeb.h>
+#include "md5.h"
+#include "libsiren/siren7.h"
+
+#ifdef _WIN32
+#define random rand
+#endif
+
+namespace MSN
+{
+ std::pair<std::string, int> splitServerAddress(const std::string & address, int default_port)
+ {
+ size_t pos;
+ std::string host = address;
+ int port = default_port;
+
+ if ((pos = address.find(":")) != std::string::npos)
+ {
+ std::string port_s = address.substr(pos + 1);
+ host = address.substr(0, pos);
+ port = decimalFromString(port_s);
+ }
+
+ if (host == "" || port < 0)
+ throw std::runtime_error("Invalid zero-length address or negative port number!");
+
+ return std::make_pair(host, port);
+ }
+
+ std::string decodeURL(const std::string & s)
+ {
+ std::string out;
+ std::string::const_iterator i;
+
+ for (i = s.begin(); i != s.end(); i++)
+ {
+ if (*i == '%')
+ {
+ char entity[3] = {0, 0, 0};
+ if (++i == s.end())
+ break;
+
+ entity[0] = *i;
+
+ bool doBreak = false;
+ if (++i != s.end())
+ entity[1] = *i;
+ else
+ doBreak = true;
+
+ int c = strtol(entity, NULL, 16);
+ out += c;
+
+ if (doBreak)
+ break;
+ }
+ else
+ out += *i;
+ }
+ return out;
+ }
+
+ std::string encodeURL(const std::string & s)
+ {
+ std::string out;
+ std::string::const_iterator i;
+
+ for (i = s.begin(); i != s.end(); i++)
+ {
+ if(!(isalpha(*i) || isdigit(*i)))
+ {
+ unsigned char high_nibble = ((unsigned char) *i) >> 4;
+ unsigned char low_nibble = ((unsigned char) *i) & 0x0F;
+ out += '%';
+ out += (high_nibble < 0x0A ? '0' + high_nibble : 'A' + high_nibble - 0x0A);
+ out += (low_nibble < 0x0A ? '0' + low_nibble : 'A' + low_nibble - 0x0A);
+
+ continue;
+ }
+ out += *i;
+ }
+
+ return out;
+ }
+
+ std::vector<std::string> splitString(const std::string & s, const std::string & sep, bool suppressBlanks)
+ {
+ std::vector<std::string> array;
+ size_t position, last_position;
+
+ last_position = position = 0;
+ while (position + sep.size() <= s.size())
+ {
+ if (s[position] == sep[0] && s.substr(position, sep.size()) == sep)
+ {
+ if (!suppressBlanks || position - last_position > 0)
+ array.push_back(s.substr(last_position, position - last_position));
+ last_position = position = position + sep.size();
+ }
+ else
+ position++;
+ }
+ if (!suppressBlanks || last_position - s.size())
+ array.push_back(s.substr(last_position));
+
+ return array;
+ }
+
+ int nocase_cmp(const std::string & s1, const std::string& s2)
+ {
+ std::string::const_iterator it1, it2;
+
+ for (it1 = s1.begin(), it2 = s2.begin();
+ it1 != s1.end() && it2 != s2.end();
+ ++it1, ++it2)
+ {
+ if (std::toupper(*it1) != std::toupper(*it2))
+ return std::toupper(*it1) - std::toupper(*it2);
+ }
+ size_t size1 = s1.size(), size2 = s2.size();
+ return (int) (size1 - size2);
+ }
+
+ std::string toStr(int var) {
+ std::ostringstream tmp; tmp << var; return tmp.str();
+ }
+
+ std::string unsignedToStr(unsigned int var) {
+ std::ostringstream tmp; tmp << var; return tmp.str();
+ }
+
+ unsigned int decimalFromString(const std::string & s) throw (std::logic_error)
+ {
+ unsigned int result = strtol(s.c_str(), NULL, 10);
+ errno = 0;
+ if (result == 0 && errno != 0)
+ throw std::logic_error(strerror(errno));
+ return result;
+ }
+
+ std::string hmac_sha(std::string key, std::string message)
+ {
+ unsigned int buf_len=0;
+ unsigned char buf[50];
+ memset(&buf,0,50);
+ HMAC(EVP_sha1(), key.c_str(), key.length(), (const unsigned char*)message.c_str(), message.length(), buf, &buf_len);
+ std::string a((char *)buf,buf_len);
+ return a;
+ }
+
+ std::string derive_key(std::string key, std::string magic)
+ {
+ std::string hash1(hmac_sha(key, magic));
+ std::string hash2(hmac_sha(key, hash1+magic));
+ std::string hash3(hmac_sha(key, hash1));
+ std::string hash4(hmac_sha(key, hash3+magic));
+ std::string final(hash2+hash4.substr(0,4));
+ return final;
+ }
+
+ std::string b64_encode(const char *input, int t)
+ {
+ BIO *mbio, *b64bio, *bio;
+ char *outbuf;
+ int inlen, outlen;
+ char *output;
+
+ mbio = BIO_new(BIO_s_mem());
+ b64bio = BIO_new(BIO_f_base64());
+ BIO_set_flags(b64bio, BIO_FLAGS_BASE64_NO_NL);
+ bio = BIO_push(b64bio, mbio);
+
+ inlen = t ;
+ if (BIO_write(bio, input, inlen) != inlen) {
+ return "";
+ }
+ BIO_flush(bio);
+
+ outlen = BIO_get_mem_data(bio, &outbuf);
+
+ output = (char*) malloc(outlen+1);
+ memcpy(output, outbuf, outlen);
+ output[outlen] = '\0';
+ std::string output1(output);
+ BIO_free_all(bio);
+ free(output);
+
+ return output1;
+ }
+
+ std::string b64_decode(const char *input)
+ {
+ BIO *mbio, *b64bio, *bio;
+ int inlen, outlen;
+ char *output;
+
+ mbio = BIO_new_mem_buf((void *)input, -1);
+ b64bio = BIO_new(BIO_f_base64());
+ BIO_set_flags(b64bio, BIO_FLAGS_BASE64_NO_NL);
+ bio = BIO_push(b64bio, mbio);
+
+ inlen = strlen(input);
+ outlen = inlen*2;
+
+ output = (char*) malloc(outlen+1);
+
+ if ((outlen = BIO_read(bio, output, outlen)) <= 0) {
+ return "";
+ }
+ output[outlen] = '\0';
+ std::string output1(output, outlen);
+ free(output);
+ BIO_free_all(bio);
+
+ return output1;
+ }
+
+ std::string mdi_encrypt(std::string key, std::string nonce)
+ {
+ tagMSGRUSRKEY MSGUSRKEY;
+ std::string key1,key2,key3;
+
+ key1 = b64_decode(key.c_str());
+ key2 = derive_key(key1, "WS-SecureConversationSESSION KEY HASH");
+ key3 = derive_key(key1, "WS-SecureConversationSESSION KEY ENCRYPTION");
+
+ std::string hash = hmac_sha(key2, nonce);
+
+ unsigned char workvec[8];
+ RAND_bytes(workvec, 8);
+ des_key_schedule ks1,ks2,ks3;
+
+ const char *one=key3.c_str();
+ const char *two=key3.c_str()+8;
+ const char *three=key3.c_str()+16;
+
+ des_set_key((C_Block *)one,ks1);
+ des_set_key((C_Block *)two,ks2);
+ des_set_key((C_Block *)three,ks3);
+
+ unsigned char output[72];
+ memset(&output,0,72);
+
+ memcpy(&MSGUSRKEY.aIVBytes, &workvec, sizeof(workvec));
+ memcpy(&MSGUSRKEY.aHashBytes, hash.c_str() , hash.length());
+
+ // ugly, but I think it is working properly
+ std::ostringstream buf_;
+ buf_ << nonce << "\x08\x08\x08\x08\x08\x08\x08\x08";
+ DES_ede3_cbc_encrypt((const unsigned char*)buf_.str().c_str(),output,buf_.str().size(),&ks1,&ks2,&ks3,(C_Block *)workvec,DES_ENCRYPT);
+
+ MSGUSRKEY.uStructHeaderSize=28;
+ MSGUSRKEY.uCryptMode=1;
+ MSGUSRKEY.uCipherType=0x6603;
+ MSGUSRKEY.uHashType=0x8004;
+ MSGUSRKEY.uIVLen=8;
+ MSGUSRKEY.uHashLen=hash.length();
+ MSGUSRKEY.uCipherLen=72;
+
+ // set
+ memcpy(&MSGUSRKEY.aCipherBytes,output, 72);
+ unsigned char a[129]; // last is \0 to b64_encode
+ memset(&a,0,129);
+ memcpy(&a, &MSGUSRKEY, sizeof(tagMSGRUSRKEY));
+
+ return b64_encode((const char*)a,128);
+ }
+
+ void DoMSNP11Challenge(const char *szChallenge, char *szOutput)
+ {
+ int i;
+ md5_state_t state;
+ md5_byte_t digest[16];
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)szChallenge, strlen(szChallenge));
+ md5_append(&state, (const md5_byte_t *)szClientCode, strlen(szClientCode));
+ md5_finish(&state, digest);
+
+ unsigned char pMD5Hash[16];
+ memcpy(pMD5Hash,digest,16);
+ int *pMD5Parts=(int *)digest;
+ for (i=0; i<4; i++) {
+ pMD5Parts[i]&=0x7FFFFFFF;
+ }
+ int nchlLen=strlen(szChallenge)+strlen(szClientID);
+ if (nchlLen%8!=0)
+ nchlLen+=8-(nchlLen%8);
+ char *chlString=new char[nchlLen];
+ memset(chlString,'0',nchlLen);
+ memcpy(chlString,szChallenge,strlen(szChallenge));
+ memcpy(chlString+strlen(szChallenge),szClientID,strlen(szClientID));
+ int *pchlStringParts=(int *)chlString;
+
+ long long nHigh=0;
+ long long nLow=0;
+
+ for (i=0; i<(nchlLen/4)-1; i+=2) {
+ long long temp=pchlStringParts[i];
+ temp=(pMD5Parts[0] * (((0x0E79A9C1 * (long long)pchlStringParts[i]) % 0x7FFFFFFF)+nHigh) + pMD5Parts[1])%0x7FFFFFFF;
+ nHigh=(pMD5Parts[2] * (((long long)pchlStringParts[i+1]+temp) % 0x7FFFFFFF) + pMD5Parts[3]) % 0x7FFFFFFF;
+ nLow=nLow + nHigh + temp;
+ }
+ nHigh=(nHigh+pMD5Parts[1]) % 0x7FFFFFFF;
+ nLow=(nLow+pMD5Parts[3]) % 0x7FFFFFFF;
+ delete[] chlString;
+
+ unsigned int *pNewHash=(unsigned int *)pMD5Hash;
+
+ pNewHash[0]^=nHigh;
+ pNewHash[1]^=nLow;
+ pNewHash[2]^=nHigh;
+ pNewHash[3]^=nLow;
+
+ char szHexChars[]="0123456789abcdef";
+ for (i=0; i<16; i++) {
+ szOutput[i*2]=szHexChars[(pMD5Hash[i]>>4)&0xF];
+ szOutput[(i*2)+1]=szHexChars[pMD5Hash[i]&0xF];
+ }
+ }
+ // 4-byte number
+ unsigned int little2big_endian(unsigned int i)
+ {
+ return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
+ }
+
+ int FileSize(const char* sFileName)
+ {
+ std::ifstream f;
+ f.open(sFileName, std::ios_base::binary | std::ios_base::in);
+ if (!f.good() || f.eof() || !f.is_open()) { return 0; }
+ f.seekg(0, std::ios_base::beg);
+ std::ifstream::pos_type begin_pos = f.tellg();
+ f.seekg(0, std::ios_base::end);
+ return static_cast<int>(f.tellg() - begin_pos);
+ }
+
+ std::string new_branch()
+ {
+ struct timeb t;
+ ftime(&t);
+ char branch[100];
+ srand(t.millitm);
+ unsigned int a=random();
+ srand(a);
+ unsigned short b=random();
+ srand(b);
+ unsigned short c=random();
+ srand(c);
+ unsigned short d=random();
+ srand(d);
+ double e=random();
+ sprintf(branch,"{%.8X-%.4X-%.4X-%.4X-%.12X}",a,b,c,d,(unsigned int)e);
+ std::string newbranch(branch);
+ return newbranch;
+ }
+
+ // Code from http://search.cpan.org/src/DANKOGAI/Jcode-2.06/Unicode/uni.c
+ U32 _ucs2_utf8(U8 *dst, U8 *src, U32 nchar)
+ {
+ U32 ucs2;
+ U32 result = 0;
+ for (nchar /= 2; nchar > 0; nchar--, src += 2) {
+ ucs2 = src[0]*256 + src[1];
+ if (ucs2 < 0x80){ /* 1 byte */
+ *dst++ = ucs2;
+ result += 1;
+ }else if (ucs2 < 0x800){ /* 2 bytes */
+ *dst++ = (0xC0 | (ucs2 >> 6));
+ *dst++ = (0x80 | (ucs2 & 0x3F));
+ result += 2;
+ }else{ /* 3 bytes */
+ *dst++ = (0xE0 | (ucs2 >> 12));
+ *dst++ = (0x80 | ((ucs2 >> 6) & 0x3F));
+ *dst++ = (0x80 | (ucs2 & 0x3F));
+ result += 3;
+ }
+ }
+ *dst = '\0';
+ return result;
+ }
+
+ U32 _utf8_ucs2(U8 *dst, U8 *src)
+ {
+ U32 ucs2;
+ U8 c1, c2, c3;
+ U32 result = 0;
+
+ for(; *src != '\0'; src++, result++){
+ if (*src < 0x80) { /* 1 byte */
+ ucs2 = *src;
+ }else if (*src < 0xE0){ /* 2 bytes */
+ if (src[1]){
+ c1 = *src++; c2 = *src;
+ ucs2 = ((c1 & 0x1F) << 6) | (c2 & 0x3F);
+ }else{
+ ucs2 = FB_UNI;
+ }
+ }else{ /* 3 bytes */
+ if (src[1] && src[2]){
+ c1 = *src++; c2 = *src++; c3 = *src;
+ ucs2 = ((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6)| (c3 & 0x3F);
+ }else{
+ ucs2 = FB_UNI;
+ if (src[1])
+ src++;
+ }
+ }
+ *dst++ = (ucs2 & 0xff00) >> 8; /* 1st byte */
+ *dst++ = (ucs2 & 0xff); /* 2nd byte */;
+ }
+ return result * 2;
+ }
+
+ // convert from siren codec to a regular wav file
+ void
+ libmsn_Siren7_DecodeVoiceClip(std::string input_file)
+ {
+ FILE * input;
+ FILE * output;
+ riff_data riff_header;
+ wav_data current_chunk;
+ fmt_chunk_ex fmt_info;
+ unsigned char *out_data = NULL;
+ unsigned char *out_ptr = NULL;
+ unsigned char in_buffer[40];
+ unsigned int file_offset;
+ unsigned int chunk_offset;
+
+ std::string new_voice(input_file.c_str());
+ std::string old_voice = new_voice + "-old";
+ rename(new_voice.c_str(), old_voice.c_str());
+
+ SirenDecoder decoder = Siren7_NewDecoder (16000);
+
+ input = fopen (old_voice.c_str(), "rb");
+ output = fopen (new_voice.c_str(), "wb");
+
+ file_offset = 0;
+ fread (&riff_header, sizeof (riff_data), 1, input);
+ file_offset += sizeof (riff_data);
+
+ riff_header.chunk_id = GUINT32_FROM_LE (riff_header.chunk_id);
+ riff_header.chunk_size = GUINT32_FROM_LE (riff_header.chunk_size);
+ riff_header.type_id = GUINT32_FROM_LE (riff_header.type_id);
+
+ if (riff_header.chunk_id == RIFF_ID && riff_header.type_id == WAVE_ID)
+ {
+ while (file_offset < riff_header.chunk_size)
+ {
+ fread (&current_chunk, sizeof (wav_data), 1, input);
+ file_offset += sizeof (wav_data);
+ current_chunk.chunk_id = GUINT32_FROM_LE (current_chunk.chunk_id);
+ current_chunk.chunk_size = GUINT32_FROM_LE (current_chunk.chunk_size);
+
+ chunk_offset = 0;
+ if (current_chunk.chunk_id == FMT_ID)
+ {
+ fread (&fmt_info, sizeof (fmt_chunk), 1, input);
+ /* Should convert from LE the fmt_info structure, but it's not necessary... */
+ if (current_chunk.chunk_size > sizeof (fmt_chunk))
+ {
+ fread (&(fmt_info.extra_size), sizeof (short), 1, input);
+ fmt_info.extra_size = GUINT32_FROM_LE (fmt_info.extra_size);
+ fmt_info.extra_content = (unsigned char *) malloc (fmt_info.extra_size);
+ fread (fmt_info.extra_content, fmt_info.extra_size, 1, input);
+ }
+ else
+ {
+ fmt_info.extra_size = 0;
+ fmt_info.extra_content = NULL;
+ }
+ }
+ else if (current_chunk.chunk_id == DATA_ID)
+ {
+ out_data = (unsigned char *) malloc (current_chunk.chunk_size * 16);
+ out_ptr = out_data;
+ while (chunk_offset + 40 <= current_chunk.chunk_size)
+ {
+ fread (in_buffer, 1, 40, input);
+ Siren7_DecodeFrame (decoder, in_buffer, out_ptr);
+ out_ptr += 640;
+ chunk_offset += 40;
+ }
+ fread (in_buffer, 1, current_chunk.chunk_size - chunk_offset, input);
+ }
+ else
+ {
+ fseek (input, current_chunk.chunk_size, SEEK_CUR);
+ }
+
+ file_offset += current_chunk.chunk_size;
+ }
+ }
+
+ /* The WAV heder should be converted TO LE, but should be done inside the library and it's not important for now ... */
+ fwrite (&(decoder->WavHeader), sizeof (decoder->WavHeader), 1, output);
+ fwrite (out_data, 1, GUINT32_FROM_LE (decoder->WavHeader.DataSize), output);
+ fclose (output);
+
+ Siren7_CloseDecoder (decoder);
+
+ free (out_data);
+ free (fmt_info.extra_content);
+
+ // remove the siren encoded file
+ unlink(old_voice.c_str());
+ }
+
+ // convert to siren codec from a regular wav file
+ void
+ libmsn_Siren7_EncodeVoiceClip(std::string input_file)
+ {
+ FILE * input;
+ FILE * output;
+ riff_data riff_header;
+ wav_data current_chunk;
+ fmt_chunk_ex fmt_info;
+ unsigned char *out_data = NULL;
+ unsigned char *out_ptr = NULL;
+ unsigned char InBuffer[640];
+ unsigned int fileOffset;
+ unsigned int chunkOffset;
+
+ SirenEncoder encoder = Siren7_NewEncoder(16000);
+
+ std::string new_voice(input_file.c_str());
+ std::string old_voice = new_voice + "-old";
+ rename(new_voice.c_str(), old_voice.c_str());
+
+ input = fopen (old_voice.c_str(), "rb");
+ output = fopen (new_voice.c_str(), "wb");
+
+ fileOffset = 0;
+ fread(&riff_header, sizeof(riff_data), 1, input);
+ fileOffset += sizeof(riff_data);
+
+ riff_header.chunk_id = GUINT32_FROM_LE(riff_header.chunk_id);
+ riff_header.chunk_size = GUINT32_FROM_LE(riff_header.chunk_size);
+ riff_header.type_id = GUINT32_FROM_LE(riff_header.type_id);
+
+ if (riff_header.chunk_id == RIFF_ID && riff_header.type_id == WAVE_ID) {
+ while (fileOffset < riff_header.chunk_size) {
+ fread(&current_chunk, sizeof(wav_data), 1, input);
+ fileOffset += sizeof(wav_data);
+ current_chunk.chunk_id = GUINT32_FROM_LE(current_chunk.chunk_id);
+ current_chunk.chunk_size = GUINT32_FROM_LE(current_chunk.chunk_size);
+
+ chunkOffset = 0;
+ if (current_chunk.chunk_id == FMT__ID) {
+ fread(&fmt_info, sizeof(fmt_chunk), 1, input);
+ /* Should convert from LE the fmt_info structure, but it's not necessary... */
+ if (current_chunk.chunk_size > sizeof(fmt_chunk)) {
+ fread(&(fmt_info.extra_size), sizeof(short), 1, input);
+ fmt_info.extra_size= GUINT32_FROM_LE(fmt_info.extra_size);
+ fmt_info.extra_content = (unsigned char *) malloc (fmt_info.extra_size);
+ fread(fmt_info.extra_content, fmt_info.extra_size, 1, input);
+ } else {
+ fmt_info.extra_size = 0;
+ fmt_info.extra_content = NULL;
+ }
+ } else if (current_chunk.chunk_id == DATA_ID) {
+ out_data = (unsigned char *) malloc(current_chunk.chunk_size / 16);
+ out_ptr = out_data;
+ while (chunkOffset + 640 <= current_chunk.chunk_size) {
+ fread(InBuffer, 1, 640, input);
+ Siren7_EncodeFrame(encoder, InBuffer, out_ptr);
+ out_ptr += 40;
+ chunkOffset += 640;
+ }
+ fread(InBuffer, 1, current_chunk.chunk_size - chunkOffset, input);
+ } else {
+ fseek(input, current_chunk.chunk_size, SEEK_CUR);
+ }
+ fileOffset += current_chunk.chunk_size;
+ }
+ }
+
+ /* The WAV heder should be converted TO LE, but should be done inside the library and it's not important for now ... */
+ fwrite(&(encoder->WavHeader), sizeof(encoder->WavHeader), 1, output);
+ fwrite(out_data, 1, GUINT32_FROM_LE(encoder->WavHeader.DataSize), output);
+ fclose(output);
+
+ Siren7_CloseEncoder(encoder);
+
+ free(out_data);
+ if (fmt_info.extra_content != NULL)
+ free(fmt_info.extra_content);
+
+ // remove the siren encoded file
+ unlink(old_voice.c_str());
+ }
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnutilh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/util.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/util.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/util.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,284 @@
</span><ins>+#ifndef __msn_util_h__
+#define __msn_util_h__
+
+/*
+ * util.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Refactored by Tiago Salem Herrmann on 08/2007.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/hmac.h>
+#include <openssl/des.h>
+
+#include <string>
+#include <sstream>
+#include <map>
+#include <vector>
+#include <stdexcept>
+#include <string>
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4290 )
+#endif
+
+// this is for CHL command
+#define szClientID "PROD0114ES4Z%Q5W"
+#define szClientCode "PK}_A_0N_K%O?A9S"
+
+#ifndef U8
+#define U8 unsigned char
+#endif
+#ifndef U16
+#define U16 unsigned short
+#endif
+#ifndef U32
+#define U32 unsigned int
+#endif
+#define FB_UNI 0xFFFd
+
+// for libsiren
+#define RIFF_ID 0x46464952
+#define WAVE_ID 0x45564157
+#define FMT_ID 0x20746d66
+#define DATA_ID 0x61746164
+#define FACT_ID 0x74636166
+
+typedef struct
+{
+ unsigned int chunk_id;
+ unsigned int chunk_size;
+} wav_data;
+
+typedef struct
+{
+ unsigned int chunk_id;
+ unsigned int chunk_size;
+ unsigned int type_id;
+} riff_data;
+
+typedef struct
+{
+ unsigned short format;
+ unsigned short channels;
+ unsigned int sample_rate;
+ unsigned int byte_rate;
+ unsigned short block_align;
+ unsigned short bits_per_sample;
+} fmt_chunk;
+
+typedef struct
+{
+ fmt_chunk fmt;
+ unsigned short extra_size;
+ unsigned char *extra_content;
+} fmt_chunk_ex;
+
+#define IDX(val, i) ((unsigned int) ((unsigned char *) &val)[i])
+
+#define GUINT16_FROM_LE(val) ((unsigned short) (IDX (val, 0) + (unsigned short) IDX (val, 1) * 256))
+#define GUINT32_FROM_LE(val) ((unsigned int) (IDX (val, 0) + IDX (val, 1) * 256 + \
+ IDX (val, 2) * 65536 + IDX (val, 3) * 16777216))
+
+namespace MSN
+{
+ /** URL-encode a string
+ *
+ * @param s The string to encode.
+ * @return A string with all non-alphanumeric characters replaced by their
+ * URL-encoded equivalent.
+ */
+ std::string encodeURL(const std::string & s);
+
+ /** URL-decode a string
+ *
+ * @param s The URL-encoded string to decode.
+ * @return A string with all URL-encoded sequences replaced by their
+ * @c ASCII equivalent.
+ */
+ std::string decodeURL(const std::string & s);
+
+ /** Split a string containing a hostname and port number into its respective parts.
+ *
+ * @param address A string in the form "hostname:port".
+ * @param default_port A port number to return in the event that ":port" is omitted from @a address.
+ * @return A pair containing the hostname and port number.
+ */
+ std::pair<std::string, int> splitServerAddress(const std::string & address, int default_port=1863);
+
+ /** Compare two strings in a case insensitive fashion
+ */
+ int nocase_cmp(const std::string & s1, const std::string & s2);
+
+ /** Split @a string at each occurence of @a separator.
+ */
+ std::vector<std::string> splitString(const std::string & string, const std::string & separator, bool suppressBlanks=true);
+
+ std::string toStr(int var);
+ std::string unsignedToStr(unsigned int var);
+ /** Convert a string, @a s, that contains decimal digits into an unsigned int.
+ */
+ unsigned int decimalFromString(const std::string & s) throw (std::logic_error);
+
+ U32 _ucs2_utf8(U8 *dst, U8 *src, U32 nchar);
+ U32 _utf8_ucs2(U8 *dst, U8 *src);
+
+ /** represents a contact pesonal message */
+ struct personalInfo
+ {
+ std::string PSM; /**< personal status message */
+ std::string mediaApp; /**< iTunes, Winamp or keep it empty */
+ std::string mediaType; /**< 'Music', 'Games' or 'Office' */
+ bool mediaIsEnabled; /**< enable/disable the Current Media setting */
+ std::string mediaFormat; /**< for example, "{0} - {1}" */
+ std::vector<std::string> mediaLines; /**< index 0 will be {0}, etc.. */
+
+ personalInfo() {
+ mediaIsEnabled = false;
+ }
+ };
+
+ struct hotmailInfo
+ {
+ std::string rru;
+ std::string url;
+ std::string id;
+ std::string sl;
+ std::string kv;
+ std::string sid;
+ std::string MSPAuth;
+ std::string creds;
+ };
+
+ /** Represents the lists present on server side */
+ typedef enum
+ {
+ LST_AB = 1, /**< Address book */
+ LST_AL = 2, /**< Allow */
+ LST_BL = 4, /**< Block */
+ LST_RL = 8, /**< Reverse */
+ LST_PL = 16 /**< Pending */
+ }ContactList;
+
+ struct tagMSGRUSRKEY
+ {
+ unsigned int uStructHeaderSize; // 28. Does not count data
+ unsigned int uCryptMode; // CRYPT_MODE_CBC (1)
+ unsigned int uCipherType; // TripleDES (0x6603)
+ unsigned int uHashType; // SHA1 (0x8004)
+ unsigned int uIVLen; // 8
+ unsigned int uHashLen; // 20
+ unsigned int uCipherLen; // 72
+ // Data
+ unsigned char aIVBytes[8];
+ unsigned char aHashBytes[20];
+ unsigned char aCipherBytes[72];
+ };
+
+ /** represents an offline message */
+ typedef struct
+ {
+ std::string from; /**< sender passport */
+ std::string fromFN; /**< sender nickname */
+ std::string id; /**< ID of this offline message */
+ } eachOIM;
+
+ std::string new_branch();
+ std::string generate_soap_auth(std::string user, std::string pass, std::string ticket);
+ std::string mdi_encrypt(std::string key, std::string nonce);
+ std::string b64_decode(const char *input);
+ std::string b64_encode(const char *input, int size);
+
+ unsigned int little2big_endian(unsigned int i);
+ int FileSize(const char* sFileName);
+ void DoMSNP11Challenge(const char *szChallenge, char *szOutput);
+
+ // stolen from kopete
+ /** List of possible capabilities for a contact */
+ typedef enum
+ {
+ WindowsMobile = 0x1,
+ InkGifSupport = 0x4,
+ InkIsfSupport = 0x8,
+ SupportWebcam = 0x10,
+ SupportMultiPacketMessaging = 0x20,
+ MSNMobileDevice = 0x40,
+ MSNDirectDevice = 0x80,
+ WebMessenger = 0x100,
+ OtherSideWebMessenger = 0x200,
+ InternalMicrosoftClient = 0x800, //Internal Microsoft client and/or Microsoft Office Live client.
+ MSNSpace = 0x1000,
+ WinXPMediaCenter = 0x2000, // This means you are using Windows XP Media Center Edition.
+ SupportDirectIM = 0x4000,
+ SupportWinks = 0x8000,
+ MSNSearch = 0x10000,
+ VoiceClips = 0x40000,
+ SecureChannel = 0x80000,
+ SIPInvitations = 0x100000,
+ TunnelSIPInvitations = 0x200000,
+ SharingFolders = 0x400000,
+ MSNC1 = 0x10000000,
+ MSNC2 = 0x20000000,
+ MSNC3 = 0x30000000,
+ MSNC4 = 0x40000000,
+ MSNC5 = 0x50000000,
+ MSNC6 = 0x60000000,
+ MSNC7 = 0x70000000,
+        MSNC8 = 0x80000000,
+        MSNC9 = 0x90000000,
+        MSNC10 = 0xA0000000,
+        P2PAware = 0xF0000000
+ } MSNClientInformationFields;
+
+ /** Defines the file transfer type */
+ enum fileTransferType
+ {
+ FILE_TRANSFER_WITH_PREVIEW = 0x0, /**< With preview */
+ FILE_TRANSFER_WITHOUT_PREVIEW = 0x1, /**< Without preview */
+ FILE_TRANSFER_BACKGROUND_SHARING = 0x4, /**< Transfer of a sharing background */
+ // it is not a simple jpg file, there is a cab file inside it
+ FILE_TRANSFER_BACKGROUND_SHARING_CUSTOM = 0xC /**< Custom and not supported by libmsn yet */
+ };
+
+ /** Type of the error when a file transfer fails */
+ enum fileTransferError
+ {
+ FILE_TRANSFER_ERROR_USER_CANCELED, /**< The other user canceled */
+ FILE_TRANSFER_ERROR_UNKNOWN /**< Unknown error */
+ };
+
+ /** Represents a file transfer request */
+ typedef struct
+ {
+ int type; /**< 0 = no preview, 1 = has preview, 4 = background sharing */
+ unsigned int sessionId; /**< Id of this session */
+ std::string userPassport; /**< passport of the origin or the destination */
+ std::string filename; /**< name the file to receive, or the path of the file to send */
+ std::string friendlyname; /**< suggested name <- required when sending a file */
+ std::string preview; /**< base64 encoded 96x96 png file, if applicable */
+ unsigned long long filesize; /**< size of the file to send or receive */
+ } fileTransferInvite;
+
+ void libmsn_Siren7_DecodeVoiceClip(std::string input_file);
+ void libmsn_Siren7_EncodeVoiceClip(std::string input_file);
+}
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnxmlParsercpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,2675 @@
</span><ins>+/**
+ ****************************************************************************
+ * <P> XML.c - implementation file for basic XML parser written in ANSI C++
+ * for portability. It works by using recursion and a node tree for breaking
+ * down the elements of an XML document. </P>
+ *
+ * @version V2.29
+ * @author Frank Vanden Berghen
+ *
+ * NOTE:
+ *
+ * If you add "#define STRICT_PARSING", on the first line of this file
+ * the parser will see the following XML-stream:
+ * <a><b>some text</b><b>other text </a>
+ * as an error. Otherwise, this tring will be equivalent to:
+ * <a><b>some text</b><b>other text</b></a>
+ *
+ * NOTE:
+ *
+ * If you add "#define APPROXIMATE_PARSING" on the first line of this file
+ * the parser will see the following XML-stream:
+ * <data name="n1">
+ * <data name="n2">
+ * <data name="n3" />
+ * as equivalent to the following XML-stream:
+ * <data name="n1" />
+ * <data name="n2" />
+ * <data name="n3" />
+ * This can be useful for badly-formed XML-streams but prevent the use
+ * of the following XML-stream (problem is: tags at contiguous levels
+ * have the same names):
+ * <data name="n1">
+ * <data name="n2">
+ * <data name="n3" />
+ * </data>
+ * </data>
+ *
+ * NOTE:
+ *
+ * If you add "#define _XMLPARSER_NO_MESSAGEBOX_" on the first line of this file
+ * the "openFileHelper" function will always display error messages inside the
+ * console instead of inside a message-box-window. Message-box-windows are
+ * available on windows 9x/NT/2000/XP/Vista only.
+ *
+ * BSD license:
+ * Copyright (c) 2002, Frank Vanden Berghen
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Frank Vanden Berghen nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************
+ */
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#include "xmlParser.h"
+#ifdef _XMLWINDOWS
+//#ifdef _DEBUG
+//#define _CRTDBG_MAP_ALLOC
+//#include <crtdbg.h>
+//#endif
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
+ // to have "MessageBoxA" to display error messages for openFilHelper
+#endif
+
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+XMLCSTR XMLNode::getVersion() { return _T("v2.29"); }
+void freeXMLString(XMLSTR t){free(t);}
+
+static XMLNode::XMLCharEncoding characterEncoding=XMLNode::encoding_UTF8;
+static char guessWideCharChars=1, dropWhiteSpace=1;
+
+inline int mmin( const int t1, const int t2 ) { return t1 < t2 ? t1 : t2; }
+
+// You can modify the initialization of the variable "XMLClearTags" below
+// to change the clearTags that are currently recognized by the library.
+// The number on the second columns is the length of the string inside the
+// first column. The "<!DOCTYPE" declaration must be the second in the list.
+typedef struct { XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;} ALLXMLClearTag;
+static ALLXMLClearTag XMLClearTags[] =
+{
+ { _T("<![CDATA["),9, _T("]]>") },
+ { _T("<!DOCTYPE"),9, _T(">") },
+ { _T("<PRE>") ,5, _T("</PRE>") },
+ { _T("<Script>") ,8, _T("</Script>")},
+ { _T("<!--") ,4, _T("-->") },
+ { NULL ,0, NULL }
+};
+
+// You can modify the initialization of the variable "XMLEntities" below
+// to change the character entities that are currently recognized by the library.
+// The number on the second columns is the length of the string inside the
+// first column. Additionally, the syntaxes "&#xA0;" and "&#160;" are recognized.
+typedef struct { XMLCSTR s; int l; XMLCHAR c;} XMLCharacterEntity;
+static XMLCharacterEntity XMLEntities[] =
+{
+ { _T("&amp;" ), 5, _T('&' )},
+ { _T("&lt;" ), 4, _T('<' )},
+ { _T("&gt;" ), 4, _T('>' )},
+ { _T("&quot;"), 6, _T('\"')},
+ { _T("&apos;"), 6, _T('\'')},
+ { NULL , 0, '\0' }
+};
+
+// When rendering the XMLNode to a string (using the "createXMLString" function),
+// you can ask for a beautiful formatting. This formatting is using the
+// following indentation character:
+#define INDENTCHAR _T('\t')
+
+// The following function parses the XML errors into a user friendly string.
+// You can edit this to change the output language of the library to something else.
+XMLCSTR XMLNode::getError(XMLError xerror)
+{
+ switch (xerror)
+ {
+ case eXMLErrorNone: return _T("No error");
+ case eXMLErrorMissingEndTag: return _T("Warning: Unmatched end tag");
+ case eXMLErrorEmpty: return _T("Error: No XML data");
+ case eXMLErrorFirstNotStartTag: return _T("Error: First token not start tag");
+ case eXMLErrorMissingTagName: return _T("Error: Missing start tag name");
+ case eXMLErrorMissingEndTagName: return _T("Error: Missing end tag name");
+ case eXMLErrorNoMatchingQuote: return _T("Error: Unmatched quote");
+ case eXMLErrorUnmatchedEndTag: return _T("Error: Unmatched end tag");
+ case eXMLErrorUnmatchedEndClearTag: return _T("Error: Unmatched clear tag end");
+ case eXMLErrorUnexpectedToken: return _T("Error: Unexpected token found");
+ case eXMLErrorInvalidTag: return _T("Error: Invalid tag found");
+ case eXMLErrorNoElements: return _T("Error: No elements found");
+ case eXMLErrorFileNotFound: return _T("Error: File not found");
+ case eXMLErrorFirstTagNotFound: return _T("Error: First Tag not found");
+ case eXMLErrorUnknownCharacterEntity:return _T("Error: Unknown character entity");
+ case eXMLErrorCharConversionError: return _T("Error: unable to convert between WideChar and MultiByte chars");
+ case eXMLErrorCannotOpenWriteFile: return _T("Error: unable to open file for writing");
+ case eXMLErrorCannotWriteFile: return _T("Error: cannot write into file");
+
+ case eXMLErrorBase64DataSizeIsNotMultipleOf4: return _T("Warning: Base64-string length is not a multiple of 4");
+ case eXMLErrorBase64DecodeTruncatedData: return _T("Warning: Base64-string is truncated");
+ case eXMLErrorBase64DecodeIllegalCharacter: return _T("Error: Base64-string contains an illegal character");
+ case eXMLErrorBase64DecodeBufferTooSmall: return _T("Error: Base64 decode output buffer is too small");
+ };
+ return _T("Unknown");
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Here start the abstraction layer to be OS-independent //
+/////////////////////////////////////////////////////////////////////////
+
+// Here is an abstraction layer to access some common string manipulation functions.
+// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
+// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
+// If you plan to "port" the library to a new system/compiler, all you have to do is
+// to edit the following lines.
+#ifdef XML_NO_WIDE_CHAR
+char myIsTextWideChar(const void *b, int len) { return FALSE; }
+#else
+ #if defined (UNDER_CE) || !defined(WIN32)
+ char myIsTextWideChar(const void *b, int len) // inspired by the Wine API: RtlIsTextUnicode
+ {
+#ifdef sun
+ // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
+ if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
+#endif
+ const wchar_t *s=(const wchar_t*)b;
+
+ // buffer too small:
+ if (len<(int)sizeof(wchar_t)) return FALSE;
+
+ // odd length test
+ if (len&1) return FALSE;
+
+ /* only checks the first 256 characters */
+ len=mmin(256,len/sizeof(wchar_t));
+
+ // Check for the special byte order:
+ if (*((unsigned short*)s) == 0xFFFE) return TRUE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+ if (*((unsigned short*)s) == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE
+
+ // checks for ASCII characters in the UNICODE stream
+ int i,stats=0;
+ for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++;
+ if (stats>len/2) return TRUE;
+
+ // Check for UNICODE NULL chars
+ for (i=0; i<len; i++) if (!s[i]) return TRUE;
+
+ return FALSE;
+ }
+ #else
+ char myIsTextWideChar(const void *b,int l) { return (char)IsTextUnicode((CONST LPVOID)b,l,NULL); };
+ #endif
+#endif
+
+#ifdef _XMLWINDOWS
+// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET,
+ #ifdef _XMLWIDECHAR
+ wchar_t *myMultiByteToWideChar(const char *s)
+ {
+ int i;
+ if (characterEncoding==XMLNode::encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,NULL,0);
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,NULL,0);
+ if (i<0) return NULL;
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(XMLCHAR));
+ if (characterEncoding==XMLNode::encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,d,i);
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,d,i);
+ d[i]=0;
+ return d;
+ }
+ #else
+ char *myWideCharToMultiByte(const wchar_t *s)
+ {
+ UINT codePage=CP_ACP; if (characterEncoding==XMLNode::encoding_UTF8) codePage=CP_UTF8;
+ int i=(int)WideCharToMultiByte(codePage, // code page
+ 0, // performance and mapping flags
+ s, // wide-character string
+ -1, // number of chars in string
+ NULL, // buffer for new string
+ 0, // size of buffer
+ NULL, // default for unmappable chars
+ NULL // set when default char used
+ );
+ if (i<0) return NULL;
+ char *d=(char*)malloc(i+1);
+ WideCharToMultiByte(codePage, // code page
+ 0, // performance and mapping flags
+ s, // wide-character string
+ -1, // number of chars in string
+ d, // buffer for new string
+ i, // size of buffer
+ NULL, // default for unmappable chars
+ NULL // set when default char used
+ );
+ d[i]=0;
+ return d;
+ }
+ #endif
+ #ifdef __BORLANDC__
+ int _strnicmp(char *c1, char *c2, int l){ return strnicmp(c1,c2,l);}
+ #endif
+#else
+// for gcc and CC
+ #ifdef XML_NO_WIDE_CHAR
+ char *myWideCharToMultiByte(const wchar_t *s) { return NULL; }
+ #else
+ char *myWideCharToMultiByte(const wchar_t *s)
+ {
+ const wchar_t *ss=s;
+ int i=(int)wcsrtombs(NULL,&ss,0,NULL);
+ if (i<0) return NULL;
+ char *d=(char *)malloc(i+1);
+ wcsrtombs(d,&s,i,NULL);
+ d[i]=0;
+ return d;
+ }
+ #endif
+ #ifdef _XMLWIDECHAR
+ wchar_t *myMultiByteToWideChar(const char *s)
+ {
+ const char *ss=s;
+ int i=(int)mbsrtowcs(NULL,&ss,0,NULL);
+ if (i<0) return NULL;
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(wchar_t));
+ mbsrtowcs(d,&s,i,NULL);
+ d[i]=0;
+ return d;
+ }
+ int _tcslen(XMLCSTR c) { return wcslen(c); }
+ #ifdef sun
+ // for CC
+ #include <widec.h>
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncasecmp(c1,c2,l);}
+ int _tcsncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return wscasecmp(c1,c2); }
+ #else
+ // for gcc
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncasecmp(c1,c2,l);}
+ int _tcsncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return wcscasecmp(c1,c2); }
+ #endif
+ XMLSTR _tcsstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
+ XMLSTR _tcsncpy(XMLSTR c1, XMLCSTR c2, int n) {
+                        if (n<=0) {
+                                return NULL;
+                        }
+ XMLSTR result=(XMLSTR)wcsncpy(c1,c2,n);
+ result[n-1]=L'\0';
+ return result;
+ }
+ FILE *_tfopen(XMLCSTR filename,XMLCSTR mode)
+ {
+ char *filenameAscii=myWideCharToMultiByte(filename);
+ FILE *f;
+ if (mode[0]==_T('r')) f=fopen(filenameAscii,"rb");
+ else f=fopen(filenameAscii,"wb");
+ free(filenameAscii);
+ return f;
+ }
+ #else
+ FILE *_tfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
+ int _tcslen(XMLCSTR c) { return strlen(c); }
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncasecmp(c1,c2,l);}
+ int _tcsncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return strcasecmp(c1,c2); }
+ XMLSTR _tcsstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
+ XMLSTR _tcsncpy(XMLSTR c1, XMLCSTR c2, int n) {
+                        if (n<=0) {
+                                return NULL;
+                        }
+ XMLSTR result=(XMLSTR)strncpy(c1,c2,n);
+ result[n-1]='\0';
+ return result;
+ }
+ #endif
+ int _strnicmp(const char *c1,const char *c2, int l) { return strncasecmp(c1,c2,l);}
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// the "openFileHelper" function //
+/////////////////////////////////////////////////////////////////////////
+
+// Since each application has its own way to report and deal with errors, you should modify & rewrite
+// the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs.
+XMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag)
+{
+ // guess the value of the global parameter "characterEncoding"
+ // (the guess is based on the first 200 bytes of the file).
+ FILE *f=_tfopen(filename,_T("rb"));
+ if (f)
+ {
+ char bb[205];
+ int l=(int)fread(bb,1,200,f);
+ setGlobalOptions(guessCharEncoding(bb,l),guessWideCharChars,dropWhiteSpace);
+ fclose(f);
+ }
+
+ // parse the file
+ XMLResults pResults;
+ XMLNode xnode=XMLNode::parseFile(filename,tag,&pResults);
+
+ // display error message (if any)
+ if (pResults.error != eXMLErrorNone)
+ {
+ // create message
+ char message[2000],*s1=(char*)"",*s3=(char*)""; XMLCSTR s2=_T("");
+ if (pResults.error==eXMLErrorFirstTagNotFound) { s1=(char*)"First Tag should be '"; s2=tag; s3=(char*)"'.\n"; }
+ sprintf(message,
+#ifdef _XMLWIDECHAR
+ "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
+#else
+ "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
+#endif
+ ,filename,XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn,s1,s2,s3);
+
+ // display message
+#if defined(WIN32) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
+ MessageBoxA(NULL,message,"XML Parsing error",MB_OK|MB_ICONERROR|MB_TOPMOST);
+#else
+ printf("%s",message);
+#endif
+ exit(255);
+ }
+ return xnode;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Here start the core implementation of the XMLParser library //
+/////////////////////////////////////////////////////////////////////////
+
+// You should normally not change anything below this point.
+
+#ifndef _XMLWIDECHAR
+// If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte.
+// If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes).
+// If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes).
+// This table is used as lookup-table to know the length of a character (in byte) based on the
+// content of the first byte of the character.
+// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
+static const char XML_utf8ByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70End of ASCII range
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 0x80 to 0xc1 invalid
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
+ 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 0xc2 to 0xdf 2 byte
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,// 0xe0 0xe0 to 0xef 3 byte
+ 4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+static const char XML_asciiByteTable[256] =
+{
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+static const char XML_sjisByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 End of ASCII range
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0x9F 2 bytes
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xc0
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xd0
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 0xe0 to 0xef 2 bytes
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 // 0xf0
+};
+static const char *XML_ByteTable=(const char *)XML_utf8ByteTable; // the default is "characterEncoding=XMLNode::encoding_UTF8"
+#endif
+
+
+XMLNode XMLNode::emptyXMLNode;
+XMLClear XMLNode::emptyXMLClear={ NULL, NULL, NULL};
+XMLAttribute XMLNode::emptyXMLAttribute={ NULL, NULL};
+
+// Enumeration used to decipher what type a token is
+typedef enum XMLTokenTypeTag
+{
+ eTokenText = 0,
+ eTokenQuotedText,
+ eTokenTagStart, /* "<" */
+ eTokenTagEnd, /* "</" */
+ eTokenCloseTag, /* ">" */
+ eTokenEquals, /* "=" */
+ eTokenDeclaration, /* "<?" */
+ eTokenShortHandClose, /* "/>" */
+ eTokenClear,
+ eTokenError
+} XMLTokenType;
+
+// Main structure used for parsing XML
+typedef struct XML
+{
+ XMLCSTR lpXML;
+ XMLCSTR lpszText;
+ int nIndex,nIndexMissigEndTag;
+ enum XMLError error;
+ XMLCSTR lpEndTag;
+ int cbEndTag;
+ XMLCSTR lpNewElement;
+ int cbNewElement;
+ int nFirst;
+} XML;
+
+typedef struct
+{
+ ALLXMLClearTag *pClr;
+ XMLCSTR pStr;
+} NextToken;
+
+// Enumeration used when parsing attributes
+typedef enum Attrib
+{
+ eAttribName = 0,
+ eAttribEquals,
+ eAttribValue
+} Attrib;
+
+// Enumeration used when parsing elements to dictate whether we are currently
+// inside a tag
+typedef enum Status
+{
+ eInsideTag = 0,
+ eOutsideTag
+} Status;
+
+XMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const
+{
+ if (!d) return eXMLErrorNone;
+ FILE *f=_tfopen(filename,_T("wb"));
+ if (!f) return eXMLErrorCannotOpenWriteFile;
+#ifdef _XMLWIDECHAR
+ unsigned char h[2]={ 0xFF, 0xFE };
+ if (!fwrite(h,2,1,f)) return eXMLErrorCannotWriteFile;
+ if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
+ {
+ if (!fwrite(_T("<?xml version=\"1.0\" encoding=\"utf-16\"?>\n"),sizeof(wchar_t)*40,1,f))
+ return eXMLErrorCannotWriteFile;
+ }
+#else
+ if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
+ {
+ if (characterEncoding==encoding_UTF8)
+ {
+ // header so that windows recognize the file as UTF-8:
+ unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
+ encoding="utf-8";
+ } else if (characterEncoding==encoding_ShiftJIS) encoding="SHIFT-JIS";
+
+ if (!encoding) encoding="ISO-8859-1";
+ if (fprintf(f,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",encoding)<0) return eXMLErrorCannotWriteFile;
+ } else
+ {
+ if (characterEncoding==encoding_UTF8)
+ {
+ unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
+ }
+ }
+#endif
+ int i;
+ XMLSTR t=createXMLString(nFormat,&i);
+ if (!fwrite(t,sizeof(XMLCHAR)*i,1,f)) return eXMLErrorCannotWriteFile;
+ if (fclose(f)!=0) return eXMLErrorCannotWriteFile;
+ free(t);
+ return eXMLErrorNone;
+}
+
+// Duplicate a given string.
+XMLSTR stringDup(XMLCSTR lpszData, int cbData)
+{
+ if (lpszData==NULL) return NULL;
+
+ XMLSTR lpszNew;
+ if (cbData==0) cbData=(int)_tcslen(lpszData);
+ lpszNew = (XMLSTR)malloc((cbData+1) * sizeof(XMLCHAR));
+ if (lpszNew)
+ {
+ memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
+ lpszNew[cbData] = (XMLCHAR)NULL;
+ }
+ return lpszNew;
+}
+
+XMLSTR toXMLStringUnSafe(XMLSTR dest,XMLCSTR source,int length)
+{
+ XMLSTR dd=dest;
+ XMLCHAR ch;
+ XMLCharacterEntity *entity;
+ while ((ch=*source) && length > 0)
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (ch==entity->c)
+ {
+ _tcsncpy(dest,entity->s,length);
+ dest+=entity->l;
+ length-=entity->l;
+ source++;
+ goto out_of_loop1;
+ }
+ entity++;
+ } while(entity->s);
+ if (length > 0)
+ {
+#ifdef _XMLWIDECHAR
+ *(dest++)=*(source++);
+ length--;
+#else
+ switch(XML_ByteTable[(unsigned char)ch])
+ {
+ case 4: *(dest++)=*(source++); length--;
+ case 3: *(dest++)=*(source++); length--;
+ case 2: *(dest++)=*(source++); length--;
+ case 1: *(dest++)=*(source++); length--;
+ }
+ }
+#endif
+out_of_loop1:
+ ;
+ }
+ *dest=0;
+ return dd;
+}
+
+// private (used while rendering):
+int lengthXMLString(XMLCSTR source)
+{
+ int r=0;
+ XMLCharacterEntity *entity;
+ XMLCHAR ch;
+ while ((ch=*source))
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (ch==entity->c) { r+=entity->l; source++; goto out_of_loop1; }
+ entity++;
+ } while(entity->s);
+#ifdef _XMLWIDECHAR
+ r++; source++;
+#else
+ ch=XML_ByteTable[(unsigned char)ch]; r+=ch; source+=ch;
+#endif
+out_of_loop1:
+ ;
+ }
+ return r;
+}
+
+ToXMLStringTool::~ToXMLStringTool(){ freeBuffer(); }
+void ToXMLStringTool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
+XMLSTR ToXMLStringTool::toXML(XMLCSTR source)
+{
+ int l=lengthXMLString(source)+1;
+ if (l>buflen) { buflen=l; buf=(XMLSTR)realloc(buf,l*sizeof(XMLCHAR)); }
+ return toXMLStringUnSafe(buf,source,buflen);
+}
+
+// private:
+XMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML)
+{
+ // This function is the opposite of the function "toXMLString". It decodes the escape
+ // sequences &amp;, &quot;, &apos;, &lt;, &gt; and replace them by the characters
+ // &,",',<,>. This function is used internally by the XML Parser. All the calls to
+ // the XML library will always gives you back "decoded" strings.
+ //
+ // in: string (s) and length (lo) of string
+ // out: new allocated string converted from xml
+ if (!s) return NULL;
+
+ int ll=0,j;
+ XMLSTR d;
+ XMLCSTR ss=s;
+ XMLCharacterEntity *entity;
+ while ((lo>0)&&(*s))
+ {
+ if (*s==_T('&'))
+ {
+ if ((lo>2)&&(s[1]==_T('#')))
+ {
+ s+=2; lo-=2;
+ if ((*s==_T('X'))||(*s==_T('x'))) { s++; lo--; }
+ while ((*s)&&(*s!=_T(';'))&&((lo--)>0)) s++;
+ if (*s!=_T(';'))
+ {
+ pXML->error=eXMLErrorUnknownCharacterEntity;
+ return NULL;
+ }
+ s++; lo--;
+ } else
+ {
+ entity=XMLEntities;
+ do
+ {
+ if ((lo>=entity->l)&&(_tcsnicmp(s,entity->s,entity->l)==0)) { s+=entity->l; lo-=entity->l; break; }
+ entity++;
+ } while(entity->s);
+ if (!entity->s)
+ {
+ pXML->error=eXMLErrorUnknownCharacterEntity;
+ return NULL;
+ }
+ }
+ } else
+ {
+#ifdef _XMLWIDECHAR
+ s++; lo--;
+#else
+ j=XML_ByteTable[(unsigned char)*s]; s+=j; lo-=j; ll+=j-1;
+#endif
+ }
+ ll++;
+ }
+
+ d=(XMLSTR)malloc((ll+1)*sizeof(XMLCHAR));
+ s=d;
+ while (ll-->0)
+ {
+ if (*ss==_T('&'))
+ {
+ if (ss[1]==_T('#'))
+ {
+ ss+=2; j=0;
+ if ((*ss==_T('X'))||(*ss==_T('x')))
+ {
+ ss++;
+ while (*ss!=_T(';'))
+ {
+ if ((*ss>=_T('0'))&&(*ss<=_T('9'))) j=(j<<4)+*ss-_T('0');
+ else if ((*ss>=_T('A'))&&(*ss<=_T('F'))) j=(j<<4)+*ss-_T('A')+10;
+ else if ((*ss>=_T('a'))&&(*ss<=_T('f'))) j=(j<<4)+*ss-_T('a')+10;
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
+ ss++;
+ }
+ } else
+ {
+ while (*ss!=_T(';'))
+ {
+ if ((*ss>=_T('0'))&&(*ss<=_T('9'))) j=(j*10)+*ss-_T('0');
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
+ ss++;
+ }
+ }
+ (*d++)=(XMLCHAR)j; ss++;
+ } else
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (_tcsnicmp(ss,entity->s,entity->l)==0) { *(d++)=entity->c; ss+=entity->l; break; }
+ entity++;
+ } while(entity->s);
+ }
+ } else
+ {
+#ifdef _XMLWIDECHAR
+ *(d++)=*(ss++);
+#else
+ switch(XML_ByteTable[(unsigned char)*ss])
+ {
+ case 4: *(d++)=*(ss++); ll--;
+ case 3: *(d++)=*(ss++); ll--;
+ case 2: *(d++)=*(ss++); ll--;
+ case 1: *(d++)=*(ss++);
+ }
+#endif
+ }
+ }
+ *d=0;
+ return (XMLSTR)s;
+}
+
+#define XML_isSPACECHAR(ch) ((ch==_T('\n'))||(ch==_T(' '))||(ch== _T('\t'))||(ch==_T('\r')))
+
+// private:
+char myTagCompare(XMLCSTR cclose, XMLCSTR copen)
+// !!!! WARNING strange convention&:
+// return 0 if equals
+// return 1 if different
+{
+ if (!cclose) return 1;
+ int l=(int)_tcslen(cclose);
+ if (_tcsnicmp(cclose, copen, l)!=0) return 1;
+ const XMLCHAR c=copen[l];
+ if (XML_isSPACECHAR(c)||
+ (c==_T('/' ))||
+ (c==_T('<' ))||
+ (c==_T('>' ))||
+ (c==_T('=' ))) return 0;
+ return 1;
+}
+
+// Obtain the next character from the string.
+static inline XMLCHAR getNextChar(XML *pXML)
+{
+ XMLCHAR ch = pXML->lpXML[pXML->nIndex];
+#ifdef _XMLWIDECHAR
+ if (ch!=0) pXML->nIndex++;
+#else
+ pXML->nIndex+=XML_ByteTable[(unsigned char)ch];
+#endif
+ return ch;
+}
+
+// Find the next token in a string.
+// pcbToken contains the number of characters that have been read.
+static NextToken GetNextToken(XML *pXML, int *pcbToken, enum XMLTokenTypeTag *pType)
+{
+ NextToken result;
+ XMLCHAR ch;
+ XMLCHAR chTemp;
+ int indexStart,nFoundMatch,nIsText=FALSE;
+ result.pClr=NULL; // prevent warning
+
+ // Find next non-white space character
+ do { indexStart=pXML->nIndex; ch=getNextChar(pXML); } while XML_isSPACECHAR(ch);
+
+ if (ch)
+ {
+ // Cache the current string pointer
+ result.pStr = &pXML->lpXML[indexStart];
+
+ // First check whether the token is in the clear tag list (meaning it
+ // does not need formatting).
+ ALLXMLClearTag *ctag=XMLClearTags;
+ do
+ {
+ if (_tcsncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen)==0)
+ {
+ result.pClr=ctag;
+ pXML->nIndex+=ctag->openTagLen-1;
+ *pType=eTokenClear;
+ return result;
+ }
+ ctag++;
+ } while(ctag->lpszOpen);
+
+ // If we didn't find a clear tag then check for standard tokens
+ switch(ch)
+ {
+ // Check for quotes
+ case _T('\''):
+ case _T('\"'):
+ // Type of token
+ *pType = eTokenQuotedText;
+ chTemp = ch;
+
+ // Set the size
+ nFoundMatch = FALSE;
+
+ // Search through the string to find a matching quote
+ while((ch = getNextChar(pXML)))
+ {
+ if (ch==chTemp) { nFoundMatch = TRUE; break; }
+ if (ch==_T('<')) break;
+ }
+
+ // If we failed to find a matching quote
+ if (nFoundMatch == FALSE)
+ {
+ pXML->nIndex=indexStart+1;
+ nIsText=TRUE;
+ break;
+ }
+
+// 4.02.2002
+// if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
+
+ break;
+
+ // Equals (used with attribute values)
+ case _T('='):
+ *pType = eTokenEquals;
+ break;
+
+ // Close tag
+ case _T('>'):
+ *pType = eTokenCloseTag;
+ break;
+
+ // Check for tag start and tag end
+ case _T('<'):
+
+ // Peek at the next character to see if we have an end tag '</',
+ // or an xml declaration '<?'
+ chTemp = pXML->lpXML[pXML->nIndex];
+
+ // If we have a tag end...
+ if (chTemp == _T('/'))
+ {
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenTagEnd;
+ }
+
+ // If we have an XML declaration tag
+ else if (chTemp == _T('?'))
+ {
+
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenDeclaration;
+ }
+
+ // Otherwise we must have a start tag
+ else
+ {
+ *pType = eTokenTagStart;
+ }
+ break;
+
+ // Check to see if we have a short hand type end tag ('/>').
+ case _T('/'):
+
+ // Peek at the next character to see if we have a short end tag '/>'
+ chTemp = pXML->lpXML[pXML->nIndex];
+
+ // If we have a short hand end tag...
+ if (chTemp == _T('>'))
+ {
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenShortHandClose;
+ break;
+ }
+
+ // If we haven't found a short hand closing tag then drop into the
+ // text process
+
+ // Other characters
+ default:
+ nIsText = TRUE;
+ }
+
+ // If this is a TEXT node
+ if (nIsText)
+ {
+ // Indicate we are dealing with text
+ *pType = eTokenText;
+ while((ch = getNextChar(pXML)))
+ {
+ if XML_isSPACECHAR(ch)
+ {
+ indexStart++; break;
+
+ } else if (ch==_T('/'))
+ {
+ // If we find a slash then this maybe text or a short hand end tag
+ // Peek at the next character to see it we have short hand end tag
+ ch=pXML->lpXML[pXML->nIndex];
+ // If we found a short hand end tag then we need to exit the loop
+ if (ch==_T('>')) { pXML->nIndex--; break; }
+
+ } else if ((ch==_T('<'))||(ch==_T('>'))||(ch==_T('=')))
+ {
+ pXML->nIndex--; break;
+ }
+ }
+ }
+ *pcbToken = pXML->nIndex-indexStart;
+ } else
+ {
+ // If we failed to obtain a valid character
+ *pcbToken = 0;
+ *pType = eTokenError;
+ result.pStr=NULL;
+ }
+
+ return result;
+}
+
+XMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName)
+{
+ if (!d) { free(lpszName); return NULL; }
+ if (d->lpszName&&(lpszName!=d->lpszName)) free((void*)d->lpszName);
+ d->lpszName=lpszName;
+ return lpszName;
+}
+
+// private:
+XMLNode::XMLNode(struct XMLNodeDataTag *p){ d=p; (p->ref_count)++; }
+XMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration)
+{
+ d=(XMLNodeData*)malloc(sizeof(XMLNodeData));
+ d->ref_count=1;
+
+ d->lpszName=NULL;
+ d->nChild= 0;
+ d->nText = 0;
+ d->nClear = 0;
+ d->nAttribute = 0;
+
+ d->isDeclaration = isDeclaration;
+
+ d->pParent = pParent;
+ d->pChild= NULL;
+ d->pText= NULL;
+ d->pClear= NULL;
+ d->pAttribute= NULL;
+ d->pOrder= NULL;
+
+ updateName_WOSD(lpszName);
+}
+
+XMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) { return XMLNode(NULL,lpszName,isDeclaration); }
+XMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,stringDup(lpszName),isDeclaration); }
+
+#define MEMORYINCREASE 50
+
+static inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem)
+{
+ if (p==NULL) { if (memInc) return malloc(memInc*sizeofElem); return malloc(sizeofElem); }
+ if ((memInc==0)||((newsize%memInc)==0)) p=realloc(p,(newsize+memInc)*sizeofElem);
+// if (!p)
+// {
+// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
+// }
+ return p;
+}
+
+// private:
+int XMLNode::findPosition(XMLNodeData *d, int index, XMLElementType xtype)
+{
+ if (index<0) return -1;
+ int i=0,j=(int)((index<<2)+xtype),*o=d->pOrder; while (o[i]!=j) i++; return i;
+}
+
+// private:
+// update "order" information when deleting a content of a XMLNode
+int XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index)
+{
+ int n=d->nChild+d->nText+d->nClear, *o=d->pOrder,i=findPosition(d,index,t);
+ memmove(o+i, o+i+1, (n-i)*sizeof(int));
+ for (;i<n;i++)
+ if ((o[i]&3)==(int)t) o[i]-=4;
+ // We should normally do:
+ // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
+ // but we skip reallocation because it's too time consuming.
+ // Anyway, at the end, it will be free'd completely at once.
+ return i;
+}
+
+void *XMLNode::addToOrder(int memoryIncrease,int *_pos, int nc, void *p, int size, XMLElementType xtype)
+{
+ // in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
+ // out: *_pos is the index inside p
+ p=myRealloc(p,(nc+1),memoryIncrease,size);
+ int n=d->nChild+d->nText+d->nClear;
+ d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int));
+ int pos=*_pos,*o=d->pOrder;
+
+ if ((pos<0)||(pos>=n)) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
+
+ int i=pos;
+ memmove(o+i+1, o+i, (n-i)*sizeof(int));
+
+ while ((pos<n)&&((o[pos]&3)!=(int)xtype)) pos++;
+ if (pos==n) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
+
+ o[i]=o[pos];
+ for (i=pos+1;i<=n;i++) if ((o[i]&3)==(int)xtype) o[i]+=4;
+
+ *_pos=pos=o[pos]>>2;
+ memmove(((char*)p)+(pos+1)*size,((char*)p)+pos*size,(nc-pos)*size);
+
+ return p;
+}
+
+// Add a child node to the given element.
+XMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName, char isDeclaration, int pos)
+{
+ if (!lpszName) return emptyXMLNode;
+ d->pChild=(XMLNode*)addToOrder(memoryIncrease,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
+ d->pChild[pos].d=NULL;
+ d->pChild[pos]=XMLNode(d,lpszName,isDeclaration);
+ d->nChild++;
+ return d->pChild[pos];
+}
+
+// Add an attribute to an element.
+XMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease,XMLSTR lpszName, XMLSTR lpszValuev)
+{
+ if (!lpszName) return &emptyXMLAttribute;
+ if (!d) { if (lpszName) free(lpszName); if (lpszValuev) free(lpszValuev); return &emptyXMLAttribute; }
+ int nc=d->nAttribute;
+ d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(nc+1),memoryIncrease,sizeof(XMLAttribute));
+ XMLAttribute *pAttr=d->pAttribute+nc;
+ pAttr->lpszName = lpszName;
+ pAttr->lpszValue = lpszValuev;
+ d->nAttribute++;
+ return pAttr;
+}
+
+// Add text to the element.
+XMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos)
+{
+ if (!lpszValue) return NULL;
+ if (!d) { if (lpszValue) free(lpszValue); return NULL; }
+ d->pText=(XMLCSTR*)addToOrder(memoryIncrease,&pos,d->nText,d->pText,sizeof(XMLSTR),eNodeText);
+ d->pText[pos]=lpszValue;
+ d->nText++;
+ return lpszValue;
+}
+
+// Add clear (unformatted) text to the element.
+XMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+{
+ if (!lpszValue) return &emptyXMLClear;
+ if (!d) { if (lpszValue) free(lpszValue); return &emptyXMLClear; }
+ d->pClear=(XMLClear *)addToOrder(memoryIncrease,&pos,d->nClear,d->pClear,sizeof(XMLClear),eNodeClear);
+ XMLClear *pNewClear=d->pClear+pos;
+ pNewClear->lpszValue = lpszValue;
+ if (!lpszOpen) lpszOpen=XMLClearTags->lpszOpen;
+ if (!lpszClose) lpszClose=XMLClearTags->lpszClose;
+ pNewClear->lpszOpenTag = lpszOpen;
+ pNewClear->lpszCloseTag = lpszClose;
+ d->nClear++;
+ return pNewClear;
+}
+
+// private:
+// Parse a clear (unformatted) type node.
+char XMLNode::parseClearTag(void *px, void *_pClear)
+{
+ XML *pXML=(XML *)px;
+ ALLXMLClearTag *pClear=(ALLXMLClearTag*)_pClear;
+ int cbTemp=0;
+ XMLCSTR lpszTemp=NULL;
+ XMLCSTR lpXML=&pXML->lpXML[pXML->nIndex];
+ static XMLCSTR docTypeEnd=_T("]>");
+
+ // Find the closing tag
+ // Seems the <!DOCTYPE need a better treatment so lets handle it
+ if (pClear->lpszOpen==XMLClearTags[1].lpszOpen)
+ {
+ XMLCSTR pCh=lpXML;
+ while (*pCh)
+ {
+ if (*pCh==_T('<')) { pClear->lpszClose=docTypeEnd; lpszTemp=_tcsstr(lpXML,docTypeEnd); break; }
+ else if (*pCh==_T('>')) { lpszTemp=pCh; break; }
+#ifdef _XMLWIDECHAR
+ pCh++;
+#else
+ pCh+=XML_ByteTable[(unsigned char)(*pCh)];
+#endif
+ }
+ } else lpszTemp=_tcsstr(lpXML, pClear->lpszClose);
+
+ if (lpszTemp)
+ {
+ // Cache the size and increment the index
+ cbTemp = (int)(lpszTemp - lpXML);
+
+ pXML->nIndex += cbTemp+(int)_tcslen(pClear->lpszClose);
+
+ // Add the clear node to the current element
+ addClear_priv(MEMORYINCREASE,stringDup(lpXML,cbTemp), pClear->lpszOpen, pClear->lpszClose,-1);
+ return 0;
+ }
+
+ // If we failed to find the end tag
+ pXML->error = eXMLErrorUnmatchedEndClearTag;
+ return 1;
+}
+
+void XMLNode::exactMemory(XMLNodeData *d)
+{
+ if (d->pOrder) d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nText+d->nClear)*sizeof(int));
+ if (d->pChild) d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode));
+ if (d->pAttribute) d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute));
+ if (d->pText) d->pText=(XMLCSTR*)realloc(d->pText,d->nText*sizeof(XMLSTR));
+ if (d->pClear) d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear));
+}
+
+char XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr)
+{
+ XML *pXML=(XML *)pa;
+ XMLCSTR lpszText=pXML->lpszText;
+ if (!lpszText) return 0;
+ if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText)&&(lpszText!=tokenPStr)) lpszText++;
+ int cbText = (int)(tokenPStr - lpszText);
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
+ if (dropWhiteSpace) { cbText--; while ((cbText)&&XML_isSPACECHAR(lpszText[cbText])) cbText--; cbText++; }
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
+ XMLSTR lpt=fromXMLString(lpszText,cbText,pXML);
+ if (!lpt) return 1;
+ addText_priv(MEMORYINCREASE,lpt,-1);
+ pXML->lpszText=NULL;
+ return 0;
+}
+// private:
+// Recursively parse an XML element.
+int XMLNode::ParseXMLElement(void *pa)
+{
+ XML *pXML=(XML *)pa;
+ int cbToken;
+ enum XMLTokenTypeTag type;
+ NextToken token;
+ XMLCSTR lpszTemp=NULL;
+ int cbTemp=0;
+ char nDeclaration;
+ XMLNode pNew;
+ enum Status status; // inside or outside a tag
+ enum Attrib attrib = eAttribName;
+
+ assert(pXML);
+
+ // If this is the first call to the function
+ if (pXML->nFirst)
+ {
+ // Assume we are outside of a tag definition
+ pXML->nFirst = FALSE;
+ status = eOutsideTag;
+ } else
+ {
+ // If this is not the first call then we should only be called when inside a tag.
+ status = eInsideTag;
+ }
+
+ // Iterate through the tokens in the document
+ for(;;)
+ {
+ // Obtain the next token
+ token = GetNextToken(pXML, &cbToken, &type);
+
+ if (type != eTokenError)
+ {
+ // Check the current status
+ switch(status)
+ {
+
+ // If we are outside of a tag definition
+ case eOutsideTag:
+
+ // Check what type of token we obtained
+ switch(type)
+ {
+ // If we have found text or quoted text
+ case eTokenText:
+ case eTokenCloseTag: /* '>' */
+ case eTokenShortHandClose: /* '/>' */
+ case eTokenQuotedText:
+ case eTokenEquals:
+ break;
+
+ // If we found a start tag '<' and declarations '<?'
+ case eTokenTagStart:
+ case eTokenDeclaration:
+
+ // Cache whether this new element is a declaration or not
+ nDeclaration = (type == eTokenDeclaration);
+
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+
+ // Find the name of the tag
+ token = GetNextToken(pXML, &cbToken, &type);
+
+ // Return an error if we couldn't obtain the next token or
+ // it wasnt text
+ if (type != eTokenText)
+ {
+ pXML->error = eXMLErrorMissingTagName;
+ return FALSE;
+ }
+
+ // If we found a new element which is the same as this
+ // element then we need to pass this back to the caller..
+
+#ifdef APPROXIMATE_PARSING
+ if (d->lpszName &&
+ myTagCompare(d->lpszName, token.pStr) == 0)
+ {
+ // Indicate to the caller that it needs to create a
+ // new element.
+ pXML->lpNewElement = token.pStr;
+ pXML->cbNewElement = cbToken;
+ return TRUE;
+ } else
+#endif
+ {
+ // If the name of the new element differs from the name of
+ // the current element we need to add the new element to
+ // the current one and recurse
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(token.pStr,cbToken), nDeclaration,-1);
+
+ while (!pNew.isEmpty())
+ {
+ // Callself to process the new node. If we return
+ // FALSE this means we dont have any more
+ // processing to do...
+
+ if (!pNew.ParseXMLElement(pXML)) return FALSE;
+ else
+ {
+ // If the call to recurse this function
+ // evented in a end tag specified in XML then
+ // we need to unwind the calls to this
+ // function until we find the appropriate node
+ // (the element name and end tag name must
+ // match)
+ if (pXML->cbEndTag)
+ {
+ // If we are back at the root node then we
+ // have an unmatched end tag
+ if (!d->lpszName)
+ {
+ pXML->error=eXMLErrorUnmatchedEndTag;
+ return FALSE;
+ }
+
+ // If the end tag matches the name of this
+ // element then we only need to unwind
+ // once more...
+
+ if (myTagCompare(d->lpszName, pXML->lpEndTag)==0)
+ {
+ pXML->cbEndTag = 0;
+ }
+
+ return TRUE;
+ } else
+ if (pXML->cbNewElement)
+ {
+ // If the call indicated a new element is to
+ // be created on THIS element.
+
+ // If the name of this element matches the
+ // name of the element we need to create
+ // then we need to return to the caller
+ // and let it process the element.
+
+ if (myTagCompare(d->lpszName, pXML->lpNewElement)==0)
+ {
+ return TRUE;
+ }
+
+ // Add the new element and recurse
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(pXML->lpNewElement,pXML->cbNewElement),0,-1);
+ pXML->cbNewElement = 0;
+ }
+ else
+ {
+ // If we didn't have a new element to create
+ pNew = emptyXMLNode;
+
+ }
+ }
+ }
+ }
+ break;
+
+ // If we found an end tag
+ case eTokenTagEnd:
+
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+
+ // Find the name of the end tag
+ token = GetNextToken(pXML, &cbTemp, &type);
+
+ // The end tag should be text
+ if (type != eTokenText)
+ {
+ pXML->error = eXMLErrorMissingEndTagName;
+ return FALSE;
+ }
+ lpszTemp = token.pStr;
+
+ // After the end tag we should find a closing tag
+ token = GetNextToken(pXML, &cbToken, &type);
+ if (type != eTokenCloseTag)
+ {
+ pXML->error = eXMLErrorMissingEndTagName;
+ return FALSE;
+ }
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+
+ // We need to return to the previous caller. If the name
+ // of the tag cannot be found we need to keep returning to
+ // caller until we find a match
+ if (myTagCompare(d->lpszName, lpszTemp) != 0)
+#ifdef STRICT_PARSING
+ {
+ pXML->error=eXMLErrorUnmatchedEndTag;
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ return FALSE;
+ }
+#else
+ {
+ pXML->error=eXMLErrorMissingEndTag;
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ pXML->lpEndTag = lpszTemp;
+ pXML->cbEndTag = cbTemp;
+ }
+#endif
+
+ // Return to the caller
+ exactMemory(d);
+ return TRUE;
+
+ // If we found a clear (unformatted) token
+ case eTokenClear:
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+ if (parseClearTag(pXML, token.pClr)) return FALSE;
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ // If we are inside a tag definition we need to search for attributes
+ case eInsideTag:
+
+ // Check what part of the attribute (name, equals, value) we
+ // are looking for.
+ switch(attrib)
+ {
+ // If we are looking for a new attribute
+ case eAttribName:
+
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text...
+ // Eg. 'attribute'
+ case eTokenText:
+ // Cache the token then indicate that we are next to
+ // look for the equals
+ lpszTemp = token.pStr;
+ cbTemp = cbToken;
+ attrib = eAttribEquals;
+ break;
+
+ // If we found a closing tag...
+ // Eg. '>'
+ case eTokenCloseTag:
+ // We are now outside the tag
+ status = eOutsideTag;
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ break;
+
+ // If we found a short hand '/>' closing tag then we can
+ // return to the caller
+ case eTokenShortHandClose:
+ exactMemory(d);
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ return TRUE;
+
+ // Errors...
+ case eTokenQuotedText: /* '"SomeText"' */
+ case eTokenTagStart: /* '<' */
+ case eTokenTagEnd: /* '</' */
+ case eTokenEquals: /* '=' */
+ case eTokenDeclaration: /* '<?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ default: break;
+ }
+ break;
+
+ // If we are looking for an equals
+ case eAttribEquals:
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text...
+ // Eg. 'Attribute AnotherAttribute'
+ case eTokenText:
+ // Add the unvalued attribute to the list
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
+ // Cache the token then indicate. We are next to
+ // look for the equals attribute
+ lpszTemp = token.pStr;
+ cbTemp = cbToken;
+ break;
+
+ // If we found a closing tag 'Attribute >' or a short hand
+ // closing tag 'Attribute />'
+ case eTokenShortHandClose:
+ case eTokenCloseTag:
+ // If we are a declaration element '<?' then we need
+ // to remove extra closing '?' if it exists
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+
+ if (d->isDeclaration &&
+ (lpszTemp[cbTemp-1]) == _T('?'))
+ {
+ cbTemp--;
+ }
+
+ if (cbTemp)
+ {
+ // Add the unvalued attribute to the list
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
+ }
+
+ // If this is the end of the tag then return to the caller
+ if (type == eTokenShortHandClose)
+ {
+ exactMemory(d);
+ return TRUE;
+ }
+
+ // We are now outside the tag
+ status = eOutsideTag;
+ break;
+
+ // If we found the equals token...
+ // Eg. 'Attribute ='
+ case eTokenEquals:
+ // Indicate that we next need to search for the value
+ // for the attribute
+ attrib = eAttribValue;
+ break;
+
+ // Errors...
+ case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
+ case eTokenTagStart: /* 'Attribute <' */
+ case eTokenTagEnd: /* 'Attribute </' */
+ case eTokenDeclaration: /* 'Attribute <?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ default: break;
+ }
+ break;
+
+ // If we are looking for an attribute value
+ case eAttribValue:
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text or quoted text...
+ // Eg. 'Attribute = "Value"' or 'Attribute = Value' or
+ // 'Attribute = 'Value''.
+ case eTokenText:
+ case eTokenQuotedText:
+ // If we are a declaration element '<?' then we need
+ // to remove extra closing '?' if it exists
+ if (d->isDeclaration &&
+ (token.pStr[cbToken-1]) == _T('?'))
+ {
+ cbToken--;
+ }
+
+ if (cbTemp)
+ {
+ // Add the valued attribute to the list
+ if (type==eTokenQuotedText) { token.pStr++; cbToken-=2; }
+ XMLSTR attrVal=(XMLSTR)token.pStr;
+ if (attrVal)
+ {
+ attrVal=fromXMLString(attrVal,cbToken,pXML);
+ if (!attrVal) return FALSE;
+ }
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal);
+ }
+
+ // Indicate we are searching for a new attribute
+ attrib = eAttribName;
+ break;
+
+ // Errors...
+ case eTokenTagStart: /* 'Attr = <' */
+ case eTokenTagEnd: /* 'Attr = </' */
+ case eTokenCloseTag: /* 'Attr = >' */
+ case eTokenShortHandClose: /* "Attr = />" */
+ case eTokenEquals: /* 'Attr = =' */
+ case eTokenDeclaration: /* 'Attr = <?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+ // If we failed to obtain the next token
+ else
+ {
+ if ((!d->isDeclaration)&&(d->pParent))
+ {
+#ifdef STRICT_PARSING
+ pXML->error=eXMLErrorUnmatchedEndTag;
+#else
+ pXML->error=eXMLErrorMissingEndTag;
+#endif
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ }
+ return FALSE;
+ }
+ }
+}
+
+// Count the number of lines and columns in an XML string.
+static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults)
+{
+ XMLCHAR ch;
+ assert(lpXML);
+ assert(pResults);
+
+ struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
+
+ pResults->nLine = 1;
+ pResults->nColumn = 1;
+ while (xml.nIndex<nUpto)
+ {
+ ch = getNextChar(&xml);
+ if (ch != _T('\n')) pResults->nColumn++;
+ else
+ {
+ pResults->nLine++;
+ pResults->nColumn=1;
+ }
+ }
+}
+
+// Parse XML and return the root element.
+XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults)
+{
+ if (!lpszXML)
+ {
+ if (pResults)
+ {
+ pResults->error=eXMLErrorNoElements;
+ pResults->nLine=0;
+ pResults->nColumn=0;
+ }
+ return emptyXMLNode;
+ }
+
+ XMLNode xnode(NULL,NULL,FALSE);
+ struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
+
+ // Create header element
+ xnode.ParseXMLElement(&xml);
+ enum XMLError error = xml.error;
+ if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node
+
+ // If no error occurred
+ if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag))
+ {
+ XMLCSTR name=xnode.getName();
+ if (tag&&_tcslen(tag)&&((!name)||(_tcsicmp(xnode.getName(),tag))))
+ {
+ XMLNode nodeTmp;
+ int i=0;
+ while (i<xnode.nChildNode())
+ {
+ nodeTmp=xnode.getChildNode(i);
+ if (_tcsicmp(nodeTmp.getName(),tag)==0) break;
+ if (nodeTmp.isDeclaration()) { xnode=nodeTmp; i=0; } else i++;
+ }
+ if (i>=xnode.nChildNode())
+ {
+ if (pResults)
+ {
+ pResults->error=eXMLErrorFirstTagNotFound;
+ pResults->nLine=0;
+ pResults->nColumn=0;
+ }
+ return emptyXMLNode;
+ }
+ xnode=nodeTmp;
+ }
+ } else
+ {
+ // Cleanup: this will destroy all the nodes
+ xnode = emptyXMLNode;
+ }
+
+
+ // If we have been given somewhere to place results
+ if (pResults)
+ {
+ pResults->error = error;
+
+ // If we have an error
+ if (error!=eXMLErrorNone)
+ {
+ if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag;
+ // Find which line and column it starts on.
+ CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
+ }
+ }
+ return xnode;
+}
+
+XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults)
+{
+ if (pResults) { pResults->nLine=0; pResults->nColumn=0; }
+ FILE *f=_tfopen(filename,_T("rb"));
+ if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; }
+ fseek(f,0,SEEK_END);
+ int l=ftell(f),headerSz=0;
+ if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; return emptyXMLNode; }
+ fseek(f,0,SEEK_SET);
+ unsigned char *buf=(unsigned char*)malloc(l+4);
+ fread(buf,l,1,f);
+ fclose(f);
+ buf[l]=0;buf[l+1]=0;buf[l+2]=0;buf[l+3]=0;
+#ifdef _XMLWIDECHAR
+ if (guessWideCharChars)
+ {
+ if (!myIsTextWideChar(buf,l))
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
+ XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz));
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
+ } else
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
+ }
+ }
+#else
+ if (guessWideCharChars)
+ {
+ if (myIsTextWideChar(buf,l))
+ {
+ l/=sizeof(wchar_t);
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
+ char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz));
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
+ } else
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
+ }
+ }
+#endif
+
+ if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; }
+ XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults);
+ free(buf);
+ return x;
+}
+
+static inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; }
+// private:
+// Creates an user friendly XML string from a given element with
+// appropriate white space and carriage returns.
+//
+// This recurses through all subnodes then adds contents of the nodes to the
+// string.
+int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int length, int nFormat)
+{
+ int nResult = 0;
+ int cb;
+ int cbElement;
+ int nChildFormat=-1;
+ int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear;
+ int i,j;
+
+ assert(pEntry);
+
+#define LENSTR(lpsz) (lpsz ? _tcslen(lpsz) : 0)
+
+ // If the element has no name then assume this is the head node.
+ cbElement = (int)LENSTR(pEntry->lpszName);
+
+ if (cbElement)
+ {
+ // "<elementname "
+ cb = nFormat == -1 ? 0 : nFormat;
+
+ if (lpszMarker)
+ {
+ if (cb) charmemset(lpszMarker, INDENTCHAR, sizeof(XMLCHAR)*cb);
+ nResult = cb;
+ lpszMarker[nResult++]=_T('<');
+ if (pEntry->isDeclaration) lpszMarker[nResult++]=_T('?');
+ _tcsncpy(&lpszMarker[nResult], pEntry->lpszName, length-nResult);
+ nResult+=cbElement;
+ lpszMarker[nResult++]=_T(' ');
+
+ } else
+ {
+ nResult+=cbElement+2+cb;
+ if (pEntry->isDeclaration) nResult++;
+ }
+
+ // Enumerate attributes and add them to the string
+ XMLAttribute *pAttr=pEntry->pAttribute;
+ for (i=0; i<pEntry->nAttribute; i++)
+ {
+ // "Attrib
+ cb = (int)LENSTR(pAttr->lpszName);
+ if (cb)
+ {
+ if (lpszMarker) _tcsncpy(&lpszMarker[nResult], pAttr->lpszName, length-nResult);
+ nResult += cb;
+ // "Attrib=Value "
+ if (pAttr->lpszValue)
+ {
+ cb=(int)lengthXMLString(pAttr->lpszValue);
+ if (lpszMarker)
+ {
+ lpszMarker[nResult]=_T('=');
+ lpszMarker[nResult+1]=_T('"');
+ if (cb) toXMLStringUnSafe(&lpszMarker[nResult+2],pAttr->lpszValue, length-(nResult+2));
+ lpszMarker[nResult+cb+2]=_T('"');
+ }
+ nResult+=cb+3;
+ }
+ if (lpszMarker) lpszMarker[nResult] = _T(' ');
+ nResult++;
+ }
+ pAttr++;
+ }
+
+ if (pEntry->isDeclaration)
+ {
+ if (lpszMarker)
+ {
+ lpszMarker[nResult-1]=_T('?');
+ lpszMarker[nResult]=_T('>');
+ }
+ nResult++;
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult]=_T('\n');
+ nResult++;
+ }
+ } else
+ // If there are child nodes we need to terminate the start tag
+ if (nElementI)
+ {
+ if (lpszMarker) lpszMarker[nResult-1]=_T('>');
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult]=_T('\n');
+ nResult++;
+ }
+ } else nResult--;
+ }
+
+ // Calculate the child format for when we recurse. This is used to
+ // determine the number of spaces used for prefixes.
+ if (nFormat!=-1)
+ {
+ if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1;
+ else nChildFormat=nFormat;
+ }
+
+ // Enumerate through remaining children
+ for (i=0; i<nElementI; i++)
+ {
+ j=pEntry->pOrder[i];
+ switch((XMLElementType)(j&3))
+ {
+ // Text nodes
+ case eNodeText:
+ {
+ // "Text"
+ XMLCSTR pChild=pEntry->pText[j>>2];
+ cb = (int)lengthXMLString(pChild);
+ if (cb)
+ {
+ if (nFormat!=-1)
+ {
+ if (lpszMarker)
+ {
+ charmemset(&lpszMarker[nResult],INDENTCHAR,sizeof(XMLCHAR)*(nFormat + 1));
+ toXMLStringUnSafe(&lpszMarker[nResult+nFormat+1],pChild, length - (nResult + nFormat + 1));
+ lpszMarker[nResult+nFormat+1+cb]=_T('\n');
+ }
+ nResult+=cb+nFormat+2;
+ } else
+ {
+ if (lpszMarker) toXMLStringUnSafe(&lpszMarker[nResult], pChild, length - nResult);
+ nResult += cb;
+ }
+ }
+ break;
+ }
+
+ // Clear type nodes
+ case eNodeClear:
+ {
+ XMLClear *pChild=pEntry->pClear+(j>>2);
+ // "OpenTag"
+ cb = (int)LENSTR(pChild->lpszOpenTag);
+ if (cb)
+ {
+ if (nFormat!=-1)
+ {
+ if (lpszMarker)
+ {
+ charmemset(&lpszMarker[nResult], INDENTCHAR, sizeof(XMLCHAR)*(nFormat + 1));
+ _tcsncpy(&lpszMarker[nResult+nFormat+1], pChild->lpszOpenTag, length - (nResult + nFormat + 1));
+ }
+ nResult+=cb+nFormat+1;
+ }
+ else
+ {
+ if (lpszMarker)_tcsncpy(&lpszMarker[nResult], pChild->lpszOpenTag, length - nResult);
+ nResult += cb;
+ }
+ }
+
+ // "OpenTag Value"
+ cb = (int)LENSTR(pChild->lpszValue);
+ if (cb)
+ {
+ if (lpszMarker) _tcsncpy(&lpszMarker[nResult], pChild->lpszValue, length - nResult);
+ nResult += cb;
+ }
+
+ // "OpenTag Value CloseTag"
+ cb = (int)LENSTR(pChild->lpszCloseTag);
+ if (cb)
+ {
+ if (lpszMarker) _tcsncpy(&lpszMarker[nResult], pChild->lpszCloseTag, length - nResult);
+ nResult += cb;
+ }
+
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult] = _T('\n');
+ nResult++;
+ }
+ break;
+ }
+
+ // Element nodes
+ case eNodeChild:
+ {
+ // Recursively add child nodes
+ nResult += CreateXMLStringR(pEntry->pChild[j>>2].d, lpszMarker ? lpszMarker + nResult : 0, lpszMarker ? length - nResult : 0, nChildFormat);
+ break;
+ }
+ default: break;
+ }
+ }
+
+ if ((cbElement)&&(!pEntry->isDeclaration))
+ {
+ // If we have child entries we need to use long XML notation for
+ // closing the element - "<elementname>blah blah blah</elementname>"
+ if (nElementI)
+ {
+ // "</elementname>\0"
+ if (lpszMarker)
+ {
+ if (nFormat != -1)
+ {
+ if (nFormat)
+ {
+ charmemset(&lpszMarker[nResult], INDENTCHAR,sizeof(XMLCHAR)*nFormat);
+ nResult+=nFormat;
+ }
+ }
+
+ _tcsncpy(&lpszMarker[nResult], _T("</"), length - nResult);
+ nResult += 2;
+ _tcsncpy(&lpszMarker[nResult], pEntry->lpszName, length - nResult);
+ nResult += cbElement;
+
+ if (nFormat == -1)
+ {
+ _tcsncpy(&lpszMarker[nResult], _T(">"), length - nResult);
+ nResult++;
+ } else
+ {
+ _tcsncpy(&lpszMarker[nResult], _T(">\n"), length - nResult);
+ nResult+=2;
+ }
+ } else
+ {
+ if (nFormat != -1) nResult+=cbElement+4+nFormat;
+ else nResult+=cbElement+3;
+ }
+ } else
+ {
+ // If there are no children we can use shorthand XML notation -
+ // "<elementname/>"
+ // "/>\0"
+ if (lpszMarker)
+ {
+ if (nFormat == -1)
+ {
+ _tcsncpy(&lpszMarker[nResult], _T("/>"), length - nResult);
+ nResult += 2;
+ }
+ else
+ {
+ _tcsncpy(&lpszMarker[nResult], _T("/>\n"), length - nResult);
+ nResult += 3;
+ }
+ }
+ else
+ {
+ nResult += nFormat == -1 ? 2 : 3;
+ }
+ }
+ }
+
+ return nResult;
+}
+
+#undef LENSTR
+
+// Create an XML string
+// @param int nFormat - 0 if no formatting is required
+// otherwise nonzero for formatted text
+// with carriage returns and indentation.
+// @param int *pnSize - [out] pointer to the size of the
+// returned string not including the
+// NULL terminator.
+// @return XMLSTR - Allocated XML string, you must free
+// this with free().
+XMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const
+{
+ if (!d) { if (pnSize) *pnSize=0; return NULL; }
+
+ XMLSTR lpszResult = NULL;
+ int cbStr;
+
+ // Recursively Calculate the size of the XML string
+ if (!dropWhiteSpace) nFormat=0;
+ nFormat = nFormat ? 0 : -1;
+ cbStr = CreateXMLStringR(d, 0, 0, nFormat);
+ assert(cbStr);
+ // Alllocate memory for the XML string + the NULL terminator and
+ // create the recursively XML string.
+ lpszResult=(XMLSTR)malloc((cbStr+1)*sizeof(XMLCHAR));
+ CreateXMLStringR(d, lpszResult, cbStr+1, nFormat);
+ if (pnSize) *pnSize = cbStr;
+ return lpszResult;
+}
+
+XMLNode::~XMLNode() { deleteNodeContent(); }
+
+int XMLNode::detachFromParent(XMLNodeData *d)
+{
+ XMLNode *pa=d->pParent->pChild;
+ int i=0;
+ while (((void*)(pa[i].d))!=((void*)d)) i++;
+ d->pParent->nChild--;
+ if (d->pParent->nChild) memmove(pa+i,pa+i+1,(d->pParent->nChild-i)*sizeof(XMLNode));
+ else { free(pa); d->pParent->pChild=NULL; }
+ return removeOrderElement(d->pParent,eNodeChild,i);
+}
+
+void XMLNode::deleteNodeContent(char force)
+{
+ if (!d) return;
+ (d->ref_count) --;
+ if ((d->ref_count==0)||force)
+ {
+ int i;
+ if (d->pParent) detachFromParent(d);
+ for(i=0; i<d->nChild; i++) { d->pChild[i].d->pParent=NULL; d->pChild[i].deleteNodeContent(force); }
+ free(d->pChild);
+ for(i=0; i<d->nText; i++) free((void*)d->pText[i]);
+ free(d->pText);
+ for(i=0; i<d->nClear; i++) free((void*)d->pClear[i].lpszValue);
+ free(d->pClear);
+ for(i=0; i<d->nAttribute; i++)
+ {
+ free((void*)d->pAttribute[i].lpszName);
+ if (d->pAttribute[i].lpszValue) free((void*)d->pAttribute[i].lpszValue);
+ }
+ free(d->pAttribute);
+ free(d->pOrder);
+ free((void*)d->lpszName);
+ free(d);
+ d=NULL;
+ }
+}
+
+XMLNode XMLNode::addChild(XMLNode childNode, int pos)
+{
+ XMLNodeData *dc=childNode.d;
+ if ((!dc)||(!d)) return childNode;
+ if (dc->pParent) { if ((detachFromParent(dc)<=pos)&&(dc->pParent==d)) pos--; } else dc->ref_count++;
+ dc->pParent=d;
+// int nc=d->nChild;
+// d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
+ d->pChild=(XMLNode*)addToOrder(0,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
+ d->pChild[pos].d=dc;
+ d->nChild++;
+ return childNode;
+}
+
+void XMLNode::deleteAttribute(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nAttribute)) return;
+ d->nAttribute--;
+ XMLAttribute *p=d->pAttribute+i;
+ free((void*)p->lpszName);
+ if (p->lpszValue) free((void*)p->lpszValue);
+ if (d->nAttribute) memmove(p,p+1,(d->nAttribute-i)*sizeof(XMLAttribute)); else { free(p); d->pAttribute=NULL; }
+}
+
+void XMLNode::deleteAttribute(XMLAttribute *a){ if (a) deleteAttribute(a->lpszName); }
+void XMLNode::deleteAttribute(XMLCSTR lpszName)
+{
+ int j=0;
+ getAttribute(lpszName,&j);
+ if (j) deleteAttribute(j-1);
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,int i)
+{
+ if (!d) { if (lpszNewValue) free(lpszNewValue); if (lpszNewName) free(lpszNewName); return NULL; }
+ if (i>=d->nAttribute)
+ {
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
+ return NULL;
+ }
+ XMLAttribute *p=d->pAttribute+i;
+ if (p->lpszValue&&p->lpszValue!=lpszNewValue) free((void*)p->lpszValue);
+ p->lpszValue=lpszNewValue;
+ if (lpszNewName&&p->lpszName!=lpszNewName) { free((void*)p->lpszName); p->lpszName=lpszNewName; };
+ return p;
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
+{
+ if (oldAttribute) return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,(XMLSTR)newAttribute->lpszName,oldAttribute->lpszName);
+ return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,(XMLSTR)newAttribute->lpszValue);
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName)
+{
+ int j=0;
+ getAttribute(lpszOldName,&j);
+ if (j) return updateAttribute_WOSD(lpszNewValue,lpszNewName,j-1);
+ else
+ {
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
+ else return addAttribute_WOSD(stringDup(lpszOldName),lpszNewValue);
+ }
+}
+
+int XMLNode::indexText(XMLCSTR lpszValue) const
+{
+ if (!d) return -1;
+ int i,l=d->nText;
+ if (!lpszValue) { if (l) return 0; return -1; }
+ XMLCSTR *p=d->pText;
+ for (i=0; i<l; i++) if (lpszValue==p[i]) return i;
+ return -1;
+}
+
+void XMLNode::deleteText(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nText)) return;
+ d->nText--;
+ XMLCSTR *p=d->pText+i;
+ free((void*)*p);
+ if (d->nText) memmove(p,p+1,(d->nText-i)*sizeof(XMLCSTR)); else { free(p); d->pText=NULL; }
+ removeOrderElement(d,eNodeText,i);
+}
+
+void XMLNode::deleteText(XMLCSTR lpszValue) { deleteText(indexText(lpszValue)); }
+
+XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i)
+{
+ if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
+ if (i>=d->nText) return addText_WOSD(lpszNewValue);
+ XMLCSTR *p=d->pText+i;
+ if (*p!=lpszNewValue) { free((void*)*p); *p=lpszNewValue; }
+ return lpszNewValue;
+}
+
+XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue)
+{
+ if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
+ int i=indexText(lpszOldValue);
+ if (i>=0) return updateText_WOSD(lpszNewValue,i);
+ return addText_WOSD(lpszNewValue);
+}
+
+void XMLNode::deleteClear(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nClear)) return;
+ d->nClear--;
+ XMLClear *p=d->pClear+i;
+ free((void*)p->lpszValue);
+ if (d->nClear) memmove(p,p+1,(d->nClear-i)*sizeof(XMLClear)); else { free(p); d->pClear=NULL; }
+ removeOrderElement(d,eNodeClear,i);
+}
+
+int XMLNode::indexClear(XMLCSTR lpszValue) const
+{
+ if (!d) return -1;
+ int i,l=d->nClear;
+ if (!lpszValue) { if (l) return 0; return -1; }
+ XMLClear *p=d->pClear;
+ for (i=0; i<l; i++) if (lpszValue==p[i].lpszValue) return i;
+ return -1;
+}
+
+void XMLNode::deleteClear(XMLCSTR lpszValue) { deleteClear(indexClear(lpszValue)); }
+void XMLNode::deleteClear(XMLClear *a) { if (a) deleteClear(a->lpszValue); }
+
+XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i)
+{
+ if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
+ if (i>=d->nClear) return addClear_WOSD(lpszNewContent);
+ XMLClear *p=d->pClear+i;
+ if (lpszNewContent!=p->lpszValue) { free((void*)p->lpszValue); p->lpszValue=lpszNewContent; }
+ return p;
+}
+
+XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, XMLCSTR lpszOldValue)
+{
+ if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
+ int i=indexClear(lpszOldValue);
+ if (i>=0) return updateClear_WOSD(lpszNewContent,i);
+ return addClear_WOSD(lpszNewContent);
+}
+
+XMLClear *XMLNode::updateClear_WOSD(XMLClear *newP,XMLClear *oldP)
+{
+ if (oldP) return updateClear_WOSD((XMLSTR)newP->lpszValue,(XMLSTR)oldP->lpszValue);
+ return NULL;
+}
+
+XMLNode& XMLNode::operator=( const XMLNode& A )
+{
+ // shallow copy
+ if (this != &A)
+ {
+ deleteNodeContent();
+ d=A.d;
+ if (d) (d->ref_count) ++ ;
+ }
+ return *this;
+}
+
+XMLNode::XMLNode(const XMLNode &A)
+{
+ // shallow copy
+ d=A.d;
+ if (d) (d->ref_count)++ ;
+}
+
+int XMLNode::nChildNode(XMLCSTR name) const
+{
+ if (!d) return 0;
+ int i,j=0,n=d->nChild;
+ XMLNode *pc=d->pChild;
+ for (i=0; i<n; i++)
+ {
+ if (_tcsicmp(pc->d->lpszName, name)==0) j++;
+ pc++;
+ }
+ return j;
+}
+
+XMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const
+{
+ if (!d) return emptyXMLNode;
+ int i=0,n=d->nChild;
+ if (j) i=*j;
+ XMLNode *pc=d->pChild+i;
+ for (; i<n; i++)
+ {
+ if (_tcsicmp(pc->d->lpszName, name)==0)
+ {
+ if (j) *j=i+1;
+ return *pc;
+ }
+ pc++;
+ }
+ return emptyXMLNode;
+}
+
+XMLNode XMLNode::getChildNode(XMLCSTR name, int j) const
+{
+ if (!d) return emptyXMLNode;
+ int i=0;
+ while (j-->0) getChildNode(name,&i);
+ return getChildNode(name,&i);
+}
+
+int XMLNode::positionOfText (int i) const { if (i>=d->nText ) i=d->nText-1; return findPosition(d,i,eNodeText ); }
+int XMLNode::positionOfClear (int i) const { if (i>=d->nClear) i=d->nClear-1; return findPosition(d,i,eNodeClear); }
+int XMLNode::positionOfChildNode(int i) const { if (i>=d->nChild) i=d->nChild-1; return findPosition(d,i,eNodeChild); }
+int XMLNode::positionOfText (XMLCSTR lpszValue) const { return positionOfText (indexText (lpszValue)); }
+int XMLNode::positionOfClear(XMLCSTR lpszValue) const { return positionOfClear(indexClear(lpszValue)); }
+int XMLNode::positionOfClear(XMLClear *a) const { if (a) return positionOfClear(a->lpszValue); return positionOfClear(); }
+int XMLNode::positionOfChildNode(XMLNode x) const
+{
+ if ((!d)||(!x.d)) return -1;
+ XMLNodeData *dd=x.d;
+ XMLNode *pc=d->pChild;
+ int i=d->nChild;
+ while (i--) if (pc[i].d==dd) return findPosition(d,i,eNodeChild);
+ return -1;
+}
+int XMLNode::positionOfChildNode(XMLCSTR name, int count) const
+{
+ if (!name) return positionOfChildNode(count);
+ int j=0;
+ do { getChildNode(name,&j); if (j<0) return -1; } while (count--);
+ return findPosition(d,j-1,eNodeChild);
+}
+
+XMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name,XMLCSTR attributeName,XMLCSTR attributeValue, int *k) const
+{
+ int i=0,j;
+ if (k) i=*k;
+ XMLNode x;
+ XMLCSTR t;
+ do
+ {
+ x=getChildNode(name,&i);
+ if (!x.isEmpty())
+ {
+ if (attributeValue)
+ {
+ j=0;
+ do
+ {
+ t=x.getAttribute(attributeName,&j);
+ if (t&&(_tcsicmp(attributeValue,t)==0)) { if (k) *k=i+1; return x; }
+ } while (t);
+ } else
+ {
+ if (x.isAttributeSet(attributeName)) { if (k) *k=i+1; return x; }
+ }
+ }
+ } while (!x.isEmpty());
+ return emptyXMLNode;
+}
+
+// Find an attribute on an node.
+XMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const
+{
+ if (!d) return NULL;
+ int i=0,n=d->nAttribute;
+ if (j) i=*j;
+ XMLAttribute *pAttr=d->pAttribute+i;
+ for (; i<n; i++)
+ {
+ if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0)
+ {
+ if (j) *j=i+1;
+ return pAttr->lpszValue;
+ }
+ pAttr++;
+ }
+ return NULL;
+}
+
+char XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const
+{
+ if (!d) return FALSE;
+ int i,n=d->nAttribute;
+ XMLAttribute *pAttr=d->pAttribute;
+ for (i=0; i<n; i++)
+ {
+ if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0)
+ {
+ return TRUE;
+ }
+ pAttr++;
+ }
+ return FALSE;
+}
+
+XMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const
+{
+ if (!d) return NULL;
+ int i=0;
+ while (j-->0) getAttribute(name,&i);
+ return getAttribute(name,&i);
+}
+
+XMLNodeContents XMLNode::enumContents(int i) const
+{
+ XMLNodeContents c;
+ if (!d) { c.type=eNodeNULL; return c; }
+ if (i<d->nAttribute)
+ {
+ c.type=eNodeAttribute;
+ c.attrib=d->pAttribute[i];
+ return c;
+ }
+ i-=d->nAttribute;
+ c.type=(XMLElementType)(d->pOrder[i]&3);
+ i=(d->pOrder[i])>>2;
+ switch (c.type)
+ {
+ case eNodeChild: c.child = d->pChild[i]; break;
+ case eNodeText: c.text = d->pText[i]; break;
+ case eNodeClear: c.clear = d->pClear[i]; break;
+ default: break;
+ }
+ return c;
+}
+
+XMLCSTR XMLNode::getName() const { if (!d) return NULL; return d->lpszName; }
+int XMLNode::nText() const { if (!d) return 0; return d->nText; }
+int XMLNode::nChildNode() const { if (!d) return 0; return d->nChild; }
+int XMLNode::nAttribute() const { if (!d) return 0; return d->nAttribute; }
+int XMLNode::nClear() const { if (!d) return 0; return d->nClear; }
+int XMLNode::nElement() const { if (!d) return 0; return d->nAttribute+d->nChild+d->nText+d->nClear; }
+XMLClear XMLNode::getClear (int i) const { if ((!d)||(i>=d->nClear )) return emptyXMLClear; return d->pClear[i]; }
+XMLAttribute XMLNode::getAttribute (int i) const { if ((!d)||(i>=d->nAttribute)) return emptyXMLAttribute; return d->pAttribute[i]; }
+XMLCSTR XMLNode::getAttributeName (int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszName; }
+XMLCSTR XMLNode::getAttributeValue(int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszValue; }
+XMLCSTR XMLNode::getText (int i) const { if ((!d)||(i>=d->nText )) return NULL; return d->pText[i]; }
+XMLNode XMLNode::getChildNode (int i) const { if ((!d)||(i>=d->nChild )) return emptyXMLNode; return d->pChild[i]; }
+XMLNode XMLNode::getParentNode ( ) const { if ((!d)||(!d->pParent )) return emptyXMLNode; return XMLNode(d->pParent); }
+char XMLNode::isDeclaration ( ) const { if (!d) return 0; return d->isDeclaration; }
+char XMLNode::isEmpty ( ) const { return (d==NULL); }
+XMLNode XMLNode::emptyNode ( ) { return XMLNode::emptyXMLNode; }
+
+XMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration, int pos)
+ { return addChild_priv(0,stringDup(lpszName),isDeclaration,pos); }
+XMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration, int pos)
+ { return addChild_priv(0,lpszName,isDeclaration,pos); }
+XMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue)
+ { return addAttribute_priv(0,stringDup(lpszName),stringDup(lpszValue)); }
+XMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev)
+ { return addAttribute_priv(0,lpszName,lpszValuev); }
+XMLCSTR XMLNode::addText(XMLCSTR lpszValue, int pos)
+ { return addText_priv(0,stringDup(lpszValue),pos); }
+XMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, int pos)
+ { return addText_priv(0,lpszValue,pos); }
+XMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+ { return addClear_priv(0,stringDup(lpszValue),lpszOpen,lpszClose,pos); }
+XMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+ { return addClear_priv(0,lpszValue,lpszOpen,lpszClose,pos); }
+XMLCSTR XMLNode::updateName(XMLCSTR lpszName)
+ { return updateName_WOSD(stringDup(lpszName)); }
+XMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
+ { return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),stringDup(newAttribute->lpszName),oldAttribute->lpszName); }
+XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i)
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),i); }
+XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName)
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),lpszOldName); }
+XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i)
+ { return updateText_WOSD(stringDup(lpszNewValue),i); }
+XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+ { return updateText_WOSD(stringDup(lpszNewValue),lpszOldValue); }
+XMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i)
+ { return updateClear_WOSD(stringDup(lpszNewContent),i); }
+XMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+ { return updateClear_WOSD(stringDup(lpszNewValue),lpszOldValue); }
+XMLClear *XMLNode::updateClear(XMLClear *newP,XMLClear *oldP)
+ { return updateClear_WOSD(stringDup(newP->lpszValue),oldP->lpszValue); }
+
+char XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding, char _guessWideCharChars, char _dropWhiteSpace)
+{
+ guessWideCharChars=_guessWideCharChars; dropWhiteSpace=_dropWhiteSpace;
+#ifdef _XMLWIDECHAR
+ if (_characterEncoding) characterEncoding=_characterEncoding;
+#else
+ switch(_characterEncoding)
+ {
+ case encoding_UTF8: characterEncoding=_characterEncoding; XML_ByteTable=XML_utf8ByteTable; break;
+ case encoding_ascii: characterEncoding=_characterEncoding; XML_ByteTable=XML_asciiByteTable; break;
+ case encoding_ShiftJIS: characterEncoding=_characterEncoding; XML_ByteTable=XML_sjisByteTable; break;
+ default: return 1;
+ }
+#endif
+ return 0;
+}
+
+XMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf,int l, char useXMLEncodingAttribute)
+{
+#ifdef _XMLWIDECHAR
+ return (XMLCharEncoding)0;
+#else
+ if (l<25) return (XMLCharEncoding)0;
+ if (guessWideCharChars&&(myIsTextWideChar(buf,l))) return (XMLCharEncoding)0;
+ unsigned char *b=(unsigned char*)buf;
+ if ((b[0]==0xef)&&(b[1]==0xbb)&&(b[2]==0xbf)) return encoding_UTF8;
+
+ // Match utf-8 model ?
+ XMLCharEncoding bestGuess=encoding_UTF8;
+ int i=0;
+ while (i<l)
+ switch (XML_utf8ByteTable[b[i]])
+ {
+ case 4: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=encoding_ascii; i=l; } // 10bbbbbb ?
+ case 3: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=encoding_ascii; i=l; } // 10bbbbbb ?
+ case 2: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=encoding_ascii; i=l; } // 10bbbbbb ?
+ case 1: i++; break;
+ case 0: i=l;
+ }
+ if (!useXMLEncodingAttribute) return bestGuess;
+ // if encoding is specified and different from utf-8 than it's non-utf8
+ // otherwise it's utf-8
+ char bb[201];
+ l=mmin(l,200);
+ memcpy(bb,buf,l); // copy buf into bb to be able to do "bb[l]=0"
+ bb[l]=0;
+ b=(unsigned char*)strstr(bb,"encoding");
+ if (!b) return bestGuess;
+ b+=8; while XML_isSPACECHAR(*b) b++; if (*b!='=') return bestGuess;
+ b++; while XML_isSPACECHAR(*b) b++; if ((*b!='\'')&&(*b!='"')) return bestGuess;
+ b++; while XML_isSPACECHAR(*b) b++;
+
+ if ((_strnicmp((char*)b,"utf-8",5)==0)||
+ (_strnicmp((char*)b,"utf8",4)==0))
+ {
+ if (bestGuess==encoding_ascii) return (XMLCharEncoding)0;
+ return encoding_UTF8;
+ }
+
+ if ((_strnicmp((char*)b,"shiftjis",8)==0)||
+ (_strnicmp((char*)b,"shift-jis",9)==0)||
+ (_strnicmp((char*)b,"sjis",4)==0)) return encoding_ShiftJIS;
+
+ return encoding_ascii;
+#endif
+}
+#undef XML_isSPACECHAR
+
+//////////////////////////////////////////////////////////
+// Here starts the base64 conversion functions. //
+//////////////////////////////////////////////////////////
+
+static const char base64Fillchar = _T('='); // used to mark partial words at the end
+
+// this lookup table defines the base64 encoding
+XMLCSTR base64EncodeTable=_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+
+// Decode Table gives the index of any valid base64 character in the Base64 table]
+// 96: '=' - 97: space char - 98: illegal char - 99: end of string
+const unsigned char base64DecodeTable[] = {
+ 99,98,98,98,98,98,98,98,98,97, 97,98,98,97,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //00 -29
+ 98,98,97,98,98,98,98,98,98,98, 98,98,98,62,98,98,98,63,52,53, 54,55,56,57,58,59,60,61,98,98, //30 -59
+ 98,96,98,98,98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24, //60 -89
+ 25,98,98,98,98,98,98,26,27,28, 29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48, //90 -119
+ 49,50,51,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //120 -149
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //150 -179
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //180 -209
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //210 -239
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98 //240 -255
+};
+
+XMLParserBase64Tool::~XMLParserBase64Tool(){ freeBuffer(); }
+
+void XMLParserBase64Tool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
+
+int XMLParserBase64Tool::encodeLength(int inlen, char formatted)
+{
+ unsigned int i=((inlen-1)/3*4+4+1);
+ if (formatted) i+=inlen/54;
+ return i;
+}
+
+XMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen, char formatted)
+{
+ int i=encodeLength(inlen,formatted),k=17,eLen=inlen/3,j;
+ alloc(i*sizeof(XMLCHAR));
+ XMLSTR curr=(XMLSTR)buf;
+ for(i=0;i<eLen;i++)
+ {
+ // Copy next three bytes into lower 24 bits of int, paying attention to sign.
+ j=(inbuf[0]<<16)|(inbuf[1]<<8)|inbuf[2]; inbuf+=3;
+ // Encode the int into four chars
+ *(curr++)=base64EncodeTable[ j>>18 ];
+ *(curr++)=base64EncodeTable[(j>>12)&0x3f];
+ *(curr++)=base64EncodeTable[(j>> 6)&0x3f];
+ *(curr++)=base64EncodeTable[(j )&0x3f];
+ if (formatted) { if (!k) { *(curr++)=_T('\n'); k=18; } k--; }
+ }
+ eLen=inlen-eLen*3; // 0 - 2.
+ if (eLen==1)
+ {
+ *(curr++)=base64EncodeTable[ inbuf[0]>>2 ];
+ *(curr++)=base64EncodeTable[(inbuf[0]<<4)&0x3F];
+ *(curr++)=base64Fillchar;
+ *(curr++)=base64Fillchar;
+ } else if (eLen==2)
+ {
+ j=(inbuf[0]<<8)|inbuf[1];
+ *(curr++)=base64EncodeTable[ j>>10 ];
+ *(curr++)=base64EncodeTable[(j>> 4)&0x3f];
+ *(curr++)=base64EncodeTable[(j<< 2)&0x3f];
+ *(curr++)=base64Fillchar;
+ }
+ *(curr++)=0;
+ return (XMLSTR)buf;
+}
+
+unsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data,XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ int size=0;
+ unsigned char c;
+ //skip any extra characters (e.g. newlines or spaces)
+ while (*data)
+ {
+#ifdef _XMLWIDECHAR
+ if (*data>255) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#endif
+ c=base64DecodeTable[(unsigned char)(*data)];
+ if (c<97) size++;
+ else if (c==98) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+ data++;
+ }
+ if (xe&&(size%4!=0)) *xe=eXMLErrorBase64DataSizeIsNotMultipleOf4;
+ if (size==0) return 0;
+ do { data--; size--; } while(*data==base64Fillchar); size++;
+ return (unsigned int)((size*3)/4);
+}
+
+unsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf, int len, XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ int i=0,p=0;
+ unsigned char d,c;
+ for(;;)
+ {
+
+#ifdef _XMLWIDECHAR
+#define BASE64DECODE_READ_NEXT_CHAR(c) \
+ do { \
+ if (data[i]>255){ c=98; break; } \
+ c=base64DecodeTable[(unsigned char)data[i++]]; \
+ }while (c==97); \
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#else
+#define BASE64DECODE_READ_NEXT_CHAR(c) \
+ do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#endif
+
+ BASE64DECODE_READ_NEXT_CHAR(c)
+ if (c==99) { return 2; }
+ if (c==96)
+ {
+ if (p==(int)len) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeTruncatedData;
+ return 1;
+ }
+
+ BASE64DECODE_READ_NEXT_CHAR(d)
+ if ((d==99)||(d==96)) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len) { if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; return 0; }
+ buf[p++]=(unsigned char)((c<<2)|((d>>4)&0x3));
+
+ BASE64DECODE_READ_NEXT_CHAR(c)
+ if (c==99) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len)
+ {
+ if (c==96) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
+ return 0;
+ }
+ if (c==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ buf[p++]=(unsigned char)(((d<<4)&0xf0)|((c>>2)&0xf));
+
+ BASE64DECODE_READ_NEXT_CHAR(d)
+ if (d==99 ) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len)
+ {
+ if (d==96) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
+ return 0;
+ }
+ if (d==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ buf[p++]=(unsigned char)(((c<<6)&0xc0)|d);
+ }
+}
+#undef BASE64DECODE_READ_NEXT_CHAR
+
+void XMLParserBase64Tool::alloc(int newsize)
+{
+ if ((!buf)&&(newsize)) { buf=malloc(newsize); buflen=newsize; return; }
+ if (newsize>buflen) { buf=realloc(buf,newsize); buflen=newsize; }
+}
+
+unsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ unsigned int len=decodeSize(data,xe);
+ if (outlen) *outlen=len;
+ if (!len) return NULL;
+ alloc(len+1);
+ if(!decode(data,(unsigned char*)buf,len,xe)){ return NULL; }
+ return (unsigned char*)buf;
+}
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsnxmlParserh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.h (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.h         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msn/xmlParser.h        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,553 @@
</span><ins>+/**
+ ****************************************************************************
+ * <P> XML.c - implementation file for basic XML parser written in ANSI C++
+ * for portability. It works by using recursion and a node tree for breaking
+ * down the elements of an XML document. </P>
+ *
+ * @version V2.29
+ * @author Frank Vanden Berghen
+ *
+ * BSD license:
+ * Copyright (c) 2002, Frank Vanden Berghen
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Frank Vanden Berghen nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************
+ */
+#ifndef __INCLUDE_XML_NODE__
+#define __INCLUDE_XML_NODE__
+
+#include <stdlib.h>
+
+#ifdef _UNICODE
+ // If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
+ // This is useful when you get error messages like:
+ // 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
+ // The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
+ // must be defined) or utf8-mode(the pre-processor variable must be undefined).
+#define _XMLWIDECHAR
+#endif
+
+#if defined(WIN32) || defined(UNDER_CE)
+ // comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET)
+#define _XMLWINDOWS
+#endif
+
+#ifdef XMLDLLENTRY
+#undef XMLDLLENTRY
+#endif
+#ifdef _USE_XMLPARSER_DLL
+#ifdef _DLL_EXPORTS_
+#define XMLDLLENTRY __declspec(dllexport)
+#else
+#define XMLDLLENTRY __declspec(dllimport)
+#endif
+#else
+#define XMLDLLENTRY
+#endif
+
+ // uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
+ //#define XML_NO_WIDE_CHAR
+
+#ifdef XML_NO_WIDE_CHAR
+#undef _XMLWINDOWS
+#undef _XMLWIDECHAR
+#endif
+
+#ifdef _XMLWINDOWS
+#include <tchar.h>
+#else
+#define XMLDLLENTRY
+#ifndef XML_NO_WIDE_CHAR
+#include <wchar.h> // to have 'wcsrtombs' for ANSI version
+ // to have 'mbsrtowcs' for WIDECHAR version
+#endif
+#endif
+
+ // Some common types for char set portable code
+#ifdef _XMLWIDECHAR
+ #ifndef _T
+ #define _T(c) L ## c
+ #endif
+ #define XMLCSTR const wchar_t *
+ #define XMLSTR wchar_t *
+ #define XMLCHAR wchar_t
+#else
+ #ifndef _T
+ #define _T(c) c
+ #endif
+ #define XMLCSTR const char *
+ #define XMLSTR char *
+ #define XMLCHAR char
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif /* FALSE */
+#ifndef TRUE
+ #define TRUE 1
+#endif /* TRUE */
+
+
+ // Enumeration for XML parse errors.
+ typedef enum XMLError
+ {
+ eXMLErrorNone = 0,
+ eXMLErrorMissingEndTag,
+ eXMLErrorEmpty,
+ eXMLErrorFirstNotStartTag,
+ eXMLErrorMissingTagName,
+ eXMLErrorMissingEndTagName,
+ eXMLErrorNoMatchingQuote,
+ eXMLErrorUnmatchedEndTag,
+ eXMLErrorUnmatchedEndClearTag,
+ eXMLErrorUnexpectedToken,
+ eXMLErrorInvalidTag,
+ eXMLErrorNoElements,
+ eXMLErrorFileNotFound,
+ eXMLErrorFirstTagNotFound,
+ eXMLErrorUnknownCharacterEntity,
+ eXMLErrorCharConversionError,
+ eXMLErrorCannotOpenWriteFile,
+ eXMLErrorCannotWriteFile,
+
+ eXMLErrorBase64DataSizeIsNotMultipleOf4,
+ eXMLErrorBase64DecodeIllegalCharacter,
+ eXMLErrorBase64DecodeTruncatedData,
+ eXMLErrorBase64DecodeBufferTooSmall
+ } XMLError;
+
+
+ // Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
+ typedef enum XMLElementType
+ {
+ eNodeChild=0,
+ eNodeAttribute=1,
+ eNodeText=2,
+ eNodeClear=3,
+ eNodeNULL=4
+ } XMLElementType;
+
+ // Structure used to obtain error details if the parse fails.
+ typedef struct XMLResults
+ {
+ enum XMLError error;
+ int nLine,nColumn;
+ } XMLResults;
+
+ // Structure for XML clear (unformatted) node (usually comments)
+ typedef struct XMLClear {
+ XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
+ } XMLClear;
+
+ // Structure for XML attribute.
+ typedef struct XMLAttribute {
+ XMLCSTR lpszName; XMLCSTR lpszValue;
+ } XMLAttribute;
+
+ struct XMLNodeContents;
+
+ typedef struct XMLDLLENTRY XMLNode
+ {
+ private:
+
+ struct XMLNodeDataTag;
+
+ // protected constructors: use one of these four methods to get your first instance of XMLNode:
+ // - parseString
+ // - parseFile
+ // - openFileHelper
+ // - createXMLTopNode
+ XMLNode(struct XMLNodeDataTag *pParent, XMLSTR lpszName, char isDeclaration);
+ XMLNode(struct XMLNodeDataTag *p);
+
+ public:
+
+ // You can create your first instance of XMLNode with these 4 functions:
+ // (see complete explanation of parameters below)
+
+ static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE);
+ static XMLNode parseString (XMLCSTR lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
+ static XMLNode parseFile (XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
+ static XMLNode openFileHelper(XMLCSTR filename, XMLCSTR tag=NULL );
+
+ // The tag parameter should be the name of the first tag inside the XML file.
+ // If the tag parameter is omitted, the 3 functions return a node that represents
+ // the head of the xml document including the declaration term (<? ... ?>).
+
+ // The "openFileHelper" reports to the screen all the warnings & errors that occurred during
+ // parsing of the XML file. Since each application has its own way to report and deal with errors,
+ // you should rather use the "parseFile" function to parse XML files and program yourself thereafter
+ // an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
+ // mechanism included inside the "openFileHelper" function).
+
+ // If the XML document is corrupted:
+ // * The "openFileHelper" method will:
+ // - display an error message on the console (or inside a messageBox for windows).
+ // - stop execution (exit).
+ // I suggest that you write your own "openFileHelper" method tailored to your needs.
+ // * The 2 other methods will initialize the "pResults" variable with some information that
+ // can be used to trace the error.
+ // * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as
+ // explained inside the note at the beginning of the "xmlParser.cpp" file.
+ // You can have a user-friendly explanation of the parsing error with this function:
+ static XMLCSTR getError(XMLError error);
+ static XMLCSTR getVersion();
+
+ XMLCSTR getName() const; // name of the node
+ XMLCSTR getText(int i=0) const; // return ith text field
+ int nText() const; // nbr of text field
+ XMLNode getParentNode() const; // return the parent node
+ XMLNode getChildNode(int i=0) const; // return ith child node
+ XMLNode getChildNode(XMLCSTR name, int i) const; // return ith child node with specific name
+ // (return an empty node if failing)
+ XMLNode getChildNode(XMLCSTR name, int *i=NULL) const; // return next child node with specific name
+ // (return an empty node if failing)
+ XMLNode getChildNodeWithAttribute(XMLCSTR tagName, // return child node with specific name/attribute
+ XMLCSTR attributeName, // (return an empty node if failing)
+ XMLCSTR attributeValue=NULL, //
+ int *i=NULL) const; //
+ int nChildNode(XMLCSTR name) const; // return the number of child node with specific name
+ int nChildNode() const; // nbr of child node
+ XMLAttribute getAttribute(int i=0) const; // return ith attribute
+ XMLCSTR getAttributeName(int i=0) const; // return ith attribute name
+ XMLCSTR getAttributeValue(int i=0) const; // return ith attribute value
+ char isAttributeSet(XMLCSTR name) const; // test if an attribute with a specific name is given
+ XMLCSTR getAttribute(XMLCSTR name, int i) const; // return ith attribute content with specific name
+ // (return a NULL if failing)
+ XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const; // return next attribute content with specific name
+ // (return a NULL if failing)
+ int nAttribute() const; // nbr of attribute
+ XMLClear getClear(int i=0) const; // return ith clear field (comments)
+ int nClear() const; // nbr of clear field
+ XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const; // create XML string starting from current XMLNode
+ // if nFormat==0, no formatting is required
+ // otherwise this returns an user friendly XML string from a
+ // given element with appropriate white spaces and carriage returns.
+ // if pnSize is given it returns the size in character of the string.
+ XMLError writeToFile(XMLCSTR filename, const char *encoding=NULL, char nFormat=1) const;
+ // Save the content of an xmlNode inside a file.
+ // The nFormat parameter has the same meaning as in the
+ // createXMLString function. If the global parameter
+ // "characterEncoding==encoding_UTF8", then the "encoding" parameter is
+ // ignored and always set to "utf-8". If the global parameter
+ // "characterEncoding==encoding_ShiftJIS", then the "encoding" parameter
+ // is ignored and always set to "SHIFT-JIS". If "_XMLWIDECHAR=1", then
+ // the "encoding" parameter is ignored and always set to "utf-16".
+ // If no "encoding" parameter is given the "ISO-8859-1" encoding is used.
+ XMLNodeContents enumContents(int i) const; // enumerate all the different contents (attribute,child,text,
+ // clear) of the current XMLNode. The order is reflecting
+ // the order of the original file/string.
+ // NOTE: 0 <= i < nElement();
+ int nElement() const; // nbr of different contents for current node
+ char isEmpty() const; // is this node Empty?
+ char isDeclaration() const; // is this node a declaration <? .... ?>
+ static XMLNode emptyNode(); // return XMLNode::emptyXMLNode;
+
+// to allow shallow/fast copy:
+ ~XMLNode();
+ XMLNode(const XMLNode &A);
+ XMLNode& operator=( const XMLNode& A );
+
+ XMLNode(): d(NULL){};
+ static XMLNode emptyXMLNode;
+ static XMLClear emptyXMLClear;
+ static XMLAttribute emptyXMLAttribute;
+
+ // The following functions allows you to create from scratch (or update) a XMLNode structure
+ // Start by creating your top node with the "createXMLTopNode" function and then add new nodes with the "addChild" function.
+ // The parameter 'pos' gives the position where the childNode, the text or the XMLClearTag will be inserted.
+ // The default value (pos=-1) inserts at the end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end).
+ // REMARK: 0 <= pos < nChild()+nText()+nClear()
+ XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, int pos=-1);
+ XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev);
+ XMLCSTR addText(XMLCSTR lpszValue, int pos=-1);
+ XMLClear *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, int pos=-1);
+ // default values: lpszOpen ="<![CDATA["
+ // lpszClose="]]>"
+ XMLNode addChild(XMLNode nodeToAdd, int pos=-1); // If the "nodeToAdd" has some parents, it will be detached
+ // from it's parents before being attached to the current XMLNode
+ // Some update functions:
+ XMLCSTR updateName(XMLCSTR lpszName); // change node's name
+ XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); // if the attribute to update is missing, a new one will be added
+ XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0); // if the attribute to update is missing, a new one will be added
+ XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName); // set lpszNewName=NULL if you don't want to change the name of the attribute
+ // if the attribute to update is missing, a new one will be added
+ XMLCSTR updateText(XMLCSTR lpszNewValue, int i=0); // if the text to update is missing, a new one will be added
+ XMLCSTR updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); // if the text to update is missing, a new one will be added
+ XMLClear *updateClear(XMLCSTR lpszNewContent, int i=0); // if the clearTag to update is missing, a new one will be added
+ XMLClear *updateClear(XMLClear *newP,XMLClear *oldP); // if the clearTag to update is missing, a new one will be added
+ XMLClear *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); // if the clearTag to update is missing, a new one will be added
+
+ // Some deletion functions:
+ void deleteNodeContent(char force=0); // delete the content of this XMLNode and the subtree.
+ // if force=0, while (references to this node still exist), no memory free occurs
+ // if force=1, always delete the content of this XMLNode and the subtree and free associated memory
+ void deleteAttribute(XMLCSTR lpszName);
+ void deleteAttribute(int i=0);
+ void deleteAttribute(XMLAttribute *anAttribute);
+ void deleteText(int i=0);
+ void deleteText(XMLCSTR lpszValue);
+ void deleteClear(int i=0);
+ void deleteClear(XMLClear *p);
+ void deleteClear(XMLCSTR lpszValue);
+
+ // The strings given as parameters for the following add and update methods (all these methods have
+ // a name with the postfix "_WOSD" that means "WithOut String Duplication" ) will be free'd by the
+ // XMLNode class. For example, it means that this is incorrect:
+ // xNode.addText_WOSD("foo");
+ // xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
+ // In opposition, this is correct:
+ // xNode.addText("foo");
+ // xNode.addText_WOSD(stringDup("foo"));
+ // xNode.updateAttribute("#newcolor" ,NULL,"color");
+ // xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
+ // Typically, you will never do:
+ // char *b=(char*)malloc(...);
+ // xNode.addText(b);
+ // free(b);
+ // ... but rather:
+ // char *b=(char*)malloc(...);
+ // xNode.addText_WOSD(b);
+ // ('free(b)' is performed by the XMLNode class)
+
+ static XMLNode createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration=FALSE);
+ XMLNode addChild_WOSD(XMLSTR lpszName, char isDeclaration=FALSE, int pos=-1);
+ XMLAttribute *addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValue);
+ XMLCSTR addText_WOSD(XMLSTR lpszValue, int pos=-1);
+ XMLClear *addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, int pos=-1);
+
+ XMLCSTR updateName_WOSD(XMLSTR lpszName);
+ XMLAttribute *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);
+ XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName=NULL,int i=0);
+ XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName);
+ XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, int i=0);
+ XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue);
+ XMLClear *updateClear_WOSD(XMLSTR lpszNewContent, int i=0);
+ XMLClear *updateClear_WOSD(XMLClear *newP,XMLClear *oldP);
+ XMLClear *updateClear_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue);
+
+ // These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
+ // middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
+ // methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
+ int positionOfText(int i=0) const;
+ int positionOfText(XMLCSTR lpszValue) const;
+ int positionOfClear(int i=0) const;
+ int positionOfClear(XMLCSTR lpszValue) const;
+ int positionOfClear(XMLClear *a) const;
+ int positionOfChildNode(int i=0) const;
+ int positionOfChildNode(XMLNode x) const;
+ int positionOfChildNode(XMLCSTR name, int i=0) const; // return the position of the ith childNode with the specified name
+ // if (name==NULL) return the position of the ith childNode
+
+ // The setGlobalOptions function allows you to change tree global parameters that affect string&file
+ // parsing. First of all, you most-probably will never have to change these 3 global parameters.
+ // The return value of the setGlobalOptions function is "0" when there are no errors. If you try to
+ // set an unrecognized encoding then the return value will be "1" to signal an error.
+ //
+ // About the "guessWideCharChars" parameter:
+ // If "guessWideCharChars=1" and if this library is compiled in WideChar mode, then the
+ // "parseFile" and "openFileHelper" functions will test if the file contains ASCII
+ // characters. If this is the case, then the file will be loaded and converted in memory to
+ // WideChar before being parsed. If "guessWideCharChars=0", no conversion will
+ // be performed.
+ //
+ // If "guessWideCharChars=1" and if this library is compiled in ASCII/UTF8/char* mode, then the
+ // "parseFile" and "openFileHelper" functions will test if the file contains WideChar
+ // characters. If this is the case, then the file will be loaded and converted in memory to
+ // ASCII/UTF8/char* before being parsed. If "guessWideCharChars=0", no conversion will
+ // be performed
+ //
+ // Sometime, it's useful to set "guessWideCharChars=0" to disable any conversion
+ // because the test to detect the file-type (ASCII/UTF8/char* or WideChar) may fail (rarely).
+ //
+ // About the "characterEncoding" parameter:
+ // This parameter is only meaningful when compiling in char* mode (multibyte character mode).
+ // In wchar_t* (wide char mode), this parameter is ignored. This parameter should be one of the
+ // three currently recognized encodings: XMLNode::encoding_UTF8, XMLNode::encoding_ascii,
+ // XMLNode::encoding_ShiftJIS.
+ //
+ // About the "dropWhiteSpace" parameter:
+ // In most situations, text fields containing only white spaces (and carriage returns)
+ // are useless. Even more, these "empty" text fields are annoying because they increase the
+ // complexity of the user's code for parsing. So, 99% of the time, it's better to drop
+ // the "empty" text fields. However The XML specification indicates that no white spaces
+ // should be lost when parsing the file. So to be perfectly XML-compliant, you should set
+ // dropWhiteSpace=0. A note of caution: if you set "dropWhiteSpace=0", the parser will be
+ // slower and your code will be more complex.
+
+ // Enumeration for XML character encoding.
+ typedef enum XMLCharEncoding { encoding_UTF8=1, encoding_ascii=2, encoding_ShiftJIS=3 } XMLCharEncoding;
+
+ static char setGlobalOptions(XMLCharEncoding characterEncoding=XMLNode::encoding_UTF8, char guessWideCharChars=1, char dropWhiteSpace=1);
+
+ // The next function try to guess the character encoding. You most-probably will never
+ // have to use this function. It then returns the appropriate value of the global parameter
+ // "characterEncoding" described above. The guess is based on the content of a buffer of length
+ // "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
+ // file to be parsed. The "openFileHelper" function is using this function to automatically compute
+ // the value of the "characterEncoding" global parameter. There are several heuristics used to do the
+ // guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
+ // forbids to use this attribute to do the guess but you can still use it if you set
+ // "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers).
+ // If an inconsistency in the encoding is detected, then the return value is "0".
+
+ static XMLCharEncoding guessCharEncoding(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
+
+ private:
+
+// these are functions and structures used internally by the XMLNode class (don't bother about them):
+
+ typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
+ {
+ XMLCSTR lpszName; // Element name (=NULL if root)
+ int nChild, // Number of child nodes
+ nText, // Number of text fields
+ nClear, // Number of Clear fields (comments)
+ nAttribute; // Number of attributes
+ char isDeclaration; // Whether node is an XML declaration - '<?xml ?>'
+ struct XMLNodeDataTag *pParent; // Pointer to parent element (=NULL if root)
+ XMLNode *pChild; // Array of child nodes
+ XMLCSTR *pText; // Array of text fields
+ XMLClear *pClear; // Array of clear fields
+ XMLAttribute *pAttribute; // Array of attributes
+ int *pOrder; // order of the child_nodes,text_fields,clear_fields
+ int ref_count; // for garbage collection (smart pointers)
+ } XMLNodeData;
+ XMLNodeData *d;
+
+ char parseClearTag(void *px, void *pa);
+ char maybeAddTxT(void *pa, XMLCSTR tokenPStr);
+ int ParseXMLElement(void *pXML);
+ void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype);
+ int indexText(XMLCSTR lpszValue) const;
+ int indexClear(XMLCSTR lpszValue) const;
+ XMLNode addChild_priv(int,XMLSTR,char,int);
+ XMLAttribute *addAttribute_priv(int,XMLSTR,XMLSTR);
+ XMLCSTR addText_priv(int,XMLSTR,int);
+ XMLClear *addClear_priv(int,XMLSTR,XMLCSTR,XMLCSTR,int);
+ static inline int findPosition(XMLNodeData *d, int index, XMLElementType xtype);
+ static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int length, int nFormat);
+ static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
+ static void exactMemory(XMLNodeData *d);
+ static int detachFromParent(XMLNodeData *d);
+} XMLNode;
+
+// This structure is given by the function "enumContents".
+typedef struct XMLNodeContents
+{
+ // This dictates what's the content of the XMLNodeContent
+ enum XMLElementType type;
+ // should be an union to access the appropriate data.
+ // compiler does not allow union of object with constructor... too bad.
+ XMLNode child;
+ XMLAttribute attrib;
+ XMLCSTR text;
+ XMLClear clear;
+
+} XMLNodeContents;
+
+XMLDLLENTRY void freeXMLString(XMLSTR t); // {free(t);}
+
+// Duplicate (copy in a new allocated buffer) the source string. This is
+// a very handy function when used with all the "XMLNode::*_WOSD" functions.
+// (If (cbData!=0) then cbData is the number of chars to duplicate)
+XMLDLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=0);
+
+// The following class is processing strings so that all the characters
+// &,",',<,> are replaced by their XML equivalent: &amp;, &quot;, &apos;, &lt;, &gt;.
+// This class is useful when creating from scratch an XML file using the
+// "printf", "fprintf", "cout",... functions. If you are creating from scratch an
+// XML file using the provided XMLNode class you must not use the "ToXMLStringTool"
+// class (the "XMLNode" class does the processing job for you during rendering).
+// Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient
+// way to produce VERY large XML documents VERY fast.
+typedef struct XMLDLLENTRY ToXMLStringTool
+{
+public:
+ ToXMLStringTool(): buf(NULL),buflen(0){}
+ ~ToXMLStringTool();
+ void freeBuffer();
+
+ XMLSTR toXML(XMLCSTR source);
+
+ // The next function is deprecated because there is a possibility of
+ // "destination-buffer-overflow". It converts the string
+ // "source" to the string "dest".
+ static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source);
+
+private:
+ XMLSTR buf;
+ int buflen;
+}ToXMLStringTool;
+
+// Below is a class that allows you to include any binary data (images, sounds,...)
+// into an XML document using "Base64 encoding". This class is completely
+// separated from the rest of the xmlParser library and can be removed without any problem.
+// To include some binary data into an XML file, you must convert the binary data into
+// standard text (using "encode"). To retrieve the original binary data from the
+// b64-encoded text included inside the XML file use "decode". Alternatively, these
+// functions can also be used to "encrypt/decrypt" some critical data contained inside
+// the XML (it's not a strong encryption at all, but sometimes it can be useful).
+
+typedef struct XMLDLLENTRY XMLParserBase64Tool
+{
+public:
+ XMLParserBase64Tool(): buf(NULL),buflen(0){}
+ ~XMLParserBase64Tool();
+ void freeBuffer();
+
+ // returns the length of the base64 string that encodes a data buffer of size inBufLen bytes.
+ // If "formatted" parameter is true, some space will be reserved for a carriage-return every 72 chars.
+ static int encodeLength(int inBufLen, char formatted=0);
+
+ // The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
+ // from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
+ // The string will be free'd when the XMLParserBase64Tool object is deleted.
+ // All returned strings are sharing the same memory space.
+ XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0);
+
+ // returns the number of bytes which will be decoded from "inString".
+ static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
+
+ // returns a pointer to a buffer containing the binary data decoded from "inString"
+ // If "inString" is malformed NULL will be returned
+ // The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
+ // All output buffer are sharing the same memory space.
+ unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL);
+
+ // The next function is deprecated.
+ // decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
+ // in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
+ // will be returned; otherwise "TRUE".
+ static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL);
+
+private:
+ void *buf;
+ int buflen;
+ void alloc(int newsize);
+}XMLParserBase64Tool;
+
+#undef XMLDLLENTRY
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsntestCMakeListstxt"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msntest/CMakeLists.txt (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msntest/CMakeLists.txt         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msntest/CMakeLists.txt        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+set(msntest_SRCS
+ msntest.cpp
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR})
+
+add_executable (msntest ${msntest_SRCS} )
+target_link_libraries(msntest crypto msn ssl)
+
+########### install files ###############
+install(TARGETS msntest DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribshahzadlibmsnmsntestmsntestcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/shahzad/libmsn/msntest/msntest.cpp (0 => 14779)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/shahzad/libmsn/msntest/msntest.cpp         (rev 0)
+++ freeswitch/trunk/contrib/shahzad/libmsn/msntest/msntest.cpp        2009-09-07 22:13:09 UTC (rev 14779)
</span><span class="lines">@@ -0,0 +1,1404 @@
</span><ins>+/*
+ * msntest.cpp
+ * libmsn
+ *
+ * Created by Meredydd Luff.
+ * Refactored by Tiago Salem Herrmann
+ * Copyright (c) 2004 Meredydd Luff. All rights reserved.
+ * Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/ssl.h>
+
+#include <msn/msn.h>
+#include <string>
+#include <iostream>
+
+class Callbacks : public MSN::Callbacks
+{
+
+ virtual void registerSocket(void *s, int read, int write, bool isSSL);
+
+ virtual void unregisterSocket(void *s);
+
+ virtual void closeSocket(void *s);
+
+ virtual void showError(MSN::Connection * conn, std::string msg);
+
+ virtual void buddyChangedStatus(MSN::NotificationServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::BuddyStatus state, unsigned int clientID, std::string msnobject);
+
+ virtual void buddyOffline(MSN::NotificationServerConnection * conn, MSN::Passport buddy);
+
+ virtual void log(int writing, const char* buf);
+
+ virtual void buddyChangedPersonalInfo(MSN::NotificationServerConnection * conn, MSN::Passport fromPassport, MSN::personalInfo);
+
+ virtual void gotFriendlyName(MSN::NotificationServerConnection * conn, std::string friendlyname);
+
+ virtual void gotBuddyListInfo(MSN::NotificationServerConnection * conn, MSN::ListSyncInfo * data);
+
+ virtual void gotLatestListSerial(MSN::NotificationServerConnection * conn, std::string lastChange);
+
+ virtual void gotGTC(MSN::NotificationServerConnection * conn, char c);
+
+ virtual void gotBLP(MSN::NotificationServerConnection * conn, char c);
+
+ virtual void addedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy, std::string friendlyname);
+
+ virtual void removedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy);
+
+ virtual void addedGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupName, std::string groupID);
+
+ virtual void removedGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupID);
+
+ virtual void renamedGroup(MSN::NotificationServerConnection * conn, bool renamed, std::string newGroupName, std::string groupID);
+
+ virtual void addedContactToGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupId, std::string contactId);
+
+ virtual void removedContactFromGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId, std::string contactId);
+
+ virtual void addedContactToAddressBook(MSN::NotificationServerConnection * conn, bool added, std::string passport, std::string displayName, std::string guid);
+
+ virtual void removedContactFromAddressBook(MSN::NotificationServerConnection * conn, bool removed, std::string contactId, std::string passport);
+
+ virtual void enabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool enabled, std::string contactId, std::string passport);
+ virtual void disabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool disabled, std::string contactId);
+
+ virtual void gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag);
+
+ virtual void buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, int is_initial);
+
+ virtual void buddyLeftConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy);
+
+ virtual void gotInstantMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::Message * msg);
+
+ virtual void gotMessageSentACK(MSN::SwitchboardServerConnection * conn, int trID);
+
+ virtual void gotEmoticonNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string alias, std::string msnobject);
+
+ virtual void failedSendingMessage(MSN::Connection * conn);
+
+ virtual void buddyTyping(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname);
+
+ virtual void gotNudge(MSN::SwitchboardServerConnection * conn, MSN::Passport from);
+
+ virtual void gotVoiceClipNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string msnobject);
+
+ virtual void gotWinkNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string msnobject);
+
+ virtual void gotInk(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string image);
+
+ virtual void gotVoiceClipFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file);
+
+ virtual void gotEmoticonFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string alias, std::string file);
+
+ virtual void gotWinkFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file);
+
+ virtual void gotActionMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string message);
+
+ virtual void gotInitialEmailNotification(MSN::NotificationServerConnection * conn, int msgs_inbox, int unread_inbox, int msgs_folders, int unread_folders);
+
+ virtual void gotNewEmailNotification(MSN::NotificationServerConnection * conn, std::string from, std::string subject);
+
+ virtual void fileTransferProgress(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, long long unsigned transferred, long long unsigned total);
+
+ virtual void fileTransferFailed(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, MSN::fileTransferError error);
+
+ virtual void fileTransferSucceeded(MSN::SwitchboardServerConnection * conn, unsigned int sessionID);
+
+ virtual void fileTransferInviteResponse(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, bool response);
+
+ virtual void gotNewConnection(MSN::Connection * conn);
+
+ virtual void gotOIMList(MSN::NotificationServerConnection * conn, std::vector<MSN::eachOIM> OIMs);
+
+ virtual void gotOIM(MSN::NotificationServerConnection * conn, bool success, std::string id, std::string message);
+
+ virtual void gotOIMSendConfirmation(MSN::NotificationServerConnection * conn, bool success, int id);
+
+ virtual void gotOIMDeleteConfirmation(MSN::NotificationServerConnection * conn, bool success, std::string id);
+
+ virtual void gotContactDisplayPicture(MSN::SwitchboardServerConnection * conn, MSN::Passport passport, std::string filename );
+
+ virtual void closingConnection(MSN::Connection * conn);
+
+ virtual void changedStatus(MSN::NotificationServerConnection * conn, MSN::BuddyStatus state);
+
+ virtual void * connectToServer(std::string server, int port, bool *connected, bool isSSL);
+
+ virtual void connectionReady(MSN::Connection * conn);
+
+ virtual void askFileTransfer(MSN::SwitchboardServerConnection *conn, MSN::fileTransferInvite ft);
+
+ virtual int listenOnPort(int port);
+
+ virtual std::string getOurIP();
+
+ virtual int getSocketFileDescriptor (void *sock);
+
+ virtual size_t getDataFromSocket (void *sock, char *data, size_t size);
+
+ virtual size_t writeDataToSocket (void *sock, char *data, size_t size);
+
+ virtual std::string getSecureHTTPProxy();
+#ifdef LIBMSN_INBOX_URL_ENABLED
+ virtual void gotInboxUrl (MSN::NotificationServerConnection *conn, MSN::hotmailInfo info);
+#endif
+};
+
+struct pollfd mySockets[21];
+struct ssl {
+ bool isSSL;
+ bool isConnected;
+ SSL *ssl;
+ SSL_CTX *ctx;
+} mySocketsSsl[21];
+
+void handle_command(MSN::NotificationServerConnection &);
+int countsocks(void);
+std::string myFriendlyName;
+std::string myUsername;
+//std::string lastObject;
+
+// should be random
+unsigned int sessionID = 123456;
+
+int main()
+{
+ for (int i = 1; i < 20; i++)
+ {
+ mySockets[i].fd = -1;
+ mySockets[i].events = POLLIN;
+ mySockets[i].revents = 0;
+ mySocketsSsl[i].isSSL = false;
+ mySocketsSsl[i].isConnected = false;
+ mySocketsSsl[i].ctx = NULL;
+ mySocketsSsl[i].ssl = NULL;
+ }
+
+ mySockets[0].fd = 0;
+ mySockets[0].events = POLLIN;
+ mySockets[0].revents = 0;
+
+ Callbacks cb;
+ MSN::Passport uname;
+ char *pass = NULL;
+
+ uname = "test.voiper@live.com";
+ pass = (char*)"shari_786pk";
+
+/*
+ while (1)
+ {
+ fprintf(stderr, "Enter your login name: ");
+ fflush(stdout);
+ try
+ {
+ std::cin >> uname;
+ myUsername = uname;
+ break;
+ }
+ catch (MSN::InvalidPassport & e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ }
+
+ pass = getpass("Enter your password: ");
+*/
+
+ fprintf(stderr, "Connecting to the MSN Messenger service...\n");
+
+ MSN::NotificationServerConnection mainConnection(uname, pass, cb);
+ mainConnection.connect("messenger.hotmail.com", 1863);
+ fprintf(stderr, "> ");
+ fflush(stderr);
+ while (1)
+ {
+ poll(mySockets, 20, -1);
+ for (int i = 1; i < 20; i++)
+ {
+ if (mySockets[i].fd == -1)
+ break;
+ if (mySockets[i].revents & POLLHUP)
+ {
+ mySockets[i].revents = 0;
+ continue;
+ }
+ if (mySockets[i].revents & (POLLIN | POLLOUT | POLLPRI))
+ {
+ MSN::Connection *c;
+
+ // Retrieve the connection associated with the
+ // socket's file handle on which the event has
+ // occurred.
+ c = mainConnection.connectionWithSocket((void*)mySockets[i].fd);
+
+ // if this is a libmsn socket
+ if (c != NULL)
+ {
+ // If we aren't connected yet, a socket event means that
+ // our connection attempt has completed.
+ if(mySocketsSsl[i].isSSL && !mySocketsSsl[i].isConnected)
+ {
+ BIO *bio_socket_new;
+ SSL_METHOD *meth=NULL;
+ meth=SSLv23_client_method();
+ SSLeay_add_ssl_algorithms();
+ mySocketsSsl[i].ctx = SSL_CTX_new(meth);
+ mySocketsSsl[i].ssl = SSL_new(mySocketsSsl[i].ctx);
+ bio_socket_new = BIO_new_socket(mySockets[i].fd, BIO_CLOSE);
+ if(!mySocketsSsl[i].ssl)
+ break;
+ BIO_set_nbio(bio_socket_new, 0);
+ SSL_set_bio(mySocketsSsl[i].ssl, bio_socket_new, bio_socket_new);
+ SSL_set_mode(mySocketsSsl[i].ssl, SSL_MODE_AUTO_RETRY);
+
+ // TODO - fix-me - not async and buggy
+ int ret = SSL_connect(mySocketsSsl[i].ssl);
+ mySocketsSsl[i].isConnected = true;
+ }
+ if (c->isConnected() == false)
+ c->socketConnectionCompleted();
+
+ // If this event is due to new data becoming available
+ if (mySockets[i].revents & POLLIN)
+ {
+ if(mySocketsSsl[i].isSSL && mySocketsSsl[i].isConnected)
+ {
+ if(SSL_want_read(mySocketsSsl[i].ssl))
+ {
+ mySockets[i].revents = 0;
+ continue;
+ }
+ }
+ c->dataArrivedOnSocket();
+ }
+
+ // If this event is due to the socket becoming writable
+ if (mySockets[i].revents & POLLOUT)
+ {
+ c->socketIsWritable();
+ }
+ }
+ }
+
+ if (mySockets[i].revents & (POLLERR | POLLNVAL))
+ {
+ printf("Dud socket (%d)! Code %x (ERR=%x, INVAL=%x)\n", mySockets[i].fd, mySockets[i].revents, POLLERR, POLLNVAL);
+
+ MSN::Connection *c;
+
+ // Retrieve the connection associated with the
+ // socket's file handle on which the event has
+ // occurred.
+ c = mainConnection.connectionWithSocket((void*)mySockets[i].fd);
+
+ // if this is a libmsn socket
+ if (c != NULL)
+ {
+ // Delete the connection. This will cause the resources
+ // that are being used to be freed.
+ delete c;
+ }
+
+ mySockets[i].fd = -1;
+ mySockets[i].revents = 0;
+ continue;
+ }
+ }
+
+ if (mySockets[0].revents & POLLIN)
+ {
+ handle_command(mainConnection);
+ mySockets[0].revents = 0;
+ }
+ }
+}
+
+void handle_command(MSN::NotificationServerConnection & mainConnection)
+{
+ char command[40];
+
+ if (scanf(" %s", command) == EOF)
+ {
+ printf("\n");
+ exit(0);
+ }
+
+ if (!strcmp(command, "quit"))
+ {
+ exit(0);
+ } else if (!strcmp(command, "sendoim")) {
+ char rcpt[80];
+ char msg[1024];
+
+ scanf(" %s", rcpt);
+
+ fgets(msg, 1024, stdin);
+
+ msg[strlen(msg)-1] = '\0';
+
+ const std::string rcpt_ = rcpt;
+ const std::string msg_ = msg;
+
+ MSN::Soap::OIM oim;
+ oim.myFname = myFriendlyName;
+ oim.toUsername = rcpt;
+ oim.message = msg;
+ oim.myUsername = myUsername;
+ oim.id = 1;
+
+ mainConnection.send_oim(oim);
+ } else if (!strcmp(command, "addtogroup")) {
+ char gid[80];
+ char uid[80];
+
+ scanf(" %s", gid);
+
+ fgets(uid, 80, stdin);
+
+ uid[strlen(uid)-1] = '\0';
+
+ const std::string uid_ = uid;
+ const std::string gid_ = gid;
+
+ mainConnection.addToGroup(gid,uid);
+ } else if (!strcmp(command, "delfromgroup")) {
+ char gid[80];
+ char uid[80];
+
+ scanf(" %s", gid);
+
+ fgets(uid, 80, stdin);
+
+ uid[strlen(uid)-1] = '\0';
+
+ const std::string uid_ = uid;
+ const std::string gid_ = gid;
+
+ mainConnection.removeFromGroup(gid,uid);
+ } else if (!strcmp(command, "renamegroup")) {
+ char gid[80];
+ char name[80];
+
+ scanf(" %s", gid);
+
+ fgets(name, 80, stdin);
+
+ name[strlen(name)-1] = '\0';
+
+ const std::string name_ = name;
+ const std::string gid_ = gid;
+
+ mainConnection.renameGroup(gid,name);
+ } else if (!strcmp(command, "getoim")) {
+ char id[80];
+
+ scanf(" %s", id);
+
+ const std::string _id = id;
+ mainConnection.get_oim(id,false);
+ } else if (!strcmp(command, "addgroup")) {
+ char gname[80];
+
+ scanf(" %s", gname);
+
+ const std::string _gname = gname;
+ mainConnection.addGroup(_gname);
+ } else if (!strcmp(command, "delgroup")) {
+ char gname[80];
+
+ scanf(" %s", gname);
+
+ const std::string _gname = gname;
+ mainConnection.removeGroup(_gname);
+ } else if (!strcmp(command, "deloim")) {
+ char id[80];
+
+ scanf(" %s", id);
+
+ const std::string _id = id;
+ mainConnection.delete_oim(id);
+
+ } else if (!strcmp(command, "msg")) {
+ char rcpt[80];
+ char msg[1024];
+
+ scanf(" %s", rcpt);
+
+ fgets(msg, 1024, stdin);
+
+ msg[strlen(msg)-1] = '\0';
+
+ const std::string rcpt_ = rcpt;
+ const std::string msg_ = msg;
+ const std::pair<std::string, std::string> *ctx = new std::pair<std::string, std::string>(rcpt_, msg_);
+ mainConnection.requestSwitchboardConnection(ctx);
+ } else if (!strcmp(command, "status")) {
+ char state[10];
+
+ scanf(" %s", state);
+ mainConnection.change_DisplayPicture("/tmp/global-photo.png");
+ uint clientid=0;
+
+ clientid += MSN::P2PAware;
+ clientid += MSN::MSNC10;
+ clientid += MSN::MSNC9;
+ clientid += MSN::MSNC8;
+ clientid += MSN::MSNC7;
+ clientid += MSN::MSNC6;
+ clientid += MSN::MSNC5;
+ clientid += MSN::MSNC4;
+ clientid += MSN::MSNC3;
+ clientid += MSN::MSNC2;
+ clientid += MSN::MSNC1;
+ clientid += MSN::SupportWinks;
+ clientid += MSN::VoiceClips;
+ clientid += MSN::InkGifSupport;
+ clientid += MSN::SIPInvitations;
+ clientid += MSN::TunnelSIPInvitations;
+ clientid += MSN::SupportMultiPacketMessaging;
+
+ mainConnection.setState(MSN::buddyStatusFromString(state), clientid);
+ } else if (!strcmp(command, "friendlyname")) {
+ char fn[256];
+
+ fgets(fn, 256, stdin);
+
+ fn[strlen(fn)-1] = '\0';
+
+ mainConnection.setFriendlyName(fn);
+ } else if (!strcmp(command, "addtolist")) {
+ MSN::ContactList list;
+ char user[128];
+
+ scanf(" %d %s", (int*)&list, user);
+
+ mainConnection.addToList(list, user);
+ } else if (!strcmp(command, "add")) {
+ char user[128];
+ char nick[128];
+
+ scanf(" %s %s", user, nick);
+
+ mainConnection.addToAddressBook(user, nick);
+ } else if (!strcmp(command, "block")) {
+ char user[128];
+
+ scanf(" %s", user);
+
+ mainConnection.blockContact(user);
+ } else if (!strcmp(command, "unblock")) {
+ char user[128];
+
+ scanf(" %s", user);
+
+ mainConnection.unblockContact(user);
+ } else if (!strcmp(command, "delfromlist")) {
+ MSN::ContactList list;
+ char user[128];
+
+ scanf(" %d %s", (int*)&list, user);
+
+ mainConnection.removeFromList(list, user);
+ } else if (!strcmp(command, "del")) {
+ char contactid[128];
+ char passport[128];
+
+ scanf(" %s %s", contactid, passport);
+
+ mainConnection.delFromAddressBook(contactid, passport);
+ } else if (!strcmp(command, "enable")) {
+ char contactid[128];
+ char passport[128];
+
+ scanf(" %s %s", contactid, passport);
+
+ mainConnection.enableContactOnAddressBook(contactid,passport);
+ } else if (!strcmp(command, "disable")) {
+ char contactid[128];
+ char passport[128];
+
+ scanf(" %s %s", contactid, passport);
+
+ mainConnection.disableContactOnAddressBook(contactid,passport);
+ } else if (!strcmp(command, "reconnect")) {
+ if (mainConnection.connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED)
+ mainConnection.disconnect();
+
+ mainConnection.connect("messenger.hotmail.com", 1863);
+ } else if (!strcmp(command, "disconnect")) {
+ mainConnection.disconnectNS();
+ } else if (!strcmp(command, "inboxurl")) {
+ mainConnection.getInboxUrl();
+ } else {
+ fprintf(stderr, "\nBad command \"%s\"", command);
+ }
+
+ fprintf(stderr, "\n> ");
+ fflush(stderr);
+}
+
+int countsocks(void)
+{
+ int retval = 0;
+
+ for (int a = 0; a < 20; a++)
+ {
+ if (mySockets[a].fd == -1)
+ break;
+
+ retval++;
+ }
+ return retval;
+}
+
+void Callbacks::registerSocket(void *s, int reading, int writing, bool isSSL)
+{
+ for (int a = 1; a < 20; a++)
+ {
+ if (mySockets[a].fd == -1 || mySockets[a].fd == getSocketFileDescriptor(s))
+ {
+ if(mySockets[a].fd == -1)
+ mySockets[a].events = 0;
+ if (reading)
+ mySockets[a].events |= POLLIN;
+
+ if (writing)
+ mySockets[a].events |= POLLOUT;
+
+ mySockets[a].fd = getSocketFileDescriptor(s);
+ if(isSSL)
+ mySocketsSsl[a].isSSL = true;
+ return;
+ }
+ }
+}
+
+int
+Callbacks::getSocketFileDescriptor (void *sock)
+{
+ long a = (long)sock;
+ return (int)a;
+}
+
+void Callbacks::closeSocket(void *s)
+{
+ for (int a = 1; a < 20; a++)
+ {
+ if (mySockets[a].fd == getSocketFileDescriptor(s))
+ {
+ close(getSocketFileDescriptor(s));
+ if(mySocketsSsl[a].isSSL)
+ {
+ if(mySocketsSsl[a].ssl)
+ {
+ if(mySocketsSsl[a].ssl) SSL_set_shutdown(mySocketsSsl[a].ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+ if(mySocketsSsl[a].ssl) SSL_free(mySocketsSsl[a].ssl);
+ if(mySocketsSsl[a].ctx) SSL_CTX_free(mySocketsSsl[a].ctx);
+ mySocketsSsl[a].ssl=NULL;
+ mySocketsSsl[a].ctx=NULL;
+ }
+ }
+ for (int b = a; b < 19; b++)
+ {
+ mySockets[b].fd = mySockets[b + 1].fd;
+ mySockets[b].revents = mySockets[b + 1].revents;
+ mySockets[b].events = mySockets[b + 1].events;
+ mySocketsSsl[b].isSSL = mySocketsSsl[b + 1].isSSL;
+ mySocketsSsl[b].isConnected = mySocketsSsl[b + 1].isConnected;
+ mySocketsSsl[b].ssl = mySocketsSsl[b + 1].ssl;
+ mySocketsSsl[b].ctx = mySocketsSsl[b + 1].ctx;
+ }
+ mySockets[19].fd = -1;
+ mySocketsSsl[19].isConnected = false;
+ mySocketsSsl[19].isSSL = false;
+ mySocketsSsl[19].ssl = NULL;
+ mySocketsSsl[19].ctx = NULL;
+ }
+ }
+}
+
+void Callbacks::unregisterSocket(void *s)
+{
+ for (int a = 1; a < 20; a++)
+ {
+ if (mySockets[a].fd == getSocketFileDescriptor(s))
+ {
+ mySockets[a].events = 0;
+ }
+ }
+}
+
+void Callbacks::gotFriendlyName(MSN::NotificationServerConnection * conn, std::string friendlyname)
+{
+ myFriendlyName = friendlyname.c_str();
+ printf("Your friendlyname is now: %s\n", friendlyname.c_str());
+}
+
+void Callbacks::gotBuddyListInfo(MSN::NotificationServerConnection * conn, MSN::ListSyncInfo * info)
+{
+ // IMPORTANT
+ // Here you need to fill a vector with all your contacts
+ // both received by the server and previous ones.
+ // Next pass this vector to the function completeConnection()
+ // if you dont call completeConnection(), the service will
+ // not work.
+ std::map<std::string, MSN::Buddy *>::iterator i = info->contactList.begin();
+ std::map<std::string, int> allContacts;
+
+ for (; i != info->contactList.end(); i++)
+ {
+ MSN::Buddy *contact = (*i).second;
+ if(contact->lists & MSN::LST_AB ) // only if it is the address book
+ {
+ allContacts[contact->userName.c_str()]=0;
+ allContacts[contact->userName.c_str()] |= MSN::LST_AB;
+ printf("-AB %s (%s)\n Id: %s\n", contact->friendlyName.c_str(), contact->userName.c_str(), contact->properties["contactId"].c_str());
+
+ if(contact->properties["isMessengerUser"]=="false")
+ printf(" Not Messenger User\n");
+
+ std::list<MSN::Buddy::PhoneNumber>::iterator pns = contact->phoneNumbers.begin();
+ std::list<MSN::Group *>::iterator g = contact->groups.begin();
+
+ for (; g != contact->groups.end(); g++)
+ {
+ printf(" G: %s\n", (*g)->name.c_str());
+ }
+
+ for (; pns != contact->phoneNumbers.end(); pns++)
+ {
+ printf(" %s: %s (%d)\n", (*pns).title.c_str(), (*pns).number.c_str(), (*pns).enabled);
+ }
+ }
+ if(contact->lists & MSN::LST_AL )
+ {
+ allContacts[contact->userName.c_str()] |= MSN::LST_AL;
+ printf("-AL %s \n", contact->userName.c_str());
+ }
+
+ if(contact->lists & MSN::LST_BL )
+ {
+ allContacts[contact->userName.c_str()] |= MSN::LST_BL;
+ printf("-BL %s \n", contact->userName.c_str());
+ }
+
+ if(contact->lists & MSN::LST_RL )
+ {
+ printf("-RL %s \n", contact->userName.c_str());
+ }
+ if(contact->lists & MSN::LST_PL )
+ {
+ printf("-PL %s \n", contact->userName.c_str());
+ }
+ }
+ printf("Available Groups:\n");
+ std::map<std::string, MSN::Group>::iterator g = info->groups.begin();
+
+ for (; g != info->groups.end(); g++)
+ {
+ printf(" %s: %s\n", (*g).second.groupID.c_str(), (*g).second.name.c_str());
+ }
+
+ std::map<std::string, int>::iterator b = allContacts.begin();
+
+ // this will send the ADL command to the server
+ // It is necessary. Dont forget to add *all* your contacts to allContacts,
+ // (both Forward, allow and block lists) or you probably will
+ // loose someone.
+ // A contact cannot be present both on allow and block lists or the
+ // server will return an error, so you need to let your application
+ // choose the better list to put it in.
+ conn->completeConnection(allContacts,info);
+}
+
+void Callbacks::gotLatestListSerial(MSN::NotificationServerConnection * conn, std::string lastChange)
+{
+ // The application needs to track this number to not ask for the whole contact
+ // list every login
+ printf("The latest change number is: %s\n", lastChange.c_str());
+}
+
+void Callbacks::gotGTC(MSN::NotificationServerConnection * conn, char c)
+{
+ printf("Your GTC value is now %c\n", c);
+}
+
+void Callbacks::gotOIMDeleteConfirmation(MSN::NotificationServerConnection * conn, bool success, std::string id)
+{
+ if(success)
+ std::cout << "OIM "<< id << " removed sucessfully." << std::endl;
+ else
+ std::cout << "OIM "<< id << " not removed sucessfully." << std::endl;
+
+}
+
+void Callbacks::gotOIMSendConfirmation(MSN::NotificationServerConnection * conn, bool success, int id)
+{
+ if(success)
+ std::cout << "OIM " << id << " sent sucessfully." << std::endl;
+ else
+ std::cout << "OIM " << id << " not sent sucessfully." << std::endl;
+}
+
+void Callbacks::gotOIM(MSN::NotificationServerConnection * conn, bool success, std::string id, std::string message)
+{
+ if(success)
+ std::cout << "ID: " << id << std::endl << "\t" << message << std::endl;
+ else
+ std::cout << "Error retreiving OIM " << id << std::endl;
+}
+
+void Callbacks::gotOIMList(MSN::NotificationServerConnection * conn, std::vector<MSN::eachOIM> OIMs)
+{
+ if(OIMs.size()==0)
+ {
+ printf("No Offline messages\n");
+ return;
+ }
+ std::vector<MSN::eachOIM>::iterator i = OIMs.begin();
+ for(; i<OIMs.end();i++)
+ {
+ printf("Offline message from: %s\n\t - Friendly Name: %s\n\t - Id: %s\n",(*i).from.c_str(), (*i).fromFN.c_str(), (*i).id.c_str());
+ }
+}
+
+void Callbacks::connectionReady(MSN::Connection * conn)
+{
+ printf("The connection is ready. You can change your status now!\n");
+}
+
+void Callbacks::gotBLP(MSN::NotificationServerConnection * conn, char c)
+{
+ printf("Your BLP value is now %cL\n", c);
+}
+
+void Callbacks::addedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport username, std::string friendlyname)
+{
+ if(list == MSN::LST_RL)
+ // after adding the user you need to delete it from the pending list.
+ // it will be added automatically by the msn service
+ printf("%s is now on your list %d. FriendlyName: %s\n", username.c_str(), list, friendlyname.c_str());
+ else
+ // on normal lists you'll never receive the contacts displayname
+ // it is not needed anyway
+ printf("%s is now on your list %d\n", username.c_str(), list);
+}
+
+void Callbacks::removedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport username)
+{
+ // list is a number which matches with MSN::ContactList enum on util.h
+ printf("%s has been removed from list %d\n", username.c_str(), list);
+}
+
+void Callbacks::addedGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupName, std::string groupID)
+{
+ if(added)
+ printf("A group named %s (%s) was added\n", groupName.c_str(), groupID.c_str());
+ else
+ printf("Group (%s) was NOT added\n", groupName.c_str());
+}
+
+void Callbacks::removedGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupID)
+{
+ if(removed)
+ printf("A group with ID %s was removed\n", groupID.c_str());
+ else
+ printf("Group (%s) was NOT removed\n", groupID.c_str());
+}
+
+void Callbacks::renamedGroup(MSN::NotificationServerConnection * conn, bool renamed, std::string newGroupName, std::string groupID)
+{
+ if(renamed)
+ printf("A group with ID %s was renamed to %s\n", groupID.c_str(), newGroupName.c_str());
+ else
+ printf("A group with ID %s was NOT renamed to %s\n", groupID.c_str(), newGroupName.c_str());
+}
+
+void Callbacks::showError(MSN::Connection * conn, std::string msg)
+{
+ printf("MSN: Error: %s\n", msg.c_str());
+}
+
+void Callbacks::buddyChangedStatus(MSN::NotificationServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::BuddyStatus status, unsigned int clientID, std::string msnobject)
+{
+ printf("%s (%s) is now %s\n", friendlyname.c_str(), buddy.c_str(), MSN::buddyStatusToString(status).c_str());
+ if (clientID & MSN::SupportWebcam)
+ printf("\t Supports Webcam\n");
+ if (clientID & MSN::VoiceClips)
+ printf("\t Supports VoiceClips\n");
+ if (clientID & MSN::SupportDirectIM)
+ printf("\t Supports DirectIM\n");
+ if (clientID & MSN::SharingFolders)
+ printf("\t Supports SharingFolders\n");
+ if (clientID & MSN::MSNC1)
+ printf("\t Supports MSNC1\n");
+ if (clientID & MSN::MSNC2)
+ printf("\t Supports MSNC2\n");
+ if (clientID & MSN::MSNC3)
+ printf("\t Supports MSNC3\n");
+ if (clientID & MSN::MSNC4)
+ printf("\t Supports MSNC4\n");
+ if (clientID & MSN::MSNC5)
+ printf("\t Supports MSNC5\n");
+ if (clientID & MSN::MSNC6)
+ printf("\t Supports MSNC6\n");
+ if (clientID & MSN::MSNC7)
+ printf("\t Supports MSNC7\n");
+ if (clientID & MSN::MSNC8)
+ printf("\t Supports MSNC8\n");
+ if (clientID & MSN::MSNC9)
+ printf("\t Supports MSNC9\n");
+ if (clientID & MSN::MSNC10)
+ printf("\t Supports MSNC10\n");
+ if (clientID & MSN::P2PAware)
+ printf("\t Supports P2PAware\n");
+ if (clientID & MSN::InkGifSupport)
+ printf("\t Supports Ink Gif\n");
+ if (clientID & MSN::InkIsfSupport)
+ printf("\t Supports Ink Isf\n");
+ if (clientID & MSN::SIPInvitations)
+ printf("\t Supports SIPInvitations\n");
+ if (clientID & MSN::TunnelSIPInvitations)
+ printf("\t Supports TunnelSIPInvitations\n");
+
+// lastObject = msnobject;
+}
+
+void Callbacks::buddyOffline(MSN::NotificationServerConnection * conn, MSN::Passport buddy)
+{
+ printf("%s is now offline\n", buddy.c_str());
+}
+
+void Callbacks::gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag)
+{
+ printf("Got switchboard connection\n");
+ if (tag)
+ {
+ const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(tag);
+ conn->inviteUser(ctx->first);
+ }
+}
+
+void Callbacks::buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname, int is_initial)
+{
+ printf("%s (%s) is now in the session\n", friendlyname.c_str(), username.c_str());
+ if (conn->auth.tag)
+ {
+ const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(conn->auth.tag);
+ // Example of sending a custom emoticon
+// conn->sendEmoticon("(EMOTICON)", filename);
+
+ int trid = conn->sendMessage(ctx->second);
+ std::cout << "Message " << trid << " queued" << std::endl;
+ delete ctx;
+ conn->auth.tag = NULL;
+
+ //Example of sending a file
+// MSN::fileTransferInvite ft;
+// ft.filename = "/tmp/filetosend.txt";
+// ft.friendlyname = "filetosend2.txt";
+// ft.sessionId = sessionID++;
+// ft.type = MSN::FILE_TRANSFER_WITHOUT_PREVIEW;
+// conn->sendFile(ft);
+
+// conn->sendNudge();
+// conn->sendAction("Action message here");
+
+ // Exemple of requesting a display picture.
+// std::string filename2("/tmp/displayPicture.bin"+MSN::toStr(sessionID));
+ // lastObject is the msnobject received on each contact status change
+ // you should generate a random sessionID
+// conn->requestDisplayPicture(sessionID++, filename2, lastObject);
+
+ // Example of sending a voice clip
+// conn->myNotificationServer()->msnobj.addMSNObject("/tmp/voiceclip.wav",11);
+// std::string obj;
+// conn->myNotificationServer()->msnobj.getMSNObjectXML("/tmp/voiceclip.wav", 11, obj);
+// conn->sendVoiceClip(obj);
+ // exemple of sending an ink
+// std::string ink("base64 data here...");
+// conn->sendInk(ink);
+ }
+}
+
+void Callbacks::buddyLeftConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport username)
+{
+ printf("%s has now left the session\n", username.c_str());
+}
+
+void Callbacks::gotInstantMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname, MSN::Message * msg)
+{
+ printf("--- Message from %s (%s) in font %s:\n%s\n", friendlyname.c_str(), username.c_str(), msg->getFontName().c_str(), msg->getBody().c_str());
+}
+
+void Callbacks::gotEmoticonNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string alias, std::string msnobject)
+{
+ std::string filename2("/tmp/emoticon.bin"+MSN::toStr(sessionID));
+ printf("--- Emoticon '%s' from %s -> %s\n", alias.c_str(), username.c_str(), msnobject.c_str());
+ conn->requestEmoticon(sessionID++, filename2, msnobject, alias);
+}
+
+void Callbacks::failedSendingMessage(MSN::Connection * conn)
+{
+ printf("**************************************************\n");
+ printf("ERROR: Your last message failed to send correctly\n");
+ printf("**************************************************\n");
+}
+
+void Callbacks::buddyTyping(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname)
+{
+ printf("\t%s (%s) is typing...\n", friendlyname.c_str(), username.c_str());
+
+}
+
+void Callbacks::gotNudge(MSN::SwitchboardServerConnection * conn, MSN::Passport username)
+{
+ printf("\t%s sent you a nudge ...\n", username.c_str());
+}
+
+void Callbacks::gotVoiceClipNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject)
+{
+ printf("\t%s sent you a voice clip...\n", username.c_str());
+ std::string filename2("/tmp/voiceclip.bin"+MSN::toStr(sessionID));
+ conn->requestVoiceClip(sessionID++, filename2, msnobject);
+}
+
+void Callbacks::gotWinkNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject)
+{
+ printf("\t%s sent you a Wink...\n", username.c_str());
+ std::string filename2("/tmp/wink.bin"+MSN::toStr(sessionID));
+ // you should generate a random sessionID number
+ conn->requestWink(sessionID++, filename2, msnobject);
+}
+
+void Callbacks::gotInk(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string image)
+{
+ // image variable is the base64 encoded gif file
+ printf("\t%s sent you an Ink...\n", username.c_str());
+// std::string filename2("/tmp/ink.bin"+MSN::toStr(sessionID));
+ // you should generate a random sessionID number
+// conn->requestFile(sessionID++, filename2, msnobject);
+}
+
+void Callbacks::gotContactDisplayPicture(MSN::SwitchboardServerConnection * conn, MSN::Passport passport, std::string filename )
+{
+ printf("Received display picture from %s. File: %s\n", passport.c_str(), filename.c_str());
+}
+
+void Callbacks::gotActionMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string message)
+{
+ printf("\t%s sent you an action message: %s\n", username.c_str(), message.c_str());
+}
+
+void Callbacks::gotInitialEmailNotification(MSN::NotificationServerConnection * conn, int msgs_inbox, int unread_inbox, int msgs_folders, int unread_folders)
+{
+ if (unread_inbox > 0)
+ printf("You have %d new messages in your Inbox. Total: %d\n", unread_inbox, msgs_inbox);
+
+ if (unread_folders > 0)
+ printf("You have %d new messages in other folders. Total: %d\n", unread_folders, msgs_folders);
+}
+
+void Callbacks::gotNewEmailNotification(MSN::NotificationServerConnection * conn, std::string from, std::string subject)
+{
+ printf("New e-mail has arrived from %s.\nSubject: %s\n", from.c_str(), subject.c_str());
+}
+
+void Callbacks::fileTransferInviteResponse(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, bool response)
+{
+ if(response)
+ printf("Session accepted %d: \n", sessionID);
+ else
+ printf("Session not accepted %d: \n", sessionID);
+}
+
+void Callbacks::fileTransferProgress(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, unsigned long long transferred, unsigned long long total)
+{
+ printf("File transfer: session %d\t(%llu/%llu bytes sent/received)\n", sessionID, transferred, total);
+}
+
+void Callbacks::fileTransferFailed(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, MSN::fileTransferError error)
+{
+ if( error == MSN::FILE_TRANSFER_ERROR_USER_CANCELED)
+ printf("The other user canceled the file transfer failed. Session: %d\n", sessionID);
+ if( error == MSN::FILE_TRANSFER_ERROR_UNKNOWN)
+ printf("File transfer failed. Session: %d\n", sessionID);
+}
+
+void Callbacks::fileTransferSucceeded(MSN::SwitchboardServerConnection * conn, unsigned int sessionID)
+{
+ printf("File transfer successfully completed. session: %d\n", sessionID);
+}
+
+void Callbacks::gotNewConnection(MSN::Connection * conn)
+{
+ if (dynamic_cast<MSN::NotificationServerConnection *>(conn))
+ dynamic_cast<MSN::NotificationServerConnection *>(conn)->synchronizeContactList();
+}
+
+void Callbacks::buddyChangedPersonalInfo(MSN::NotificationServerConnection * conn, MSN::Passport fromPassport, MSN::personalInfo pInfo)
+{
+ // MSN::personalInfo shows all the data you can grab from the contact
+ printf("User %s Personal Message: %s\n", fromPassport.c_str(),pInfo.PSM.c_str());
+}
+
+void Callbacks::closingConnection(MSN::Connection * conn)
+{
+ printf("Closed connection with socket %d\n", (int)conn->sock);
+}
+
+void Callbacks::changedStatus(MSN::NotificationServerConnection * conn, MSN::BuddyStatus state)
+{
+ printf("Your state is now: %s\n", MSN::buddyStatusToString(state).c_str());
+
+ MSN::personalInfo pInfo;
+ pInfo.PSM="my personal message";
+ pInfo.mediaType="Music";
+ pInfo.mediaIsEnabled=1;
+ pInfo.mediaFormat="{0} - {1}";
+ pInfo.mediaLines.push_back("Artist");
+ pInfo.mediaLines.push_back("Song");
+ conn->setPersonalStatus(pInfo);
+}
+
+void * Callbacks::connectToServer(std::string hostname, int port, bool *connected, bool isSSL)
+{
+ struct sockaddr_in sa;
+ struct hostent *hp;
+ int s;
+
+ if ((hp = gethostbyname(hostname.c_str())) == NULL) {
+ errno = ECONNREFUSED;
+ return (void*)-1;
+ }
+
+ memset(&sa,0,sizeof(sa));
+ memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */
+ sa.sin_family = hp->h_addrtype;
+ sa.sin_port = htons((u_short)port);
+
+ if ((s = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) /* get socket */
+ return (void*)-1;
+
+ int oldfdArgs = fcntl(s, F_GETFL, 0);
+ fcntl(s, F_SETFL, oldfdArgs | O_NONBLOCK);
+
+ if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0)
+ {
+ if (errno != EINPROGRESS)
+ {
+ close(s);
+ return (void*)-1;
+ }
+ *connected = false;
+ }
+ else
+ *connected = true;
+ return (void*)s;
+}
+
+int Callbacks::listenOnPort(int port)
+{
+ int s;
+ struct sockaddr_in addr;
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ if (bind(s, (sockaddr *)(&addr), sizeof(addr)) < 0 || listen(s, 1) < 0)
+ {
+ close(s);
+ return -1;
+ }
+
+ return s;
+}
+
+std::string Callbacks::getOurIP(void)
+{
+ struct hostent * hn;
+ char buf2[1024];
+
+ gethostname(buf2,1024);
+ hn = gethostbyname(buf2);
+
+ return inet_ntoa( *((struct in_addr*)hn->h_addr));
+}
+
+void Callbacks::log(int i, const char *s)
+{
+        std::cout << (i ? "Client: " : "Server: ") << s;
+}
+
+std::string Callbacks::getSecureHTTPProxy()
+{
+ return "";
+}
+
+void Callbacks::gotMessageSentACK(MSN::SwitchboardServerConnection * conn, int trID)
+{
+ std::cout << "Message " << trID << " delivered" << std::endl;
+}
+
+void Callbacks::askFileTransfer(MSN::SwitchboardServerConnection * conn, MSN::fileTransferInvite ft)
+{
+ std::string filename2("/tmp/"+ft.filename);
+ switch(ft.type)
+ {
+ case MSN::FILE_TRANSFER_BACKGROUND_SHARING:
+ printf("User %s wants to share with you a background file named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
+ break;
+ case MSN::FILE_TRANSFER_BACKGROUND_SHARING_CUSTOM:
+ printf("User %s wants to share with you a *custom background file named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
+ break;
+ case MSN::FILE_TRANSFER_WITH_PREVIEW:
+ printf("User %s wants to send you a file *with preview named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
+ // ft.preview has the base64 encoded png file
+ break;
+ case MSN::FILE_TRANSFER_WITHOUT_PREVIEW:
+ printf("User %s wants to send you a file *without preview named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
+ break;
+ default:
+ printf("Unknown filetransfer type from %s..\n", ft.userPassport.c_str());
+
+ }
+ conn->fileTransferResponse(ft.sessionId, filename2, true);
+}
+
+void Callbacks::addedContactToGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupId, std::string contactId)
+{
+ if(added)
+ printf("User Id (%s) added to group Id (%s)\n", contactId.c_str(),groupId.c_str());
+ else
+ printf("User Id (%s) NOT added to group Id (%s)\n", contactId.c_str(),groupId.c_str());
+}
+
+void Callbacks::removedContactFromGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId, std::string contactId)
+{
+ if(removed)
+ printf("User Id (%s) removed from group Id (%s)\n", contactId.c_str(),groupId.c_str());
+ else
+ printf("User Id (%s) NOT removed from group Id (%s)\n", contactId.c_str(),groupId.c_str());
+}
+
+void Callbacks::addedContactToAddressBook(MSN::NotificationServerConnection * conn, bool added, std::string passport, std::string displayName, std::string guid)
+{
+ if(added)
+ printf("User (%s - %s) added to AddressBook. Guid (%s)\n", passport.c_str(),displayName.c_str(), guid.c_str());
+ else
+ printf("User (%s - %s) NOT added to AddressBook.\n", passport.c_str(),displayName.c_str());
+}
+
+void Callbacks::removedContactFromAddressBook(MSN::NotificationServerConnection * conn, bool removed, std::string contactId, std::string passport)
+{
+ if(removed)
+ printf("User %s removed from AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
+ else
+ printf("User %s NOT removed from AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
+}
+
+void Callbacks::enabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool enabled, std::string contactId, std::string passport)
+{
+ // this is used to enable a contact previously disabled from msn, but not fully removed
+ if(enabled)
+ printf("User (%s) enabled on AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
+ else
+ printf("User (%s) NOT enabled on AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
+}
+
+void Callbacks::disabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool disabled, std::string contactId)
+{
+ // this is used when you have disabled this user from msn, but not deleted from hotmail
+ // I suggest to delete the contact instead of disable, since I haven't tested this too much yet
+ if(disabled)
+ printf("User disabled on AddressBook. Guid (%s)\n", contactId.c_str());
+ else
+ printf("User NOT disabled on AddressBook. Guid (%s)\n", contactId.c_str());
+}
+
+size_t Callbacks::getDataFromSocket (void *sock, char *data, size_t size)
+{
+ int fd;
+ int idx=0;
+ bool ssl_done = false;
+ int amountRead = 0;
+ int newAmountRead = 0;
+ for (int i = 1; i < 20; i++)
+ {
+ if(mySockets[i].fd == getSocketFileDescriptor(sock))
+ {
+ idx = i;
+ break;
+ }
+ }
+ if(!idx)
+ return 0;
+
+ if(!mySocketsSsl[idx].isSSL)
+ {
+ int newWritten = ::recv(getSocketFileDescriptor(sock), data, size, 0);
+ if (errno == EAGAIN)
+ return -1;
+ return newWritten;
+ }
+
+ if (!mySocketsSsl[idx].isConnected)
+ return 0;
+
+ while(!ssl_done)
+ {
+ if(!mySocketsSsl[idx].ssl) break;
+ newAmountRead = SSL_read(mySocketsSsl[idx].ssl, data, size);
+ switch(SSL_get_error(mySocketsSsl[idx].ssl,newAmountRead))
+ {
+ case SSL_ERROR_NONE:
+ return newAmountRead;
+ case SSL_ERROR_ZERO_RETURN:
+ return 0;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ ssl_done=false;
+ break;
+ case SSL_ERROR_SSL:
+ return 0;
+ break;
+ case SSL_ERROR_SYSCALL:
+ return 0;
+ break;
+ default:
+ return newAmountRead;
+ }
+ }
+ return 0;
+}
+
+size_t Callbacks::writeDataToSocket (void *sock, char *data, size_t size)
+{
+ size_t written = 0;
+ int idx;
+ for (int i = 1; i < 20; i++)
+ {
+ if(mySockets[i].fd == getSocketFileDescriptor(sock))
+ {
+ idx = i;
+ break;
+ }
+ }
+
+ while (written < size)
+ {
+ int newWritten;
+ if (mySocketsSsl[idx].isSSL)
+ {
+ if(!mySocketsSsl[idx].isConnected)
+ return 0;
+ newWritten = SSL_write(mySocketsSsl[idx].ssl, data, (int) (size - written));
+ int error = SSL_get_error(mySocketsSsl[idx].ssl,newWritten);
+ switch(error)
+ {
+ case SSL_ERROR_NONE:
+ written += newWritten;
+ data+=newWritten;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ continue;
+ case SSL_ERROR_ZERO_RETURN:
+ break;
+ case SSL_ERROR_SYSCALL:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ newWritten = ::send(getSocketFileDescriptor(sock), data, (int)(size - written), 0);
+
+ if (newWritten <= 0)
+ {
+ if (errno == EAGAIN)
+ continue;
+ else
+ break;
+ }
+ written += newWritten;
+ data+=newWritten;
+ }
+ }
+ if (written != size)
+ {
+ // TODO: return an error
+ showError(NULL, "Error on socket");
+ unregisterSocket(sock);
+ closeSocket(sock);
+ return written;
+ }
+ return written;
+}
+
+void Callbacks::gotVoiceClipFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file)
+{
+ printf("--- Voice clip file '%s'\n", file.c_str());
+
+}
+
+void Callbacks::gotEmoticonFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string alias, std::string file)
+{
+ printf("--- Voice emoticon file '%s' for '%s'\n", file.c_str(), alias.c_str());
+}
+
+void Callbacks::gotWinkFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file)
+{
+ printf("--- Voice Wink file '%s'\n", file.c_str());
+}
+
+#ifdef LIBMSN_INBOX_URL_ENABLED
+void Callbacks::gotInboxUrl(MSN::NotificationServerConnection *conn, MSN::hotmailInfo info)
+{
+ std::vector<std::string>::const_iterator i;
+
+ std::cout << "--- Inbox URL data :" << std::endl;
+ std::cout << "sid: " << info.sid << std::endl;
+ std::cout << "kv: " << info.kv << std::endl;
+ std::cout << "id: " << info.id << std::endl;
+ std::cout << "sl: " << info.sl << std::endl;
+ std::cout << "rru: " << info.rru << std::endl;
+ std::cout << "auth: " << info.MSPAuth << std::endl;
+ std::cout << "creds: " << info.creds << std::endl;
+}
+#endif
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>