ÂÂmoving libmsn code from branch to the Caya subproject

This commit is contained in:
barrett 2010-09-24 13:48:01 +00:00
parent a9df932fec
commit b6b44c0d8a
53 changed files with 19228 additions and 0 deletions

View File

@ -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 ;

353
libs/libmsn/COPYING Executable file
View File

@ -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.

37
libs/libmsn/Jamfile Normal file
View File

@ -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 ;

60
libs/libmsn/README Executable file
View File

@ -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.

21
libs/libmsn/THANKS Executable file
View File

@ -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)

42
libs/libmsn/TODO Executable file
View File

@ -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)

28
libs/libmsn/authdata.cpp Normal file
View File

@ -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"

44
libs/libmsn/authdata.h Normal file
View File

@ -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

76
libs/libmsn/buddy.cpp Normal file
View File

@ -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!");
}
}

138
libs/libmsn/buddy.h Normal file
View File

@ -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

5
libs/libmsn/config.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef LIBMSN_CONFIG_H
#define LIBMSN_CONFIG_H
#endif

241
libs/libmsn/connection.cpp Normal file
View File

@ -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());
}
}

154
libs/libmsn/connection.h Normal file
View File

@ -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

101
libs/libmsn/errorcodes.h Normal file
View File

@ -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

333
libs/libmsn/externals.h Normal file
View File

@ -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

View File

@ -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_

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 */

392
libs/libmsn/md5.cpp Normal file
View File

@ -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));
}

94
libs/libmsn/md5.h Normal file
View File

@ -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 */

338
libs/libmsn/message.cpp Normal file
View File

@ -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 "";
}
}

211
libs/libmsn/message.h Normal file
View File

@ -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

38
libs/libmsn/msn.h Normal file
View File

@ -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

185
libs/libmsn/msnobject.cpp Normal file
View File

@ -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;
}
}

64
libs/libmsn/msnobject.h Normal file
View File

@ -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

1375
libs/libmsn/msntest.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

1413
libs/libmsn/p2p.cpp Normal file

File diff suppressed because it is too large Load Diff

322
libs/libmsn/p2p.h Normal file
View File

@ -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

68
libs/libmsn/passport.cpp Normal file
View File

@ -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);
}

74
libs/libmsn/passport.h Normal file
View File

@ -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

2711
libs/libmsn/soap.cpp Normal file

File diff suppressed because it is too large Load Diff

221
libs/libmsn/soap.h Normal file
View File

@ -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 &notificationServer; };
};
}
#endif

74
libs/libmsn/sstream_fix.h Normal file
View File

@ -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

View File

@ -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);
}
}

View File

@ -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 &notificationServer; };
void callback_continueTransfer(std::vector<std::string> & args, int trid, unsigned int sessionID);
/** Request an emoticon
*/
void requestEmoticon(unsigned int id, std::string filename, std::string msnobject, std::string alias);
/** Request a voice clip
*/
void requestVoiceClip(unsigned int id, std::string filename, std::string msnobject);
/** Request a wink
*/
void requestWink(unsigned int id, std::string filename, std::string msnobject);
/** Request a display picture
*/
void requestDisplayPicture(unsigned int id, std::string filename, std::string msnobject);
protected:
virtual void handleIncomingData();
SwitchboardServerState _connectionState;
void setConnectionState(SwitchboardServerState s) { this->_connectionState = s; };
void assertConnectionStateIs(SwitchboardServerState s) { assert(this->_connectionState == s); };
void assertConnectionStateIsNot(SwitchboardServerState s) { assert(this->_connectionState != s); };
void assertConnectionStateIsAtLeast(SwitchboardServerState s) { assert(this->_connectionState >= s); };
private:
NotificationServerConnection & notificationServer;
std::list<FileTransferConnectionP2P *> _fileTransferConnectionsP2P;
std::map<int, std::pair<SwitchboardServerCallback, void *> > callbacks;
std::map<int, std::pair<SwitchboardServerCallback2, unsigned int> > callbacks2;
static std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &)> commandHandlers;
static std::map<std::string, void (SwitchboardServerConnection::*)(std::vector<std::string> &, std::string, std::string)> messageHandlers;
void registerCommandHandlers();
void registerMessageHandlers();
void handle_BYE(std::vector<std::string> & args);
void handle_JOI(std::vector<std::string> & args);
void handle_NAK(std::vector<std::string> & args);
void handle_MSG(std::vector<std::string> & args);
void callback_InviteUsers(std::vector<std::string> & args, int trid, void * data);
void callback_AnsweredCall(std::vector<std::string> & args, int trid, void * data);
void callback_messageACK(std::vector<std::string> & args, int trid, void * data);
void handleInvite(Passport from, const std::string & friendly, const std::string & mime, const std::string & body);
void handleNewInvite(Passport & from, const std::string & friendly, const std::string & mime, const std::string & body);
void message_plain(std::vector<std::string> & args, std::string mime, std::string body);
void message_invitation(std::vector<std::string> & args, std::string mime, std::string body);
void message_typing_user(std::vector<std::string> & args, std::string mime, std::string body);
void message_p2p(std::vector<std::string> & args, std::string mime, std::string body);
void message_datacast(std::vector<std::string> & args, std::string mime, std::string body);
void message_emoticon(std::vector<std::string> & args, std::string mime, std::string body);
public:
void message_ink(std::vector<std::string> & args, std::string mime, std::string body);
friend class Connection;
};
}
#endif

624
libs/libmsn/util.cpp Normal file
View File

@ -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 (&current_chunk, sizeof (wav_data), 1, input);
file_offset += sizeof (wav_data);
current_chunk.chunk_id = GUINT32_FROM_LE (current_chunk.chunk_id);
current_chunk.chunk_size = GUINT32_FROM_LE (current_chunk.chunk_size);
chunk_offset = 0;
if (current_chunk.chunk_id == FMT_ID)
{
fread (&fmt_info, sizeof (fmt_chunk), 1, input);
/* Should convert from LE the fmt_info structure, but it's not necessary... */
if (current_chunk.chunk_size > sizeof (fmt_chunk))
{
fread (&(fmt_info.extra_size), sizeof (short), 1, input);
fmt_info.extra_size = GUINT32_FROM_LE (fmt_info.extra_size);
fmt_info.extra_content = (unsigned char *) malloc (fmt_info.extra_size);
fread (fmt_info.extra_content, fmt_info.extra_size, 1, input);
}
else
{
fmt_info.extra_size = 0;
fmt_info.extra_content = NULL;
}
}
else if (current_chunk.chunk_id == DATA_ID)
{
out_data = (unsigned char *) malloc (current_chunk.chunk_size * 16);
out_ptr = out_data;
while (chunk_offset + 40 <= current_chunk.chunk_size)
{
fread (in_buffer, 1, 40, input);
Siren7_DecodeFrame (decoder, in_buffer, out_ptr);
out_ptr += 640;
chunk_offset += 40;
}
fread (in_buffer, 1, current_chunk.chunk_size - chunk_offset, input);
}
else
{
fseek (input, current_chunk.chunk_size, SEEK_CUR);
}
file_offset += current_chunk.chunk_size;
}
}
/* The WAV heder should be converted TO LE, but should be done inside the library and it's not important for now ... */
fwrite (&(decoder->WavHeader), sizeof (decoder->WavHeader), 1, output);
fwrite (out_data, 1, GUINT32_FROM_LE (decoder->WavHeader.DataSize), output);
fclose (output);
Siren7_CloseDecoder (decoder);
free (out_data);
free (fmt_info.extra_content);
// remove the siren encoded file
unlink(old_voice.c_str());
}
// convert to siren codec from a regular wav file
void
libmsn_Siren7_EncodeVoiceClip(std::string input_file)
{
FILE * input;
FILE * output;
riff_data riff_header;
wav_data current_chunk;
fmt_chunk_ex fmt_info;
unsigned char *out_data = NULL;
unsigned char *out_ptr = NULL;
unsigned char InBuffer[640];
unsigned int fileOffset;
unsigned int chunkOffset;
SirenEncoder encoder = Siren7_NewEncoder(16000);
std::string new_voice(input_file.c_str());
std::string old_voice = new_voice + "-old";
rename(new_voice.c_str(), old_voice.c_str());
input = fopen (old_voice.c_str(), "rb");
output = fopen (new_voice.c_str(), "wb");
fileOffset = 0;
fread(&riff_header, sizeof(riff_data), 1, input);
fileOffset += sizeof(riff_data);
riff_header.chunk_id = GUINT32_FROM_LE(riff_header.chunk_id);
riff_header.chunk_size = GUINT32_FROM_LE(riff_header.chunk_size);
riff_header.type_id = GUINT32_FROM_LE(riff_header.type_id);
if (riff_header.chunk_id == RIFF_ID && riff_header.type_id == WAVE_ID) {
while (fileOffset < riff_header.chunk_size) {
fread(&current_chunk, sizeof(wav_data), 1, input);
fileOffset += sizeof(wav_data);
current_chunk.chunk_id = GUINT32_FROM_LE(current_chunk.chunk_id);
current_chunk.chunk_size = GUINT32_FROM_LE(current_chunk.chunk_size);
chunkOffset = 0;
if (current_chunk.chunk_id == FMT__ID) {
fread(&fmt_info, sizeof(fmt_chunk), 1, input);
/* Should convert from LE the fmt_info structure, but it's not necessary... */
if (current_chunk.chunk_size > sizeof(fmt_chunk)) {
fread(&(fmt_info.extra_size), sizeof(short), 1, input);
fmt_info.extra_size= GUINT32_FROM_LE(fmt_info.extra_size);
fmt_info.extra_content = (unsigned char *) malloc (fmt_info.extra_size);
fread(fmt_info.extra_content, fmt_info.extra_size, 1, input);
} else {
fmt_info.extra_size = 0;
fmt_info.extra_content = NULL;
}
} else if (current_chunk.chunk_id == DATA_ID) {
out_data = (unsigned char *) malloc(current_chunk.chunk_size / 16);
out_ptr = out_data;
while (chunkOffset + 640 <= current_chunk.chunk_size) {
fread(InBuffer, 1, 640, input);
Siren7_EncodeFrame(encoder, InBuffer, out_ptr);
out_ptr += 40;
chunkOffset += 640;
}
fread(InBuffer, 1, current_chunk.chunk_size - chunkOffset, input);
} else {
fseek(input, current_chunk.chunk_size, SEEK_CUR);
}
fileOffset += current_chunk.chunk_size;
}
}
/* The WAV heder should be converted TO LE, but should be done inside the library and it's not important for now ... */
fwrite(&(encoder->WavHeader), sizeof(encoder->WavHeader), 1, output);
fwrite(out_data, 1, GUINT32_FROM_LE(encoder->WavHeader.DataSize), output);
fclose(output);
Siren7_CloseEncoder(encoder);
free(out_data);
if (fmt_info.extra_content != NULL)
free(fmt_info.extra_content);
// remove the siren encoded file
unlink(old_voice.c_str());
}
}

279
libs/libmsn/util.h Normal file
View File

@ -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

2675
libs/libmsn/xmlParser.cpp Normal file

File diff suppressed because it is too large Load Diff

553
libs/libmsn/xmlParser.h Executable file
View File

@ -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: &amp;, &quot;, &apos;, &lt;, &gt;.
// This class is useful when creating from scratch an XML file using the
// "printf", "fprintf", "cout",... functions. If you are creating from scratch an
// XML file using the provided XMLNode class you must not use the "ToXMLStringTool"
// class (the "XMLNode" class does the processing job for you during rendering).
// Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient
// way to produce VERY large XML documents VERY fast.
typedef struct XMLDLLENTRY ToXMLStringTool
{
public:
ToXMLStringTool(): buf(NULL),buflen(0){}
~ToXMLStringTool();
void freeBuffer();
XMLSTR toXML(XMLCSTR source);
// The next function is deprecated because there is a possibility of
// "destination-buffer-overflow". It converts the string
// "source" to the string "dest".
static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source);
private:
XMLSTR buf;
int buflen;
}ToXMLStringTool;
// Below is a class that allows you to include any binary data (images, sounds,...)
// into an XML document using "Base64 encoding". This class is completely
// separated from the rest of the xmlParser library and can be removed without any problem.
// To include some binary data into an XML file, you must convert the binary data into
// standard text (using "encode"). To retrieve the original binary data from the
// b64-encoded text included inside the XML file use "decode". Alternatively, these
// functions can also be used to "encrypt/decrypt" some critical data contained inside
// the XML (it's not a strong encryption at all, but sometimes it can be useful).
typedef struct XMLDLLENTRY XMLParserBase64Tool
{
public:
XMLParserBase64Tool(): buf(NULL),buflen(0){}
~XMLParserBase64Tool();
void freeBuffer();
// returns the length of the base64 string that encodes a data buffer of size inBufLen bytes.
// If "formatted" parameter is true, some space will be reserved for a carriage-return every 72 chars.
static int encodeLength(int inBufLen, char formatted=0);
// The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
// from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
// The string will be free'd when the XMLParserBase64Tool object is deleted.
// All returned strings are sharing the same memory space.
XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0);
// returns the number of bytes which will be decoded from "inString".
static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
// returns a pointer to a buffer containing the binary data decoded from "inString"
// If "inString" is malformed NULL will be returned
// The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
// All output buffer are sharing the same memory space.
unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL);
// The next function is deprecated.
// decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
// in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
// will be returned; otherwise "TRUE".
static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL);
private:
void *buf;
int buflen;
void alloc(int newsize);
}XMLParserBase64Tool;
#undef XMLDLLENTRY
#endif