ÂÂmoving libmsn code from branch to the Caya subproject
This commit is contained in:
parent
a9df932fec
commit
b6b44c0d8a
|
@ -2,4 +2,5 @@ SubDir TOP libs ;
|
||||||
|
|
||||||
# Include all the components.
|
# Include all the components.
|
||||||
SubInclude TOP libs libgloox ;
|
SubInclude TOP libs libgloox ;
|
||||||
|
SubInclude TOP libs libmsn ;
|
||||||
SubInclude TOP libs libsupport ;
|
SubInclude TOP libs libsupport ;
|
||||||
|
|
|
@ -0,0 +1,353 @@
|
||||||
|
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.
|
|
@ -0,0 +1,37 @@
|
||||||
|
SubDir TOP libs libmsn ;
|
||||||
|
|
||||||
|
SubDirSysHdrs [ FDirName $(TOP) ] ;
|
||||||
|
SubDirSysHdrs [ FDirName $(TOP) libs ] ;
|
||||||
|
|
||||||
|
SubDirSysHdrs [ FDirName $(OPENSSL_INCLUDE_DIR) ] ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(TOP) libs ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(TOP) libs libmsn libsiren ] ;
|
||||||
|
|
||||||
|
local sources =
|
||||||
|
# libmsn
|
||||||
|
authdata.cpp
|
||||||
|
buddy.cpp
|
||||||
|
connection.cpp
|
||||||
|
md5.cpp
|
||||||
|
message.cpp
|
||||||
|
msnobject.cpp
|
||||||
|
# msntest.cpp
|
||||||
|
notificationserver.cpp
|
||||||
|
p2p.cpp
|
||||||
|
passport.cpp
|
||||||
|
soap.cpp
|
||||||
|
switchboardserver.cpp
|
||||||
|
util.cpp
|
||||||
|
xmlParser.cpp
|
||||||
|
|
||||||
|
# libsiren
|
||||||
|
common.cpp
|
||||||
|
dct4.cpp
|
||||||
|
decoder.cpp
|
||||||
|
encoder.cpp
|
||||||
|
huffman.cpp
|
||||||
|
rmlt.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
StaticLibrary libmsn.a : $(sources) : be root $(TARGET_LIBSTDC++) ssl crypto ;
|
|
@ -0,0 +1,60 @@
|
||||||
|
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.
|
|
@ -0,0 +1,21 @@
|
||||||
|
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)
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 "authdata.h"
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#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 "passport.h"
|
||||||
|
|
||||||
|
#include "libmsn_export.h"
|
||||||
|
|
||||||
|
namespace MSN
|
||||||
|
{
|
||||||
|
class LIBMSN_EXPORT AuthData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Passport username;
|
||||||
|
|
||||||
|
AuthData(Passport username_) : username(username_) {};
|
||||||
|
virtual ~AuthData() {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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 "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!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
#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 "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
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef LIBMSN_CONFIG_H
|
||||||
|
#define LIBMSN_CONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* 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 "connection.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "passport.h"
|
||||||
|
#include "externals.h"
|
||||||
|
#include "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->connected = false;
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
#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>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#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
|
|
@ -0,0 +1,101 @@
|
||||||
|
#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 "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
|
|
@ -0,0 +1,333 @@
|
||||||
|
#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 "config.h"
|
||||||
|
#include "buddy.h"
|
||||||
|
#include "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;
|
||||||
|
|
||||||
|
virtual void gotInboxUrl (MSN::NotificationServerConnection * /*conn*/, MSN::hotmailInfo /*info*/) {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
#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_
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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_ */
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
|
@ -0,0 +1,382 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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_ */
|
|
@ -0,0 +1,528 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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_ */
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
|
@ -0,0 +1,392 @@
|
||||||
|
/*
|
||||||
|
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));
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
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 */
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*
|
||||||
|
* 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 "message.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "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(0UL, 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(0UL, 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 "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
#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
|
|
@ -0,0 +1,38 @@
|
||||||
|
#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 "authdata.h"
|
||||||
|
#include "connection.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "externals.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include "notificationserver.h"
|
||||||
|
#include "switchboardserver.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "soap.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* 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 "util.h"
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "msnobject.h"
|
||||||
|
#include "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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,549 @@
|
||||||
|
#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 "connection.h"
|
||||||
|
#include "authdata.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "buddy.h"
|
||||||
|
#include "passport.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "externals.h"
|
||||||
|
#include "msnobject.h"
|
||||||
|
#include "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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,322 @@
|
||||||
|
#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 "connection.h"
|
||||||
|
#include "authdata.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "buddy.h"
|
||||||
|
#include "passport.h"
|
||||||
|
#include "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
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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 "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);
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
#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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,221 @@
|
||||||
|
#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 "connection.h"
|
||||||
|
#include "authdata.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "buddy.h"
|
||||||
|
#include "passport.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "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 ¬ificationServer; };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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
|
|
@ -0,0 +1,749 @@
|
||||||
|
/*
|
||||||
|
* 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 "switchboardserver.h"
|
||||||
|
#include "notificationserver.h"
|
||||||
|
#include "errorcodes.h"
|
||||||
|
#include "externals.h"
|
||||||
|
#include "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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
delete [] 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()
|
||||||
|
{
|
||||||
|
if (this->connectionState() == SB_DISCONNECTED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
#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 "message.h"
|
||||||
|
#include "authdata.h"
|
||||||
|
#include "connection.h"
|
||||||
|
#include "passport.h"
|
||||||
|
#include "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 ¬ificationServer; };
|
||||||
|
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
|
|
@ -0,0 +1,624 @@
|
||||||
|
/*
|
||||||
|
* 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 "util.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <cctype>
|
||||||
|
#include <fstream>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include <posix/unistd.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 (¤t_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(¤t_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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
#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,
|
||||||
|
SharingFolders = 0x400000,
|
||||||
|
MSNC1 = 0x10000000,
|
||||||
|
MSNC2 = 0x20000000,
|
||||||
|
MSNC3 = 0x30000000,
|
||||||
|
MSNC4 = 0x40000000,
|
||||||
|
MSNC5 = 0x50000000,
|
||||||
|
MSNC6 = 0x60000000,
|
||||||
|
MSNC7 = 0x70000000
|
||||||
|
} 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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,553 @@
|
||||||
|
/**
|
||||||
|
****************************************************************************
|
||||||
|
* <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: &, ", ', <, >.
|
||||||
|
// 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
|
Ŝarĝante…
Reference in New Issue