summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Tlen/docs/InstallScript.xml27
-rw-r--r--protocols/Tlen/docs/changelog_tlen.txt269
-rw-r--r--protocols/Tlen/docs/gpl.txt340
-rw-r--r--protocols/Tlen/docs/gpl_comment.txt20
-rw-r--r--protocols/Tlen/docs/readme_tlen.txt61
-rw-r--r--protocols/Tlen/docs/tlen-translation.txt153
-rw-r--r--protocols/Tlen/res/auth_grant.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/auth_request.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/groupchats.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/image.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/mail.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/microphone.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/speaker.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/tlen.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/tlen.rc439
-rw-r--r--protocols/Tlen/res/tlenchats.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/res/voicechat.icobin0 -> 2550 bytes
-rw-r--r--protocols/Tlen/src/codec/gsm.h65
-rw-r--r--protocols/Tlen/src/codec/gsm_codec.c283
-rw-r--r--protocols/Tlen/src/codec/gsm_long.c183
-rw-r--r--protocols/Tlen/src/codec/gsm_lpc.c208
-rw-r--r--protocols/Tlen/src/codec/gsm_preprocess.c103
-rw-r--r--protocols/Tlen/src/codec/gsm_rpe.c248
-rw-r--r--protocols/Tlen/src/codec/gsm_short.c211
-rw-r--r--protocols/Tlen/src/commons.h32
-rw-r--r--protocols/Tlen/src/crypto/aes.c1336
-rw-r--r--protocols/Tlen/src/crypto/bignum.c2097
-rw-r--r--protocols/Tlen/src/crypto/padlock.c162
-rw-r--r--protocols/Tlen/src/crypto/polarssl/aes.h167
-rw-r--r--protocols/Tlen/src/crypto/polarssl/bignum.h587
-rw-r--r--protocols/Tlen/src/crypto/polarssl/bn_mul.h738
-rw-r--r--protocols/Tlen/src/crypto/polarssl/config.h625
-rw-r--r--protocols/Tlen/src/crypto/polarssl/padlock.h100
-rw-r--r--protocols/Tlen/src/jabber.h507
-rw-r--r--protocols/Tlen/src/jabber_iq.cpp114
-rw-r--r--protocols/Tlen/src/jabber_iq.h61
-rw-r--r--protocols/Tlen/src/jabber_iqid.cpp642
-rw-r--r--protocols/Tlen/src/jabber_list.cpp315
-rw-r--r--protocols/Tlen/src/jabber_list.h90
-rw-r--r--protocols/Tlen/src/jabber_misc.cpp218
-rw-r--r--protocols/Tlen/src/jabber_opt.cpp710
-rw-r--r--protocols/Tlen/src/jabber_svc.cpp1364
-rw-r--r--protocols/Tlen/src/jabber_thread.cpp1467
-rw-r--r--protocols/Tlen/src/jabber_util.cpp647
-rw-r--r--protocols/Tlen/src/jabber_ws.cpp160
-rw-r--r--protocols/Tlen/src/jabber_xml.cpp568
-rw-r--r--protocols/Tlen/src/jabber_xml.h79
-rw-r--r--protocols/Tlen/src/resource.h147
-rw-r--r--protocols/Tlen/src/tlen.cpp524
-rw-r--r--protocols/Tlen/src/tlen_advsearch.cpp113
-rw-r--r--protocols/Tlen/src/tlen_avatar.cpp427
-rw-r--r--protocols/Tlen/src/tlen_avatar.h34
-rw-r--r--protocols/Tlen/src/tlen_file.cpp708
-rw-r--r--protocols/Tlen/src/tlen_file.h34
-rw-r--r--protocols/Tlen/src/tlen_muc.cpp1069
-rw-r--r--protocols/Tlen/src/tlen_muc.h45
-rw-r--r--protocols/Tlen/src/tlen_p2p_new.cpp352
-rw-r--r--protocols/Tlen/src/tlen_p2p_old.cpp535
-rw-r--r--protocols/Tlen/src/tlen_p2p_old.h70
-rw-r--r--protocols/Tlen/src/tlen_picture.cpp320
-rw-r--r--protocols/Tlen/src/tlen_picture.h33
-rw-r--r--protocols/Tlen/src/tlen_presence.cpp318
-rw-r--r--protocols/Tlen/src/tlen_presence.h29
-rw-r--r--protocols/Tlen/src/tlen_userinfo.cpp335
-rw-r--r--protocols/Tlen/src/tlen_voice.cpp1121
-rw-r--r--protocols/Tlen/src/tlen_voice.h70
-rw-r--r--protocols/Tlen/tlen_10.vcxproj366
-rw-r--r--protocols/Tlen/tlen_10.vcxproj.filters208
-rw-r--r--protocols/Tlen/tlen_czaty/mucc.vcxproj479
-rw-r--r--protocols/Tlen/tlen_czaty/mucc.vcxproj.filters178
-rw-r--r--protocols/Tlen/tlen_czaty/res/admin.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/administration.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/blank.icobin0 -> 318 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/bold.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/chat.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/delete.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/glowner.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/invite.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/italic.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/message.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/mucc.rc579
-rw-r--r--protocols/Tlen/tlen_czaty/res/next.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/options.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/owner.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/prev.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/r_anon.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/r_memb.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/r_mod.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/registered.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/save.icobin0 -> 318 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/search.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/sendmail.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/smile.icobin0 -> 1406 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/tlenbig.icobin0 -> 2238 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/tlensmall.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/res/underline.icobin0 -> 894 bytes
-rw-r--r--protocols/Tlen/tlen_czaty/src/AdminWindow.cpp490
-rw-r--r--protocols/Tlen/tlen_czaty/src/AdminWindow.h63
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatContainer.cpp480
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatContainer.h100
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatEvent.cpp174
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatEvent.h60
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatGroup.cpp99
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatGroup.h55
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatRoom.cpp68
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatRoom.h51
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatUser.cpp83
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatUser.h49
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatWindow.cpp2109
-rw-r--r--protocols/Tlen/tlen_czaty/src/ChatWindow.h196
-rw-r--r--protocols/Tlen/tlen_czaty/src/FontList.cpp206
-rw-r--r--protocols/Tlen/tlen_czaty/src/FontList.h90
-rw-r--r--protocols/Tlen/tlen_czaty/src/HelperDialog.cpp589
-rw-r--r--protocols/Tlen/tlen_czaty/src/HelperDialog.h95
-rw-r--r--protocols/Tlen/tlen_czaty/src/ManagerWindow.cpp1067
-rw-r--r--protocols/Tlen/tlen_czaty/src/ManagerWindow.h93
-rw-r--r--protocols/Tlen/tlen_czaty/src/Options.cpp789
-rw-r--r--protocols/Tlen/tlen_czaty/src/Options.h75
-rw-r--r--protocols/Tlen/tlen_czaty/src/Utils.cpp138
-rw-r--r--protocols/Tlen/tlen_czaty/src/Utils.h38
-rw-r--r--protocols/Tlen/tlen_czaty/src/mucc.cpp166
-rw-r--r--protocols/Tlen/tlen_czaty/src/mucc.h106
-rw-r--r--protocols/Tlen/tlen_czaty/src/mucc_services.cpp140
-rw-r--r--protocols/Tlen/tlen_czaty/src/mucc_services.h35
-rw-r--r--protocols/Tlen/tlen_czaty/src/resource.h218
125 files changed, 31412 insertions, 0 deletions
diff --git a/protocols/Tlen/docs/InstallScript.xml b/protocols/Tlen/docs/InstallScript.xml
new file mode 100644
index 0000000000..7d8a8f28fe
--- /dev/null
+++ b/protocols/Tlen/docs/InstallScript.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<installscript>
+ <info>
+ <name>Tlen Protocol</name>
+ <author>Santithorn Bunchua</author>
+ <version>0.1.0.2</version>
+ <type>Plugin</type>
+ </info>
+
+ <packageinfo>
+ <title>Main Files</title>
+ <file>tlen.dll</file>
+ <file>tlen_czaty.dll</file>
+ </packageinfo>
+
+ <packageinfo>
+ <optional/>
+ <title>Documentation</title>
+ <file>readme_tlen.txt</file>
+ <document/>
+ </packageinfo>
+
+ <autorun>
+ <file>readme_tlen.txt</file>
+ <document/>
+ </autorun>
+</installscript>
diff --git a/protocols/Tlen/docs/changelog_tlen.txt b/protocols/Tlen/docs/changelog_tlen.txt
new file mode 100644
index 0000000000..b2c05c760a
--- /dev/null
+++ b/protocols/Tlen/docs/changelog_tlen.txt
@@ -0,0 +1,269 @@
+Version 2.0.5.0
+-------
+* Project cleanup
+ + change mucc.dll to tlen_czaty.dll
+ + compile tlen_czaty in Unicode and x64
+* fix warnings, project files changes
+Version 2.0.4.1
+-------
+- fix accounts... dialog
+Version 2.0.4.0
+-------
++ x64 version
+* set timeout to NETLIBOPENCONNECTION (patch by piotrw)
+* fix for display texts at comboboxes in unicode (patch by piotrw)
+* fixes in Find/Add Contacts search (by piotrw, dezeath and wsx22)
+* fix warnings, project files changes (add VS2010)
+Version 2.0.3.2
+-------
+* update PolarSSL library to polarssl-1.0.0
+* change compile options to not require microsoft visual studio runtime libs on user system, (100KB larger file but no problems with msvcr90.dll not found on user system)
+Version 2.0.2.0
+-------
+* "Leave status message after disconnection", "Send and receive client version information" and "Log alerts as messages" options enabled by default (AL|EN suggestion)
+Version 2.0.1.0
+-------
+merge changes from wsx22 mod
+* fix in typing notify message handling
+* fix in logging to server message
+Version 2.0.0.0
+-------
++ Image transfer
+* other bug fixes and improvements
+Version 1.8.0.2
+-------
+improved icons handling
+minor fixes on account unloading
+1.8.0.1
+-------
+* bugfix: removed ME_SYSTEM_MODULESLOADED hook
+1.8.0.0
+-------
++ support for account manager (requires MIM 0.8)
+* many bugfixes and small improvements
+1.1.0.0
+-------
+* avatar support improvements
+1.0.9.2
+-------
+* avatar management UI changes
+* user info page changes
+* some clean-up and bugfixes
+* fix for advertisement blocking
+* fix for file transfers
+1.0.9.1
+-------
+* avatar management improvements
+1.0.9.0
+-------
++ message encryption
+* improved search (up to 200 results displayed)
+* some avatar-related fixes
+* MIM 0.7 compatibility
+1.0.7.7
+-------
+* new icons by Angelika
+1.0.7.6
+-------
++ support for Tlen avatars
+1.0.7.5
+-------
+* bugfix: settings changes were not loaded properly
+1.0.7.4
+-------
+* p2p connections refactoring
+* UPnP support
+* managed services/hooks
+* support for IcoLib
+* new icons
+* support for Miranda Memory Manager
+1.0.7.3
+--------
+* bugfix: offline status message
+1.0.7.2
+--------
+! fixed compatibility issues with new versions of IEView (1.0.9.0 or higher)
++ support for Nudge plugin
+* improved avatar support
+* improved sending/receiving client version info
+1.0.7.1
+---------
+* bugfix: sending/receiving client version info
+1.0.7.0
+---------
++ full support for avatars (compatible with tAvatar 0.0.2.1 or higher)
++ sending and receiving full client version info
+* optimized DB usage
+* code cleanup
+1.0.6.9
+---------
++ experimental client recognition
++ voice chat notification sound
+* bugfix: offline message timestamp
+* code clean-up
+1.0.6.8
+---------
+* bugfix: compatibility with Unicode contact lists
+* bugfix: user login is always converted to lower case
+* bugfix: typing notifications
+* other bugfixes
+1.0.6.7
+---------
++ possibility to send files to offline users
++ public status visibility settings
+* bugfixes
+1.0.6.6
+---------
+* fixed IEView support (text scrolling issue)
+* code cleanup
+1.0.6.5
+---------
++ option to ignore advertisements
+* bugfixes
+1.0.6.4
+---------
++ alert, voice chat and group chat policies
++ received alerts are logged as messages
+* offline message timestamp improvements (thanks to Atay for the idea)
+* removed obsolete, Jabber-specific code
+* a lot of more or less important bugfixes
+1.0.6.3
+---------
++ group names encoding
++ log saving in IEView mode
+* simplified option page
+1.0.6.2
+---------
++ support for IEView group chats (IEView 1.0.3.0 or later)
++ improvements of group chats in RichEdit mode (context menu, better scrolling)
+1.0.6.1
+---------
+* bugfix: proper filename encoding
+* options page rearranged
+* code cleanup, other fixes and improvements
+1.0.6.0
+---------
++ group chat window flashing
++ message icons in tabbed mode
++ web messages grouped as a single contact
+* offline message timestamp handling fixed (again)
+1.0.5.10 RC2
+---------
++ tabbed mode available in group chat window
++ saving chat log to file
++ smiley selection button in group chat window
++ new shortcuts: ctrl+w (close), ctrl+a (select all)
++ saving chat fonts setting
++ new menu items: request and grant authorization
+* several bugfixes in MUCC plugin, better MUCC architecture
+1.0.5.9 RC
+---------
++ voice chat improvements (better sound quality and smarter delay reduction, bugfixes)
++ separate group for Global Owners in chat user list
+* bugfix: web messages receiving (fix by MoMaT)
+1.0.5.8
+---------
++ playback and recording device selection
++ sending and receiving alerts (use <alert> to send)
++ enabling/disabling Always Visible support
+* bugfixes
+1.0.5.7
+---------
++ chat room administration window (user administration and browser)
++ unban option
++ dynamic user groups
++ voice chat p2p connection negotiation
++ voice chat status display
++ incoming voice chat invitation dialog
++ removing contacts from roster on authorization denial
++ offline status message selection
+* a lot of fixes in group chats interface
+1.0.5.6
+---------
++ voice chats ! (experimental)
++ chat room administration: destroying room, changing users' roles, kick & ban
++ MUCC option: send on Enter
++ status messages of offline contacts (use mToolTip to read them)
+* bugfix: contact name encoding when adding new contact
+* bugfix: offline messages time ('more inteligent' Daylight Saving Time handling)
+* bugfix: closing all file transfers at shutdown
+* other minor fixes
+1.0.5.5
+---------
++ improved file transfer (p2p connection negotiation, error notification)
++ MUCC options page (fonts, colors, default filters)
++ chat room events logging (user has joined etc.)
++ registering and uregistering nick names
++ creating chat rooms
++ chat room topic displaying and setting
++ improved errors handling
+* look & feel improvements
+* bugfix: correct chat room name returned by search
+* bugfix: removing users from contact list groups
+* source code refactoring
+1.0.5.4
+---------
++ group chats error handling
++ message log formatting options
++ chat room searching
++ list of contacts in 'invite to group chat' dialog
++ Multi-User Conference item in contact menu
++ some look & feel improvements (better resizing, new icons)
++ internal history of messages
+* a lot of bugfixes and code improvements
+* code clean-up
+1.0.5.3
+---------
++ full text formatting (font name, font size)
++ private messaging sessions
++ displaying user details (administrator/moderator/registered nickname)
++ displaying chat room details icons (moderated/members only/anonymous nicknames not allowed)
++ browsing own chat rooms/registered nicknames
+* code clean-up
+* bugfixes
+1.0.5.2
+---------
++ text formatting (bold, italic, underline, text color for now)
++ chat rooms browsing page by page
+* bugfixes and code clean-up
+1.0.5.1
+---------
++ initial multi-user conferences and chats support
++ MUCC plugin responsible for chats GUI (manager window (groups/rooms), messanging window, helper dialogs)
+
+2004-09-23 Version 1.0.4.0
+ Jabber and Tlen now have separate source trees (Tlen plugin is compliant with GCC now)
+ File transfer with forwarding and SOCKS4/5 proxy support
+ vCard viewing and editing
+ Web messages receiving
+ Incoming email notification through the popup plugin and sounds
+ User typing notification (patch by Adam Libura)
+ Searching users by login
+ New user details page
+ Invisible status message
+ Option to leave offline status message
+ Option to show offline users with status message as invisible
+ Link to create new account
+ Fixed bug: adjust offline message time
+ A lot of other fixes and improvements
+
+2003-08-19 Version 0.1.0.2
+ Fixed bug: crash when receiving some invisible presence
+ Fixed bug: incorrect newline encoding/decoding (tlen uses \r\n while jabber uses \n)
+ Fixed bug: User detail text is not decoded
+ Use new invisible presence (now conform to Jabber invisible presence)
+ Advanced search
+ Based on Jabber plugin 0.1.1.2
+
+2003-05-12 Version 0.1.0.1
+ Fixed bug: slightly incorrect online presence
+ Based on Jabber plugin 0.1.1.0
+
+2003-01-19 Version 0.1.0.0
+ Based on Jabber plugin 0.1.0.7
+ Tlen basic user info
+ Tlen invisible status
+ Tlen visible/invisible list
+ Option to show invisible users as invisible
+ Find/add users using tlen user database
+ Rebase DLL to 0x32600000
diff --git a/protocols/Tlen/docs/gpl.txt b/protocols/Tlen/docs/gpl.txt
new file mode 100644
index 0000000000..45645b4b53
--- /dev/null
+++ b/protocols/Tlen/docs/gpl.txt
@@ -0,0 +1,340 @@
+ 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.
diff --git a/protocols/Tlen/docs/gpl_comment.txt b/protocols/Tlen/docs/gpl_comment.txt
new file mode 100644
index 0000000000..3e51542c78
--- /dev/null
+++ b/protocols/Tlen/docs/gpl_comment.txt
@@ -0,0 +1,20 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2012 Santithorn Bunchua, Piotr Piastucki
+
+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.
+
+*/
diff --git a/protocols/Tlen/docs/readme_tlen.txt b/protocols/Tlen/docs/readme_tlen.txt
new file mode 100644
index 0000000000..6eef0b8a95
--- /dev/null
+++ b/protocols/Tlen/docs/readme_tlen.txt
@@ -0,0 +1,61 @@
+Tlen Protocol Plugin for Miranda NG
+===================================
+
+Introduction:
+ Tlen is a protocol used by a propritary instant messaging network
+ at tlen.pl. It is based on Jabber, and, therefore, this plugin
+ is very much based on Jabber protocol plugin for Miranda. All
+ necessary helps to create this Tlen plugin are from Adam Strzelecki.
+
+Installation:
+ Copy tlen.dll and (optional) tlen_czaty.dll to Miranda's plugins directory.
+
+ If you want to have multiple Tlen accounts online at the same time,
+ you need to have multiple copies of tlen.dll, each with different name,
+ all in Miranda's plugins directory. Note that all configurations for a
+ Tlen account (including your contact list) are associated with the
+ DLL's name. In addition, it is highly recommended that you do NOT choose
+ the name that is in conflict with other plugins or any database categories
+ used by Miranda core (use DatabaseViewer or DatabaseEditor to see what
+ database categories are already in use).
+
+More information:
+ Web: http://mtlen.berlios.de
+ E-mail: the_leech@users.berlios.de
+
+Copyright (c) 2002-2012 Santithorn Bunchua (keh@au.edu), Piotr Piastucki
+
+Acknowledgement:
+ We would like to thank the following people for their helps and/or comments
+ (alphabetically listed):
+ Dmitry Balabanov
+ Nikola Dachev
+ Sam Kothari
+ Adam Libura
+ Jörgen Persson
+ Robert Rainwater
+ Adam Strzelecki
+ Michal Wojciechowski
+ Szymon Tokarz (wsx22)
+
+================================================================
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C)
+ 2002-2012 Santithorn Bunchua, Piotr Piastucki (Miranga IM)
+ 2012 Szymon Tokarz (Miranda IM / NG)
+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.
+
+================================================================
diff --git a/protocols/Tlen/docs/tlen-translation.txt b/protocols/Tlen/docs/tlen-translation.txt
new file mode 100644
index 0000000000..6406f204c7
--- /dev/null
+++ b/protocols/Tlen/docs/tlen-translation.txt
@@ -0,0 +1,153 @@
+;***********************************
+;******* Tlen language by raq ******
+
+[Tlen czaty]
+;[Authentication failed for]
+;[Tlen Authentication]
+[Network]
+[Advanced]
+[PopUps]
+[Accept all alerts]
+[Ignore alerts from unauthorized contacts]
+[Ignore all alerts]
+[Always ask me]
+[Accept invitations from authorized contacts]
+[Accept all invitations]
+[Ignore invitations from unauthorized contacts]
+[Ignore all invitation]
+[Always ask me]
+[<Last message>]
+[<Ask me>]
+[Online]
+[Away]
+[NA]
+[DND]
+[Free for chat]
+[Invisible]
+[These changes will take effect the next time you connect to the Tlen network.]
+[Tlen Protocol Option]
+[Forwarding]
+;[SOCKS4]
+;[SOCKS5]
+;[Tlen login]
+[Enter password for]
+[Error: Not enough memory]
+[Error: Cannot connect to the server]
+[The connection requires an OpenSSL library, which is not installed.]
+;[Jabber Connection Error]
+[%s Web Messages]
+[Web message]
+[From]
+;[E-mail]
+[An alert has been received.]
+[Private conference]
+[New mail]
+[Subject]
+;[both]
+[to]
+[from]
+[none]
+;[not on roster]
+[Error]
+[Unknown error message]
+[connection]
+[Incoming mail]
+;[Alert]
+[Multi-User Conference]
+[Tlen Chats...]
+[Voice Chat]
+[Voice chat]
+[Request authorization]
+[Grant authorization]
+[You have been kicked. Reason: %s ]
+[You cannot join this chat room, because you are banned.]
+[Chat room not found.]
+[This is a private chat room and you are not one of the members.]
+[You cannot send any message unless you join this chat room.]
+[Chat room with already created.]
+[Nickname '%s' is already registered.]
+[Nickname already in use, please try another one. Hint: '%s' is free.]
+[You cannot register more than %s nicknames.]
+[You cannot create more than %s chat rooms.]
+[You cannot join more than %s chat rooms.]
+[Anonymous nicknames are not allowed in this chat room.]
+[Unknown error code : %d]
+[Default]
+
+;tlen.rc
+
+[Username:]
+[Create a new account]
+[Password:]
+[Save password]
+[Use SSL]
+[Options]
+[Automatically reconnect after unintentional disconnection]
+[Leave status message after disconnection]
+[Ignore advertisements]
+[Automatically delete contacts not in my roster]
+[Show offline users with status messages as invisible in contact list]
+[Enable avatars]
+[Send and receive version information]
+[Use Nudge plugin]
+[Log alerts as messages]
+[Alert policy]
+[Group chat policy]
+[Voice Chats]
+[Voice chat policy]
+[Recording device:]
+[Playback device:]
+[Expert Options]
+[Login server:]
+[Connection Host:]
+;[Port:]
+[Keep connection alive]
+[Enable Always Visible and Never Visible]
+[File Transfer and Voice Chats]
+[Use proxy for incoming connections]
+[Proxy type:]
+[Proxy server:]
+[Proxy requires authorization]
+[Delay]
+[&From PopUp plugin]
+[&Custom]
+[P&ermanent]
+[Colours]
+[Background]
+[Text]
+[General Options]
+[Preview]
+[Enable incoming mail notification]
+;[OK]
+[Cancel]
+[Nick name:]
+[First name:]
+[Last name:]
+;[E-mail:]
+[Gender:]
+[Year of birth:]
+[City:]
+[School:]
+[Occupation:]
+[Looking for:]
+[Voice chats]
+[Save changes]
+;[Subscription:]
+[Age:]
+[Personal Information]
+;[Status:]
+[Plan:]
+[&Accept]
+[From:]
+[Software:]
+[Version:]
+[System:]
+[The following invitation to join a voice chat is received.]
+[Current Avatar]
+[New Avatar]
+[Public]
+[Browse...]
+[Set]
+[Delete]
+[Note: Image size max. 64x64]
+[Enable encryption]
diff --git a/protocols/Tlen/res/auth_grant.ico b/protocols/Tlen/res/auth_grant.ico
new file mode 100644
index 0000000000..8d1ba94308
--- /dev/null
+++ b/protocols/Tlen/res/auth_grant.ico
Binary files differ
diff --git a/protocols/Tlen/res/auth_request.ico b/protocols/Tlen/res/auth_request.ico
new file mode 100644
index 0000000000..116ed47baf
--- /dev/null
+++ b/protocols/Tlen/res/auth_request.ico
Binary files differ
diff --git a/protocols/Tlen/res/groupchats.ico b/protocols/Tlen/res/groupchats.ico
new file mode 100644
index 0000000000..ecd2070d20
--- /dev/null
+++ b/protocols/Tlen/res/groupchats.ico
Binary files differ
diff --git a/protocols/Tlen/res/image.ico b/protocols/Tlen/res/image.ico
new file mode 100644
index 0000000000..832b9a8b69
--- /dev/null
+++ b/protocols/Tlen/res/image.ico
Binary files differ
diff --git a/protocols/Tlen/res/mail.ico b/protocols/Tlen/res/mail.ico
new file mode 100644
index 0000000000..c5ded81702
--- /dev/null
+++ b/protocols/Tlen/res/mail.ico
Binary files differ
diff --git a/protocols/Tlen/res/microphone.ico b/protocols/Tlen/res/microphone.ico
new file mode 100644
index 0000000000..1edeb90d1f
--- /dev/null
+++ b/protocols/Tlen/res/microphone.ico
Binary files differ
diff --git a/protocols/Tlen/res/speaker.ico b/protocols/Tlen/res/speaker.ico
new file mode 100644
index 0000000000..77545c0598
--- /dev/null
+++ b/protocols/Tlen/res/speaker.ico
Binary files differ
diff --git a/protocols/Tlen/res/tlen.ico b/protocols/Tlen/res/tlen.ico
new file mode 100644
index 0000000000..a166dd4c5b
--- /dev/null
+++ b/protocols/Tlen/res/tlen.ico
Binary files differ
diff --git a/protocols/Tlen/res/tlen.rc b/protocols/Tlen/res/tlen.rc
new file mode 100644
index 0000000000..98ba762f77
--- /dev/null
+++ b/protocols/Tlen/res/tlen.rc
@@ -0,0 +1,439 @@
+#include "..\src\resource.h"
+#include "..\src\commons.h"
+#ifdef __MINGW32__
+ #define WINVER 0x500
+ #define _WIN32_IE 0x500
+#endif
+#include <windows.h>
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif
+#ifdef APSTUDIO_INVOKED
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "..\\src\\resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ACCMGRUI DIALOGEX 0, 0, 186, 134
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Username:",IDC_STATIC,0,14,38,12,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT_USERNAME,65,14,115,12,ES_AUTOHSCROLL
+ LTEXT "Password:",IDC_STATIC,0,30,38,12,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT_PASSWORD,65,30,115,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Save password",IDC_SAVEPASSWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,65,46,115,10
+ CONTROL "Create new account",IDC_REGISTERACCOUNT,"Hyperlink",
+ 0x0,0,62,100,8
+END
+
+
+IDD_OPTIONS_BASIC DIALOGEX 0, 0, 304, 200
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Tlen",IDC_TLEN,0,0,304,42
+ LTEXT "Username:",IDC_STATIC,8,12,52,8
+ EDITTEXT IDC_EDIT_USERNAME,70,10,86,12,ES_AUTOHSCROLL
+ CONTROL "Create new account",IDC_REGISTERACCOUNT,"Hyperlink",
+ 0x0,170,12,100,8
+ LTEXT "Password:",IDC_STATIC,8,26,52,8
+ EDITTEXT IDC_EDIT_PASSWORD,70,24,86,12,ES_PASSWORD |
+ ES_AUTOHSCROLL
+ CONTROL "Save password",IDC_SAVEPASSWORD,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,170,26,100,10
+ GROUPBOX "Options",IDC_SIMPLE,0,44,304,156
+ CONTROL "Automatically reconnect after unintentional disconnection",
+ IDC_RECONNECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8, 56,239,10
+ CONTROL "Leave status message after disconnection",
+ IDC_OFFLINE_MESSAGE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,8,68,168,10
+ COMBOBOX IDC_OFFLINE_MESSAGE_OPTION,190,67,75,140,
+ CBS_DROPDOWNLIST | WS_TABSTOP
+ CONTROL "Ignore advertisements",
+ IDC_IGNORE_ADVERTISEMENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8, 80,250,10
+ CONTROL "Automatically delete contacts not in my roster",
+ IDC_ROSTER_SYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8, 92,250,10
+ CONTROL "Show offline users with status messages as invisible in contact list",
+ IDC_SHOW_OFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 8,104,250,10
+ CONTROL "Enable avatars",
+ IDC_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 8,116,250,10
+ CONTROL "Send and receive client version information",
+ IDC_VERSIONINFO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 8,128,250,10
+ LTEXT "Alert policy",IDC_STATIC,8,140,70,8
+ COMBOBOX IDC_ALERT_POLICY,95,139,190,100,
+ CBS_DROPDOWNLIST | WS_TABSTOP
+ CONTROL "Use Nudge plugin",
+ IDC_NUDGE_SUPPORT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 24,153,120,10
+ CONTROL "Log alerts as messages",
+ IDC_LOG_ALERTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 150,153,130,10
+ LTEXT "Group chat policy",IDC_STATIC,8,168,70,8
+ COMBOBOX IDC_MUC_POLICY,95,166,190,100,
+ CBS_DROPDOWNLIST | WS_TABSTOP
+ LTEXT "Image transfer policy",IDC_STATIC,8,183,70,8
+ COMBOBOX IDC_IMAGE_POLICY,95,181,190,100,
+ CBS_DROPDOWNLIST | WS_TABSTOP
+END
+
+
+IDD_OPTIONS_VOICE DIALOGEX 0, 0, 304, 200
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Voice Chats",IDC_STATIC,0,0,304,57
+ LTEXT "Voice chat policy",IDC_STATIC,8,12,70,8
+ COMBOBOX IDC_VOICE_POLICY,95,10,190,100,
+ CBS_DROPDOWNLIST | WS_TABSTOP
+ LTEXT "Recording device:",IDC_STATIC,8,26,105,8
+ COMBOBOX IDC_VOICE_DEVICE_IN,120,24,110,100,CBS_DROPDOWNLIST |
+ WS_TABSTOP
+ LTEXT "Playback device:",IDC_STATIC,8,40,105,8
+ COMBOBOX IDC_VOICE_DEVICE_OUT,120,38,110,100,CBS_DROPDOWNLIST |
+ WS_TABSTOP
+END
+
+IDD_OPTIONS_ADVANCED DIALOGEX 0, 0, 304, 200
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Expert Options",IDC_STATIC,0,0,304,74
+ LTEXT "Login server:",IDC_STATIC,8,18,75,8
+ EDITTEXT IDC_EDIT_LOGIN_SERVER,90,16,90,12,ES_AUTOHSCROLL
+ LTEXT "Connection Host:",IDC_STATIC,8,32,75,8
+ EDITTEXT IDC_HOST,90,30,90,12,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "Port:",IDC_STATIC,194,32,35,8
+ EDITTEXT IDC_HOSTPORT,230,30,26,12,ES_AUTOHSCROLL | ES_NUMBER |
+ WS_DISABLED
+ CONTROL "Keep connection alive",IDC_KEEPALIVE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,8,47,250,10
+ CONTROL "Enable encryption",IDC_USE_SSL,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,8,60,250,10
+
+ CONTROL "Enable Always Visible and Never Visible",
+ IDC_VISIBILITY_SUPPORT,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE |
+ WS_TABSTOP,8,60,250,10
+
+ GROUPBOX "P2P Connections",IDC_STATIC,0,100,304,98
+ CONTROL "Use proxy for incoming connections",IDC_FILE_USE_PROXY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,114,271,10
+ LTEXT "Proxy type:",IDC_FILE_PROXY_TYPE_LABEL,10,130,48,8,
+ WS_DISABLED
+ COMBOBOX IDC_FILE_PROXY_TYPE,68,128,80,48,CBS_DROPDOWNLIST |
+ WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Proxy server:",IDC_FILE_PROXY_HOST_LABEL,10,145,48,8,
+ WS_DISABLED
+ EDITTEXT IDC_FILE_PROXY_HOST,68,143,80,12,ES_AUTOHSCROLL |
+ WS_DISABLED | WS_GROUP
+ LTEXT "Port:",IDC_FILE_PROXY_PORT_LABEL,174,145,25,8,
+ WS_DISABLED
+ EDITTEXT IDC_FILE_PROXY_PORT,204,143,30,12,ES_AUTOHSCROLL |
+ ES_NUMBER | WS_DISABLED
+ CONTROL "Proxy requires authorization",IDC_FILE_PROXY_USE_AUTH,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,8,
+ 160,271,10
+ LTEXT "Username:",IDC_FILE_PROXY_USER_LABEL,10,176,47,8,
+ WS_DISABLED
+ EDITTEXT IDC_FILE_PROXY_USER,68,175,80,12,ES_AUTOHSCROLL |
+ WS_DISABLED
+ LTEXT "Password:",IDC_FILE_PROXY_PASSWORD_LABEL,153,176,45,8,
+ WS_DISABLED
+ EDITTEXT IDC_FILE_PROXY_PASSWORD,204,175,81,12,ES_PASSWORD |
+ ES_AUTOHSCROLL | WS_DISABLED
+
+
+END
+
+IDD_OPTIONS_POPUPS DIALOG DISCARDABLE 0, 0, 304, 143
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+
+ GROUPBOX "Mail Notification",IDC_STATIC,0,0,304,110
+ CONTROL "Enable incoming mail notification",IDC_ENABLEPOPUP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,12,267,10
+ GROUPBOX "Colours",IDC_STATIC,8,26,140,55
+ LTEXT "Background",IDC_STATIC,47,43,95,8
+ LTEXT "Text",IDC_STATIC,47,62,96,8
+ CONTROL "",IDC_COLORBKG,"ColourPicker",WS_TABSTOP,17,41,24,12
+ CONTROL "",IDC_COLORTXT,"ColourPicker",WS_TABSTOP,17,59,24,12
+ GROUPBOX "Delay",IDC_STATIC,157,26,140,55
+ CONTROL "&From PopUp plugin",IDC_DELAY_POPUP,"Button",
+ BS_AUTORADIOBUTTON,164,40,125,10
+ CONTROL "&Custom",IDC_DELAY_CUSTOM,"Button",BS_AUTORADIOBUTTON,
+ 164,53,98,10
+ EDITTEXT IDC_DELAY,267,51,21,14,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "P&ermanent",IDC_DELAY_PERMANENT,"Button",
+ BS_AUTORADIOBUTTON,164,67,123,10
+ PUSHBUTTON "Preview",IDC_PREVIEW,119,90,70,14
+END
+
+IDD_PASSWORD DIALOG DISCARDABLE 0, 0, 151, 63
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION
+CAPTION "Jabber Password"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ EDITTEXT IDC_JID,7,7,137,12,ES_READONLY | NOT WS_BORDER | NOT
+ WS_TABSTOP
+ EDITTEXT IDC_PASSWORD,7,22,137,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,23,42,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,77,42,50,14
+END
+
+IDD_USER_VCARD DIALOGEX 0, 0, 222, 140
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Nick name:",IDC_STATIC,5,8,51,8
+ EDITTEXT IDC_NICKNAME,58,6,102,12,ES_AUTOHSCROLL
+ LTEXT "First name:",IDC_STATIC,5,21,51,8
+ EDITTEXT IDC_FIRSTNAME,58,19,102,12,ES_AUTOHSCROLL
+ LTEXT "Last name:",IDC_STATIC,5,34,51,8
+ EDITTEXT IDC_LASTNAME,58,32,102,12,ES_AUTOHSCROLL
+ LTEXT "E-mail:",IDC_STATIC,5,47,51,8
+ EDITTEXT IDC_EMAIL,58,45,102,12,ES_AUTOHSCROLL
+ LTEXT "Gender:",IDC_STATIC,5,61,51,8
+ COMBOBOX IDC_GENDER,58,59,55,52,CBS_DROPDOWN | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Year of birth:",IDC_STATIC,120,61,53,8
+ EDITTEXT IDC_AGE,176,59,27,12,ES_AUTOHSCROLL
+ LTEXT "City:",IDC_STATIC,6,75,51,8
+ EDITTEXT IDC_CITY,58,73,102,12,ES_AUTOHSCROLL
+ LTEXT "School:",IDC_STATIC,5,88,51,8
+ EDITTEXT IDC_SCHOOL,58,86,102,12,ES_AUTOHSCROLL
+ LTEXT "Occupation:",IDC_STATIC,5,102,51,8
+ COMBOBOX IDC_OCCUPATION,57,100,102,96,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Looking for:",IDC_STATIC,5,116,51,8
+ COMBOBOX IDC_LOOKFOR,57,114,102,96,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Voice chats",IDC_VOICECONVERSATIONS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,5,130,107,10
+ CONTROL "Publicly visible status",IDC_PUBLICSTATUS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,112,130,107,10
+ PUSHBUTTON "Save changes",IDC_SAVE,164,111,53,16
+END
+
+IDD_USER_CHANGEAVATAR DIALOGEX 0, 0, 180, 80
+STYLE DS_SETFONT | DS_3DLOOK | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+CAPTION "Avatar"
+BEGIN
+ GROUPBOX "Avatar Options",IDC_STATIC,5,2,170,55
+ CONTROL "Public avatar",IDC_PUBLICAVATAR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,15,150,13
+ PUSHBUTTON "OK",IDOK,115,62,60,13
+END
+
+
+IDD_USER_INFO DIALOG DISCARDABLE 0, 0, 222, 146
+STYLE DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Tlen login:",IDC_STATIC,5,2,48,8
+ EDITTEXT IDC_INFO_JID,53,2,73,12,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER
+ LTEXT "Subscription:",IDC_STATIC,5,14,48,8,NOT WS_GROUP
+ EDITTEXT IDC_SUBSCRIPTION,53,14,131,12,ES_READONLY | NOT WS_BORDER |
+ NOT WS_TABSTOP
+ LTEXT "School:",IDC_STATIC,5,44,48,8
+ EDITTEXT IDC_SCHOOL,53,44,131,12,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER
+ LTEXT "Occupation:",IDC_STATIC,5,56,48,8
+ EDITTEXT IDC_OCCUPATION_TEXT,53,56,135,12,ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_BORDER
+ LTEXT "Looking for:",IDC_STATIC,5,68,48,8
+ EDITTEXT IDC_LOOKFOR_TEXT,53,68,136,12,ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_BORDER
+ LTEXT "Software:",IDC_STATIC,5,100,48,8
+ EDITTEXT IDC_SOFTWARE,54,100,140,12,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Version:",IDC_STATIC,5,112,48,8
+ EDITTEXT IDC_VERSION,54,112,140,12,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "System:",IDC_STATIC,5,124,48,8
+ EDITTEXT IDC_SYSTEM,54,124,140,12,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+END
+
+IDD_ADVSEARCH DIALOGEX 0, 0, 334, 178
+STYLE DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_BORDER
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Personal Information",IDC_PERSONALGROUP,7,7,156,164
+ LTEXT "First name:",IDC_STATIC,15,22,50,8
+ EDITTEXT IDC_FIRSTNAME,65,20,91,12,ES_AUTOHSCROLL
+ LTEXT "Last name:",IDC_STATIC,15,37,50,8
+ EDITTEXT IDC_LASTNAME,65,35,91,12,ES_AUTOHSCROLL
+ LTEXT "Nickname:",IDC_STATIC,15,52,50,8
+ EDITTEXT IDC_NICK,65,50,91,12,ES_AUTOHSCROLL
+ LTEXT "E-mail:",IDC_STATIC,15,67,50,8
+ EDITTEXT IDC_EMAIL,65,65,91,12,ES_AUTOHSCROLL
+ LTEXT "Gender:",IDC_STATIC,15,85,50,8
+ COMBOBOX IDC_GENDER,65,83,91,51,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Age:",IDC_STATIC,15,100,50,8
+ EDITTEXT IDC_AGEFROM,65,98,27,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "to",IDC_STATIC,98,100,21,8
+ EDITTEXT IDC_AGETO,123,98,27,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "City:",IDC_STATIC,15,118,50,8
+ EDITTEXT IDC_CITY,65,116,91,12,ES_AUTOHSCROLL
+ LTEXT "Occupation:",IDC_STATIC,15,135,50,8
+ COMBOBOX IDC_OCCUPATION,65,133,91,93,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "School:",IDC_STATIC,15,150,50,8
+ EDITTEXT IDC_SCHOOL,65,148,91,12,ES_AUTOHSCROLL
+ GROUPBOX "Extra Search Criterias",IDC_EXTRAGROUP,171,7,156,67
+ LTEXT "Status:",IDC_STATIC,177,22,50,8
+ COMBOBOX IDC_STATUS,227,20,91,113,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Looking for:",IDC_STATIC,177,37,50,8
+ COMBOBOX IDC_LOOKFOR,227,35,91,172,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Plan:",IDC_STATIC,177,52,50,8,WS_DISABLED
+ COMBOBOX IDC_PLAN,227,50,91,113,CBS_DROPDOWNLIST | WS_DISABLED |
+ WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_VOICE DIALOG DISCARDABLE 0, 0, 151, 122
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "Tlen Voice Chat"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "",IDC_MICROPHONE,"MButtonClass",0x0,12,7,16,16,
+ 0x18000000L
+ CONTROL "",IDC_VUMETERIN,"Static",SS_OWNERDRAW,47,10,120,8
+ CONTROL "",IDC_SPEAKER,"MButtonClass",0x0,12,29,16,16,
+ 0x18000000L
+ CONTROL "",IDC_VUMETEROUT,"Static",SS_OWNERDRAW,47,31,120,8
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,53,140,4
+ LTEXT "Quality",IDC_STATIC,10,64,45,8
+ COMBOBOX IDC_VCQUALITY,55,62,88,100,CBS_DROPDOWNLIST | WS_VSCROLL
+ LTEXT "In",IDC_STATIC,10,80,25,8
+ LTEXT "",IDC_BYTESIN,35,80,30,8
+ LTEXT "Out",IDC_STATIC,90,80,25,8
+ LTEXT "",IDC_BYTESOUT,115,80,30,8
+ EDITTEXT IDC_STATUS,10,91,131,8,ES_CENTER | ES_AUTOHSCROLL |
+ WS_DISABLED | NOT WS_BORDER
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,100,140,4
+ PUSHBUTTON "Finish",IDCANCEL,50,106,50,14
+END
+
+IDD_ACCEPT_VOICE DIALOG DISCARDABLE 0, 0, 210, 70
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Tlen Voice Chat Invitation"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "&Accept",IDC_ACCEPT,98,50,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,155,50,50,14
+ LTEXT "From:",IDC_STATIC,25,24,60,8
+ LTEXT "The following invitation to join a voice chat is received.",
+ IDC_STATIC,3,4,204,8
+ EDITTEXT IDC_FROM,85,20,100,12,ES_AUTOHSCROLL | ES_READONLY
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,3,40,203,4
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION TLEN_FILEVERSION_STRING
+ PRODUCTVERSION TLEN_FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041504e3"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "http://miranda-ng.org/\0"
+ VALUE "FileDescription", "Tlen Protocol Plugin for Miranda NG\0"
+ VALUE "FileVersion", TLEN_VERSION_STRING
+ VALUE "InternalName", "tlen\0"
+ VALUE "LegalCopyright", "Copyright (c) 2002-2011 Santithorn Bunchua, Piotr Piastucki\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "tlen.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Tlen Protocol Plugin\0"
+ VALUE "ProductVersion", TLEN_VERSION_STRING
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x415, 1251
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_TLEN ICON DISCARDABLE "res\\tlen.ico"
+IDI_MAIL ICON DISCARDABLE "res\\mail.ico"
+IDI_MUC ICON DISCARDABLE "res\\groupchats.ico"
+IDI_CHATS ICON DISCARDABLE "res\\tlenchats.ico"
+IDI_GRANT ICON DISCARDABLE "res\\auth_grant.ico"
+IDI_REQUEST ICON DISCARDABLE "res\\auth_request.ico"
+IDI_VOICE ICON DISCARDABLE "res\\voicechat.ico"
+IDI_MICROPHONE ICON DISCARDABLE "res\\microphone.ico"
+IDI_SPEAKER ICON DISCARDABLE "res\\speaker.ico"
+IDI_IMAGE ICON DISCARDABLE "res\\image.ico"
+#endif // English (U.S.) resources
+
+
+
diff --git a/protocols/Tlen/res/tlenchats.ico b/protocols/Tlen/res/tlenchats.ico
new file mode 100644
index 0000000000..52ab77ff63
--- /dev/null
+++ b/protocols/Tlen/res/tlenchats.ico
Binary files differ
diff --git a/protocols/Tlen/res/voicechat.ico b/protocols/Tlen/res/voicechat.ico
new file mode 100644
index 0000000000..f989d5b212
--- /dev/null
+++ b/protocols/Tlen/res/voicechat.ico
Binary files differ
diff --git a/protocols/Tlen/src/codec/gsm.h b/protocols/Tlen/src/codec/gsm.h
new file mode 100644
index 0000000000..f522739d10
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm.h
@@ -0,0 +1,65 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 <windows.h>
+
+#define P_MAX 8 /* order p of LPC analysis, typically 8..14 */
+
+typedef struct {
+ int LARpp[2][8]; /* LAR coefficients for previous and current frame */
+ int j; /* current frame index in LARpp[j][] */
+ int qLARs[8]; /* quantized LARs for current frame */
+ int u[8]; /* used by short term analysis filter */
+ int v[9]; /* used by short term synthesis filter */
+ int subframe; /* subframe index (0..3)*/
+ short dp0[ 280 ]; /* previous short-term filter output/prediction, used by long term analysis*/
+ int e[160]; /* errors (residuals) */
+ int nrp; /* long term synthesis */
+ int Nc[4], bc[4]; /* long-term lag and gain for current frame */
+ int Mc[4]; /* RPE grid index (0..3) */
+ int xMaxc[4]; /* RPE maximum error quantized and encoded (mantissa + exp) */
+ int xMc[52]; /* quantized residuals (errors) 4 * 13 */
+
+ int z1; /* preprocessing.c, Offset_com. */
+ int z2; /* Offset_com. */
+ int mp; /* Preemphasis */
+ int msr; /* decoder.c, Postprocessing */
+
+ unsigned char gsmFrame[33];
+}gsm_state;
+
+extern gsm_state * gsm_create() ;
+extern void gsm_release(gsm_state *ptr);
+extern void gsm_encode(gsm_state *state, short *in);
+extern void gsm_decode(gsm_state *state, short *out);
+
+extern void gsm_preprocessing( gsm_state *state, short *in, short *out);
+extern void shortTermAnalysis(gsm_state *state, short *in);
+extern void longTermAnalysis(gsm_state *state, short *in);
+extern void encodeRPE(gsm_state *state);
+extern void decodeRPE(gsm_state *state);
+extern void longTermSynthesis(gsm_state *state);
+extern void shortTermSynthesis(gsm_state *state, short *in, short *out);
+extern void gsm_postprocessing( gsm_state *state, short *in, short *out);
diff --git a/protocols/Tlen/src/codec/gsm_codec.c b/protocols/Tlen/src/codec/gsm_codec.c
new file mode 100644
index 0000000000..afa1ef32de
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_codec.c
@@ -0,0 +1,283 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 "gsm.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define GSM_MAGIC 0xD
+
+gsm_state * gsm_create()
+{
+ gsm_state * state = (gsm_state *)malloc(sizeof(gsm_state));
+ memset(state, 0, sizeof(gsm_state));
+ state->nrp = 40;
+ return state;
+}
+
+void gsm_release(gsm_state *ptr)
+{
+ free(ptr);
+}
+
+void gsm_encode(gsm_state *state, short *in)
+{ int i, j;
+ unsigned char *c = state->gsmFrame;
+ short temp_in[160];
+
+ gsm_preprocessing(state, in, temp_in);
+ shortTermAnalysis(state, temp_in);
+ for (i = 0; i < 4; i++) {
+ state->subframe = i;
+ longTermAnalysis(state, temp_in + 40 * i);
+ encodeRPE(state);
+ for (j = 0; j < 40; j++) {
+ int ii = (int) state->dp0[120 + i * 40 + j] + state->e[i * 40 + j];
+ if (ii<-32768) ii = -32768;
+ else if (ii>32767) ii=32767;
+ state->dp0[120 + i * 40 + j] = ii;
+ }
+ }
+ memcpy(state->dp0, state->dp0 + 160, 120 * sizeof(short));
+ state->j ^= 1;
+ *c++ = ((GSM_MAGIC & 0xF) << 4)
+ | ((state->qLARs[0] >> 2) & 0xF);
+ *c++ = ((state->qLARs[0] & 0x3) << 6)
+ | (state->qLARs[1] & 0x3F);
+ *c++ = ((state->qLARs[2] & 0x1F) << 3)
+ | ((state->qLARs[3] >> 2) & 0x7);
+ *c++ = ((state->qLARs[3] & 0x3) << 6)
+ | ((state->qLARs[4] & 0xF) << 2)
+ | ((state->qLARs[5] >> 2) & 0x3);
+ *c++ = ((state->qLARs[5] & 0x3) << 6)
+ | ((state->qLARs[6] & 0x7) << 3)
+ | (state->qLARs[7] & 0x7);
+ *c++ = ((state->Nc[0] & 0x7F) << 1)
+ | ((state->bc[0] >> 1) & 0x1);
+ *c++ = ((state->bc[0] & 0x1) << 7)
+ | ((state->Mc[0] & 0x3) << 5)
+ | ((state->xMaxc[0] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[0] & 0x1) << 7)
+ | ((state->xMc[0] & 0x7) << 4)
+ | ((state->xMc[1] & 0x7) << 1)
+ | ((state->xMc[2] >> 2) & 0x1);
+ *c++ = ((state->xMc[2] & 0x3) << 6)
+ | ((state->xMc[3] & 0x7) << 3)
+ | (state->xMc[4] & 0x7);
+ *c++ = ((state->xMc[5] & 0x7) << 5)
+ | ((state->xMc[6] & 0x7) << 2)
+ | ((state->xMc[7] >> 1) & 0x3);
+ *c++ = ((state->xMc[7] & 0x1) << 7)
+ | ((state->xMc[8] & 0x7) << 4)
+ | ((state->xMc[9] & 0x7) << 1)
+ | ((state->xMc[10] >> 2) & 0x1);
+ *c++ = ((state->xMc[10] & 0x3) << 6)
+ | ((state->xMc[11] & 0x7) << 3)
+ | (state->xMc[12] & 0x7);
+ *c++ = ((state->Nc[1] & 0x7F) << 1)
+ | ((state->bc[1] >> 1) & 0x1);
+ *c++ = ((state->bc[1] & 0x1) << 7)
+ | ((state->Mc[1] & 0x3) << 5)
+ | ((state->xMaxc[1] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[1] & 0x1) << 7)
+ | ((state->xMc[13] & 0x7) << 4)
+ | ((state->xMc[14] & 0x7) << 1)
+ | ((state->xMc[15] >> 2) & 0x1);
+ *c++ = ((state->xMc[15] & 0x3) << 6)
+ | ((state->xMc[16] & 0x7) << 3)
+ | (state->xMc[17] & 0x7);
+ *c++ = ((state->xMc[18] & 0x7) << 5)
+ | ((state->xMc[19] & 0x7) << 2)
+ | ((state->xMc[20] >> 1) & 0x3);
+ *c++ = ((state->xMc[20] & 0x1) << 7)
+ | ((state->xMc[21] & 0x7) << 4)
+ | ((state->xMc[22] & 0x7) << 1)
+ | ((state->xMc[23] >> 2) & 0x1);
+ *c++ = ((state->xMc[23] & 0x3) << 6)
+ | ((state->xMc[24] & 0x7) << 3)
+ | (state->xMc[25] & 0x7);
+ *c++ = ((state->Nc[2] & 0x7F) << 1)
+ | ((state->bc[2] >> 1) & 0x1);
+ *c++ = ((state->bc[2] & 0x1) << 7)
+ | ((state->Mc[2] & 0x3) << 5)
+ | ((state->xMaxc[2] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[2] & 0x1) << 7)
+ | ((state->xMc[26] & 0x7) << 4)
+ | ((state->xMc[27] & 0x7) << 1)
+ | ((state->xMc[28] >> 2) & 0x1);
+ *c++ = ((state->xMc[28] & 0x3) << 6)
+ | ((state->xMc[29] & 0x7) << 3)
+ | (state->xMc[30] & 0x7);
+ *c++ = ((state->xMc[31] & 0x7) << 5)
+ | ((state->xMc[32] & 0x7) << 2)
+ | ((state->xMc[33] >> 1) & 0x3);
+ *c++ = ((state->xMc[33] & 0x1) << 7)
+ | ((state->xMc[34] & 0x7) << 4)
+ | ((state->xMc[35] & 0x7) << 1)
+ | ((state->xMc[36] >> 2) & 0x1);
+ *c++ = ((state->xMc[36] & 0x3) << 6)
+ | ((state->xMc[37] & 0x7) << 3)
+ | (state->xMc[38] & 0x7);
+ *c++ = ((state->Nc[3] & 0x7F) << 1)
+ | ((state->bc[3] >> 1) & 0x1);
+ *c++ = ((state->bc[3] & 0x1) << 7)
+ | ((state->Mc[3] & 0x3) << 5)
+ | ((state->xMaxc[3] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[3] & 0x1) << 7)
+ | ((state->xMc[39] & 0x7) << 4)
+ | ((state->xMc[40] & 0x7) << 1)
+ | ((state->xMc[41] >> 2) & 0x1);
+ *c++ = ((state->xMc[41] & 0x3) << 6)
+ | ((state->xMc[42] & 0x7) << 3)
+ | (state->xMc[43] & 0x7);
+ *c++ = ((state->xMc[44] & 0x7) << 5)
+ | ((state->xMc[45] & 0x7) << 2)
+ | ((state->xMc[46] >> 1) & 0x3);
+ *c++ = ((state->xMc[46] & 0x1) << 7)
+ | ((state->xMc[47] & 0x7) << 4)
+ | ((state->xMc[48] & 0x7) << 1)
+ | ((state->xMc[49] >> 2) & 0x1);
+ *c++ = ((state->xMc[49] & 0x3) << 6)
+ | ((state->xMc[50] & 0x7) << 3)
+ | (state->xMc[51] & 0x7);
+}
+
+void gsm_decode(gsm_state *state, short *out)
+{
+ int i;
+ unsigned char *c = state->gsmFrame;
+
+ if (((*c >> 4) & 0x0F) != GSM_MAGIC) return ;
+ state->qLARs[0] = (*c++ & 0xF) << 2;
+ state->qLARs[0] |= (*c >> 6) & 0x3;
+ state->qLARs[1] = *c++ & 0x3F;
+ state->qLARs[2] = (*c >> 3) & 0x1F;
+ state->qLARs[3] = (*c++ & 0x7) << 2;
+ state->qLARs[3] |= (*c >> 6) & 0x3;
+ state->qLARs[4] = (*c >> 2) & 0xF;
+ state->qLARs[5] = (*c++ & 0x3) << 2;
+ state->qLARs[5] |= (*c >> 6) & 0x3;
+ state->qLARs[6] = (*c >> 3) & 0x7;
+ state->qLARs[7] = *c++ & 0x7;
+ state->Nc[0] = (*c >> 1) & 0x7F;
+ state->bc[0] = (*c++ & 0x1) << 1;
+ state->bc[0] |= (*c >> 7) & 0x1;
+ state->Mc[0] = (*c >> 5) & 0x3;
+ state->xMaxc[0] = (*c++ & 0x1F) << 1;
+ state->xMaxc[0] |= (*c >> 7) & 0x1;
+ state->xMc[0] = (*c >> 4) & 0x7;
+ state->xMc[1] = (*c >> 1) & 0x7;
+ state->xMc[2] = (*c++ & 0x1) << 2;
+ state->xMc[2] |= (*c >> 6) & 0x3;
+ state->xMc[3] = (*c >> 3) & 0x7;
+ state->xMc[4] = *c++ & 0x7;
+ state->xMc[5] = (*c >> 5) & 0x7;
+ state->xMc[6] = (*c >> 2) & 0x7;
+ state->xMc[7] = (*c++ & 0x3) << 1;
+ state->xMc[7] |= (*c >> 7) & 0x1;
+ state->xMc[8] = (*c >> 4) & 0x7;
+ state->xMc[9] = (*c >> 1) & 0x7;
+ state->xMc[10] = (*c++ & 0x1) << 2;
+ state->xMc[10] |= (*c >> 6) & 0x3;
+ state->xMc[11] = (*c >> 3) & 0x7;
+ state->xMc[12] = *c++ & 0x7;
+ state->Nc[1] = (*c >> 1) & 0x7F;
+ state->bc[1] = (*c++ & 0x1) << 1;
+ state->bc[1] |= (*c >> 7) & 0x1;
+ state->Mc[1] = (*c >> 5) & 0x3;
+ state->xMaxc[1] = (*c++ & 0x1F) << 1;
+ state->xMaxc[1] |= (*c >> 7) & 0x1;
+ state->xMc[13] = (*c >> 4) & 0x7;
+ state->xMc[14] = (*c >> 1) & 0x7;
+ state->xMc[15] = (*c++ & 0x1) << 2;
+ state->xMc[15] |= (*c >> 6) & 0x3;
+ state->xMc[16] = (*c >> 3) & 0x7;
+ state->xMc[17] = *c++ & 0x7;
+ state->xMc[18] = (*c >> 5) & 0x7;
+ state->xMc[19] = (*c >> 2) & 0x7;
+ state->xMc[20] = (*c++ & 0x3) << 1;
+ state->xMc[20] |= (*c >> 7) & 0x1;
+ state->xMc[21] = (*c >> 4) & 0x7;
+ state->xMc[22] = (*c >> 1) & 0x7;
+ state->xMc[23] = (*c++ & 0x1) << 2;
+ state->xMc[23] |= (*c >> 6) & 0x3;
+ state->xMc[24] = (*c >> 3) & 0x7;
+ state->xMc[25] = *c++ & 0x7;
+ state->Nc[2] = (*c >> 1) & 0x7F;
+ state->bc[2] = (*c++ & 0x1) << 1;
+ state->bc[2] |= (*c >> 7) & 0x1;
+ state->Mc[2] = (*c >> 5) & 0x3;
+ state->xMaxc[2] = (*c++ & 0x1F) << 1;
+ state->xMaxc[2] |= (*c >> 7) & 0x1;
+ state->xMc[26] = (*c >> 4) & 0x7;
+ state->xMc[27] = (*c >> 1) & 0x7;
+ state->xMc[28] = (*c++ & 0x1) << 2;
+ state->xMc[28] |= (*c >> 6) & 0x3;
+ state->xMc[29] = (*c >> 3) & 0x7;
+ state->xMc[30] = *c++ & 0x7;
+ state->xMc[31] = (*c >> 5) & 0x7;
+ state->xMc[32] = (*c >> 2) & 0x7;
+ state->xMc[33] = (*c++ & 0x3) << 1;
+ state->xMc[33] |= (*c >> 7) & 0x1;
+ state->xMc[34] = (*c >> 4) & 0x7;
+ state->xMc[35] = (*c >> 1) & 0x7;
+ state->xMc[36] = (*c++ & 0x1) << 2;
+ state->xMc[36] |= (*c >> 6) & 0x3;
+ state->xMc[37] = (*c >> 3) & 0x7;
+ state->xMc[38] = *c++ & 0x7;
+ state->Nc[3] = (*c >> 1) & 0x7F;
+ state->bc[3] = (*c++ & 0x1) << 1;
+ state->bc[3] |= (*c >> 7) & 0x1;
+ state->Mc[3] = (*c >> 5) & 0x3;
+ state->xMaxc[3] = (*c++ & 0x1F) << 1;
+ state->xMaxc[3] |= (*c >> 7) & 0x1;
+ state->xMc[39] = (*c >> 4) & 0x7;
+ state->xMc[40] = (*c >> 1) & 0x7;
+ state->xMc[41] = (*c++ & 0x1) << 2;
+ state->xMc[41] |= (*c >> 6) & 0x3;
+ state->xMc[42] = (*c >> 3) & 0x7;
+ state->xMc[43] = *c++ & 0x7;
+ state->xMc[44] = (*c >> 5) & 0x7;
+ state->xMc[45] = (*c >> 2) & 0x7;
+ state->xMc[46] = (*c++ & 0x3) << 1;
+ state->xMc[46] |= (*c >> 7) & 0x1;
+ state->xMc[47] = (*c >> 4) & 0x7;
+ state->xMc[48] = (*c >> 1) & 0x7;
+ state->xMc[49] = (*c++ & 0x1) << 2;
+ state->xMc[49] |= (*c >> 6) & 0x3;
+ state->xMc[50] = (*c >> 3) & 0x7;
+ state->xMc[51] = *c & 0x7;
+
+ for (i = 0; i < 4; i++) {
+ state->subframe = i;
+ decodeRPE(state);
+ longTermSynthesis(state);
+ }
+ memcpy(state->dp0, state->dp0 + 160, 120 * sizeof(short));
+ shortTermSynthesis(state, &state->dp0[120], out);
+ gsm_postprocessing(state, out, out);
+ state->j ^= 1;
+}
diff --git a/protocols/Tlen/src/codec/gsm_long.c b/protocols/Tlen/src/codec/gsm_long.c
new file mode 100644
index 0000000000..56d83f7873
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_long.c
@@ -0,0 +1,183 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 "gsm.h"
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+/* Decision levels */
+const static int gsm_DLB[4] = { 6554, 16384, 26214, 32767 };
+/* Quantization levels */
+const static int gsm_QLB[4] = { 3277, 11469, 21299, 32767 };
+
+/*
+ * Long term parameters calculation - lag (Nc) and gain (bc).
+ */
+static void longTermLTPCalculation(gsm_state *state, short *in, short *in_1)
+{
+ int k, lambda;
+ int Nc, bc;
+ float in_1_float_base[120], * in_1_float = in_1_float_base + 120;
+ float in_float[40];
+ float L_result, L_max, L_power;
+
+ for (k = -120; k < 0; k++) in_1_float[k] = (float)in_1[k];
+ for (k = 0; k < 40; k++) in_float[k] = (float)in[k];
+
+ /* Search for the maximum cross-correlation and coding of the LTP lag */
+
+ L_max = 0;
+ Nc = 40; /* index for the maximum cross-correlation */
+
+ for (lambda = 40; lambda < 121; lambda++) {
+ for (L_result = 0, L_power = 0, k = 0; k < 40; k++) {
+ L_result += in_float[k] * in_1_float[k - lambda];
+// L_power += in_1_float[k - lambda] * in_1_float[k - lambda];
+ }
+// L_result = L_result / L_power;
+ if (L_result > L_max) {
+ Nc = lambda;
+ L_max = L_result;
+ }
+ }
+ state->Nc[state->subframe] = Nc;
+ if (L_max <= 0.) {
+ state->bc[state->subframe] = 0;
+ return;
+ }
+ /* Compute the power of the reconstructed short term residual signal dp[..] */
+ in_1_float -= Nc;
+ L_power = 0;
+ for (k = 0; k < 40; k++) {
+ float f = in_1_float[k];
+ L_power += f * f;
+ }
+ if (L_max >= L_power) { //1.0
+ state->bc[state->subframe] = 3;
+ return;
+ }
+ /* Coding of the LTP gain
+ * Table gsm_DLB must be used to obtain the level DLB[i] for the
+ * quantization of the LTP gain b to get the coded version bc.
+ */
+// lambda = L_max * 32768.;
+ lambda = (int)(L_max * 32768. / L_power);
+ for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
+ state->bc[state->subframe] = bc;
+}
+
+/*
+ * Here we decode the bc parameter and compute samples of the estimate out[0..39].
+ * The decoding of bc needs the gsm_QLB table.
+ * The long term residual signal e[0..39] is then calculated to be fed to the
+ * RPE encoding section.
+ */
+static void longTermAnalysisFilter(int Nc, int bc, short *in, short *in_1, short *out, int *e)
+{
+ int gain, k, l;
+ gain = gsm_QLB[bc];
+ for (k = 0; k < 40; k++) {
+ l = (gain * (int)in_1[k - Nc] + 16384) >> 15;
+ if (l < -32768) l = -32768;
+ else if (l > 32767) l = 32767;
+ out[k] = l;
+ e[k] = in[k] - l;
+ }
+}
+
+/*
+ * This procedure uses the bcr and Ncr parameter to realize the
+ * long term synthesis filtering. The decoding of bcr needs table gsm_QLB.
+ */
+static void longTermSynthesisFilter(gsm_state * state, int Ncr, int bcr, int *e, short *out)
+{
+ int k;
+ int brp, Nr;
+
+ /* Check the limits of Nr. */
+ Nr = Ncr < 40 || Ncr > 120 ? state->nrp : Ncr;
+ state->nrp = Nr;
+ /* Decoding of the LTP gain bcr */
+ brp = gsm_QLB[ bcr ];
+
+ /* Computation of the reconstructed short term residual
+ * signal drp[0..39]
+ */
+ for (k = 0; k < 40; k++) {
+ int temp = (brp * (int)out[ k-Nr ] + 16384) >> 15;
+ out[k] = e[k] + temp;
+ }
+}
+
+/*
+ * This procedure performs long term analysis.
+ */
+void longTermAnalysis(gsm_state *state, short *in)
+{
+ short *in_1 = state->dp0 + 120 + state->subframe * 40;
+ short *out = state->dp0 + 120 + state->subframe * 40;
+ int *e = state->e + state->subframe * 40;
+/*
+
+ int i;
+ printf("Long-term in: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", in[i]);
+ }
+ printf("\n");
+ */
+ longTermLTPCalculation(state, in, in_1);
+ /* printf("Nc: %d, bc: %d \n", state->Nc[state->subframe], state->bc[state->subframe]);
+ */
+ longTermAnalysisFilter(state->Nc[state->subframe], state->bc[state->subframe], in, in_1, out, e);
+/*
+ printf("Long-term out: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", out[i]);
+ }
+ printf("\n");
+ */
+}
+
+/*
+ * This procedure performs long term synthesis.
+ */
+void longTermSynthesis(gsm_state *state)
+{
+ int Nc = state->Nc[state->subframe];
+ int bc = state->bc[state->subframe];
+ int *e = state->e + state->subframe * 40;
+ short *out = state->dp0 + 120 + state->subframe * 40;
+ //int i;
+ longTermSynthesisFilter(state, Nc, bc, e, out);
+ /*
+ printf("Long-term reconstructed: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", state->dp0[i]);
+ }
+ printf("\n");
+ */
+}
diff --git a/protocols/Tlen/src/codec/gsm_lpc.c b/protocols/Tlen/src/codec/gsm_lpc.c
new file mode 100644
index 0000000000..538a03ad92
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_lpc.c
@@ -0,0 +1,208 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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.
+
+*/
+
+/* LPC- and Reflection Coefficients
+ * The next two functions calculate linear prediction coefficients
+ * and/or the related reflection coefficients from the first P_MAX+1
+ * values of the autocorrelation function.
+ */
+#include "gsm.h" /* for P_MAX */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Compute the autocorrelation
+ * ,--,
+ * ac(l) = > x(i) * x(i-l) for all i
+ * `--'
+ * for lags l between 0 and lag-1, and x(i) == 0 for i < 0 or i >= n
+ * @param n: number of samples
+ * @param lax: max lag (order)
+ * @param in: [0...n-1] samples x
+ * @param out: [0...lag-1] autocorrelation
+ */
+static void autocorrelation(int n, float const *x, int lag, float *ac)
+{
+ float d;
+ int i, j;
+ for (j = 0; j < lag; j++) {
+ for (i = j, d = 0; i < n; i++) d += x[i] * x[i-j];
+ ac[j] = d;
+ }
+ d = (float)fabs(ac[0]);
+ if (d != 0) {
+ for (j = 0; j < lag; j++) ac[j] /= d;
+ }
+}
+
+/* The Levinson-Durbin algorithm was invented by N. Levinson in 1947
+ * and modified by J. Durbin in 1959.
+ * @param in: [0...p] autocorrelation values
+ * @param out: [0...p-1] reflection coefficients
+ * @param lpc: [0...p-1] LPC coefficients
+ * @return minimum mean square error
+ */
+/*
+static float levinson_durbin (float const *ac, float *ref, float *lpc)
+{
+ int i, j;
+ float r, error = ac[0];
+
+ if (ac[0] == 0) {
+ for (i = 0; i < P_MAX; i++) ref[i] = 0;
+ return 0;
+ }
+
+ for (i = 0; i < P_MAX; i++) {
+
+ r = -ac[i + 1];
+ for (j = 0; j < i; j++) r -= lpc[j] * ac[i - j];
+ ref[i] = r /= error;
+
+ // Update LPC coefficients and total error.
+ lpc[i] = r;
+ for (j = 0; j < i / 2; j++) {
+ float tmp = lpc[j];
+ lpc[j] = r * lpc[i - 1 - j];
+ lpc[i - 1 - j] += r * tmp;
+ }
+ if (i % 2) lpc[j] += lpc[j] * r;
+
+ error *= 1 - r * r;
+ }
+ return error;
+}
+*/
+/* I. Schur's recursion from 1917 is related to the Levinson-Durbin method,
+ * but faster on parallel architectures; where Levinson-Durbin would take time
+ * proportional to p * log(p), Schur only requires time proportional to p. The
+ * GSM coder uses an integer version of the Schur recursion.
+ * @param in: [0...p] autocorrelation values
+ * @param out: [0...p-1] reflection coefficients
+ * @return the minimum mean square error
+ */
+static float schur(float const *ac, float *ref)
+{
+ int i, m;
+ float error=ac[0], r, G[2][P_MAX];
+
+ if (ac[0] == 0.0) {
+ for (i = 0; i < P_MAX; i++) ref[i] = 0;
+ return 0;
+ }
+
+ /* Initialize the rows of the generator matrix G to ac[1...p]. */
+ for (i = 0; i < P_MAX; i++) G[0][i] = G[1][i] = ac[i + 1];
+
+ for (i = 0;;) {
+ /* Calculate this iteration's reflection coefficient and error. */
+ ref[i] = r = -G[1][0] / error;
+ error += G[1][0] * r;
+
+ if (++i >= P_MAX) return error;
+
+ /* Update the generator matrix. Unlike Levinson-Durbin's summing of
+ * reflection coefficients, this loop could be executed in parallel
+ * by p processors in constant time.
+ */
+ for (m = 0; m < P_MAX - i; m++) {
+ G[1][m] = G[1][m + 1] + r * G[0][m];
+ G[0][m] = G[1][m + 1] * r + G[0][m];
+ }
+ }
+}
+
+
+ /* 0..7 IN/OUT */
+static void rToLAR(int *r)
+/*
+ * The following scaling for r[..] and LAR[..] has been used:
+ *
+ * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1.
+ * LAR[..] = integer( real_LAR[..] * 16384 );
+ * with -1.625 <= real_LAR <= 1.625
+ */
+{
+ int temp;
+ int i;
+
+ /* Computation of the LAR[0..7] from the r[0..7]
+ */
+ for (i = 0; i < 8; i++) {
+ temp = abs(r[i]); //GSM_ABS(temp);
+ if (temp < 22118) {
+ temp >>= 1;
+ } else if (temp < 31130) {
+ temp -= 11059;
+ } else {
+ temp -= 26112;
+ temp <<= 2;
+ }
+ r[i] = r[i] < 0 ? -temp : temp;
+ }
+}
+
+static void quantizeLARs(int *LARs, int *qLARs)
+{ int qA[]={20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036};
+ int qB[]={0, 0, 2048, -2560, 94, -1792, -341, -1144};
+ int qMin[]={-32, -32, -16, -16, -8, -8, -4, -4};
+ int qMax[]={31, 31, 15, 15, 7, 7, 3, 3};
+ int i;
+ for (i = 0; i < 8; i++) {
+ int temp;
+ temp = (((LARs[i] * qA[i]) >> 15) + qB[i] + 256) >> 9;
+ if (temp < qMin[i]) temp = 0;
+ else if (temp > qMax[i]) temp = qMax[i] - qMin[i];
+ else temp = temp - qMin[i];
+ qLARs[i] = temp;
+ }
+}
+
+void lpcAnalysis(gsm_state *state, short *in)
+{ float error;
+ float samples[160];
+ float ac[9];
+ float ref[8];
+ int i;
+ int * qLARs = state->qLARs;
+ for (i = 0; i < 160; i++) {
+ samples[i] = in[i];
+ }
+ autocorrelation(160, samples, 9, ac);
+ error=schur(ac, ref);
+ /*
+ printf("reff: ");
+ for (i=0;i<8;i++) {
+ printf("%5.5f ", ref[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+ for (i = 0; i < 8; i++) {
+ qLARs[i] = (int) (32768 * ref[i]);
+ }
+ rToLAR(qLARs);
+ quantizeLARs(qLARs, qLARs);
+}
diff --git a/protocols/Tlen/src/codec/gsm_preprocess.c b/protocols/Tlen/src/codec/gsm_preprocess.c
new file mode 100644
index 0000000000..462b8e6c17
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_preprocess.c
@@ -0,0 +1,103 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 "gsm.h"
+#include <stdio.h>
+
+/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION
+ *
+ * After A-law to linear conversion (or directly from the
+ * Ato D converter) the following scaling is assumed for
+ * input to the RPE-LTP algorithm:
+ *
+ *
+ * Where S is the sign bit, v a valid bit, and * a "don't care" bit.
+ * The original signal is called sop[..]
+ *
+ */
+
+
+void gsm_preprocessing( gsm_state *state, short *in, short *out)
+{
+ int z1 = state->z1;
+ int z2 = state->z2;
+ int mp = state->mp;
+ int so, s1;
+ int msp, lsp;
+
+ int k = 160;
+
+ while (k--) {
+ /* Downscaling of the input signal
+ * in: 0.1.....................12
+ * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.*
+ * out: 0.1................... 12
+ * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0
+ */
+ so = (*in >> 3) << 2;
+ in++;
+ /* 4.2.2 Offset compensation
+ *
+ * This part implements a high-pass filter and requires extended
+ * arithmetic precision for the recursive part of this filter.
+ * The input of this procedure is the array so[0...159] and the
+ * output the array sof[ 0...159 ].
+ */
+ /* Compute the non-recursive part
+ */
+ s1 = (so - z1) << 15;
+ z1 = so;
+ msp = z2 >> 15;
+ lsp = z2 - (msp << 15);
+ s1 += ((lsp * 32735) + 16384) >> 15;
+ z2 = msp * 32735 + s1;
+ /* 4.2.3 Preemphasis
+ */
+ msp = (-28180 * mp + 16384) >> 15;
+ mp = (z2 + 16384) >> 15;
+ *out++ = mp + msp;
+ }
+ state->z1 = z1;
+ state->z2 = z2;
+ state->mp = mp;
+/*
+ printf("preprocessed: \n");
+ for (k=0;k<160;k++) {
+ printf("%7d ", out[k]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+}
+
+void gsm_postprocessing( gsm_state *state, short *in, short *out)
+{
+ int k;
+ int msr = state->msr;
+ for (k = 160; k--; in++, out++) {
+ msr = *in + ((msr * 28180 + 16384) >>15); /* Deemphasis */
+ *out = (msr + msr ) & 0xFFF8; /* Truncation & Upscaling */
+ }
+ state->msr = msr;
+}
diff --git a/protocols/Tlen/src/codec/gsm_rpe.c b/protocols/Tlen/src/codec/gsm_rpe.c
new file mode 100644
index 0000000000..21c5419672
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_rpe.c
@@ -0,0 +1,248 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 "gsm.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const int gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 };
+static const int gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 };
+static const int gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 };
+/*
+ * The coefficients of the weighting filter are stored in the gsm_H table.
+ * The following scaling is used:
+ *
+ * gsm_H[0..10] = integer( real_H[ 0..10] * 8192 );
+ */
+static void weightingFilter (int *e, int *x)
+{
+ int L_result;
+ int k, i;
+ for (k = 0; k < 40; k++) {
+ L_result = 4096;
+ for (i = 0; i < 11; i++) {
+ int ix = i + k;
+ if (ix>4 && ix<45) L_result += e[ix - 5] * gsm_H[i];
+ }
+ L_result >>= 13;
+ x[k] = (L_result < -32768 ? -32768 : (L_result > 32767 ? 32767 : L_result));
+ }
+}
+
+/*
+ * The signal x[0..39] is used to select the RPE grid which is
+ * represented by Mc.
+ */
+static void gridSelection( int *x, int *xM, int *Mc_out)
+{
+ int m, i;
+ int L_result, L_temp;
+ int EM, Mc;
+
+ EM = 0;
+ Mc = 0;
+
+ for (m = 0; m < 4; m++) {
+ L_result = 0;
+ for (i = 0; i < 13; i++) {
+ int temp = x[m + 3*i] >> 2;
+ L_temp = temp * temp << 1;
+ L_result += L_temp;
+ }
+ if (L_result > EM) {
+ Mc = m;
+ EM = L_result;
+ }
+ }
+ /* Down-sampling by a factor 3 to get the selected xM[0..12]
+ * RPE sequence.
+ */
+ for (i = 0; i < 13; i ++) xM[i] = x[Mc + 3*i];
+ *Mc_out = Mc;
+}
+
+/*
+ * This procedure computes the reconstructed long term residual signal
+ * ep[0..39] for the LTP analysis filter. The inputs are the Mc
+ * which is the grid position selection and the xMp[0..12] decoded
+ * RPE samples which are upsampled by a factor of 3 by inserting zero
+ * values.
+ */
+static void gridPositioning (int Mc, int *xMp, int *ep)
+{
+ int i, k;
+ for (k = 0; k < 40; k++) ep[k] = 0;
+ for (i = 0; i < 13; i++) {
+ ep[ Mc + (3*i) ] = xMp[i];
+ }
+}
+
+static void APCMXmaxcToExpMant (int xmaxc, int *exp_out, int *mant_out )
+{
+ int exp, mant;
+ /* Compute exponent and mantissa of the decoded version of xmaxc
+ */
+ exp = 0;
+ if (xmaxc > 15) exp = (xmaxc >> 3) - 1;
+ mant = xmaxc - (exp << 3);
+
+ if (mant == 0) {
+ exp = -4;
+ mant = 7;
+ }
+ else {
+ while (mant < 8) {
+ mant = mant << 1 | 1;
+ exp--;
+ }
+ mant -= 8;
+ }
+
+ *exp_out = exp;
+ *mant_out = mant;
+}
+
+static void APCMQuantization (int *xM, int *xMc, int *mant_out, int *exp_out, int *xmaxc_out)
+{
+ int i, itest;
+ int xmax, xmaxc, temp, temp1, temp2;
+ int exp, mant;
+
+
+ /* Find the maximum absolute value xmax of xM[0..12].
+ */
+
+ xmax = 0;
+ for (i = 0; i < 13; i++) {
+ temp = abs(xM[i]);
+ if (temp > xmax) xmax = temp;
+ }
+ if (xmax > 32767) xmax = 32767;
+ /* Qantizing and coding of xmax to get xmaxc.
+ */
+
+ exp = 0;
+ temp = xmax >> 9;
+ itest = 0;
+
+ for (i = 0; i < 6; i++) {
+ if (temp != 0) exp++;
+ temp = temp >> 1;
+ }
+
+ temp = exp + 5;
+
+ xmaxc = (xmax >> temp) + (exp << 3);
+
+ /* Quantizing and coding of the xM[0..12] RPE sequence
+ * to get the xMc[0..12]
+ */
+ APCMXmaxcToExpMant( xmaxc, &exp, &mant );
+
+ /* This computation uses the fact that the decoded version of xmaxc
+ * can be calculated by using the exponent and the mantissa part of
+ * xmaxc (logarithmic table).
+ * So, this method avoids any division and uses only a scaling
+ * of the RPE samples by a function of the exponent. A direct
+ * multiplication by the inverse of the mantissa (NRFAC[0..7]
+ * found in table 4.5) gives the 3 bit coded version xMc[0..12]
+ * of the RPE samples.
+ */
+
+ /* Direct computation of xMc[0..12] using table 4.5
+ */
+ temp = (mant|8)<<(5+exp);
+ temp1 = 6 - exp;
+ temp2 = gsm_NRFAC[ mant ];
+ for (i = 0; i < 13; i++) {
+ xMc[i] = ((xM[i] << temp1) * temp2 >> 27) + 4;
+ }
+
+ /* NOTE: This equation is used to make all the xMc[i] positive.
+ */
+
+ *mant_out = mant;
+ *exp_out = exp;
+ *xmaxc_out = xmaxc;
+}
+
+static void APCMDequantization (int *xMc, int mant, int exp, int *xMp)
+{
+ int i, temp1, temp2, temp3;
+ temp1 = gsm_FAC[ mant ];
+ temp2 = 6 - exp;
+ if (temp2 <= 0) {
+ temp3 = 1 >> (1 - temp2);
+ } else {
+ temp3 = 1 << (temp2 - 1);
+ }
+ for (i = 0; i < 13; i++) {
+ xMp[i] = ((((((xMc[i]<<1)-7)<<12)*temp1+16384)>>15)+temp3)>>temp2;
+ }
+}
+
+void encodeRPE(gsm_state *state)
+{ int x[40];
+ int xM[13], xMp[13];
+ int mant, exp;
+ int *Mc = state->Mc + state->subframe;
+ int *xMaxc = state->xMaxc + state->subframe;
+ int *xMc = state->xMc + state->subframe * 13;
+ int *e = state->e + state->subframe * 40;
+ //int i;
+ /*
+ printf("RPE in: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", e[i]);
+ }
+ printf("\n");
+ */
+ weightingFilter(e, x);
+ /*
+ printf("RPE weighting filter: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", x[i]);
+ }
+ printf("\n");
+ */
+ gridSelection(x, xM, Mc);
+ APCMQuantization(xM, xMc, &mant, &exp, xMaxc);
+ /* printf("RPE Mc(grid #)=%d xmaxc=%d mant=%d exp=%d \n", *Mc, *xMaxc, mant, exp); */
+ APCMDequantization(xMc, mant, exp, xMp);
+ gridPositioning(*Mc, xMp, e);
+}
+
+void decodeRPE(gsm_state *state)
+{
+ int exp, mant;
+ int xMp[ 13 ];
+ int *xMc = state->xMc + state->subframe * 13;
+ int *e = state->e + state->subframe * 40;
+
+ APCMXmaxcToExpMant(state->xMaxc[state->subframe], &exp, &mant);
+ APCMDequantization(xMc, mant, exp, xMp);
+ gridPositioning(state->Mc[state->subframe], xMp, e);
+}
diff --git a/protocols/Tlen/src/codec/gsm_short.c b/protocols/Tlen/src/codec/gsm_short.c
new file mode 100644
index 0000000000..4b02515a72
--- /dev/null
+++ b/protocols/Tlen/src/codec/gsm_short.c
@@ -0,0 +1,211 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+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 "gsm.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+extern void lpcAnalysis(gsm_state *state, short *in);
+
+/*
+ * Dequantize LAR coefficients
+ */
+static void dequantizeLARs(int *qLARs, int *LARs)
+{
+ int dqA[]={13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708};
+ int dqB[]={0, 0, 2048, -2560, 94, -1792, -341, -1144};
+ int dqMin[]={-32, -32, -16, -16, -8, -8, -4, -4};
+ int i;
+ for (i = 0; i < 8; i++) {
+ int temp;
+ temp = ((((qLARs[i] + dqMin[i]) << 10) - (dqB[i] << 1)) * dqA[i] + 16384) >> 15;
+ LARs[i] = temp + temp;
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 0..12)
+ */
+static void interpolateLARs_0_12 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j_1[i] >> 1) + (LARpp_j_1[i] >> 2) + (LARpp_j[i] >> 2);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 13..26)
+ */
+static void interpolateLARs_13_26 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j_1[i] >> 1) + (LARpp_j[i] >> 1);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 27..39)
+ */
+static void interpolateLARs_27_39 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j[i] >> 1) + (LARpp_j_1[i] >> 2) + (LARpp_j[i] >> 2);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 40..159)
+ */
+static void interpolateLARs_40_159 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = LARpp_j[i];
+ }
+}
+/*
+ * Convert LAR coefficients to reflection coefficients
+ */
+static void LARToR( int * LARp)
+{
+ int i;
+ int temp;
+ for (i = 0; i < 8; i++) {
+ temp = abs(LARp[i]);
+ if (temp < 11059) temp <<= 1;
+ else if (temp < 20070) temp += 11059;
+ else temp = (temp >> 2) + 26112;
+ LARp[i] = LARp[i] < 0 ? -temp : temp;
+ }
+}
+
+/*
+ * This procedure computes the short term residual signal d[..] to be fed
+ * to the RPE-LTP loop from the s[..] signal and from the local rp[..]
+ * array (quantized reflection coefficients). As the call of this
+ * procedure can be done in many ways (see the interpolation of the LAR
+ * coefficient), it is assumed that the computation begins with index
+ * k_start (for arrays d[..] and s[..]) and stops with index k_end
+ * (k_start and k_end are defined in 4.2.9.1). This procedure also
+ * needs to keep the array u[0..7] in memory for each call.
+ */
+static void shortTermAnalysisFilter (gsm_state * state, int * rp, int len, short * in)
+{
+ int * u = state->u;
+ int i;
+ int di, ui, sav, rpi;
+ for (; len--; in++) {
+ di = sav = *in;
+ for (i = 0; i < 8; i++) {
+ ui = u[i];
+ rpi = rp[i];
+ u[i] = sav;
+ sav = ui + ((rpi * di + 16384) >> 15);
+ di = di + ((rpi * ui + 16384) >> 15);
+ }
+ *in = di;
+ }
+}
+
+static void shortTermSynthesisFilter(gsm_state * state, int * rrp, int len, short * in, short *out)
+{
+ int * v = state->v;
+ int i;
+ int sri;
+ for (; len--; in++, out++) {
+ sri = *in;
+ for (i = 8; i--;) {
+ sri -= (rrp[i] * v[i] + 16384) >> 15;
+ if (sri < -32768) sri = -32768;
+ else if (sri > 32767) sri = 32767;
+ v[i+1] = v[i] + ((rrp[i] * sri + 16384) >> 15);
+ if (v[i+1] < -32768) v[i+1] = -32768;
+ else if (v[i+1] > 32767) v[i+1] = 32767;
+ }
+ *out = v[0] = sri;
+ }
+}
+
+void shortTermAnalysis(gsm_state *state, short *in)
+{
+ int * qLARs = state->qLARs;
+ int * LARpp_j = state->LARpp[state->j];
+ int * LARpp_j_1 = state->LARpp[state->j ^1];
+ int LARp[8];
+// int i;
+
+ lpcAnalysis(state, in);//i_samples);
+/*
+ printf("short term in: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", in[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+ dequantizeLARs(qLARs, LARpp_j);
+ interpolateLARs_0_12(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 13, in);
+ interpolateLARs_13_26(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 14, in+13);
+ interpolateLARs_27_39(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 13, in+27);
+ interpolateLARs_40_159(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 120, in+40);
+ /*
+ printf("short-term residuals: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", in[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+}
+
+void shortTermSynthesis(gsm_state *state, short *in, short *out)
+{
+ int * qLARs = state->qLARs;
+ int * LARpp_j = state->LARpp[state->j];
+ int * LARpp_j_1 = state->LARpp[state->j ^1];
+ int LARp[8];
+// int i;
+
+ dequantizeLARs(qLARs, LARpp_j);
+ interpolateLARs_0_12(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 13, in, out);
+ interpolateLARs_13_26(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 14, in+13, out+13);
+ interpolateLARs_27_39(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 13, in+27, out+27);
+ interpolateLARs_40_159(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 120, in+40, out+40);
+ /*
+ printf("samples[reconstructed]: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", out[i]);
+ }
+ */
+}
diff --git a/protocols/Tlen/src/commons.h b/protocols/Tlen/src/commons.h
new file mode 100644
index 0000000000..af5a9bbcd7
--- /dev/null
+++ b/protocols/Tlen/src/commons.h
@@ -0,0 +1,32 @@
+#ifndef _TLENCOMMONS_INC
+#define _TLENCOMMONS_INC
+
+
+#define TLENMUCC_MAJOR_VERSION 2
+#define TLENMUCC_MINOR_VERSION 0
+#define TLENMUCC_RELEASE_NUM 5
+#define TLENMUCC_BUILD_NUM 0
+#define TLENMUCC_VERSION_STRING "2.0.5.0"
+
+
+
+//consts for tlen.dll
+#define TLEN_MAJOR_VERSION TLENMUCC_MAJOR_VERSION
+#define TLEN_MINOR_VERSION TLENMUCC_MINOR_VERSION
+#define TLEN_RELEASE_NUM TLENMUCC_RELEASE_NUM
+#define TLEN_BUILD_NUM TLENMUCC_BUILD_NUM
+
+#define TLEN_FILEVERSION_STRING TLEN_MAJOR_VERSION,TLEN_MINOR_VERSION,TLEN_RELEASE_NUM,TLEN_BUILD_NUM
+#define TLEN_VERSION_STRING TLENMUCC_VERSION_STRING
+
+//consts for tlen_czaty.dll
+#define MUCC_MAJOR_VERSION TLENMUCC_MAJOR_VERSION
+#define MUCC_MINOR_VERSION TLENMUCC_MINOR_VERSION
+#define MUCC_RELEASE_NUM TLENMUCC_RELEASE_NUM
+#define MUCC_BUILD_NUM TLENMUCC_BUILD_NUM
+
+#define MUCC_FILEVERSION_STRING MUCC_MAJOR_VERSION,MUCC_MINOR_VERSION,MUCC_RELEASE_NUM,MUCC_BUILD_NUM
+#define MUCC_VERSION_STRING TLENMUCC_VERSION_STRING
+
+
+#endif //ifndef _TLENCOMMONS_INC
diff --git a/protocols/Tlen/src/crypto/aes.c b/protocols/Tlen/src/crypto/aes.c
new file mode 100644
index 0000000000..7bccdf93a1
--- /dev/null
+++ b/protocols/Tlen/src/crypto/aes.c
@@ -0,0 +1,1336 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_AES_C)
+
+#include "polarssl/aes.h"
+#include "polarssl/padlock.h"
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] ) \
+ | ( (unsigned long) (b)[(i) + 1] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+#if defined(POLARSSL_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+ V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+ V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+ V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+ V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+ V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+ V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+ V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+ V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+ V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+ V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+ V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+ V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+ V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+ V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+ V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+ V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+ V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+ V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+ V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+ V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+ V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+ V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+ V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+ V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+ V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+ V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+ V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+ V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+ V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+ V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+ V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+ V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+ V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+ V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+ V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+ V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+ V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+ V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+ V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+ V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+ V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+ V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+ V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+ V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+ V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+ V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+ V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+ V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+ V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+ V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+ V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+ V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+ V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+ V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+ V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+ V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+ V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+ V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+ V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+ V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+ V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+ V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+ V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+ V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+ V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+ V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+ V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+ V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+ V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+ V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+ V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+ V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+ V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+ V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+ V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+ V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+ V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+ V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+ V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+ V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+ V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+ V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+ V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+ V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+ V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+ V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+ V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+ V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+ V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+ V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+ V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+ V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+ V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+ V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+ V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+ V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+ V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+ V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+ V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+ V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+ V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+ V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+ V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+ V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+ V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+ V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+ V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+ V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+ V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+ V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+ V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+ V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+ V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+ V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+ V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+ V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+ V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+ V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+ V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+ V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+ V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+ V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+ V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+ V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+ V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+ V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+ V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+ V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const unsigned long RCON[10] =
+{
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x0000001B, 0x00000036
+};
+
+#else
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static unsigned long FT0[256];
+static unsigned long FT1[256];
+static unsigned long FT2[256];
+static unsigned long FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static unsigned long RT0[256];
+static unsigned long RT1[256];
+static unsigned long RT2[256];
+static unsigned long RT3[256];
+
+/*
+ * Round constants
+ */
+static unsigned long RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+ int i, x, y, z;
+ int pow[256];
+ int log[256];
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for( i = 0, x = 1; i < 256; i++ )
+ {
+ pow[i] = x;
+ log[x] = i;
+ x = ( x ^ XTIME( x ) ) & 0xFF;
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for( i = 0, x = 1; i < 10; i++ )
+ {
+ RCON[i] = (unsigned long) x;
+ x = XTIME( x ) & 0xFF;
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for( i = 1; i < 256; i++ )
+ {
+ x = pow[255 - log[i]];
+
+ y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y ^ 0x63;
+
+ FSb[i] = (unsigned char) x;
+ RSb[x] = (unsigned char) i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for( i = 0; i < 256; i++ )
+ {
+ x = FSb[i];
+ y = XTIME( x ) & 0xFF;
+ z = ( y ^ x ) & 0xFF;
+
+ FT0[i] = ( (unsigned long) y ) ^
+ ( (unsigned long) x << 8 ) ^
+ ( (unsigned long) x << 16 ) ^
+ ( (unsigned long) z << 24 );
+
+ FT1[i] = ROTL8( FT0[i] );
+ FT2[i] = ROTL8( FT1[i] );
+ FT3[i] = ROTL8( FT2[i] );
+
+ x = RSb[i];
+
+ RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^
+ ( (unsigned long) MUL( 0x09, x ) << 8 ) ^
+ ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^
+ ( (unsigned long) MUL( 0x0B, x ) << 24 );
+
+ RT1[i] = ROTL8( RT0[i] );
+ RT2[i] = ROTL8( RT1[i] );
+ RT3[i] = ROTL8( RT2[i] );
+ }
+}
+
+#endif
+
+/*
+ * AES key schedule (encryption)
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ unsigned int i;
+ unsigned long *RK;
+
+#if !defined(POLARSSL_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+ }
+#endif
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(PADLOCK_ALIGN16)
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+#else
+ ctx->rk = RK = ctx->buf;
+#endif
+
+ for( i = 0; i < (keysize >> 5); i++ )
+ {
+ GET_ULONG_LE( RK[i], key, i << 2 );
+ }
+
+ switch( ctx->nr )
+ {
+ case 10:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int i, j;
+ aes_context cty;
+ unsigned long *RK;
+ unsigned long *SK;
+ int ret;
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(PADLOCK_ALIGN16)
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+#else
+ ctx->rk = RK = ctx->buf;
+#endif
+
+ ret = aes_setkey_enc( &cty, key, keysize );
+ if( ret != 0 )
+ return( ret );
+
+ SK = cty.rk + cty.nr * 4;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+ {
+ for( j = 0; j < 4; j++, SK++ )
+ {
+ *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
+ RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
+ RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+ RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+ }
+ }
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ memset( &cty, 0, sizeof( aes_context ) );
+
+ return( 0 );
+}
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
+ FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
+ FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y0 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
+ FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
+ FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y2 >> 24 ) & 0xFF ]; \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
+ RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
+ RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y2 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
+ RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
+ RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y0 >> 24 ) & 0xFF ]; \
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( padlock_supports( PADLOCK_ACE ) )
+ {
+ if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ RK = ctx->rk;
+
+ GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
+ GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
+ GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
+ GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
+
+ if( mode == AES_DECRYPT )
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+ }
+ else /* AES_ENCRYPT */
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+ }
+
+ PUT_ULONG_LE( X0, output, 0 );
+ PUT_ULONG_LE( X1, output, 4 );
+ PUT_ULONG_LE( X2, output, 8 );
+ PUT_ULONG_LE( X3, output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( padlock_supports( PADLOCK_ACE ) )
+ {
+ if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ aes_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ aes_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i, cb;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
+
+ i = 15;
+ do {
+ nonce_counter[i]++;
+ cb = nonce_counter[i] == 0;
+ } while( i-- && cb );
+
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+ { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+ 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+ { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+ 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+ { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+ 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+ { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+ 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+ { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+ 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+ { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+ 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+ { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+ 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+ { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+ 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+ { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+ 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+ { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+ 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+ { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+ 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+ { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+ 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+ 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+ 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+ 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+ 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+ 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+ 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+ 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+ 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+ 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+ 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+ 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+ 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+ 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+ 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+ 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+ { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+ 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+ { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+ 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+ 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+ 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+ { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+ 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+ 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+ 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+ 0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int aes_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char prv[16];
+ unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
+ size_t offset;
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ int len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+ aes_context ctx;
+
+ memset( key, 0, 32 );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( iv , 0, 16 );
+ memset( prv, 0, 16 );
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[16];
+
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ memcpy( tmp, prv, 16 );
+ memcpy( prv, buf, 16 );
+ memcpy( buf, tmp, 16 );
+ }
+
+ if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ /*
+ * CFB128 mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_cfb128_iv, 16 );
+ memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ if( v == AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_cfb128_ct[u], 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ memcpy( buf, aes_test_cfb128_pt, 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CTR-128 (%s): ",
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, aes_test_ctr_key[u], 16 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 );
+
+ if( v == AES_DECRYPT )
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_ct[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_pt[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/protocols/Tlen/src/crypto/bignum.c b/protocols/Tlen/src/crypto/bignum.c
new file mode 100644
index 0000000000..eabfbfe6f9
--- /dev/null
+++ b/protocols/Tlen/src/crypto/bignum.c
@@ -0,0 +1,2097 @@
+/*
+ * Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This MPI implementation is based on:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * http://www.stillhq.com/extracted/gnupg-api/mpi/
+ * http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#include <stdlib.h>
+
+#define ciL (sizeof(t_uint)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ if( X->p != NULL )
+ {
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+ t_uint *p;
+
+ if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+ return( 1 );
+
+ if( X->n < nblimbs )
+ {
+ if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
+ return( 1 );
+
+ memset( p, 0, nblimbs * ciL );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+ int ret;
+ size_t i;
+
+ if( X == Y )
+ return( 0 );
+
+ for( i = Y->n - 1; i > 0; i-- )
+ if( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ MPI_CHK( mpi_grow( X, i ) );
+
+ memset( X->p, 0, X->n * ciL );
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+ mpi T;
+
+ memcpy( &T, X, sizeof( mpi ) );
+ memcpy( X, Y, sizeof( mpi ) );
+ memcpy( Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( mpi *X, size_t pos )
+{
+ if( X->n * biL <= pos )
+ return( 0 );
+
+ return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+ int ret = 0;
+ size_t off = pos / biL;
+ size_t idx = pos % biL;
+
+ if( val != 0 && val != 1 )
+ return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+
+ if( X->n * biL <= pos )
+ {
+ if( val == 0 )
+ return ( 0 );
+
+ MPI_CHK( mpi_grow( X, off + 1 ) );
+ }
+
+ X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+ size_t i, j, count = 0;
+
+ for( i = 0; i < X->n; i++ )
+ for( j = 0; j < biL; j++, count++ )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+ size_t i, j;
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = biL; j > 0; j-- )
+ if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+ break;
+
+ return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+ return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_uint *d, int radix, char c )
+{
+ *d = 255;
+
+ if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+ if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+ if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+ if( *d >= (t_uint) radix )
+ return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+ return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+ int ret;
+ size_t i, j, slen, n;
+ t_uint d;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &T );
+
+ slen = strlen( s );
+
+ if( radix == 16 )
+ {
+ n = BITS_TO_LIMBS( slen << 2 );
+
+ MPI_CHK( mpi_grow( X, n ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = slen, j = 0; i > 0; i--, j++ )
+ {
+ if( i == 1 && s[i - 1] == '-' )
+ {
+ X->s = -1;
+ break;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+ X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = 0; i < slen; i++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ continue;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+ if( X->s == 1 )
+ {
+ MPI_CHK( mpi_add_int( X, &T, d ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( X, &T, d ) );
+ }
+ }
+ }
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+ int ret;
+ t_uint r;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_mod_int( &r, X, radix ) );
+ MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+ if( mpi_cmp_int( X, 0 ) != 0 )
+ MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+ if( r < 10 )
+ *(*p)++ = (char)( r + 0x30 );
+ else
+ *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
+{
+ int ret = 0;
+ size_t n;
+ char *p;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ n = mpi_msb( X );
+ if( radix >= 4 ) n >>= 1;
+ if( radix >= 16 ) n >>= 1;
+ n += 3;
+
+ if( *slen < n )
+ {
+ *slen = n;
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+
+ p = s;
+ mpi_init( &T );
+
+ if( X->s == -1 )
+ *p++ = '-';
+
+ if( radix == 16 )
+ {
+ int c;
+ size_t i, j, k;
+
+ for( i = X->n, k = 0; i > 0; i-- )
+ {
+ for( j = ciL; j > 0; j-- )
+ {
+ c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+ if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+ continue;
+
+ p += sprintf( p, "%02X", c );
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_copy( &T, X ) );
+
+ if( T.s == -1 )
+ T.s = 1;
+
+ MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+ }
+
+ *p++ = '\0';
+ *slen = p - s;
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+ t_uint d;
+ size_t slen;
+ char *p;
+ char s[1024];
+
+ memset( s, 0, sizeof( s ) );
+ if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+ slen = strlen( s );
+ if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+ p = s + slen;
+ while( --p >= s )
+ if( mpi_get_digit( &d, radix, *p ) != 0 )
+ break;
+
+ return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+ int ret;
+ size_t n, slen, plen;
+ char s[2048];
+
+ n = sizeof( s );
+ memset( s, 0, n );
+ n -= 2;
+
+ MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
+
+ if( p == NULL ) p = "";
+
+ plen = strlen( p );
+ slen = strlen( s );
+ s[slen++] = '\r';
+ s[slen++] = '\n';
+
+ if( fout != NULL )
+ {
+ if( fwrite( p, 1, plen, fout ) != plen ||
+ fwrite( s, 1, slen, fout ) != slen )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+ }
+ else
+ printf( "%s%s", p, s );
+
+cleanup:
+
+ return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t i, j, n;
+
+ for( n = 0; n < buflen; n++ )
+ if( buf[n] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = buflen, j = 0; i > n; i--, j++ )
+ X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+ size_t i, j, n;
+
+ n = mpi_size( X );
+
+ if( buflen < n )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+ int ret;
+ size_t i, v0, t1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mpi_msb( X ) + count;
+
+ if( X->n * biL < i )
+ MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = X->n; i > v0; i-- )
+ X->p[i - 1] = X->p[i - v0 - 1];
+
+ for( ; i > 0; i-- )
+ X->p[i - 1] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( t1 > 0 )
+ {
+ for( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+ size_t i, v0, v1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( v1 > 0 )
+ {
+ for( i = X->n; i > 0; i-- )
+ {
+ r1 = X->p[i - 1] << (biL - v1);
+ X->p[i - 1] >>= v1;
+ X->p[i - 1] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( 1 );
+ if( j > i ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( X->s );
+ if( j > i ) return( -X->s );
+
+ if( X->s > 0 && Y->s < 0 ) return( 1 );
+ if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+ mpi Y;
+ t_uint p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ t_uint *o, *p, c;
+
+ if( X == B )
+ {
+ const mpi *T = A; A = X; B = T;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned additions.
+ */
+ X->s = 1;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, j ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ for( i = 0; i < j; i++, o++, p++ )
+ {
+ *p += c; c = ( *p < c );
+ *p += *o; c += ( *p < *o );
+ }
+
+ while( c != 0 )
+ {
+ if( i >= X->n )
+ {
+ MPI_CHK( mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+ size_t i;
+ t_uint c, z;
+
+ for( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; i++; d++;
+ }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ mpi TB;
+ int ret;
+ size_t n;
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+ mpi_init( &TB );
+
+ if( X == B )
+ {
+ MPI_CHK( mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned substractions.
+ */
+ X->s = 1;
+
+ ret = 0;
+
+ for( n = B->n; n > 0; n-- )
+ if( B->p[n - 1] != 0 )
+ break;
+
+ mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+ mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s < 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s > 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+ t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else
+ for( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mpi TA, TB;
+
+ mpi_init( &TA ); mpi_init( &TB );
+
+ if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+ if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+ for( i = A->n; i > 0; i-- )
+ if( A->p[i - 1] != 0 )
+ break;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, i + j ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i++; j > 0; j-- )
+ mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mpi_free( &TB ); mpi_free( &TA );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, n, t, k;
+ mpi X, Y, Z, T1, T2;
+
+ if( mpi_cmp_int( B, 0 ) == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+ mpi_init( &T1 ); mpi_init( &T2 );
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ {
+ if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+ if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+ return( 0 );
+ }
+
+ MPI_CHK( mpi_copy( &X, A ) );
+ MPI_CHK( mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+ MPI_CHK( mpi_lset( &Z, 0 ) );
+ MPI_CHK( mpi_grow( &T1, 2 ) );
+ MPI_CHK( mpi_grow( &T2, 3 ) );
+
+ k = mpi_msb( &Y ) % biL;
+ if( k < biL - 1 )
+ {
+ k = biL - 1 - k;
+ MPI_CHK( mpi_shift_l( &X, k ) );
+ MPI_CHK( mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ mpi_shift_l( &Y, biL * (n - t) );
+
+ while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ mpi_sub_mpi( &X, &X, &Y );
+ }
+ mpi_shift_r( &Y, biL * (n - t) );
+
+ for( i = n; i > t ; i-- )
+ {
+ if( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+#if defined(POLARSSL_HAVE_LONGLONG)
+ t_dbl r;
+
+ r = (t_dbl) X.p[i] << biL;
+ r |= (t_dbl) X.p[i - 1];
+ r /= Y.p[t];
+ if( r > ((t_dbl) 1 << biL) - 1)
+ r = ((t_dbl) 1 << biL) - 1;
+
+ Z.p[i - t - 1] = (t_uint) r;
+#else
+ /*
+ * __udiv_qrnnd_c, from gmp/longlong.h
+ */
+ t_uint q0, q1, r0, r1;
+ t_uint d0, d1, d, m;
+
+ d = Y.p[t];
+ d0 = ( d << biH ) >> biH;
+ d1 = ( d >> biH );
+
+ q1 = X.p[i] / d1;
+ r1 = X.p[i] - d1 * q1;
+ r1 <<= biH;
+ r1 |= ( X.p[i - 1] >> biH );
+
+ m = q1 * d0;
+ if( r1 < m )
+ {
+ q1--, r1 += d;
+ while( r1 >= d && r1 < m )
+ q1--, r1 += d;
+ }
+ r1 -= m;
+
+ q0 = r1 / d1;
+ r0 = r1 - d1 * q0;
+ r0 <<= biH;
+ r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+ m = q0 * d0;
+ if( r0 < m )
+ {
+ q0--, r0 += d;
+ while( r0 >= d && r0 < m )
+ q0--, r0 += d;
+ }
+ r0 -= m;
+
+ Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MPI_CHK( mpi_lset( &T1, 0 ) );
+ T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MPI_CHK( mpi_lset( &T2, 0 ) );
+ T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+ T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+ MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if( mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MPI_CHK( mpi_copy( &T1, &Y ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if( Q != NULL )
+ {
+ mpi_copy( Q, &Z );
+ Q->s = A->s * B->s;
+ }
+
+ if( R != NULL )
+ {
+ mpi_shift_r( &X, k );
+ mpi_copy( R, &X );
+
+ R->s = A->s;
+ if( mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+ mpi_free( &T1 ); mpi_free( &T2 );
+
+ return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ *
+ * Returns 0 if successful
+ * 1 if memory allocation failed
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+
+ if( mpi_cmp_int( B, 0 ) < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+ while( mpi_cmp_int( R, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+ while( mpi_cmp_mpi( R, B ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+ size_t i;
+ t_uint x, y, z;
+
+ if( b == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ if( b < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ /*
+ * handle trivial cases
+ */
+ if( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for( i = A->n, y = 0; i > 0; i-- )
+ {
+ x = A->p[i - 1];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ /*
+ * If A is negative, then the current y represents a negative value.
+ * Flipping it to the positive side.
+ */
+ if( A->s < 0 && y != 0 )
+ y = b - y;
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+ t_uint x, m0 = N->p[0];
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+ x *= ( 2 - ( m0 * x ) );
+
+ if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+{
+ size_t i, n, m;
+ t_uint u0, u1, *d;
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, (n + 1) * ciL );
+
+ if( mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+ t_uint z = 1;
+ mpi U;
+
+ U.n = U.s = z;
+ U.p = &z;
+
+ mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+ int ret;
+ size_t wbits, wsize, one = 1;
+ size_t i, j, nblimbs;
+ size_t bufsize, nbits;
+ t_uint ei, mm, state;
+ mpi RR, T, W[64];
+
+ if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mpi_init( &RR ); mpi_init( &T );
+ memset( W, 0, sizeof( W ) );
+
+ i = mpi_msb( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ j = N->n + 1;
+ MPI_CHK( mpi_grow( X, j ) );
+ MPI_CHK( mpi_grow( &W[1], j ) );
+ MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if( _RR == NULL || _RR->p == NULL )
+ {
+ MPI_CHK( mpi_lset( &RR, 1 ) );
+ MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+ if( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if( mpi_cmp_mpi( A, N ) >= 0 )
+ mpi_mod_mpi( &W[1], A, N );
+ else mpi_copy( &W[1], A );
+
+ mpi_montmul( &W[1], &RR, N, mm, &T );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MPI_CHK( mpi_copy( X, &RR ) );
+ mpi_montred( X, N, mm, &T );
+
+ if( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = one << (wsize - 1);
+
+ MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[j], &W[1] ) );
+
+ for( i = 0; i < wsize - 1; i++ )
+ mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for( i = j + 1; i < (one << wsize); i++ )
+ {
+ MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+ mpi_montmul( &W[i], &W[1], N, mm, &T );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while( 1 )
+ {
+ if( bufsize == 0 )
+ {
+ if( nblimbs-- == 0 )
+ break;
+
+ bufsize = sizeof( t_uint ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if( ei == 0 && state == 0 )
+ continue;
+
+ if( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ mpi_montmul( X, X, N, mm, &T );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= (ei << (wsize - nbits));
+
+ if( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for( i = 0; i < wsize; i++ )
+ mpi_montmul( X, X, N, mm, &T );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ mpi_montmul( X, &W[wbits], N, mm, &T );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for( i = 0; i < nbits; i++ )
+ {
+ mpi_montmul( X, X, N, mm, &T );
+
+ wbits <<= 1;
+
+ if( (wbits & (one << wsize)) != 0 )
+ mpi_montmul( X, &W[1], N, mm, &T );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ mpi_montred( X, N, mm, &T );
+
+cleanup:
+
+ for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+ mpi_free( &W[i] );
+
+ mpi_free( &W[1] ); mpi_free( &T );
+
+ if( _RR == NULL )
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t lz, lzt;
+ mpi TG, TA, TB;
+
+ mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
+
+ MPI_CHK( mpi_copy( &TA, A ) );
+ MPI_CHK( mpi_copy( &TB, B ) );
+
+ lz = mpi_lsb( &TA );
+ lzt = mpi_lsb( &TB );
+
+ if ( lzt < lz )
+ lz = lzt;
+
+ MPI_CHK( mpi_shift_r( &TA, lz ) );
+ MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+ TA.s = TB.s = 1;
+
+ while( mpi_cmp_int( &TA, 0 ) != 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+ MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+ if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+ MPI_CHK( mpi_shift_r( &TA, 1 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+ MPI_CHK( mpi_shift_r( &TB, 1 ) );
+ }
+ }
+
+ MPI_CHK( mpi_shift_l( &TB, lz ) );
+ MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+ mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
+
+ return( ret );
+}
+
+int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng )
+{
+ int ret;
+ size_t k;
+ unsigned char *p;
+
+ MPI_CHK( mpi_grow( X, size ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ p = (unsigned char *) X->p;
+ for( k = 0; k < X->n * ciL; k++ )
+ *p++ = (unsigned char) f_rng( p_rng );
+
+cleanup:
+ return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+ int ret;
+ mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+ if( mpi_cmp_int( N, 0 ) <= 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
+ mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
+ mpi_init( &V1 ); mpi_init( &V2 );
+
+ MPI_CHK( mpi_gcd( &G, A, N ) );
+
+ if( mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+ MPI_CHK( mpi_copy( &TU, &TA ) );
+ MPI_CHK( mpi_copy( &TB, N ) );
+ MPI_CHK( mpi_copy( &TV, N ) );
+
+ MPI_CHK( mpi_lset( &U1, 1 ) );
+ MPI_CHK( mpi_lset( &U2, 0 ) );
+ MPI_CHK( mpi_lset( &V1, 0 ) );
+ MPI_CHK( mpi_lset( &V2, 1 ) );
+
+ do
+ {
+ while( ( TU.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+ if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &U1, 1 ) );
+ MPI_CHK( mpi_shift_r( &U2, 1 ) );
+ }
+
+ while( ( TV.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+ if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &V1, 1 ) );
+ MPI_CHK( mpi_shift_r( &V2, 1 ) );
+ }
+
+ if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+ MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+ }
+ }
+ while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+ while( mpi_cmp_int( &V1, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+ while( mpi_cmp_mpi( &V1, N ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+ MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+ mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
+ mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
+ mpi_free( &V1 ); mpi_free( &V2 );
+
+ return( ret );
+}
+
+static const int small_prime[] =
+{
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269,
+ 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883,
+ 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, -103
+};
+
+/*
+ * Miller-Rabin primality test (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
+{
+ int ret, xs;
+ size_t i, j, n, s;
+ mpi W, R, T, A, RR;
+
+ if( mpi_cmp_int( X, 0 ) == 0 ||
+ mpi_cmp_int( X, 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ if( mpi_cmp_int( X, 2 ) == 0 )
+ return( 0 );
+
+ mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+ mpi_init( &RR );
+
+ xs = X->s; X->s = 1;
+
+ /*
+ * test trivial factors first
+ */
+ if( ( X->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ for( i = 0; small_prime[i] > 0; i++ )
+ {
+ t_uint r;
+
+ if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+ return( 0 );
+
+ MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+ if( r == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+ }
+
+ /*
+ * W = |X| - 1
+ * R = W >> lsb( W )
+ */
+ MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+ s = mpi_lsb( &W );
+ MPI_CHK( mpi_copy( &R, &W ) );
+ MPI_CHK( mpi_shift_r( &R, s ) );
+
+ i = mpi_msb( X );
+ /*
+ * HAC, table 4.4
+ */
+ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
+ ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
+ ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * pick a random A, 1 < A < |X| - 1
+ */
+ mpi_fill_random( &A, X->n, f_rng, p_rng );
+
+ if( mpi_cmp_mpi( &A, &W ) >= 0 )
+ {
+ j = mpi_msb( &A ) - mpi_msb( &W );
+ MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+ }
+ A.p[0] |= 3;
+
+ /*
+ * A = A^R mod |X|
+ */
+ MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+ if( mpi_cmp_mpi( &A, &W ) == 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ continue;
+
+ j = 1;
+ while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+ {
+ /*
+ * A = A * A mod |X|
+ */
+ MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+ MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
+
+ if( mpi_cmp_int( &A, 1 ) == 0 )
+ break;
+
+ j++;
+ }
+
+ /*
+ * not prime if A != |X| - 1 or A == 1
+ */
+ if( mpi_cmp_mpi( &A, &W ) != 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ break;
+ }
+ }
+
+cleanup:
+
+ X->s = xs;
+
+ mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *), void *p_rng )
+{
+ int ret;
+ size_t k, n;
+ mpi Y;
+
+ if( nbits < 3 || nbits > 4096 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &Y );
+
+ n = BITS_TO_LIMBS( nbits );
+
+ mpi_fill_random( X, n, f_rng, p_rng );
+
+ k = mpi_msb( X );
+ if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+ if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+ X->p[0] |= 3;
+
+ if( dh_flag == 0 )
+ {
+ while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+ {
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+ while( 1 )
+ {
+ if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+ {
+ if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+ break;
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+ }
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+ }
+ }
+
+cleanup:
+
+ mpi_free( &Y );
+
+ return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT 3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+ { 693, 609, 21 },
+ { 1764, 868, 28 },
+ { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+ int ret, i;
+ mpi A, E, N, X, Y, U, V;
+
+ mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
+ mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
+
+ MPI_CHK( mpi_read_string( &A, 16,
+ "EFE021C2645FD1DC586E69184AF4A31E" \
+ "D5F53E93B5F123FA41680867BA110131" \
+ "944FE7952E2517337780CB0DB80E61AA" \
+ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+ MPI_CHK( mpi_read_string( &E, 16,
+ "B2E7EFD37075B9F03FF989C7C5051C20" \
+ "34D2A323810251127E7BF8625A4F49A5" \
+ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+ "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+ MPI_CHK( mpi_read_string( &N, 16,
+ "0066A198186C18C10B2F5ED9B522752A" \
+ "9830B69916E535C8F047518A889A43A5" \
+ "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+ MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "602AB7ECA597A3D6B56FF9829A5E8B85" \
+ "9E857EA95A03512E2BAE7391688D264A" \
+ "A5663B0341DB9CCFD2C4C5F421FEC814" \
+ "8001B72E848A38CAE1C65F78E56ABDEF" \
+ "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+ "ECF677152EF804370C1A305CAF3B5BF1" \
+ "30879B56C61DE584A0F53A2447A51E" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #1 (mul_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "256567336059E52CAE22925474705F39A94" ) );
+
+ MPI_CHK( mpi_read_string( &V, 16,
+ "6613F26162223DF488E9CD48CC132C7A" \
+ "0AC93C701B001B092E4E5B9F73BCD27B" \
+ "9EE50D0657C77F374E903CDFA4C642" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #2 (div_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 ||
+ mpi_cmp_mpi( &Y, &V ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "36E139AEA55215609D2816998ED020BB" \
+ "BD96C37890F65171D948E9BC7CBAA4D9" \
+ "325D24D6A3C12710F10A09FA08AB87" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #3 (exp_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+#if defined(POLARSSL_GENPRIME)
+ MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+ "C3DBA76456363A10869622EAC2DD84EC" \
+ "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #4 (inv_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+#endif
+
+ if( verbose != 0 )
+ printf( " MPI test #5 (simple gcd): " );
+
+ for ( i = 0; i < GCD_PAIR_COUNT; i++)
+ {
+ MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+ MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+ MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+ if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed at %d\n", i );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+cleanup:
+
+ if( ret != 0 && verbose != 0 )
+ printf( "Unexpected error, return code = %08X\n", ret );
+
+ mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
+ mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( ret );
+}
+
+#endif
+
+#endif
diff --git a/protocols/Tlen/src/crypto/padlock.c b/protocols/Tlen/src/crypto/padlock.c
new file mode 100644
index 0000000000..2e2e4775ff
--- /dev/null
+++ b/protocols/Tlen/src/crypto/padlock.c
@@ -0,0 +1,162 @@
+/*
+ * VIA PadLock support functions
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This implementation is based on the VIA PadLock Programming Guide:
+ *
+ * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ * programming_guide.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PADLOCK_C)
+
+#include "polarssl/padlock.h"
+
+#if defined(POLARSSL_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int padlock_supports( int feature )
+{
+ static int flags = -1;
+ int ebx, edx;
+
+ if( flags == -1 )
+ {
+ asm( "movl %%ebx, %0 \n" \
+ "movl $0xC0000000, %%eax \n" \
+ "cpuid \n" \
+ "cmpl $0xC0000001, %%eax \n" \
+ "movl $0, %%edx \n" \
+ "jb unsupported \n" \
+ "movl $0xC0000001, %%eax \n" \
+ "cpuid \n" \
+ "unsupported: \n" \
+ "movl %%edx, %1 \n" \
+ "movl %2, %%ebx \n"
+ : "=m" (ebx), "=m" (edx)
+ : "m" (ebx)
+ : "eax", "ecx", "edx" );
+
+ flags = edx;
+ }
+
+ return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int ebx;
+ unsigned long *rk;
+ unsigned long *blk;
+ unsigned long *ctrl;
+ unsigned char buf[256];
+
+ rk = ctx->rk;
+ blk = PADLOCK_ALIGN16( buf );
+ memcpy( blk, input, 16 );
+
+ ctrl = blk + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+ asm( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl $1, %%ecx \n" \
+ "movl %2, %%edx \n" \
+ "movl %3, %%ebx \n" \
+ "movl %4, %%esi \n" \
+ "movl %4, %%edi \n" \
+ ".byte 0xf3,0x0f,0xa7,0xc8\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+ : "ecx", "edx", "esi", "edi" );
+
+ memcpy( output, blk, 16 );
+
+ return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ebx;
+ size_t count;
+ unsigned long *rk;
+ unsigned long *iw;
+ unsigned long *ctrl;
+ unsigned char buf[256];
+
+ if( ( (long) input & 15 ) != 0 ||
+ ( (long) output & 15 ) != 0 )
+ return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
+
+ rk = ctx->rk;
+ iw = PADLOCK_ALIGN16( buf );
+ memcpy( iw, iv, 16 );
+
+ ctrl = iw + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
+
+ count = (length + 15) >> 4;
+
+ asm( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl %2, %%ecx \n" \
+ "movl %3, %%edx \n" \
+ "movl %4, %%ebx \n" \
+ "movl %5, %%esi \n" \
+ "movl %6, %%edi \n" \
+ "movl %7, %%eax \n" \
+ ".byte 0xf3,0x0f,0xa7,0xd0\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (count), "m" (ctrl),
+ "m" (rk), "m" (input), "m" (output), "m" (iw)
+ : "eax", "ecx", "edx", "esi", "edi" );
+
+ memcpy( iv, iw, 16 );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/protocols/Tlen/src/crypto/polarssl/aes.h b/protocols/Tlen/src/crypto/polarssl/aes.h
new file mode 100644
index 0000000000..efc13daf5b
--- /dev/null
+++ b/protocols/Tlen/src/crypto/polarssl/aes.h
@@ -0,0 +1,167 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AES_H
+#define POLARSSL_AES_H
+
+#include <string.h>
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
+#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
+
+/**
+ * \brief AES context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ unsigned long *rk; /*!< AES round keys */
+ unsigned long buf[68]; /*!< unaligned data */
+}
+aes_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief AES key schedule (encryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES key schedule (decryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key decryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES-ECB block encryption/decryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief AES-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief AES-CFB128 buffer encryption/decryption.
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/*
+ * \brief AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/protocols/Tlen/src/crypto/polarssl/bignum.h b/protocols/Tlen/src/crypto/polarssl/bignum.h
new file mode 100644
index 0000000000..7938406708
--- /dev/null
+++ b/protocols/Tlen/src/crypto/polarssl/bignum.h
@@ -0,0 +1,587 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include <stdio.h>
+#include <string.h>
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The output buffer is too small to write too. */
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
+
+#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define POLARSSL_MPI_MAX_LIMBS 10000
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef signed char t_sint;
+typedef unsigned char t_uint;
+typedef unsigned short t_udbl;
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef signed short t_sint;
+typedef unsigned short t_uint;
+typedef unsigned long t_udbl;
+#else
+ typedef signed long t_sint;
+ typedef unsigned long t_uint;
+ #if defined(_MSC_VER) && defined(_M_IX86)
+ typedef unsigned __int64 t_udbl;
+ #else
+ #if defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__)
+ typedef unsigned int t_udbl __attribute__((mode(TI)));
+ #else
+ #if defined(POLARSSL_HAVE_LONGLONG)
+ typedef unsigned long long t_udbl;
+ #endif
+ #endif
+ #endif
+#endif
+#endif
+
+/**
+ * \brief MPI structure
+ */
+typedef struct
+{
+ int s; /*!< integer sign */
+ size_t n; /*!< total # of limbs */
+ t_uint *p; /*!< pointer to limbs */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize one MPI
+ *
+ * \param X One MPI to initialize.
+ */
+void mpi_init( mpi *X );
+
+/**
+ * \brief Unallocate one MPI
+ *
+ * \param X One MPI to unallocate.
+ */
+void mpi_free( mpi *X );
+
+/**
+ * \brief Enlarge to the specified number of limbs
+ *
+ * \param X MPI to grow
+ * \param nblimbs The target number of limbs
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_grow( mpi *X, size_t nblimbs );
+
+/**
+ * \brief Copy the contents of Y into X
+ *
+ * \param X Destination MPI
+ * \param Y Source MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief Swap the contents of X and Y
+ *
+ * \param X First MPI value
+ * \param Y Second MPI value
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief Set value from integer
+ *
+ * \param X MPI to set
+ * \param z Value to use
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_lset( mpi *X, t_sint z );
+
+/*
+ * \brief Get a specific bit from X
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ *
+ * \return Either a 0 or a 1
+ */
+int mpi_get_bit( mpi *X, size_t pos );
+
+/*
+ * \brief Set a bit of X to a specific value of 0 or 1
+ *
+ * \note Will grow X if necessary to set a bit to 1 in a not yet
+ * existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ * \param val The value to set the bit to (0 or 1)
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief Return the number of least significant bits
+ *
+ * \param X MPI to use
+ */
+size_t mpi_lsb( const mpi *X );
+
+/**
+ * \brief Return the number of most significant bits
+ *
+ * \param X MPI to use
+ */
+size_t mpi_msb( const mpi *X );
+
+/**
+ * \brief Return the total size in bytes
+ *
+ * \param X MPI to use
+ */
+size_t mpi_size( const mpi *X );
+
+/**
+ * \brief Import from an ASCII string
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param s Null-terminated string buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief Export into an ASCII string
+ *
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param s String buffer
+ * \param slen String buffer size
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code.
+ * *slen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *slen = 0 to obtain the
+ * minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
+
+/**
+ * \brief Read X from an opened file
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param fin Input file handle
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p Prefix, can be NULL
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param fout Output file handle (can be NULL)
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note Set fout == NULL to print X on the console.
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+
+/**
+ * \brief Import X from unsigned binary data, big endian
+ *
+ * \param X Destination MPI
+ * \param buf Input buffer
+ * \param buflen Input buffer size
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian
+ *
+ * \param X Source MPI
+ * \param buf Output buffer
+ * \param buflen Output buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Left-shift: X <<= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, size_t count );
+
+/**
+ * \brief Right-shift: X >>= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, size_t count );
+
+/**
+ * \brief Compare unsigned values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if |X| is greater than |Y|,
+ * -1 if |X| is lesser than |Y| or
+ * 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if X is greater than Y,
+ * -1 if X is lesser than Y or
+ * 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param z The integer value to compare to
+ *
+ * \return 1 if X is greater than z,
+ * -1 if X is lesser than z or
+ * 0 if X is equal to z
+ */
+int mpi_cmp_int( const mpi *X, t_sint z );
+
+/**
+ * \brief Unsigned addition: X = |A| + |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Unsigned substraction: X = |A| - |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed substraction: X = A - B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to add
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Signed substraction: X = A - b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to subtract
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Baseline multiplication: X = A * B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Baseline multiplication: X = A * b
+ * Note: b is an unsigned integer type, thus
+ * Negative values of b are ignored.
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to multiply with
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Division by mpi: A = Q * B + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Division by int: A = Q * b + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
+
+/**
+ * \brief Modulo: R = A mod B
+ *
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modulo: r = A mod b
+ *
+ * \param r Destination t_uint
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
+
+/**
+ * \brief Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param E Exponent MPI
+ * \param N Modular MPI
+ * \param _RR Speed-up MPI used for recalculations
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ *
+ * \note _RR is used to avoid re-computing R*R mod N across
+ * multiple calls, which speeds up things a bit. It can
+ * be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
+
+/**
+ * \brief Fill an MPI X with size bytes of random
+ *
+ * \param X Destination MPI
+ * \param size Size in bytes
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modular inverse: X = A^-1 mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param N Right-hand MPI
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+ POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
+
+/**
+ * \brief Miller-Rabin primality test
+ *
+ * \param X MPI to check
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief Prime number generation
+ *
+ * \param X Destination MPI
+ * \param nbits Required size of X in bits ( 3 <= nbits <= 4096 )
+ * \param dh_flag If 1, then (X-1)/2 will be prime too
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/protocols/Tlen/src/crypto/polarssl/bn_mul.h b/protocols/Tlen/src/crypto/polarssl/bn_mul.h
new file mode 100644
index 0000000000..59a32857cb
--- /dev/null
+++ b/protocols/Tlen/src/crypto/polarssl/bn_mul.h
@@ -0,0 +1,738 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * Multiply source vector [s] with b, add result
+ * to destination vector [d] and set carry c.
+ *
+ * Currently supports:
+ *
+ * . IA-32 (386+) . AMD64 / EM64T
+ * . IA-32 (SSE2) . Motorola 68000
+ * . PowerPC, 32-bit . MicroBlaze
+ * . PowerPC, 64-bit . TriCore
+ * . SPARC v8 . ARM v3+
+ * . Alpha . MIPS32
+ * . C, longlong . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT \
+ asm( " \
+ movl %%ebx, %0; \
+ movl %5, %%esi; \
+ movl %6, %%edi; \
+ movl %7, %%ecx; \
+ movl %8, %%ebx; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ lodsl; \
+ mull %%ebx; \
+ addl %%ecx, %%eax; \
+ adcl $0, %%edx; \
+ addl (%%edi), %%eax; \
+ adcl $0, %%edx; \
+ movl %%edx, %%ecx; \
+ stosl; \
+ "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT \
+ " \
+ movd %%ecx, %%mm1; \
+ movd %%ebx, %%mm0; \
+ movd (%%edi), %%mm3; \
+ paddq %%mm3, %%mm1; \
+ movd (%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ movd 4(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ movd 8(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd 12(%%esi), %%mm7; \
+ pmuludq %%mm0, %%mm7; \
+ paddq %%mm2, %%mm1; \
+ movd 4(%%edi), %%mm3; \
+ paddq %%mm4, %%mm3; \
+ movd 8(%%edi), %%mm5; \
+ paddq %%mm6, %%mm5; \
+ movd 12(%%edi), %%mm4; \
+ paddq %%mm4, %%mm7; \
+ movd %%mm1, (%%edi); \
+ movd 16(%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ psrlq $32, %%mm1; \
+ movd 20(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ paddq %%mm3, %%mm1; \
+ movd 24(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd %%mm1, 4(%%edi); \
+ psrlq $32, %%mm1; \
+ movd 28(%%esi), %%mm3; \
+ pmuludq %%mm0, %%mm3; \
+ paddq %%mm5, %%mm1; \
+ movd 16(%%edi), %%mm5; \
+ paddq %%mm5, %%mm2; \
+ movd %%mm1, 8(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm7, %%mm1; \
+ movd 20(%%edi), %%mm5; \
+ paddq %%mm5, %%mm4; \
+ movd %%mm1, 12(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm2, %%mm1; \
+ movd 24(%%edi), %%mm5; \
+ paddq %%mm5, %%mm6; \
+ movd %%mm1, 16(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm4, %%mm1; \
+ movd 28(%%edi), %%mm5; \
+ paddq %%mm5, %%mm3; \
+ movd %%mm1, 20(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm6, %%mm1; \
+ movd %%mm1, 24(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm3, %%mm1; \
+ movd %%mm1, 28(%%edi); \
+ addl $32, %%edi; \
+ addl $32, %%esi; \
+ psrlq $32, %%mm1; \
+ movd %%mm1, %%ecx; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ emms; \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+
+#else
+
+#define MULADDC_STOP \
+ " \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT \
+ asm( "movq %0, %%rsi " :: "m" (s)); \
+ asm( "movq %0, %%rdi " :: "m" (d)); \
+ asm( "movq %0, %%rcx " :: "m" (c)); \
+ asm( "movq %0, %%rbx " :: "m" (b)); \
+ asm( "xorq %r8, %r8 " );
+
+#define MULADDC_CORE \
+ asm( "movq (%rsi),%rax " ); \
+ asm( "mulq %rbx " ); \
+ asm( "addq $8, %rsi " ); \
+ asm( "addq %rcx, %rax " ); \
+ asm( "movq %r8, %rcx " ); \
+ asm( "adcq $0, %rdx " ); \
+ asm( "nop " ); \
+ asm( "addq %rax, (%rdi) " ); \
+ asm( "adcq %rdx, %rcx " ); \
+ asm( "addq $8, %rdi " );
+
+#define MULADDC_STOP \
+ asm( "movq %%rcx, %0 " : "=m" (c)); \
+ asm( "movq %%rdi, %0 " : "=m" (d)); \
+ asm( "movq %%rsi, %0 " : "=m" (s) :: \
+ "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT \
+ asm( "movl %0, %%a2 " :: "m" (s)); \
+ asm( "movl %0, %%a3 " :: "m" (d)); \
+ asm( "movl %0, %%d3 " :: "m" (c)); \
+ asm( "movl %0, %%d2 " :: "m" (b)); \
+ asm( "moveq #0, %d0 " );
+
+#define MULADDC_CORE \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "moveq #0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d4, %d3 " );
+
+#define MULADDC_STOP \
+ asm( "movl %%d3, %0 " : "=m" (c)); \
+ asm( "movl %%a3, %0 " : "=m" (d)); \
+ asm( "movl %%a2, %0 " : "=m" (s) :: \
+ "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d0, %d3 " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "ld r3, %0 " :: "m" (s)); \
+ asm( "ld r4, %0 " :: "m" (d)); \
+ asm( "ld r5, %0 " :: "m" (c)); \
+ asm( "ld r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -8 " ); \
+ asm( "addi r4, r4, -8 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu r7, 8(r3) " ); \
+ asm( "mulld r8, r7, r6 " ); \
+ asm( "mulhdu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "ld r7, 8(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stdu r8, 8(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 8 " ); \
+ asm( "addi r3, r3, 8 " ); \
+ asm( "std r5, %0 " : "=m" (c)); \
+ asm( "std r4, %0 " : "=m" (d)); \
+ asm( "std r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "ld %%r3, %0 " :: "m" (s)); \
+ asm( "ld %%r4, %0 " :: "m" (d)); \
+ asm( "ld %%r5, %0 " :: "m" (c)); \
+ asm( "ld %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -8 " ); \
+ asm( "addi %r4, %r4, -8 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu %r7, 8(%r3) " ); \
+ asm( "mulld %r8, %r7, %r6 " ); \
+ asm( "mulhdu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "ld %r7, 8(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stdu %r8, 8(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 8 " ); \
+ asm( "addi %r3, %r3, 8 " ); \
+ asm( "std %%r5, %0 " : "=m" (c)); \
+ asm( "std %%r4, %0 " : "=m" (d)); \
+ asm( "std %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "lwz r3, %0 " :: "m" (s)); \
+ asm( "lwz r4, %0 " :: "m" (d)); \
+ asm( "lwz r5, %0 " :: "m" (c)); \
+ asm( "lwz r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -4 " ); \
+ asm( "addi r4, r4, -4 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu r7, 4(r3) " ); \
+ asm( "mullw r8, r7, r6 " ); \
+ asm( "mulhwu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "lwz r7, 4(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stwu r8, 4(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 4 " ); \
+ asm( "addi r3, r3, 4 " ); \
+ asm( "stw r5, %0 " : "=m" (c)); \
+ asm( "stw r4, %0 " : "=m" (d)); \
+ asm( "stw r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "lwz %%r3, %0 " :: "m" (s)); \
+ asm( "lwz %%r4, %0 " :: "m" (d)); \
+ asm( "lwz %%r5, %0 " :: "m" (c)); \
+ asm( "lwz %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -4 " ); \
+ asm( "addi %r4, %r4, -4 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu %r7, 4(%r3) " ); \
+ asm( "mullw %r8, %r7, %r6 " ); \
+ asm( "mulhwu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "lwz %r7, 4(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stwu %r8, 4(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 4 " ); \
+ asm( "addi %r3, %r3, 4 " ); \
+ asm( "stw %%r5, %0 " : "=m" (c)); \
+ asm( "stw %%r4, %0 " : "=m" (d)); \
+ asm( "stw %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__)
+
+#define MULADDC_INIT \
+ asm( "ld %0, %%o0 " :: "m" (s)); \
+ asm( "ld %0, %%o1 " :: "m" (d)); \
+ asm( "ld %0, %%o2 " :: "m" (c)); \
+ asm( "ld %0, %%o3 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ld [%o0], %o4 " ); \
+ asm( "inc 4, %o0 " ); \
+ asm( "ld [%o1], %o5 " ); \
+ asm( "umul %o3, %o4, %o4 " ); \
+ asm( "addcc %o4, %o2, %o4 " ); \
+ asm( "rd %y, %g1 " ); \
+ asm( "addx %g1, 0, %g1 " ); \
+ asm( "addcc %o4, %o5, %o4 " ); \
+ asm( "st %o4, [%o1] " ); \
+ asm( "addx %g1, 0, %o2 " ); \
+ asm( "inc 4, %o1 " );
+
+#define MULADDC_STOP \
+ asm( "st %%o2, %0 " : "=m" (c)); \
+ asm( "st %%o1, %0 " : "=m" (d)); \
+ asm( "st %%o0, %0 " : "=m" (s) :: \
+ "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT \
+ asm( "lwi r3, %0 " :: "m" (s)); \
+ asm( "lwi r4, %0 " :: "m" (d)); \
+ asm( "lwi r5, %0 " :: "m" (c)); \
+ asm( "lwi r6, %0 " :: "m" (b)); \
+ asm( "andi r7, r6, 0xffff" ); \
+ asm( "bsrli r6, r6, 16 " );
+
+#define MULADDC_CORE \
+ asm( "lhui r8, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "lhui r9, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "mul r10, r9, r6 " ); \
+ asm( "mul r11, r8, r7 " ); \
+ asm( "mul r12, r9, r7 " ); \
+ asm( "mul r13, r8, r6 " ); \
+ asm( "bsrli r8, r10, 16 " ); \
+ asm( "bsrli r9, r11, 16 " ); \
+ asm( "add r13, r13, r8 " ); \
+ asm( "add r13, r13, r9 " ); \
+ asm( "bslli r10, r10, 16 " ); \
+ asm( "bslli r11, r11, 16 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r11 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "lwi r10, r4, 0 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r5 " ); \
+ asm( "addc r5, r13, r0 " ); \
+ asm( "swi r12, r4, 0 " ); \
+ asm( "addi r4, r4, 4 " );
+
+#define MULADDC_STOP \
+ asm( "swi r5, %0 " : "=m" (c)); \
+ asm( "swi r4, %0 " : "=m" (d)); \
+ asm( "swi r3, %0 " : "=m" (s) :: \
+ "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
+ "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT \
+ asm( "ld.a %%a2, %0 " :: "m" (s)); \
+ asm( "ld.a %%a3, %0 " :: "m" (d)); \
+ asm( "ld.w %%d4, %0 " :: "m" (c)); \
+ asm( "ld.w %%d1, %0 " :: "m" (b)); \
+ asm( "xor %d5, %d5 " );
+
+#define MULADDC_CORE \
+ asm( "ld.w %d0, [%a2+] " ); \
+ asm( "madd.u %e2, %e4, %d0, %d1 " ); \
+ asm( "ld.w %d0, [%a3] " ); \
+ asm( "addx %d2, %d2, %d0 " ); \
+ asm( "addc %d3, %d3, 0 " ); \
+ asm( "mov %d4, %d3 " ); \
+ asm( "st.w [%a3+], %d2 " );
+
+#define MULADDC_STOP \
+ asm( "st.w %0, %%d4 " : "=m" (c)); \
+ asm( "st.a %0, %%a3 " : "=m" (d)); \
+ asm( "st.a %0, %%a2 " : "=m" (s) :: \
+ "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#define MULADDC_INIT \
+ asm( "ldr r0, %0 " :: "m" (s)); \
+ asm( "ldr r1, %0 " :: "m" (d)); \
+ asm( "ldr r2, %0 " :: "m" (c)); \
+ asm( "ldr r3, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldr r4, [r0], #4 " ); \
+ asm( "mov r5, #0 " ); \
+ asm( "ldr r6, [r1] " ); \
+ asm( "umlal r2, r5, r3, r4 " ); \
+ asm( "adds r7, r6, r2 " ); \
+ asm( "adc r2, r5, #0 " ); \
+ asm( "str r7, [r1], #4 " );
+
+#define MULADDC_STOP \
+ asm( "str r2, %0 " : "=m" (c)); \
+ asm( "str r1, %0 " : "=m" (d)); \
+ asm( "str r0, %0 " : "=m" (s) :: \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT \
+ asm( "ldq $1, %0 " :: "m" (s)); \
+ asm( "ldq $2, %0 " :: "m" (d)); \
+ asm( "ldq $3, %0 " :: "m" (c)); \
+ asm( "ldq $4, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldq $6, 0($1) " ); \
+ asm( "addq $1, 8, $1 " ); \
+ asm( "mulq $6, $4, $7 " ); \
+ asm( "umulh $6, $4, $6 " ); \
+ asm( "addq $7, $3, $7 " ); \
+ asm( "cmpult $7, $3, $3 " ); \
+ asm( "ldq $5, 0($2) " ); \
+ asm( "addq $7, $5, $7 " ); \
+ asm( "cmpult $7, $5, $5 " ); \
+ asm( "stq $7, 0($2) " ); \
+ asm( "addq $2, 8, $2 " ); \
+ asm( "addq $6, $3, $3 " ); \
+ asm( "addq $5, $3, $3 " );
+
+#define MULADDC_STOP \
+ asm( "stq $3, %0 " : "=m" (c)); \
+ asm( "stq $2, %0 " : "=m" (d)); \
+ asm( "stq $1, %0 " : "=m" (s) :: \
+ "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT \
+ asm( "lw $10, %0 " :: "m" (s)); \
+ asm( "lw $11, %0 " :: "m" (d)); \
+ asm( "lw $12, %0 " :: "m" (c)); \
+ asm( "lw $13, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "lw $14, 0($10) " ); \
+ asm( "multu $13, $14 " ); \
+ asm( "addi $10, $10, 4 " ); \
+ asm( "mflo $14 " ); \
+ asm( "mfhi $9 " ); \
+ asm( "addu $14, $12, $14 " ); \
+ asm( "lw $15, 0($11) " ); \
+ asm( "sltu $12, $14, $12 " ); \
+ asm( "addu $15, $14, $15 " ); \
+ asm( "sltu $14, $15, $14 " ); \
+ asm( "addu $12, $12, $9 " ); \
+ asm( "sw $15, 0($11) " ); \
+ asm( "addu $12, $12, $14 " ); \
+ asm( "addi $11, $11, 4 " );
+
+#define MULADDC_STOP \
+ asm( "sw $12, %0 " : "=m" (c)); \
+ asm( "sw $11, %0 " : "=m" (d)); \
+ asm( "sw $10, %0 " : "=m" (s) :: \
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT \
+ __asm mov esi, s \
+ __asm mov edi, d \
+ __asm mov ecx, c \
+ __asm mov ebx, b
+
+#define MULADDC_CORE \
+ __asm lodsd \
+ __asm mul ebx \
+ __asm add eax, ecx \
+ __asm adc edx, 0 \
+ __asm add eax, [edi] \
+ __asm adc edx, 0 \
+ __asm mov ecx, edx \
+ __asm stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x1F \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x16 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
+ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
+ EMIT 0x0F EMIT 0x7E EMIT 0x0F \
+ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
+ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
+ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x7E EMIT 0xC9
+
+#define MULADDC_STOP \
+ EMIT 0x0F EMIT 0x77 \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#else
+
+#define MULADDC_STOP \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_LONGLONG)
+
+#define MULADDC_INIT \
+{ \
+ t_udbl r; \
+ t_uint r0, r1;
+
+#define MULADDC_CORE \
+ r = *(s++) * (t_udbl) b; \
+ r0 = r; \
+ r1 = r >> biL; \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#else
+#define MULADDC_INIT \
+{ \
+ t_uint s0, s1, b0, b1; \
+ t_uint r0, r1, rx, ry; \
+ b0 = ( b << biH ) >> biH; \
+ b1 = ( b >> biH );
+
+#define MULADDC_CORE \
+ s0 = ( *s << biH ) >> biH; \
+ s1 = ( *s >> biH ); s++; \
+ rx = s0 * b1; r0 = s0 * b0; \
+ ry = s1 * b0; r1 = s1 * b1; \
+ r1 += ( rx >> biH ); \
+ r1 += ( ry >> biH ); \
+ rx <<= biH; ry <<= biH; \
+ r0 += rx; r1 += (r0 < rx); \
+ r0 += ry; r1 += (r0 < ry); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#endif /* C (generic) */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/protocols/Tlen/src/crypto/polarssl/config.h b/protocols/Tlen/src/crypto/polarssl/config.h
new file mode 100644
index 0000000000..61500a75ee
--- /dev/null
+++ b/protocols/Tlen/src/crypto/polarssl/config.h
@@ -0,0 +1,625 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+#define POLARSSL_HAVE_INT8
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+#define POLARSSL_HAVE_INT16
+ */
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the use of long long.
+ *
+ * Uncomment if the compiler supports long long.
+#define POLARSSL_HAVE_LONGLONG
+ */
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm()
+ *
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/timing.c
+ * library/padlock.c
+ * include/polarssl/bn_mul.h
+ *
+ */
+#define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPI supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_DEBUG_MSG
+ *
+ * Requires: POLARSSL_DEBUG_C
+ *
+ * Enable all SSL/TLS debugging messages.
+ */
+#define POLARSSL_DEBUG_MSG
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * Enable the RSA prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+#define POLARSSL_FS_IO
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+#define POLARSSL_RSA_NO_CRT
+ */
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ *
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/ssl_tls.c
+ * library/pem.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_AES_128_SHA
+ * SSL_RSA_AES_256_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_RC4_128_MD5
+ * SSL_RSA_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multo-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/rsa.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enabled the following cipher suites:
+ * SSL_RSA_CAMELLIA_128_SHA
+ * SSL_RSA_CAMELLIA_256_SHA
+ * SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module: library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ * Caller:
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module: library/debug.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_DES_168_SHA
+ * SSL_EDH_RSA_DES_168_SHA
+ */
+#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle key exchange.
+ *
+ * Module: library/dhm.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_EDH_RSA_DES_168_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ * SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables err_strerror().
+ */
+#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Module: library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * This module enables the HAVEGE random number generator.
+ */
+#define POLARSSL_HAVEGE_C
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm
+ *
+ * Module: library/md2.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm
+ *
+ * Module: library/md4.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/**
+ * \def POLARSSL_MD5_C
+ *
+ * Enable the MD5 hash algorithm
+ *
+ * Module: library/md5.c
+ * Caller: library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module: library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/**
+ * \def POLARSSL_PEM_C
+ *
+ * Enable PEM decoding
+ *
+ * Module: library/pem.c
+ * Caller: library/x509parse.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding PEM files.
+ */
+#define POLARSSL_PEM_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable support for PKCS#11 smartcard support.
+ *
+ * Module: library/ssl_srv.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+#define POLARSSL_PKCS11_C
+ */
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509.c
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA2_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha2.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/**
+ * \def POLARSSL_SHA4_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha4.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module: library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/*
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module: library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module: library/ssl_tls.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module: library/x509parse.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+/* \} name */
+
+#endif /* config.h */
diff --git a/protocols/Tlen/src/crypto/polarssl/padlock.h b/protocols/Tlen/src/crypto/polarssl/padlock.h
new file mode 100644
index 0000000000..08fbe825c9
--- /dev/null
+++ b/protocols/Tlen/src/crypto/polarssl/padlock.h
@@ -0,0 +1,100 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PADLOCK_H
+#define POLARSSL_PADLOCK_H
+
+#include "polarssl/aes.h"
+
+#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+#ifndef POLARSSL_HAVE_X86
+#define POLARSSL_HAVE_X86
+#endif
+
+#define PADLOCK_RNG 0x000C
+#define PADLOCK_ACE 0x00C0
+#define PADLOCK_PHE 0x0C00
+#define PADLOCK_PMM 0x3000
+
+#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PadLock detection routine
+ *
+ * \param The feature to detect
+ *
+ * \return 1 if CPU has support for the feature, 0 otherwise
+ */
+int padlock_supports( int feature );
+
+/**
+ * \brief PadLock AES-ECB block en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief PadLock AES-CBC buffer en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86 */
+
+#endif /* padlock.h */
diff --git a/protocols/Tlen/src/jabber.h b/protocols/Tlen/src/jabber.h
new file mode 100644
index 0000000000..450b84c1f8
--- /dev/null
+++ b/protocols/Tlen/src/jabber.h
@@ -0,0 +1,507 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _JABBER_H_
+#define _JABBER_H_
+
+#define MIRANDA_VER 0x0A00
+
+#undef _WIN32_WINNT
+#undef _WIN32_IE
+#define _WIN32_WINNT 0x0501
+#define _WIN32_IE 0x0501
+
+#define __try
+#define __except(x) if (0)
+#define __finally
+
+#define _try __try
+#define _except __except
+#define _finally __finally
+
+
+#include "m_stdhdr.h"
+
+
+#ifdef _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+#define ENABLE_LOGGING
+
+/*******************************************************************
+ * Global compilation flags
+ *******************************************************************/
+
+/*******************************************************************
+ * Global header files
+ *******************************************************************/
+
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <limits.h>
+#include <win2k.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_netlib.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_protoint.h>
+#include <m_contacts.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_userinfo.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_utils.h>
+#include <m_message.h>
+#include <m_skin.h>
+#include <m_popup.h>
+#include <m_avatars.h>
+
+#include "jabber_xml.h"
+#include "crypto/polarssl/aes.h"
+#include "crypto/polarssl/bignum.h"
+
+/*******************************************************************
+ * Global constants
+ *******************************************************************/
+#define TLEN_DEFAULT_PORT 443
+#define JABBER_IQID "mim_"
+#define TLEN_REGISTER "http://reg.tlen.pl/"
+#define TLEN_MAX_SEARCH_RESULTS_PER_PAGE 20
+
+// User-defined message
+#define WM_TLEN_REFRESH (WM_USER + 100)
+// Error code
+#define JABBER_ERROR_REDIRECT 302
+#define JABBER_ERROR_BAD_REQUEST 400
+#define JABBER_ERROR_UNAUTHORIZED 401
+#define JABBER_ERROR_PAYMENT_REQUIRED 402
+#define JABBER_ERROR_FORBIDDEN 403
+#define JABBER_ERROR_NOT_FOUND 404
+#define JABBER_ERROR_NOT_ALLOWED 405
+#define JABBER_ERROR_NOT_ACCEPTABLE 406
+#define JABBER_ERROR_REGISTRATION_REQUIRED 407
+#define JABBER_ERROR_REQUEST_TIMEOUT 408
+#define JABBER_ERROR_CONFLICT 409
+#define JABBER_ERROR_INTERNAL_SERVER_ERROR 500
+#define JABBER_ERROR_NOT_IMPLEMENTED 501
+#define JABBER_ERROR_REMOTE_SERVER_ERROR 502
+#define JABBER_ERROR_SERVICE_UNAVAILABLE 503
+#define JABBER_ERROR_REMOTE_SERVER_TIMEOUT 504
+
+#define TLEN_ALERTS_ACCEPT_ALL 0
+#define TLEN_ALERTS_IGNORE_NIR 1
+#define TLEN_ALERTS_IGNORE_ALL 2
+
+#define TLEN_IMAGES_ACCEPT_ALL 0
+#define TLEN_IMAGES_IGNORE_NIR 1
+#define TLEN_IMAGES_IGNORE_ALL 2
+
+#define TLEN_MUC_ASK 0
+#define TLEN_MUC_ACCEPT_IR 1
+#define TLEN_MUC_ACCEPT_ALL 2
+#define TLEN_MUC_IGNORE_NIR 3
+#define TLEN_MUC_IGNORE_ALL 4
+
+#define IDC_STATIC (-1)
+
+/*******************************************************************
+ * Global data structures and data type definitions
+ *******************************************************************/
+typedef HANDLE JABBER_SOCKET;
+
+typedef enum {
+ LIST_ROSTER, // Roster list
+ LIST_CHATROOM, // Groupchat room currently joined
+ LIST_FILE, // Current file transfer session
+ LIST_INVITATIONS,// Invitations to be sent
+ LIST_SEARCH, // Rooms names being searched
+ LIST_VOICE,
+ LIST_PICTURE
+} JABBER_LIST;
+
+typedef enum {
+ IQ_PROC_NONE,
+ IQ_PROC_GETSEARCH
+} JABBER_IQ_PROCID;
+
+typedef enum {
+ SUB_NONE,
+ SUB_TO,
+ SUB_FROM,
+ SUB_BOTH
+} JABBER_SUBSCRIPTION;
+
+typedef struct {
+ char *szOnline;
+ char *szAway;
+ char *szNa;
+ char *szDnd;
+ char *szFreechat;
+ char *szInvisible;
+} JABBER_MODEMSGS;
+
+typedef struct {
+ char mailBase[256];
+ char mailMsg[256];
+ int mailMsgMthd;
+ char mailIndex[256];
+ int mailIndexMthd;
+ char mailLogin[256];
+ int mailLoginMthd;
+ char mailCompose[256];
+ int mailComposeMthd;
+ char avatarGet[256];
+ int avatarGetMthd;
+ char avatarUpload[256];
+ int avatarUploadMthd;
+ char avatarRemove[256];
+ int avatarRemoveMthd;
+} TlenConfiguration;
+
+typedef struct {
+ BOOL useEncryption;
+ BOOL reconnect;
+ BOOL rosterSync;
+ BOOL offlineAsInvisible;
+ BOOL leaveOfflineMessage;
+ int offlineMessageOption;
+ BOOL ignoreAdvertisements;
+ int alertPolicy;
+ int groupChatPolicy;
+ int voiceChatPolicy;
+ int imagePolicy;
+ BOOL enableAvatars;
+ BOOL enableVersion;
+ BOOL useNudge;
+ BOOL logAlerts;
+ BOOL useNewP2P;
+ BOOL sendKeepAlive;
+ BOOL savePassword;
+} TlenOptions;
+
+
+struct JABBER_IQ_FUNC_STRUCT;
+struct JABBER_LIST_ITEM_STRUCT;
+struct TLEN_VOICE_CONTROL_STRUCT;
+
+
+struct TlenProtocol : public PROTO_INTERFACE, public MZeroedObject
+{
+ typedef PROTO_INTERFACE CSuper;
+
+ TlenProtocol( const char*, const TCHAR* );
+ ~TlenProtocol();
+
+ //====================================================================================
+ // PROTO_INTERFACE
+ //====================================================================================
+
+ virtual HANDLE __cdecl AddToList( int flags, PROTOSEARCHRESULT* psr );
+ virtual HANDLE __cdecl AddToListByEvent( int flags, int iContact, HANDLE hDbEvent );
+
+ virtual int __cdecl Authorize(HANDLE hDbEvent);
+ virtual int __cdecl AuthDeny(HANDLE hDbEvent, const PROTOCHAR* szReason);
+ virtual int __cdecl AuthRecv(HANDLE hContact, PROTORECVEVENT*);
+ virtual int __cdecl AuthRequest(HANDLE hContact, const PROTOCHAR* szMessage);
+
+ virtual HANDLE __cdecl ChangeInfo(int iInfoType, void* pInfoData);
+
+ virtual HANDLE __cdecl FileAllow(HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath);
+ virtual int __cdecl FileCancel(HANDLE hContact, HANDLE hTransfer);
+ virtual int __cdecl FileDeny(HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason);
+ virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename);
+
+ virtual DWORD_PTR __cdecl GetCaps(int type, HANDLE hContact = NULL);
+ virtual HICON __cdecl GetIcon(int iconIndex);
+ virtual int __cdecl GetInfo(HANDLE hContact, int infoType);
+
+ virtual HANDLE __cdecl SearchBasic(const PROTOCHAR* id);
+ virtual HANDLE __cdecl SearchByEmail(const PROTOCHAR* email);
+ virtual HANDLE __cdecl SearchByName(const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName);
+ virtual HWND __cdecl SearchAdvanced(HWND owner);
+ virtual HWND __cdecl CreateExtendedSearchUI(HWND owner);
+
+ virtual int __cdecl RecvContacts(HANDLE hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvFile(HANDLE hContact, PROTOFILEEVENT*);
+ virtual int __cdecl RecvMsg(HANDLE hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvUrl(HANDLE hContact, PROTORECVEVENT*);
+
+ virtual int __cdecl SendContacts(HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList);
+ virtual HANDLE __cdecl SendFile(HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles);
+ virtual int __cdecl SendMsg(HANDLE hContact, int flags, const char* msg);
+ virtual int __cdecl SendUrl(HANDLE hContact, int flags, const char* url);
+
+ virtual int __cdecl SetApparentMode(HANDLE hContact, int mode);
+ virtual int __cdecl SetStatus(int iNewStatus);
+
+ virtual HANDLE __cdecl GetAwayMsg(HANDLE hContact);
+ virtual int __cdecl RecvAwayMsg(HANDLE hContact, int mode, PROTORECVEVENT* evt);
+ virtual int __cdecl SendAwayMsg(HANDLE hContact, HANDLE hProcess, const char* msg);
+ virtual int __cdecl SetAwayMsg(int iStatus, const PROTOCHAR* msg);
+
+ virtual int __cdecl UserIsTyping(HANDLE hContact, int type);
+
+ virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam);
+
+
+
+
+
+ HANDLE hNetlibUser;
+ HANDLE hFileNetlibUser;
+
+ JABBER_MODEMSGS modeMsgs;
+
+ struct ThreadDataStruct *threadData;
+ HANDLE hTlenNudge;
+ HANDLE hMenuMUC;
+ HANDLE hMenuChats;
+ HANDLE hMenuInbox;
+ HANDLE hMenuContactMUC;
+ HANDLE hMenuContactVoice;
+ HANDLE hMenuContactGrantAuth;
+ HANDLE hMenuContactRequestAuth;
+ HANDLE hMenuPicture;
+
+ HANDLE* hServices;
+ unsigned serviceNum;
+ HANDLE* hHooks;
+ unsigned hookNum;
+
+
+ int listsCount;
+ struct JABBER_LIST_ITEM_STRUCT *lists;
+ CRITICAL_SECTION csLists;
+
+ int iqCount;
+ int iqAlloced;
+ struct JABBER_IQ_FUNC_STRUCT *iqList;
+ CRITICAL_SECTION csIqList;
+
+ CRITICAL_SECTION csSerial;
+ unsigned int serial;
+ BOOL isOnline;
+ BOOL isConnected;
+
+ CRITICAL_SECTION modeMsgMutex;
+
+ HANDLE hMenuRoot;
+
+ char *searchJID;
+ int searchID;
+ int searchIndex;
+ char *searchQuery;
+ int searchQueryLen;
+
+ CRITICAL_SECTION csSend;
+
+ HWND voiceDlgHWND;
+ struct TLEN_VOICE_CONTROL_STRUCT *playbackControl;
+ struct TLEN_VOICE_CONTROL_STRUCT *recordingControl;
+ int framesAvailableForPlayback;
+ int availOverrunValue;
+
+ TlenOptions tlenOptions;
+
+};
+
+
+
+typedef struct ThreadDataStruct{
+ HANDLE hThread;
+ char *streamId;
+ char username[128];
+ char password[128];
+ char server[128];
+ char manualHost[128];
+ char avatarToken[128];
+ char avatarHash[64];
+ int avatarFormat;
+ WORD port;
+ BOOL useEncryption;
+
+ JABBER_SOCKET s; //HANDLE from CallService(MS_NETLIB_OPENCONNECTION (jabber_ws.c:68)
+ aes_context aes_in_context;
+ aes_context aes_out_context;
+ unsigned char aes_in_iv[16];
+ unsigned char aes_out_iv[16];
+
+ BOOL useAES;
+ TlenConfiguration tlenConfig;
+ TlenProtocol *proto;
+} ThreadData;
+
+
+typedef enum { FT_CONNECTING, FT_INITIALIZING, FT_RECEIVING, FT_DONE, FT_ERROR, FT_DENIED, FT_SWITCH } JABBER_FILE_STATE;
+typedef enum { FT_RECV, FT_SEND} JABBER_FILE_MODE;
+typedef struct TLEN_FILE_TRANSFER_STRUCT{
+ HANDLE hContact;
+ JABBER_SOCKET s;
+ NETLIBNEWCONNECTIONPROC_V2 pfnNewConnectionV2;
+ JABBER_FILE_STATE state;
+ char *jid;
+ int fileId;
+ char *iqId;
+ int mode;
+
+ // Used by file receiving only
+ char *hostName;
+ WORD wPort;
+ char *localName;
+ WORD wLocalPort;
+ char *szSavePath;
+ long fileReceivedBytes;
+ long fileTotalSize;
+
+ // Used by file sending only
+ HANDLE hFileEvent;
+ int fileCount;
+ char **files;
+ long *filesSize;
+ //long fileTotalSize; // Size of the current file (file being sent)
+ long allFileTotalSize;
+ long allFileReceivedBytes;
+ char *szDescription;
+ int currentFile;
+
+ // New p2p
+ BOOL newP2P;
+ char *id2;
+ SOCKET udps;
+ aes_context aes_context;
+ unsigned char aes_iv[16];
+ TlenProtocol *proto;
+
+} TLEN_FILE_TRANSFER;
+
+typedef struct {
+ PROTOSEARCHRESULT hdr;
+ char jid[256];
+} JABBER_SEARCH_RESULT;
+
+typedef struct {
+ char *iqId;
+ PROTOSEARCHRESULT hdr;
+ char jid[256];
+} TLEN_CONFERENCE;
+
+
+typedef struct {
+ int id;
+ TCHAR *name;
+} JABBER_FIELD_MAP;
+
+
+/*******************************************************************
+ * Global variables
+ *******************************************************************/
+extern HINSTANCE hInst;
+extern HANDLE hMainThread;
+
+/*******************************************************************
+ * Function declarations
+ *******************************************************************/
+void uninitMenuItems(TlenProtocol *proto);
+HICON GetIcolibIcon(int iconId);
+void ReleaseIcolibIcon(HICON hIcon);
+
+void JabberLog(TlenProtocol *proto, const char *fmt, ...);
+void __cdecl JabberServerThread(ThreadData *info);
+// jabber_ws.cpp
+BOOL JabberWsInit(TlenProtocol *proto);
+void JabberWsUninit(TlenProtocol *proto);
+JABBER_SOCKET JabberWsConnect(TlenProtocol *proto, char *host, WORD port);
+int JabberWsSend(TlenProtocol *proto, JABBER_SOCKET s, char *data, int datalen);
+int JabberWsRecv(TlenProtocol *proto, JABBER_SOCKET s, char *data, long datalen);
+int JabberWsSendAES(TlenProtocol *proto, char *data, int datalen, aes_context *aes_ctx, unsigned char *aes_iv);
+int JabberWsRecvAES(TlenProtocol *proto, char *data, long datalen, aes_context *aes_ctx, unsigned char *aes_iv);
+// jabber_util.cpp
+HANDLE HookEventObj_Ex(const char *name, TlenProtocol *proto, MIRANDAHOOKOBJ hook);
+HANDLE CreateServiceFunction_Ex(const char *name, TlenProtocol *proto, MIRANDASERVICEOBJ service);
+void UnhookEvents_Ex(TlenProtocol *proto);
+void DestroyServices_Ex(TlenProtocol *proto);
+void JabberSerialInit(TlenProtocol *proto);
+void JabberSerialUninit(TlenProtocol *proto);
+unsigned int JabberSerialNext(TlenProtocol *proto);
+int JabberSend(TlenProtocol *proto, const char *fmt, ...);
+HANDLE JabberHContactFromJID(TlenProtocol *proto, const char *jid);
+char *JabberJIDFromHContact(TlenProtocol *proto, HANDLE hContact);
+char *JabberLoginFromJID(const char *jid);
+char *JabberResourceFromJID(const char *jid);
+char *JabberNickFromJID(const char *jid);
+char *JabberLocalNickFromJID(const char *jid);
+char *TlenGroupEncode(const char *str);
+char *TlenGroupDecode(const char *str);
+char *JabberSha1(char *str);
+char *TlenSha1(char *str, int len);
+char *TlenPasswordHash(const char *str);
+void TlenUrlDecode(char *str);
+char *TlenUrlEncode(const char *str);
+char *JabberTextEncode(const char *str);
+char *JabberTextDecode(const char *str);
+char *JabberBase64Encode(const char *buffer, int bufferLen);
+char *JabberBase64Decode(const char *buffer, int *resultLen);
+int JabberGetPictureType(const char* buf);
+void TlenLogMessage(TlenProtocol *proto, HANDLE hContact, DWORD flags, const char *message);
+BOOL IsAuthorized(TlenProtocol *proto, const char *jid);
+//char *JabberGetVersionText();
+time_t JabberIsoToUnixTime(char *stamp);
+time_t TlenTimeToUTC(time_t time);
+void JabberSendPresence(TlenProtocol *proto,int status);
+void JabberStringAppend(char **str, int *sizeAlloced, const char *fmt, ...);
+//char *JabberGetClientJID(char *jid);
+// jabber_misc.cpp
+void JabberDBAddEvent(TlenProtocol *proto, HANDLE hContact, int eventType, DWORD flags, PBYTE pBlob, DWORD cbBlob);
+void JabberDBAddAuthRequest(TlenProtocol *proto, char *jid, char *nick);
+HANDLE JabberDBCreateContact(TlenProtocol *proto, char *jid, char *nick, BOOL temporary);
+void JabberContactListCreateGroup(char *groupName);
+unsigned long JabberForkThread(void (__cdecl *threadcode)(void*), unsigned long stacksize, void *arg);
+// jabber_svc.cpp
+int TlenRunSearch(TlenProtocol *proto);
+// jabber_opt.cpp
+void TlenLoadOptions(TlenProtocol *proto);
+// tlen_voice.cpp
+int TlenVoiceCancelAll(TlenProtocol *proto);
+// jabber_advsearch.cpp
+extern JABBER_FIELD_MAP tlenFieldGender[];
+extern JABBER_FIELD_MAP tlenFieldLookfor[];
+extern JABBER_FIELD_MAP tlenFieldStatus[];
+extern JABBER_FIELD_MAP tlenFieldOccupation[];
+extern JABBER_FIELD_MAP tlenFieldPlan[];
+// tlen_advsearch.cpp
+INT_PTR CALLBACK TlenAdvSearchDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+char *TlenAdvSearchCreateQuery(HWND hwndDlg, int iqId);
+
+
+#endif
+
diff --git a/protocols/Tlen/src/jabber_iq.cpp b/protocols/Tlen/src/jabber_iq.cpp
new file mode 100644
index 0000000000..01ce67129b
--- /dev/null
+++ b/protocols/Tlen/src/jabber_iq.cpp
@@ -0,0 +1,114 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+
+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 "jabber.h"
+#include "jabber_iq.h"
+
+
+void JabberIqInit(TlenProtocol *proto)
+{
+ InitializeCriticalSection(&proto->csIqList);
+ proto->iqList = NULL;
+ proto->iqCount = 0;
+ proto->iqAlloced = 0;
+}
+
+void JabberIqUninit(TlenProtocol *proto)
+{
+ if (proto->iqList) mir_free(proto->iqList);
+ proto->iqList = NULL;
+ proto->iqCount = 0;
+ proto->iqAlloced = 0;
+ DeleteCriticalSection(&proto->csIqList);
+}
+
+static void JabberIqRemove(TlenProtocol *proto, int index)
+{
+ EnterCriticalSection(&proto->csIqList);
+ if (index >= 0 && index<proto->iqCount) {
+ memmove(proto->iqList+index, proto->iqList+index+1, sizeof(JABBER_IQ_FUNC)*(proto->iqCount-index-1));
+ proto->iqCount--;
+ }
+ LeaveCriticalSection(&proto->csIqList);
+}
+
+static void JabberIqExpire(TlenProtocol *proto)
+{
+ int i;
+ time_t expire;
+
+ EnterCriticalSection(&proto->csIqList);
+ expire = time(NULL) - 120; // 2 minute
+ i = 0;
+ while (i < proto->iqCount) {
+ if (proto->iqList[i].requestTime < expire)
+ JabberIqRemove(proto, i);
+ else
+ i++;
+ }
+ LeaveCriticalSection(&proto->csIqList);
+}
+
+JABBER_IQ_PFUNC JabberIqFetchFunc(TlenProtocol *proto, int iqId)
+{
+ int i;
+ JABBER_IQ_PFUNC res;
+
+ EnterCriticalSection(&proto->csIqList);
+ JabberIqExpire(proto);
+ for (i=0; i<proto->iqCount && proto->iqList[i].iqId != iqId; i++);
+ if (i < proto->iqCount) {
+ res = proto->iqList[i].func;
+ JabberIqRemove(proto, i);
+ }
+ else {
+ res = (JABBER_IQ_PFUNC) NULL;
+ }
+ LeaveCriticalSection(&proto->csIqList);
+ return res;
+}
+
+void JabberIqAdd(TlenProtocol *proto, unsigned int iqId, JABBER_IQ_PROCID procId, JABBER_IQ_PFUNC func)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csIqList);
+ if (procId == IQ_PROC_NONE)
+ i = proto->iqCount;
+ else
+ for (i=0; i<proto->iqCount && proto->iqList[i].procId != procId; i++);
+
+ if (i >= proto->iqCount && proto->iqCount >= proto->iqAlloced) {
+ proto->iqAlloced = proto->iqCount + 8;
+ proto->iqList = (JABBER_IQ_FUNC*)mir_realloc(proto->iqList, sizeof(JABBER_IQ_FUNC)*proto->iqAlloced);
+ }
+
+ if (proto->iqList != NULL) {
+ proto->iqList[i].iqId = iqId;
+ proto->iqList[i].procId = procId;
+ proto->iqList[i].func = func;
+ proto->iqList[i].requestTime = time(NULL);
+ if (i == proto->iqCount) proto->iqCount++;
+ }
+ LeaveCriticalSection(&proto->csIqList);
+}
+
diff --git a/protocols/Tlen/src/jabber_iq.h b/protocols/Tlen/src/jabber_iq.h
new file mode 100644
index 0000000000..d521c85c66
--- /dev/null
+++ b/protocols/Tlen/src/jabber_iq.h
@@ -0,0 +1,61 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+#ifndef _JABBER_IQ_H_
+#define _JABBER_IQ_H_
+
+#include "jabber_xml.h"
+#include "jabber.h"
+
+typedef void (*JABBER_IQ_PFUNC)(TlenProtocol *proto, XmlNode *iqNode);
+
+typedef struct JABBER_IQ_FUNC_STRUCT {
+ int iqId; // id to match IQ get/set with IQ result
+ JABBER_IQ_PROCID procId; // must be unique in the list, except for IQ_PROC_NONE which can have multiple entries
+ JABBER_IQ_PFUNC func; // callback function
+ time_t requestTime; // time the request was sent, used to remove relinquent entries
+} JABBER_IQ_FUNC;
+
+void JabberIqInit(TlenProtocol *proto);
+void JabberIqUninit(TlenProtocol *proto);
+JABBER_IQ_PFUNC JabberIqFetchFunc(TlenProtocol *proto, int iqId);
+void JabberIqAdd(TlenProtocol *proto, unsigned int iqId, JABBER_IQ_PROCID procId, JABBER_IQ_PFUNC func);
+
+void JabberIqResultAuth(TlenProtocol *proto, XmlNode *iqNode);
+void JabberIqResultRoster(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultVcard(TlenProtocol *proto, XmlNode *iqNode);
+void JabberIqResultSearch(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultVersion(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultInfo(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultTcfg(TlenProtocol *proto, XmlNode *iqNode);
+
+void TlenIqResultChatGroups(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultChatRooms(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultUserRooms(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultUserNicks(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultRoomSearch(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultRoomInfo(TlenProtocol *proto, XmlNode *iqNode);
+void TlenIqResultChatRoomUsers(TlenProtocol *proto, XmlNode *iqNode);
+//void JabberIqResultSetPassword(XmlNode *iqNode, void *userdata);
+
+#endif
+
diff --git a/protocols/Tlen/src/jabber_iqid.cpp b/protocols/Tlen/src/jabber_iqid.cpp
new file mode 100644
index 0000000000..2fde1bb6df
--- /dev/null
+++ b/protocols/Tlen/src/jabber_iqid.cpp
@@ -0,0 +1,642 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "resource.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "tlen_muc.h"
+
+void JabberIqResultAuth(TlenProtocol *proto, XmlNode *iqNode)
+{
+ char *type;
+
+ // RECVED: authentication result
+ // ACTION: if successfully logged in, continue by requesting roster list and set my initial status
+ if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
+
+ if (!strcmp(type, "result")) {
+ DBVARIANT dbv;
+
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "Nick", &dbv))
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "Nick", proto->threadData->username);
+ else
+ DBFreeVariant(&dbv);
+// iqId = JabberSerialNext();
+// JabberIqAdd(iqId, IQ_PROC_NONE, JabberIqResultGetRoster);
+// JabberSend(info, "<iq type='get' id='"JABBER_IQID"%d'><query xmlns='jabber:iq:roster'/></iq>", iqId);
+
+ JabberSend(proto, "<iq type='get' id='GetRoster'><query xmlns='jabber:iq:roster'/></iq>");
+ JabberSend(proto, "<iq to='tcfg' type='get' id='TcfgGetAfterLoggedIn'></iq>");
+ }
+ // What to do if password error? etc...
+ else if (!strcmp(type, "error")) {
+ char text[128];
+
+ JabberSend(proto, "</s>");
+ _snprintf(text, sizeof(text), "%s %s@%s.", TranslateT("Authentication failed for"), proto->threadData->username, proto->threadData->server);
+ MessageBoxA(NULL, text, Translate("Tlen Authentication"), MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
+ proto->threadData = NULL; // To disallow auto reconnect
+ }
+}
+
+void JabberResultSetRoster(TlenProtocol *proto, XmlNode *queryNode) {
+ DBVARIANT dbv;
+ XmlNode *itemNode, *groupNode;
+ JABBER_LIST_ITEM *item;
+ HANDLE hContact;
+ char *jid, *name, *nick;
+ int i;
+ char *str;
+
+ for (i=0; i<queryNode->numChild; i++) {
+ itemNode = queryNode->child[i];
+ if (!strcmp(itemNode->name, "item")) {
+ if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
+ str = JabberXmlGetAttrValue(itemNode, "subscription");
+ if (!strcmp(str, "remove")) {
+ if ((hContact=JabberHContactFromJID(proto, jid)) != NULL) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ }
+ JabberListRemove(proto, LIST_ROSTER, jid);
+ } else {
+ item = JabberListAdd(proto, LIST_ROSTER, jid);
+ if (item != NULL) {
+ if (str == NULL) item->subscription = SUB_NONE;
+ else if (!strcmp(str, "both")) item->subscription = SUB_BOTH;
+ else if (!strcmp(str, "to")) item->subscription = SUB_TO;
+ else if (!strcmp(str, "from")) item->subscription = SUB_FROM;
+ else item->subscription = SUB_NONE;
+ if ((name=JabberXmlGetAttrValue(itemNode, "name")) != NULL) {
+ nick = JabberTextDecode(name);
+ } else {
+ nick = JabberLocalNickFromJID(jid);
+ }
+ if (nick != NULL) {
+ if (item->nick) mir_free(item->nick);
+ item->nick = nick;
+
+ if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
+ // Received roster has a new JID.
+ // Add the jid (with empty resource) to Miranda contact list.
+ hContact = JabberDBCreateContact(proto, jid, nick, FALSE);
+ }
+ DBWriteContactSettingString(hContact, "CList", "MyHandle", nick);
+ if (item->group) mir_free(item->group);
+ if ((groupNode=JabberXmlGetChild(itemNode, "group")) != NULL && groupNode->text != NULL) {
+ item->group = TlenGroupDecode(groupNode->text);
+ JabberContactListCreateGroup(item->group);
+ // Don't set group again if already correct, or Miranda may show wrong group count in some case
+ if (!DBGetContactSetting(hContact, "CList", "Group", &dbv)) {
+ if (strcmp(dbv.pszVal, item->group))
+ DBWriteContactSettingString(hContact, "CList", "Group", item->group);
+ DBFreeVariant(&dbv);
+ } else
+ DBWriteContactSettingString(hContact, "CList", "Group", item->group);
+ } else {
+ item->group = NULL;
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void JabberIqResultRoster(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode;
+ char *type;
+ char *str;
+
+ // RECVED: roster information
+ // ACTION: populate LIST_ROSTER and create contact for any new rosters
+ if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
+ if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;
+
+ if (!strcmp(type, "result")) {
+ str = JabberXmlGetAttrValue(queryNode, "xmlns");
+ if (str != NULL && !strcmp(str, "jabber:iq:roster")) {
+ DBVARIANT dbv;
+ XmlNode *itemNode, *groupNode;
+ JABBER_SUBSCRIPTION sub;
+ JABBER_LIST_ITEM *item;
+ HANDLE hContact;
+ char *jid, *name, *nick;
+ int i, oldStatus;
+
+ for (i=0; i<queryNode->numChild; i++) {
+ itemNode = queryNode->child[i];
+ if (!strcmp(itemNode->name, "item")) {
+ str = JabberXmlGetAttrValue(itemNode, "subscription");
+ if (str == NULL) sub = SUB_NONE;
+ else if (!strcmp(str, "both")) sub = SUB_BOTH;
+ else if (!strcmp(str, "to")) sub = SUB_TO;
+ else if (!strcmp(str, "from")) sub = SUB_FROM;
+ else sub = SUB_NONE;
+ //if (str != NULL && (!strcmp(str, "to") || !strcmp(str, "both"))) {
+ if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
+ if ((name=JabberXmlGetAttrValue(itemNode, "name")) != NULL) {
+ nick = JabberTextDecode(name);
+ } else {
+ nick = JabberLocalNickFromJID(jid);
+ }
+ if (nick != NULL) {
+ item = JabberListAdd(proto, LIST_ROSTER, jid);
+ if (item->nick) mir_free(item->nick);
+ item->nick = nick;
+ item->subscription = sub;
+ if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
+ // Received roster has a new JID.
+ // Add the jid (with empty resource) to Miranda contact list.
+ hContact = JabberDBCreateContact(proto, jid, nick, FALSE);
+ }
+ DBWriteContactSettingString(hContact, "CList", "MyHandle", nick);
+ if (item->group) mir_free(item->group);
+ if ((groupNode=JabberXmlGetChild(itemNode, "group")) != NULL && groupNode->text != NULL) {
+ item->group = TlenGroupDecode(groupNode->text);
+ JabberContactListCreateGroup(item->group);
+ // Don't set group again if already correct, or Miranda may show wrong group count in some case
+ if (!DBGetContactSetting(hContact, "CList", "Group", &dbv)) {
+ if (strcmp(dbv.pszVal, item->group))
+ DBWriteContactSettingString(hContact, "CList", "Group", item->group);
+ DBFreeVariant(&dbv);
+ }
+ else
+ DBWriteContactSettingString(hContact, "CList", "Group", item->group);
+ }
+ else {
+ item->group = NULL;
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "AvatarHash", &dbv)) {
+ if (item->avatarHash) mir_free(item->avatarHash);
+ item->avatarHash = mir_strdup(dbv.pszVal);
+ JabberLog(proto, "Setting hash [%s] = %s", nick, item->avatarHash);
+ DBFreeVariant(&dbv);
+ }
+ item->avatarFormat = DBGetContactSettingDword(hContact, proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN);
+ }
+ }
+ }
+ }
+ // Delete orphaned contacts (if roster sync is enabled)
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "RosterSync", FALSE) == TRUE) {
+ HANDLE *list;
+ int listSize, listAllocSize;
+
+ listSize = listAllocSize = 0;
+ list = NULL;
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ str = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (str != NULL && !strcmp(str, proto->m_szModuleName)) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ if (!JabberListExist(proto, LIST_ROSTER, dbv.pszVal)) {
+ JabberLog(proto, "Syncing roster: preparing to delete %s (hContact=0x%x)", dbv.pszVal, hContact);
+ if (listSize >= listAllocSize) {
+ listAllocSize = listSize + 100;
+ if ((list=(HANDLE *) mir_realloc(list, listAllocSize)) == NULL) {
+ listSize = 0;
+ break;
+ }
+ }
+ list[listSize++] = hContact;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ for (i=0; i<listSize; i++) {
+ JabberLog(proto, "Syncing roster: deleting 0x%x", list[i]);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM) list[i], 0);
+ }
+ if (list != NULL)
+ mir_free(list);
+ }
+ ///////////////////////////////////////
+ {
+ CLISTMENUITEM clmi;
+ memset(&clmi, 0, sizeof(CLISTMENUITEM));
+ clmi.cbSize = sizeof(CLISTMENUITEM);
+ clmi.flags = CMIM_FLAGS;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuMUC, (LPARAM) &clmi);
+ if (proto->hMenuChats != NULL){
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuChats, (LPARAM) &clmi);
+ }
+ }
+
+ proto->isOnline = TRUE;
+ JabberLog(proto, "Status changed via THREADSTART");
+ oldStatus = proto->m_iStatus;
+ JabberSendPresence(proto, proto->m_iDesiredStatus);
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, proto->m_iStatus);
+ //////////////////////////////////
+ }
+ }
+}
+
+
+// Tlen actually use jabber:iq:search for other users vCard or jabber:iq:register for own vCard
+void TlenIqResultVcard(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode, *itemNode, *n;
+ char *type, *jid;
+ char text[128];
+ HANDLE hContact;
+ char *nText;
+
+// JabberLog("<iq/> iqIdGetVcard (tlen)");
+ if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
+
+ if (!strcmp(type, "result")) {
+ BOOL hasFirst, hasLast, hasNick, hasEmail, hasCity, hasAge, hasGender, hasSchool, hasLookFor, hasOccupation;
+ DBVARIANT dbv;
+ int i;
+
+ if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;
+ if ((itemNode=JabberXmlGetChild(queryNode, "item")) == NULL) return;
+ if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) return;
+ if (strchr(jid, '@') != NULL) {
+ sprintf(text, "%s", jid);
+ } else {
+ sprintf(text, "%s@%s", jid, dbv.pszVal); // Add @tlen.pl
+ }
+ DBFreeVariant(&dbv);
+ if ((hContact=JabberHContactFromJID(proto, text)) == NULL) {
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "LoginName", &dbv)) return;
+ if (strcmp(dbv.pszVal, jid)) {
+ DBFreeVariant(&dbv);
+ return;
+ }
+ DBFreeVariant(&dbv);
+ }
+ } else {
+ hContact = NULL;
+ }
+ hasFirst = hasLast = hasNick = hasEmail = hasCity = hasAge = hasGender = hasOccupation = hasLookFor = hasSchool = FALSE;
+ for (i=0; i<itemNode->numChild; i++) {
+ n = itemNode->child[i];
+ if (n == NULL || n->name == NULL) continue;
+ if (!strcmp(n->name, "first")) {
+ if (n->text != NULL) {
+ hasFirst = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "FirstName", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "last")) {
+ if (n->text != NULL) {
+ hasLast = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "LastName", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "nick")) {
+ if (n->text != NULL) {
+ hasNick = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "Nick", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "email")) {
+ if (n->text != NULL) {
+ hasEmail = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "e-mail", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "c")) {
+ if (n->text != NULL) {
+ hasCity = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "City", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "b")) {
+ if (n->text != NULL) {
+ WORD nAge;
+ hasAge = TRUE;
+ nAge = atoi(n->text);
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Age", nAge);
+ }
+ }
+ else if (!strcmp(n->name, "s")) {
+ if (n->text != NULL && n->text[1] == '\0' && (n->text[0] == '1' || n->text[0] == '2')) {
+ hasGender = TRUE;
+ DBWriteContactSettingByte(hContact, proto->m_szModuleName, "Gender", (BYTE) (n->text[0] == '1'?'M':'F'));
+ }
+ }
+ else if (!strcmp(n->name, "e")) {
+ if (n->text != NULL) {
+ hasSchool = TRUE;
+ nText = JabberTextDecode(n->text);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "School", nText);
+ mir_free(nText);
+ }
+ }
+ else if (!strcmp(n->name, "j")) {
+ if (n->text != NULL) {
+ WORD nOccupation;
+ hasOccupation = TRUE;
+ nOccupation = atoi(n->text);
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Occupation", nOccupation);
+ }
+ }
+ else if (!strcmp(n->name, "r")) {
+ if (n->text != NULL) {
+ WORD nLookFor;
+ hasLookFor = TRUE;
+ nLookFor = atoi(n->text);
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "LookingFor", nLookFor);
+ }
+ }
+ else if (!strcmp(n->name, "g")) { // voice chat enabled
+ if (n->text != NULL) {
+ BYTE bVoice;
+ bVoice = atoi(n->text);
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "VoiceChat", bVoice);
+ }
+ }
+ else if (!strcmp(n->name, "v")) { // status visibility
+ if (n->text != NULL) {
+ BYTE bPublic;
+ bPublic = atoi(n->text);
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "PublicStatus", bPublic);
+ }
+ }
+ }
+ if (!hasFirst)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "FirstName");
+ if (!hasLast)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "LastName");
+ // We are not removing "Nick"
+// if (!hasNick)
+// DBDeleteContactSetting(hContact, m_szModuleName, "Nick");
+ if (!hasEmail)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "e-mail");
+ if (!hasCity)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "City");
+ if (!hasAge)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "Age");
+ if (!hasGender)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "Gender");
+ if (!hasSchool)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "School");
+ if (!hasOccupation)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "Occupation");
+ if (!hasLookFor)
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "LookingFor");
+ ProtoBroadcastAck(proto->m_szModuleName, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+ }
+}
+
+void JabberIqResultSearch(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode, *itemNode, *n;
+ char *type, *jid, *str;
+ int id, i, found;
+ JABBER_SEARCH_RESULT jsr = {0};
+ DBVARIANT dbv = {0};
+
+ found = 0;
+// JabberLog("<iq/> iqIdGetSearch");
+ if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
+ if ((str=JabberXmlGetAttrValue(iqNode, "id")) == NULL) return;
+ id = atoi(str+strlen(JABBER_IQID));
+
+ if (!strcmp(type, "result")) {
+ if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ jsr.hdr.cbSize = sizeof(JABBER_SEARCH_RESULT);
+ jsr.hdr.flags = PSR_TCHAR;
+ for (i=0; i<queryNode->numChild; i++) {
+ itemNode = queryNode->child[i];
+ if (!strcmp(itemNode->name, "item")) {
+ if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
+ if (strchr(jid, '@') != NULL) {
+ _snprintf(jsr.jid, sizeof(jsr.jid), "%s", jid);
+ } else {
+ _snprintf(jsr.jid, sizeof(jsr.jid), "%s@%s", jid, dbv.pszVal);
+ }
+ jsr.jid[sizeof(jsr.jid)-1] = '\0';
+ jsr.hdr.id = mir_a2t(jid);
+ if ((n=JabberXmlGetChild(itemNode, "nick")) != NULL && n->text != NULL){
+ char* buf = JabberTextDecode(n->text);
+ jsr.hdr.nick = mir_a2t(buf);
+ mir_free(buf);
+ } else {
+ jsr.hdr.nick = mir_tstrdup(TEXT(""));
+ }
+ if ((n=JabberXmlGetChild(itemNode, "first")) != NULL && n->text != NULL){
+ char* buf = JabberTextDecode(n->text);
+ jsr.hdr.firstName = mir_a2t(buf);
+ mir_free(buf);
+ } else {
+ jsr.hdr.firstName = mir_tstrdup(TEXT(""));
+ }
+ if ((n=JabberXmlGetChild(itemNode, "last")) != NULL && n->text != NULL){
+ char* buf = JabberTextDecode(n->text);
+ jsr.hdr.lastName = mir_a2t(buf);
+ mir_free(buf);
+ } else {
+ jsr.hdr.lastName = mir_tstrdup(TEXT(""));
+ }
+ if ((n=JabberXmlGetChild(itemNode, "email"))!=NULL && n->text!=NULL){
+ char* buf = JabberTextDecode(n->text);
+ jsr.hdr.email = mir_a2t(buf);
+ mir_free(buf);
+ } else {
+ jsr.hdr.email = mir_tstrdup(TEXT(""));
+ }
+
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE) id, (LPARAM) &jsr);
+ found = 1;
+ mir_free(jsr.hdr.id);
+ mir_free(jsr.hdr.nick);
+ mir_free(jsr.hdr.firstName);
+ mir_free(jsr.hdr.lastName);
+ mir_free(jsr.hdr.email);
+ }
+ }
+ }
+ if (proto->searchJID != NULL) {
+ if (!found) {
+ if (strchr(proto->searchJID, '@') != NULL) {
+ _snprintf(jsr.jid, sizeof(jsr.jid), "%s", proto->searchJID);
+ } else {
+ _snprintf(jsr.jid, sizeof(jsr.jid), "%s@%s", proto->searchJID, dbv.pszVal);
+ }
+ jsr.jid[sizeof(jsr.jid)-1] = '\0';
+ jsr.hdr.nick = mir_tstrdup(TEXT(""));
+ jsr.hdr.firstName = mir_tstrdup(TEXT(""));
+ jsr.hdr.lastName = mir_tstrdup(TEXT(""));
+ jsr.hdr.email = mir_tstrdup(TEXT(""));
+ jsr.hdr.id = mir_tstrdup(TEXT(""));
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE) id, (LPARAM) &jsr);
+ mir_free(jsr.hdr.nick);
+ mir_free(jsr.hdr.firstName);
+ mir_free(jsr.hdr.lastName);
+ mir_free(jsr.hdr.email);
+ }
+ mir_free(proto->searchJID);
+ proto->searchJID = NULL;
+ }
+ DBFreeVariant(&dbv);
+ }
+ found = 0;
+ if (queryNode->numChild == TLEN_MAX_SEARCH_RESULTS_PER_PAGE) {
+ found = TlenRunSearch(proto);
+ }
+ if (!found) {
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE) id, 0);
+ }
+ } else if (!strcmp(type, "error")) {
+ // ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE) id, 0);
+ // There is no ACKRESULT_FAILED for ACKTYPE_SEARCH :) look at findadd.c
+ // So we will just send a SUCCESS
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE) id, 0);
+ }
+}
+
+
+void GetConfigItem(XmlNode *node, char *dest, BOOL bMethod, int *methodDest) {
+ strcpy(dest, node->text);
+ TlenUrlDecode(dest);
+ if (bMethod) {
+ char *method = JabberXmlGetAttrValue(node, "method");
+ if (method != NULL && !strcmpi(method, "POST")) {
+ *methodDest = REQUEST_POST;
+ } else {
+ *methodDest = REQUEST_GET;
+ }
+ }
+}
+
+void TlenIqResultTcfg(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode, *miniMailNode, *node;
+ char *type;
+
+ if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
+ if (!strcmp(type, "result")) {
+ if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;
+ if ((miniMailNode=JabberXmlGetChild(queryNode, "mini-mail")) == NULL) return;
+ if ((node=JabberXmlGetChild(miniMailNode, "base")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.mailBase, FALSE, NULL);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "msg")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.mailMsg, TRUE, &proto->threadData->tlenConfig.mailMsgMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "index")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.mailIndex, TRUE, &proto->threadData->tlenConfig.mailIndexMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "login")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.mailLogin, TRUE, &proto->threadData->tlenConfig.mailLoginMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "compose")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.mailCompose, TRUE, &proto->threadData->tlenConfig.mailComposeMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "avatar-get")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.avatarGet, TRUE, &proto->threadData->tlenConfig.avatarGetMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "avatar-upload")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.avatarUpload, TRUE, &proto->threadData->tlenConfig.avatarUploadMthd);
+ }
+ if ((node=JabberXmlGetChild(miniMailNode, "avatar-remove")) != NULL) {
+ GetConfigItem(node, proto->threadData->tlenConfig.avatarRemove, TRUE, &proto->threadData->tlenConfig.avatarRemoveMthd);
+ }
+ }
+}
+
+void TlenIqResultVersion(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode = JabberXmlGetChild(iqNode, "query");
+ if (queryNode != NULL) {
+ char* from;
+ if (( from=JabberXmlGetAttrValue( iqNode, "from" )) != NULL ) {
+ JABBER_LIST_ITEM *item;
+ if (( item=JabberListGetItemPtr( proto, LIST_ROSTER, from )) != NULL) {
+ HANDLE hContact;
+ XmlNode *n;
+ if ( item->software ) mir_free( item->software );
+ if ( item->version ) mir_free( item->version );
+ if ( item->system ) mir_free( item->system );
+ if (( n=JabberXmlGetChild( queryNode, "name" )) != NULL && n->text ) {
+ item->software = JabberTextDecode( n->text );
+ } else
+ item->software = NULL;
+ if (( n=JabberXmlGetChild( queryNode, "version" )) != NULL && n->text )
+ item->version = JabberTextDecode( n->text );
+ else
+ item->version = NULL;
+ if (( n=JabberXmlGetChild( queryNode, "os" )) != NULL && n->text )
+ item->system = JabberTextDecode( n->text );
+ else
+ item->system = NULL;
+ if (( hContact=JabberHContactFromJID(proto, item->jid )) != NULL ) {
+ if (item->software != NULL) {
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "MirVer", item->software);
+ } else {
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "MirVer");
+ }
+ }
+ }
+ }
+ }
+}
+
+void TlenIqResultInfo(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *queryNode = JabberXmlGetChild(iqNode, "query");
+ if (queryNode != NULL) {
+ char* from;
+ if (( from=JabberXmlGetAttrValue( queryNode, "from" )) != NULL ) {
+ JABBER_LIST_ITEM *item;
+ if (( item=JabberListGetItemPtr( proto, LIST_ROSTER, from )) != NULL) {
+ HANDLE hContact;
+ XmlNode *version = JabberXmlGetChild(queryNode, "version");
+ item->protocolVersion = JabberTextDecode(version->text);
+ if (( hContact=JabberHContactFromJID(proto, item->jid )) != NULL ) {
+ if (item->software == NULL) {
+ char str[128];
+ mir_snprintf(str, sizeof(str), "Tlen Protocol %s", item->protocolVersion);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "MirVer", str);
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/protocols/Tlen/src/jabber_list.cpp b/protocols/Tlen/src/jabber_list.cpp
new file mode 100644
index 0000000000..de9fe21c78
--- /dev/null
+++ b/protocols/Tlen/src/jabber_list.cpp
@@ -0,0 +1,315 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+
+
+static void JabberListFreeItemInternal(JABBER_LIST_ITEM *item);
+
+void JabberListInit(TlenProtocol *proto)
+{
+ proto->lists = NULL;
+ proto->listsCount = 0;
+ InitializeCriticalSection(&proto->csLists);
+}
+
+void JabberListUninit(TlenProtocol *proto)
+{
+ JabberListWipe(proto);
+ DeleteCriticalSection(&proto->csLists);
+}
+
+void JabberListWipe(TlenProtocol *proto)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csLists);
+ for (i=0; i<proto->listsCount; i++)
+ JabberListFreeItemInternal(&(proto->lists[i]));
+ if (proto->lists != NULL) {
+ mir_free(proto->lists);
+ proto->lists = NULL;
+ }
+ proto->listsCount=0;
+ LeaveCriticalSection(&proto->csLists);
+}
+
+void JabberListWipeSpecial(TlenProtocol *proto)
+{
+ int i;
+ EnterCriticalSection(&proto->csLists);
+ for (i=0; i<proto->listsCount; i++) {
+ if (proto->lists[i].list != LIST_FILE && proto->lists[i].list != LIST_VOICE) {
+ JabberListFreeItemInternal(&(proto->lists[i]));
+ proto->listsCount--;
+ memmove(proto->lists+i, proto->lists+i+1, sizeof(JABBER_LIST_ITEM)*(proto->listsCount-i));
+ i--;
+ }
+ }
+ proto->lists = (JABBER_LIST_ITEM *) mir_realloc(proto->lists, sizeof(JABBER_LIST_ITEM)*proto->listsCount);
+ LeaveCriticalSection(&proto->csLists);
+}
+
+static void JabberListFreeItemInternal(JABBER_LIST_ITEM *item)
+{
+ if (item == NULL)
+ return;
+
+ if (item->jid) mir_free(item->jid);
+ if (item->nick) mir_free(item->nick);
+ if (item->statusMessage) mir_free(item->statusMessage);
+ if (item->group) mir_free(item->group);
+ if (item->messageEventIdStr) mir_free(item->messageEventIdStr);
+// if (item->type) mir_free(item->type);
+ //if (item->ft) JabberFileFreeFt(item->ft); // No need to free (it is always free when exit from JabberFileServerThread())
+ if (item->roomName) mir_free(item->roomName);
+ if (item->version) mir_free(item->version);
+ if (item->software) mir_free(item->software);
+ if (item->system) mir_free(item->system);
+ if (item->avatarHash) mir_free(item->avatarHash);
+
+ if (item->protocolVersion) mir_free(item->protocolVersion);
+ if (item->id2) mir_free(item->id2);
+}
+
+static char * GetItemId(JABBER_LIST list, const char *jid)
+{
+ char *s, *p, *q;
+ s = mir_strdup(jid);
+ if (list != LIST_PICTURE) {
+ _strlwr(s);
+ // strip resouce name if any
+ if ((p=strchr(s, '@')) != NULL) {
+ if ((q=strchr(p, '/')) != NULL)
+ *q = '\0';
+ }
+ }
+ return s;
+}
+
+
+int JabberListExist(TlenProtocol *proto, JABBER_LIST list, const char *jid)
+{
+ int i;
+ size_t len;
+ char *s, *p;
+ s = GetItemId(list, jid);
+ len = strlen(s);
+
+ EnterCriticalSection(&proto->csLists);
+ for (i=0; i<proto->listsCount; i++)
+ if (proto->lists[i].list == list) {
+ p = proto->lists[i].jid;
+ if (p && strlen(p) >= len && (p[(int)len] == '\0' || p[(int)len] == '/') && !strncmp(p, s, len)) {
+ LeaveCriticalSection(&proto->csLists);
+ mir_free(s);
+ return i+1;
+ }
+ }
+ LeaveCriticalSection(&proto->csLists);
+ mir_free(s);
+ return 0;
+}
+
+JABBER_LIST_ITEM *JabberListAdd(TlenProtocol *proto, JABBER_LIST list, const char *jid)
+{
+ char *s;
+ JABBER_LIST_ITEM *item;
+
+ EnterCriticalSection(&proto->csLists);
+ if ((item=JabberListGetItemPtr(proto, list, jid)) != NULL) {
+ LeaveCriticalSection(&proto->csLists);
+ return item;
+ }
+
+ s = GetItemId(list, jid);
+ proto->lists = (JABBER_LIST_ITEM *) mir_realloc(proto->lists, sizeof(JABBER_LIST_ITEM)*(proto->listsCount+1));
+ item = &(proto->lists[proto->listsCount]);
+ memset(item, 0, sizeof(JABBER_LIST_ITEM));
+ item->list = list;
+ item->jid = s;
+ item->nick = NULL;
+ item->status = ID_STATUS_OFFLINE;
+ item->statusMessage = NULL;
+ item->group = NULL;
+ item->messageEventIdStr = NULL;
+ item->wantComposingEvent = FALSE;
+ item->isTyping = FALSE;
+// item->type = NULL;
+ item->ft = NULL;
+ item->roomName = NULL;
+ item->version = NULL;
+ item->software = NULL;
+ item->system = NULL;
+ item->avatarHash = NULL;
+ item->avatarFormat = PA_FORMAT_UNKNOWN;
+ item->newAvatarDownloading = FALSE;
+ item->versionRequested = FALSE;
+ item->infoRequested = FALSE;
+ proto->listsCount++;
+ LeaveCriticalSection(&proto->csLists);
+
+ return item;
+}
+
+void JabberListRemove(TlenProtocol *proto, JABBER_LIST list, const char *jid)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csLists);
+ i = JabberListExist(proto, list, jid);
+ if (!i) {
+ LeaveCriticalSection(&proto->csLists);
+ return;
+ }
+ i--;
+ JabberListFreeItemInternal(&(proto->lists[i]));
+ proto->listsCount--;
+ memmove(proto->lists+i, proto->lists+i+1, sizeof(JABBER_LIST_ITEM)*(proto->listsCount-i));
+ proto->lists = (JABBER_LIST_ITEM *) mir_realloc(proto->lists, sizeof(JABBER_LIST_ITEM)*proto->listsCount);
+ LeaveCriticalSection(&proto->csLists);
+}
+
+void JabberListRemoveList(TlenProtocol *proto, JABBER_LIST list)
+{
+ int i;
+
+ i = 0;
+ while ((i=JabberListFindNext(proto, list, i)) >= 0) {
+ JabberListRemoveByIndex(proto, i);
+ }
+}
+
+void JabberListRemoveByIndex(TlenProtocol *proto, int index)
+{
+ EnterCriticalSection(&proto->csLists);
+ if (index >= 0 && index<proto->listsCount) {
+ JabberListFreeItemInternal(&(proto->lists[index]));
+ proto->listsCount--;
+ memmove(proto->lists+index, proto->lists+index+1, sizeof(JABBER_LIST_ITEM)*(proto->listsCount-index));
+ proto->lists = (JABBER_LIST_ITEM *) mir_realloc(proto->lists, sizeof(JABBER_LIST_ITEM)*proto->listsCount);
+ }
+ LeaveCriticalSection(&proto->csLists);
+}
+
+void JabberListAddResource(TlenProtocol *proto, JABBER_LIST list, const char *jid, int status, const char *statusMessage)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csLists);
+ i = JabberListExist(proto, list, jid);
+ if (!i) {
+ LeaveCriticalSection(&proto->csLists);
+ return;
+ }
+ i--;
+
+ if (proto->lists[i].statusMessage != NULL)
+ mir_free(proto->lists[i].statusMessage);
+ if (statusMessage)
+ proto->lists[i].statusMessage = mir_strdup(statusMessage);
+ else
+ proto->lists[i].statusMessage = NULL;
+ LeaveCriticalSection(&proto->csLists);
+}
+
+void JabberListRemoveResource(TlenProtocol *proto, JABBER_LIST list, const char *jid)
+{
+ int i;
+ EnterCriticalSection(&proto->csLists);
+ i = JabberListExist(proto, list, jid);
+ if (!i) {
+ LeaveCriticalSection(&proto->csLists);
+ return;
+ }
+ i--;
+ LeaveCriticalSection(&proto->csLists);
+}
+
+int JabberListFindNext(TlenProtocol *proto, JABBER_LIST list, int fromOffset)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csLists);
+ i = (fromOffset >= 0) ? fromOffset : 0;
+ for (; i<proto->listsCount; i++)
+ if (proto->lists[i].list == list) {
+ LeaveCriticalSection(&proto->csLists);
+ return i;
+ }
+ LeaveCriticalSection(&proto->csLists);
+ return -1;
+}
+
+JABBER_LIST_ITEM *JabberListGetItemPtr(TlenProtocol *proto, JABBER_LIST list, const char *jid)
+{
+ int i;
+
+ EnterCriticalSection(&proto->csLists);
+ i = JabberListExist(proto, list, jid);
+ if (!i) {
+ LeaveCriticalSection(&proto->csLists);
+ return NULL;
+ }
+ i--;
+ LeaveCriticalSection(&proto->csLists);
+ return &(proto->lists[i]);
+}
+
+JABBER_LIST_ITEM *JabberListFindItemPtrById2(TlenProtocol *proto, JABBER_LIST list, const char *id)
+{
+
+ int i;
+ size_t len;
+ char *p;
+
+ len = strlen(id);
+
+ EnterCriticalSection(&proto->csLists);
+ for (i=0; i<proto->listsCount; i++) {
+ if (proto->lists[i].list == list) {
+ p = proto->lists[i].id2;
+ if (p != NULL) {
+ if (!strncmp(p, id, len)) {
+ LeaveCriticalSection(&proto->csLists);
+ return &(proto->lists[i]);
+ }
+ }
+ }
+ }
+ LeaveCriticalSection(&proto->csLists);
+ return NULL;
+}
+
+JABBER_LIST_ITEM *JabberListGetItemPtrFromIndex(TlenProtocol *proto, int index)
+{
+ EnterCriticalSection(&proto->csLists);
+ if (index >= 0 && index<proto->listsCount) {
+ LeaveCriticalSection(&proto->csLists);
+ return &(proto->lists[index]);
+ }
+ LeaveCriticalSection(&proto->csLists);
+ return NULL;
+}
+
diff --git a/protocols/Tlen/src/jabber_list.h b/protocols/Tlen/src/jabber_list.h
new file mode 100644
index 0000000000..30eb1abbdb
--- /dev/null
+++ b/protocols/Tlen/src/jabber_list.h
@@ -0,0 +1,90 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+
+#ifndef _JABBER_LIST_H_
+#define _JABBER_LIST_H_
+
+typedef struct JABBER_LIST_ITEM_STRUCT {
+ JABBER_LIST list;
+ char *jid;
+ char *id2;
+
+ // LIST_ROSTER
+ // jid = jid of the contact
+ char *nick;
+ int status; // Main status, currently useful for transport where no resource information is kept.
+ // On normal contact, this is the same status as shown on contact list.
+ JABBER_SUBSCRIPTION subscription;
+ char *statusMessage; // Status message when the update is to JID with no resource specified (e.g. transport user)
+ char *software;
+ char *version;
+ char *system;
+ char *group;
+ char *protocolVersion;
+ int avatarFormat;
+ char *avatarHash;
+ BOOL newAvatarDownloading;
+ BOOL versionRequested;
+ BOOL infoRequested;
+ int idMsgAckPending;
+ char *messageEventIdStr;
+ BOOL wantComposingEvent;
+ BOOL isTyping;
+
+ // LIST_ROOM
+ // jid = room JID
+ // char *name; // room name
+ //char *type; // room type
+
+ // LIST_CHATROOM
+ // jid = room JID
+ // char *nick; // my nick in this chat room (SPECIAL: in UTF8)
+ // JABBER_RESOURCE_STATUS *resource; // participant nicks in this room
+ char *roomName;
+
+ // LIST_FILE
+ struct TLEN_FILE_TRANSFER_STRUCT *ft;
+} JABBER_LIST_ITEM;
+
+
+void JabberListInit(TlenProtocol *proto);
+void JabberListUninit(TlenProtocol *proto);
+void JabberListWipe(TlenProtocol *proto);
+void JabberListWipeSpecial(TlenProtocol *proto);
+int JabberListExist(TlenProtocol *proto, JABBER_LIST list, const char *jid);
+JABBER_LIST_ITEM *JabberListAdd(TlenProtocol *proto, JABBER_LIST list, const char *jid);
+void JabberListRemove(TlenProtocol *proto, JABBER_LIST list, const char *jid);
+void JabberListRemoveList(TlenProtocol *proto, JABBER_LIST list);
+void JabberListRemoveByIndex(TlenProtocol *proto, int index);
+int JabberListFindNext(TlenProtocol *proto, JABBER_LIST list, int fromOffset);
+JABBER_LIST_ITEM *JabberListGetItemPtr(TlenProtocol *proto, JABBER_LIST list, const char *jid);
+JABBER_LIST_ITEM *JabberListGetItemPtrFromIndex(TlenProtocol *proto, int index);
+JABBER_LIST_ITEM *JabberListFindItemPtrById2(TlenProtocol *proto, JABBER_LIST list, const char *id);
+
+void JabberListAddResource(TlenProtocol *proto, JABBER_LIST list, const char *jid, int status, const char *statusMessage);
+void JabberListRemoveResource(TlenProtocol *proto, JABBER_LIST list, const char *jid);
+
+#endif
+
diff --git a/protocols/Tlen/src/jabber_misc.cpp b/protocols/Tlen/src/jabber_misc.cpp
new file mode 100644
index 0000000000..c9db7eed21
--- /dev/null
+++ b/protocols/Tlen/src/jabber_misc.cpp
@@ -0,0 +1,218 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+
+void JabberDBAddEvent(TlenProtocol *proto, HANDLE hContact, int eventType, DWORD flags, PBYTE pBlob, DWORD cbBlob)
+{
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(DBEVENTINFO);
+ dbei.szModule = proto->m_szModuleName;
+ dbei.timestamp = (DWORD) time(NULL);
+ dbei.flags = flags;
+ dbei.eventType = eventType;
+ dbei.cbBlob = cbBlob;
+ dbei.pBlob = pBlob;
+ CallService(MS_DB_EVENT_ADD, (WPARAM) hContact, (LPARAM) &dbei);
+}
+void JabberDBAddAuthRequest(TlenProtocol *proto, char *jid, char *nick)
+{
+ char *s;
+ PBYTE pCurBlob;
+ PBYTE pBlob;
+ DWORD cbBlob;
+ HANDLE hContact;
+
+ if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) proto->m_szModuleName);
+ // strip resource if present
+ s = JabberLoginFromJID(jid);
+ _strlwr(s);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "jid", s);
+ mir_free(s);
+ }
+ else {
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "Hidden");
+ }
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "Nick", nick);
+ JabberLog(proto, "auth request: %s, %s", jid, nick);
+ //blob is: uin(DWORD), hContact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)
+ //blob is: 0(DWORD), hContact(HANDLE), nick(ASCIIZ), ""(ASCIIZ), ""(ASCIIZ), email(ASCIIZ), ""(ASCIIZ)
+ cbBlob = sizeof(DWORD) + sizeof(HANDLE) + (int)strlen(nick) + (int)strlen(jid) + 5;
+ pBlob = pCurBlob = (PBYTE) mir_alloc(cbBlob);
+ *((PDWORD)pCurBlob) = 0; pCurBlob += sizeof(DWORD);
+ *((PHANDLE)pCurBlob) = hContact; pCurBlob += sizeof(DWORD);
+ strcpy((char *) pCurBlob, nick); pCurBlob += strlen(nick)+1;
+ *pCurBlob = '\0'; pCurBlob++; //firstName
+ *pCurBlob = '\0'; pCurBlob++; //lastName
+ strcpy((char *) pCurBlob, jid); pCurBlob += strlen(jid)+1;
+ *pCurBlob = '\0'; //reason
+ JabberDBAddEvent(proto, NULL, EVENTTYPE_AUTHREQUEST, 0, pBlob, cbBlob);
+}
+
+char *JabberJIDFromHContact(TlenProtocol *proto, HANDLE hContact)
+{
+ char *p = NULL;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ p = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ return p;
+}
+
+HANDLE JabberHContactFromJID(TlenProtocol *proto, const char *jid)
+{
+ HANDLE hContact, hContactMatched;
+ DBVARIANT dbv;
+ char *szProto;
+ char *p;
+ if (jid == NULL) return (HANDLE) NULL;
+ hContactMatched = NULL;
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto != NULL && !strcmp(proto->m_szModuleName, szProto)) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ if ((p=dbv.pszVal) != NULL) {
+ if (!stricmp(p, jid)) { // exact match (node@domain/resource)
+ hContactMatched = hContact;
+ DBFreeVariant(&dbv);
+ break;
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ if (hContactMatched != NULL) {
+ return hContactMatched;
+ }
+ return NULL;
+}
+
+HANDLE JabberDBCreateContact(TlenProtocol *proto, char *jid, char *nick, BOOL temporary)
+{
+ HANDLE hContact;
+ if (jid == NULL || jid[0] == '\0')
+ return NULL;
+
+ if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) proto->m_szModuleName);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "jid", jid);
+ if (nick != NULL && nick[0] != '\0')
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "Nick", nick);
+ if (temporary)
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ }
+ return hContact;
+}
+
+static void JabberContactListCreateClistGroup(char *groupName)
+{
+ char str[33], newName[128];
+ int i;
+ DBVARIANT dbv;
+ char *name;
+
+ for (i=0;;i++) {
+ itoa(i, str, 10);
+ if (DBGetContactSetting(NULL, "CListGroups", str, &dbv))
+ break;
+ name = dbv.pszVal;
+ if (name[0] != '\0' && !strcmp(name+1, groupName)) {
+ // Already exist, no need to create
+ DBFreeVariant(&dbv);
+ return;
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ // Create new group with id = i (str is the text representation of i)
+ newName[0] = 1 | GROUPF_EXPANDED;
+ strncpy(newName+1, groupName, sizeof(newName)-1);
+ newName[sizeof(newName)-1] = '\0';
+ DBWriteContactSettingString(NULL, "CListGroups", str, newName);
+ CallService(MS_CLUI_GROUPADDED, i+1, 0);
+}
+
+void JabberContactListCreateGroup(char *groupName)
+{
+ char name[128];
+ char *p;
+
+ if (groupName == NULL || groupName[0] == '\0' || groupName[0] == '\\') return;
+
+ strncpy(name, groupName, sizeof(name));
+ name[sizeof(name)-1] = '\0';
+ for (p=name; *p != '\0'; p++) {
+ if (*p == '\\') {
+ *p = '\0';
+ JabberContactListCreateClistGroup(name);
+ *p = '\\';
+ }
+ }
+ JabberContactListCreateClistGroup(name);
+}
+
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void (__cdecl *threadcode)(void*);
+ void *arg;
+};
+
+static void __cdecl forkthread_r(struct FORK_ARG *fa)
+{
+ void (*callercode)(void*) = fa->threadcode;
+ void *arg = fa->arg;
+ Thread_Push(0);
+ SetEvent(fa->hEvent);
+ callercode(arg);
+ Thread_Pop();
+ return;
+}
+
+unsigned long JabberForkThread(
+ void (__cdecl *threadcode)(void*),
+ unsigned long stacksize,
+ void *arg
+)
+{
+ unsigned long rc;
+ struct FORK_ARG fa;
+
+ fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+ rc = _beginthread((void (__cdecl *)(void*))forkthread_r, stacksize, &fa);
+ if ((unsigned long) -1L != rc) {
+ WaitForSingleObject(fa.hEvent, INFINITE);
+ }
+ CloseHandle(fa.hEvent);
+ return rc;
+}
diff --git a/protocols/Tlen/src/jabber_opt.cpp b/protocols/Tlen/src/jabber_opt.cpp
new file mode 100644
index 0000000000..297ac34cae
--- /dev/null
+++ b/protocols/Tlen/src/jabber_opt.cpp
@@ -0,0 +1,710 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include "tlen_voice.h"
+#include <commctrl.h>
+#include "resource.h"
+
+static INT_PTR CALLBACK TlenBasicOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK TlenVoiceOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK TlenAdvOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK TlenPopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+typedef struct TabDefStruct {
+ DLGPROC dlgProc;
+ DWORD dlgId;
+ TCHAR *tabName;
+} TabDef;
+
+static TabDef tabPages[] = {
+ {TlenBasicOptDlgProc, IDD_OPTIONS_BASIC, LPGENT("General")},
+ {TlenVoiceOptDlgProc, IDD_OPTIONS_VOICE, LPGENT("Voice Chats")},
+ {TlenAdvOptDlgProc, IDD_OPTIONS_ADVANCED, LPGENT("Advanced")},
+ {TlenPopupsDlgProc, IDD_OPTIONS_POPUPS, LPGENT("Notifications")}
+ };
+
+void TlenLoadOptions(TlenProtocol *proto)
+{
+ proto->tlenOptions.savePassword = DBGetContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", TRUE);
+ proto->tlenOptions.useEncryption = DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseEncryption", TRUE);
+ proto->tlenOptions.reconnect = DBGetContactSettingByte(NULL, proto->m_szModuleName, "Reconnect", TRUE);
+ proto->tlenOptions.alertPolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "AlertPolicy", TLEN_ALERTS_IGNORE_NIR);
+ proto->tlenOptions.rosterSync = DBGetContactSettingByte(NULL, proto->m_szModuleName, "RosterSync", FALSE);
+ proto->tlenOptions.offlineAsInvisible = DBGetContactSettingByte(NULL, proto->m_szModuleName, "OfflineAsInvisible", FALSE);
+ proto->tlenOptions.leaveOfflineMessage = DBGetContactSettingByte(NULL, proto->m_szModuleName, "LeaveOfflineMessage", TRUE);
+ proto->tlenOptions.offlineMessageOption = DBGetContactSettingWord(NULL, proto->m_szModuleName, "OfflineMessageOption", 0);
+ proto->tlenOptions.ignoreAdvertisements = DBGetContactSettingByte(NULL, proto->m_szModuleName, "IgnoreAdvertisements", TRUE);
+ proto->tlenOptions.groupChatPolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "GroupChatPolicy", TLEN_MUC_ASK);
+ proto->tlenOptions.voiceChatPolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "VoiceChatPolicy", TLEN_MUC_ASK);
+ proto->tlenOptions.imagePolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "ImagePolicy",TLEN_IMAGES_IGNORE_NIR);
+ proto->tlenOptions.enableAvatars = DBGetContactSettingByte(NULL, proto->m_szModuleName, "EnableAvatars", TRUE);
+ proto->tlenOptions.enableVersion = DBGetContactSettingByte(NULL, proto->m_szModuleName, "EnableVersion", TRUE);
+ proto->tlenOptions.useNudge = DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseNudge", FALSE);
+ proto->tlenOptions.logAlerts = DBGetContactSettingByte(NULL, proto->m_szModuleName, "LogAlerts", TRUE);
+ proto->tlenOptions.sendKeepAlive = DBGetContactSettingByte(NULL, proto->m_szModuleName, "KeepAlive", TRUE);
+ proto->tlenOptions.useNewP2P = TRUE;
+}
+
+static int changed = 0;
+
+static void ApplyChanges(TlenProtocol *proto, int i) {
+ changed &= ~i;
+ if (changed == 0) {
+ TlenLoadOptions(proto);
+ }
+}
+
+static void MarkChanges(int i, HWND hWnd) {
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+ changed |= i;
+}
+
+
+int TlenOptionsInit(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Network");
+ odp.ptszTitle = proto->m_tszUserName;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.dwInitParam = (LPARAM)proto;
+ for (i = 0; i < SIZEOF(tabPages); i++) {
+ odp.pszTemplate = MAKEINTRESOURCEA(tabPages[i].dlgId);
+ odp.pfnDlgProc = tabPages[i].dlgProc;
+ odp.ptszTab = tabPages[i].tabName;
+ Options_AddPage(wParam, &odp);
+ }
+/*
+ if (ServiceExists(MS_POPUP_ADDPOPUP)) {
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.ptszGroup = TranslateT("PopUps");
+ odp.ptszTitle = proto->m_tszUserName;
+ odp.dwInitParam = (LPARAM)proto;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_POPUPS);
+ odp.pfnDlgProc = TlenPopupsDlgProc;
+ Options_AddPage(wParam, &odp);
+ }
+*/
+ return 0;
+}
+
+static LRESULT CALLBACK JabberValidateUsernameWndProc(HWND hwndEdit, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC oldProc = (WNDPROC) GetWindowLongPtr(hwndEdit, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_CHAR:
+ if (strchr("\"&'/:<>@", wParam&0xff) != NULL)
+ return 0;
+ break;
+ }
+ return CallWindowProc(oldProc, hwndEdit, msg, wParam, lParam);
+}
+
+INT_PTR CALLBACK TlenAccMgrUIDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char text[256];
+ WNDPROC oldProc;
+
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ DBVARIANT dbv;
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ TranslateDialogDefault(hwndDlg);
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "LoginName", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_EDIT_USERNAME, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "Password", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ SetDlgItemTextA(hwndDlg, IDC_EDIT_PASSWORD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ CheckDlgButton(hwndDlg, IDC_SAVEPASSWORD, DBGetContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", TRUE));
+
+ oldProc = (WNDPROC) GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_WNDPROC);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_USERDATA, (LONG_PTR) oldProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_WNDPROC, (LONG_PTR) JabberValidateUsernameWndProc);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_EDIT_USERNAME:
+ case IDC_EDIT_PASSWORD:
+ if ((HWND)lParam == GetFocus() && HIWORD(wParam) == EN_CHANGE)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case IDC_SAVEPASSWORD:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case IDC_REGISTERACCOUNT:
+ CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) TLEN_REGISTER);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ BOOL reconnectRequired = FALSE;
+ DBVARIANT dbv;
+
+ GetDlgItemTextA(hwndDlg, IDC_EDIT_USERNAME, text, sizeof(text));
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "LoginName", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "LoginName", strlwr(text));
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_SAVEPASSWORD)) {
+ GetDlgItemTextA(hwndDlg, IDC_EDIT_PASSWORD, text, sizeof(text));
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(text), (LPARAM) text);
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "Password", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "Password", text);
+ }
+ else
+ DBDeleteContactSetting(NULL, proto->m_szModuleName, "Password");
+
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPASSWORD));
+ if (reconnectRequired && proto->isConnected)
+ MessageBox(hwndDlg, TranslateT("These changes will take effect the next time you connect to the Tlen network."), TranslateT("Tlen Protocol Option"), MB_OK|MB_SETFOREGROUND);
+ TlenLoadOptions(proto);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK TlenBasicOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char text[256];
+ WNDPROC oldProc;
+
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ DBVARIANT dbv;
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ TranslateDialogDefault(hwndDlg);
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "LoginName", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_EDIT_USERNAME, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "Password", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ SetDlgItemTextA(hwndDlg, IDC_EDIT_PASSWORD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ CheckDlgButton(hwndDlg, IDC_SAVEPASSWORD, DBGetContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", TRUE));
+
+ CheckDlgButton(hwndDlg, IDC_RECONNECT, proto->tlenOptions.reconnect);
+ CheckDlgButton(hwndDlg, IDC_ROSTER_SYNC, proto->tlenOptions.rosterSync);
+ CheckDlgButton(hwndDlg, IDC_SHOW_OFFLINE, proto->tlenOptions.offlineAsInvisible);
+ CheckDlgButton(hwndDlg, IDC_OFFLINE_MESSAGE, proto->tlenOptions.leaveOfflineMessage);
+ CheckDlgButton(hwndDlg, IDC_IGNORE_ADVERTISEMENTS, proto->tlenOptions.ignoreAdvertisements);
+ CheckDlgButton(hwndDlg, IDC_AVATARS, proto->tlenOptions.enableAvatars);
+ CheckDlgButton(hwndDlg, IDC_VERSIONINFO, proto->tlenOptions.enableVersion);
+ CheckDlgButton(hwndDlg, IDC_NUDGE_SUPPORT, proto->tlenOptions.useNudge);
+ CheckDlgButton(hwndDlg, IDC_LOG_ALERTS, proto->tlenOptions.logAlerts);
+
+ SendDlgItemMessage(hwndDlg, IDC_ALERT_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept all alerts"));
+ SendDlgItemMessage(hwndDlg, IDC_ALERT_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore alerts from unauthorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_ALERT_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore all alerts"));
+ SendDlgItemMessage(hwndDlg, IDC_ALERT_POLICY, CB_SETCURSEL, proto->tlenOptions.alertPolicy, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Always ask me"));
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept invitations from authorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept all invitations"));
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore invitations from unauthorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore all invitation"));
+ SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_SETCURSEL, proto->tlenOptions.groupChatPolicy, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_IMAGE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept all images"));
+ SendDlgItemMessage(hwndDlg, IDC_IMAGE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore images from unauthorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_IMAGE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore all images"));
+ SendDlgItemMessage(hwndDlg, IDC_IMAGE_POLICY, CB_SETCURSEL, proto->tlenOptions.imagePolicy, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("<Last message>"));
+ //SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("<Ask me>"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Online"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Away"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("NA"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("DND"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Free for chat"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Invisible"));
+ SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_SETCURSEL, proto->tlenOptions.offlineMessageOption, 0);
+
+ oldProc = (WNDPROC) GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_WNDPROC);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_USERDATA, (LONG_PTR) oldProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT_USERNAME), GWLP_WNDPROC, (LONG_PTR) JabberValidateUsernameWndProc);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_EDIT_USERNAME:
+ case IDC_EDIT_PASSWORD:
+ if ((HWND)lParam == GetFocus() && HIWORD(wParam) == EN_CHANGE)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ // Fall through
+ case IDC_SAVEPASSWORD:
+ case IDC_RECONNECT:
+ case IDC_ROSTER_SYNC:
+ case IDC_IGNORE_ADVERTISEMENTS:
+ case IDC_SHOW_OFFLINE:
+ case IDC_OFFLINE_MESSAGE:
+ MarkChanges(1, hwndDlg);
+ break;
+ case IDC_LOG_ALERTS:
+ CheckDlgButton(hwndDlg, IDC_NUDGE_SUPPORT, BST_UNCHECKED);
+ MarkChanges(1, hwndDlg);
+ break;
+ case IDC_NUDGE_SUPPORT:
+ CheckDlgButton(hwndDlg, IDC_LOG_ALERTS, BST_UNCHECKED);
+ MarkChanges(1, hwndDlg);
+ break;
+ case IDC_REGISTERACCOUNT:
+ CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) TLEN_REGISTER);
+ break;
+ case IDC_OFFLINE_MESSAGE_OPTION:
+ case IDC_ALERT_POLICY:
+ case IDC_MUC_POLICY:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ MarkChanges(1, hwndDlg);
+ break;
+ default:
+ MarkChanges(1, hwndDlg);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ BOOL reconnectRequired = FALSE;
+ DBVARIANT dbv;
+
+ GetDlgItemTextA(hwndDlg, IDC_EDIT_USERNAME, text, sizeof(text));
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "LoginName", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "LoginName", strlwr(text));
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_SAVEPASSWORD)) {
+ GetDlgItemTextA(hwndDlg, IDC_EDIT_PASSWORD, text, sizeof(text));
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(text), (LPARAM) text);
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "Password", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "Password", text);
+ }
+ else
+ DBDeleteContactSetting(NULL, proto->m_szModuleName, "Password");
+
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPASSWORD));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "Reconnect", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_RECONNECT));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "RosterSync", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ROSTER_SYNC));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "OfflineAsInvisible", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOW_OFFLINE));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "IgnoreAdvertisements", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_IGNORE_ADVERTISEMENTS));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "LeaveOfflineMessage", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_OFFLINE_MESSAGE));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "OfflineMessageOption", (WORD) SendDlgItemMessage(hwndDlg, IDC_OFFLINE_MESSAGE_OPTION, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "AlertPolicy", (WORD) SendDlgItemMessage(hwndDlg, IDC_ALERT_POLICY, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "GroupChatPolicy", (WORD) SendDlgItemMessage(hwndDlg, IDC_MUC_POLICY, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "ImagePolicy", (WORD) SendDlgItemMessage(hwndDlg, IDC_IMAGE_POLICY, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "EnableAvatars", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AVATARS));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "EnableVersion", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_VERSIONINFO));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "UseNudge", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NUDGE_SUPPORT));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "LogAlerts", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_LOG_ALERTS));
+ if (reconnectRequired && proto->isConnected)
+ MessageBox(hwndDlg, TranslateT("These changes will take effect the next time you connect to the Tlen network."), TranslateT("Tlen Protocol Option"), MB_OK|MB_SETFOREGROUND);
+ ApplyChanges(proto, 1);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK TlenVoiceOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Always ask me"));
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept invitations from authorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Accept all invitations"));
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore invitations from unauthorized contacts"));
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_ADDSTRING, 0, (LPARAM)TranslateT("Ignore all invitation"));
+ SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_SETCURSEL, proto->tlenOptions.voiceChatPolicy, 0);
+ TlenVoiceBuildInDeviceList(proto, GetDlgItem(hwndDlg, IDC_VOICE_DEVICE_IN));
+ TlenVoiceBuildOutDeviceList(proto, GetDlgItem(hwndDlg, IDC_VOICE_DEVICE_OUT));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_VOICE_POLICY:
+ case IDC_VOICE_DEVICE_IN:
+ case IDC_VOICE_DEVICE_OUT:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ MarkChanges(2, hwndDlg);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "VoiceChatPolicy", (WORD) SendDlgItemMessage(hwndDlg, IDC_VOICE_POLICY, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "VoiceDeviceIn", (WORD) SendDlgItemMessage(hwndDlg, IDC_VOICE_DEVICE_IN, CB_GETCURSEL, 0, 0));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "VoiceDeviceOut", (WORD) SendDlgItemMessage(hwndDlg, IDC_VOICE_DEVICE_OUT, CB_GETCURSEL, 0, 0));
+ ApplyChanges(proto, 2);
+ return TRUE;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK TlenAdvOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char text[256];
+ BOOL bChecked;
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ DBVARIANT dbv;
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ TranslateDialogDefault(hwndDlg);
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_EDIT_LOGIN_SERVER, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_EDIT_LOGIN_SERVER, _T("tlen.pl"));
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_HOST), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_HOSTPORT), TRUE);
+
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "ManualHost", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_HOST, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else
+ SetDlgItemText(hwndDlg, IDC_HOST, _T("s1.tlen.pl"));
+ SetDlgItemInt(hwndDlg, IDC_HOSTPORT, DBGetContactSettingWord(NULL, proto->m_szModuleName, "ManualPort", TLEN_DEFAULT_PORT), FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_KEEPALIVE, DBGetContactSettingByte(NULL, proto->m_szModuleName, "KeepAlive", TRUE));
+
+ CheckDlgButton(hwndDlg, IDC_USE_SSL, DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseEncryption", TRUE));
+
+ CheckDlgButton(hwndDlg, IDC_VISIBILITY_SUPPORT, DBGetContactSettingByte(NULL, proto->m_szModuleName, "VisibilitySupport", FALSE));
+ // File transfer options
+ bChecked = FALSE;
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseFileProxy", FALSE) == TRUE) {
+ bChecked = TRUE;
+ CheckDlgButton(hwndDlg, IDC_FILE_USE_PROXY, TRUE);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_TYPE_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_TYPE), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_HOST_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_HOST), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PORT_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PORT), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USE_AUTH), bChecked);
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "FileProxyAuth", FALSE) == TRUE) {
+ CheckDlgButton(hwndDlg, IDC_FILE_PROXY_USE_AUTH, TRUE);
+ } else {
+ bChecked = FALSE;
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USER_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USER), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PASSWORD_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PASSWORD), bChecked);
+
+ SendDlgItemMessage(hwndDlg, IDC_FILE_PROXY_TYPE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Forwarding"));
+ SendDlgItemMessage(hwndDlg, IDC_FILE_PROXY_TYPE, CB_ADDSTRING, 0, (LPARAM)TranslateT("SOCKS4"));
+ SendDlgItemMessage(hwndDlg, IDC_FILE_PROXY_TYPE, CB_ADDSTRING, 0, (LPARAM)TranslateT("SOCKS5"));
+ SendDlgItemMessage(hwndDlg, IDC_FILE_PROXY_TYPE, CB_SETCURSEL, DBGetContactSettingWord(NULL, proto->m_szModuleName, "FileProxyType", 0), 0);
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "FileProxyHost", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_FILE_PROXY_HOST, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ SetDlgItemInt(hwndDlg, IDC_FILE_PROXY_PORT, DBGetContactSettingWord(NULL, proto->m_szModuleName, "FileProxyPort", 0), FALSE);
+ if (!DBGetContactSettingTString(NULL, proto->m_szModuleName, "FileProxyUsername", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_FILE_PROXY_USER, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "FileProxyPassword", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ SetDlgItemTextA(hwndDlg, IDC_FILE_PROXY_PASSWORD, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam)) {
+ case IDC_FILE_PROXY_TYPE:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ MarkChanges(4, hwndDlg);
+ break;
+ case IDC_EDIT_LOGIN_SERVER:
+ case IDC_HOST:
+ case IDC_HOSTPORT:
+ case IDC_FILE_PROXY_HOST:
+ case IDC_FILE_PROXY_PORT:
+ case IDC_FILE_PROXY_USER:
+ case IDC_FILE_PROXY_PASSWORD:
+ if ((HWND)lParam == GetFocus() && HIWORD(wParam) == EN_CHANGE)
+ MarkChanges(4, hwndDlg);
+ break;
+ case IDC_FILE_USE_PROXY:
+ bChecked = IsDlgButtonChecked(hwndDlg, IDC_FILE_USE_PROXY);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_TYPE_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_TYPE), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_HOST_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_HOST), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PORT_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PORT), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USE_AUTH), bChecked);
+ case IDC_FILE_PROXY_USE_AUTH:
+ bChecked = IsDlgButtonChecked(hwndDlg, IDC_FILE_PROXY_USE_AUTH) & IsDlgButtonChecked(hwndDlg, IDC_FILE_USE_PROXY);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USER_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_USER), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PASSWORD_LABEL), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILE_PROXY_PASSWORD), bChecked);
+ MarkChanges(4, hwndDlg);
+ break;
+ case IDC_KEEPALIVE:
+ case IDC_VISIBILITY_SUPPORT:
+ case IDC_USE_SSL:
+ MarkChanges(4, hwndDlg);
+ break;
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ WORD port;
+ BOOL useEncryption;
+ BOOL reconnectRequired = FALSE;
+ DBVARIANT dbv;
+ GetDlgItemTextA(hwndDlg, IDC_EDIT_LOGIN_SERVER, text, sizeof(text));
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "LoginServer", strlwr(text));
+
+ GetDlgItemTextA(hwndDlg, IDC_HOST, text, sizeof(text));
+ if (DBGetContactSetting(NULL, proto->m_szModuleName, "ManualHost", &dbv) || strcmp(text, dbv.pszVal))
+ reconnectRequired = TRUE;
+ if (dbv.pszVal != NULL) DBFreeVariant(&dbv);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "ManualHost", text);
+
+ port = (WORD) GetDlgItemInt(hwndDlg, IDC_HOSTPORT, NULL, FALSE);
+ if (DBGetContactSettingWord(NULL, proto->m_szModuleName, "ManualPort", TLEN_DEFAULT_PORT) != port)
+ reconnectRequired = TRUE;
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "ManualPort", port);
+
+ proto->tlenOptions.sendKeepAlive = IsDlgButtonChecked(hwndDlg, IDC_KEEPALIVE);
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "KeepAlive", (BYTE) proto->tlenOptions.sendKeepAlive);
+
+ useEncryption = IsDlgButtonChecked(hwndDlg, IDC_USE_SSL);
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseEncryption", TRUE) != useEncryption)
+ reconnectRequired = TRUE;
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "UseEncryption", (BYTE) useEncryption);
+
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "VisibilitySupport", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_VISIBILITY_SUPPORT));
+ // File transfer options
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "UseFileProxy", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FILE_USE_PROXY));
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "FileProxyType", (WORD) SendDlgItemMessage(hwndDlg, IDC_FILE_PROXY_TYPE, CB_GETCURSEL, 0, 0));
+ GetDlgItemTextA(hwndDlg, IDC_FILE_PROXY_HOST, text, sizeof(text));
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "FileProxyHost", text);
+ DBWriteContactSettingWord(NULL, proto->m_szModuleName, "FileProxyPort", (WORD) GetDlgItemInt(hwndDlg, IDC_FILE_PROXY_PORT, NULL, FALSE));
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "FileProxyAuth", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FILE_PROXY_USE_AUTH));
+ GetDlgItemTextA(hwndDlg, IDC_FILE_PROXY_USER, text, sizeof(text));
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "FileProxyUsername", text);
+ GetDlgItemTextA(hwndDlg, IDC_FILE_PROXY_PASSWORD, text, sizeof(text));
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(text), (LPARAM) text);
+ DBWriteContactSettingString(NULL, proto->m_szModuleName, "FileProxyPassword", text);
+ if (reconnectRequired && proto->isConnected)
+ MessageBox(hwndDlg, TranslateT("These changes will take effect the next time you connect to the Tlen network."), TranslateT("Tlen Protocol Option"), MB_OK|MB_SETFOREGROUND);
+ ApplyChanges(proto, 4);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_DESTROY:
+ break;
+ }
+
+ return FALSE;
+}
+
+#define POPUP_DEFAULT_COLORBKG 0xDCBDA5
+#define POPUP_DEFAULT_COLORTXT 0x000000
+
+static void MailPopupPreview(DWORD colorBack, DWORD colorText, char *title, char *emailInfo, int delay)
+{
+ POPUPDATAEX ppd;
+ char * lpzContactName;
+ char * lpzText;
+ HICON hIcon;
+ lpzContactName = title;
+ lpzText = emailInfo;
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = NULL;
+ hIcon = GetIcolibIcon(IDI_MAIL);
+ ppd.lchIcon = CopyIcon(hIcon);
+ ReleaseIcolibIcon(hIcon);
+ strcpy(ppd.lpzContactName, lpzContactName);
+ strcpy(ppd.lpzText, lpzText);
+ ppd.colorBack = colorBack;
+ ppd.colorText = colorText;
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData=NULL;
+ if ( ServiceExists( MS_POPUP_ADDPOPUPEX )) {
+ ppd.iSeconds = delay;
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+
+ }
+ else if ( ServiceExists( MS_POPUP_ADDPOPUP )) {
+ CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0);
+ }
+}
+
+static INT_PTR CALLBACK TlenPopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ BYTE delayMode;
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_ENABLEPOPUP, DBGetContactSettingByte(NULL, proto->m_szModuleName, "MailPopupEnabled", TRUE));
+ SendDlgItemMessage(hwndDlg, IDC_COLORBKG, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupBack", POPUP_DEFAULT_COLORBKG));
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupText", POPUP_DEFAULT_COLORTXT));
+ SetDlgItemInt(hwndDlg, IDC_DELAY, DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupDelay", 4), FALSE);
+ delayMode = DBGetContactSettingByte(NULL, proto->m_szModuleName, "MailPopupDelayMode", 0);
+ if (delayMode == 1) {
+ CheckDlgButton(hwndDlg, IDC_DELAY_CUSTOM, TRUE);
+ } else if (delayMode == 2) {
+ CheckDlgButton(hwndDlg, IDC_DELAY_PERMANENT, TRUE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_DELAY_POPUP, TRUE);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_COLORTXT:
+ case IDC_COLORBKG:
+ case IDC_ENABLEPOPUP:
+ case IDC_DELAY:
+ case IDC_DELAY_POPUP:
+ case IDC_DELAY_CUSTOM:
+ case IDC_DELAY_PERMANENT:
+ MarkChanges(8, hwndDlg);
+ break;
+ case IDC_PREVIEW:
+ {
+ int delay;
+ char title[256];
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_POPUP)) {
+ delay=0;
+ } else if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_PERMANENT)) {
+ delay=-1;
+ } else {
+ delay=GetDlgItemInt(hwndDlg, IDC_DELAY, NULL, FALSE);
+ }
+ _snprintf(title, sizeof(title), Translate("%s mail"), proto->m_szProtoName);
+ MailPopupPreview((DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORBKG,CPM_GETCOLOUR,0,0),
+ (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORTXT,CPM_GETCOLOUR,0,0),
+ title,
+ "From: test@test.test\nSubject: test",
+ delay);
+ }
+
+ }
+ break;
+
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ BYTE delayMode;
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "MailPopupEnabled", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ENABLEPOPUP));
+ DBWriteContactSettingDword(NULL, proto->m_szModuleName, "MailPopupBack", (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORBKG,CPM_GETCOLOUR,0,0));
+ DBWriteContactSettingDword(NULL, proto->m_szModuleName, "MailPopupText", (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORTXT,CPM_GETCOLOUR,0,0));
+ DBWriteContactSettingDword(NULL, proto->m_szModuleName, "MailPopupDelay", (DWORD) GetDlgItemInt(hwndDlg,IDC_DELAY, NULL, FALSE));
+ delayMode=0;
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_CUSTOM)) {
+ delayMode=1;
+ } else if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_PERMANENT)) {
+ delayMode=2;
+
+ }
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, "MailPopupDelayMode", delayMode);
+ ApplyChanges(proto, 8);
+ return TRUE;
+ }
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
diff --git a/protocols/Tlen/src/jabber_svc.cpp b/protocols/Tlen/src/jabber_svc.cpp
new file mode 100644
index 0000000000..345490df30
--- /dev/null
+++ b/protocols/Tlen/src/jabber_svc.cpp
@@ -0,0 +1,1364 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "resource.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "tlen_p2p_old.h"
+#include "tlen_avatar.h"
+#include "tlen_file.h"
+
+extern int TlenOnModulesLoaded(void *ptr, WPARAM wParam, LPARAM lParam);
+extern int TlenOptionsInit(void *ptr, WPARAM wParam, LPARAM lParam);
+extern int TlenPreShutdown(void *ptr, WPARAM wParam, LPARAM lParam);
+extern int TlenSystemModulesLoaded(void *ptr, WPARAM wParam, LPARAM lParam);
+extern int TlenPrebuildContactMenu(void *ptr, WPARAM wParam, LPARAM lParam);
+
+
+DWORD_PTR __cdecl TlenProtocol::GetCaps(int type, HANDLE hContact)
+{
+ if (type == PFLAGNUM_1)
+ return PF1_IM|PF1_AUTHREQ|PF1_SERVERCLIST|PF1_MODEMSG|PF1_BASICSEARCH|PF1_SEARCHBYEMAIL|PF1_EXTSEARCH|PF1_EXTSEARCHUI|PF1_SEARCHBYNAME|PF1_FILE;//|PF1_VISLIST|PF1_INVISLIST;
+ if (type == PFLAGNUM_2)
+ return PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_HEAVYDND|PF2_FREECHAT;
+ if (type == PFLAGNUM_3)
+ return PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_HEAVYDND|PF2_FREECHAT;
+ if (type == PFLAGNUM_4)
+ return PF4_FORCEAUTH|PF4_NOCUSTOMAUTH|PF4_SUPPORTTYPING|PF4_AVATARS|PF4_IMSENDOFFLINE|PF4_OFFLINEFILES;
+ if (type == PFLAG_UNIQUEIDTEXT)
+ return (DWORD_PTR) Translate("Tlen login");
+ if (type == PFLAG_UNIQUEIDSETTING)
+ return (DWORD_PTR) "jid";
+ return 0;
+}
+
+INT_PTR TlenGetName(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ strncpy((char *) lParam, proto->m_szProtoName, wParam);
+ return 0;
+}
+
+HICON __cdecl TlenProtocol::GetIcon(int iconIndex)
+{
+ if ((iconIndex&0xffff) == PLI_PROTOCOL) {
+ HICON hIcon = GetIcolibIcon(IDI_TLEN);
+ HICON hIconCopy = CopyIcon(hIcon);
+ ReleaseIcolibIcon(hIcon);
+ return hIconCopy;
+ }
+ return (HICON) NULL;
+}
+
+int TlenRunSearch(TlenProtocol *proto) {
+ int iqId = 0;
+ if (!proto->isOnline) return 0;
+ if (proto->searchQuery != NULL && proto->searchIndex < 10) {
+ iqId = proto->searchID;
+ JabberIqAdd(proto, iqId, IQ_PROC_GETSEARCH, JabberIqResultSearch);
+ if (proto->searchIndex == 0) {
+ JabberSend(proto, "<iq type='get' id='"JABBER_IQID"%d' to='tuba'><query xmlns='jabber:iq:search'>%s</query></iq>", iqId, proto->searchQuery);
+ } else {
+ JabberSend(proto, "<iq type='get' id='"JABBER_IQID"%d' to='tuba'><query xmlns='jabber:iq:search'>%s<f>%d</f></query></iq>", iqId, proto->searchQuery, proto->searchIndex * TLEN_MAX_SEARCH_RESULTS_PER_PAGE);
+ }
+ proto->searchIndex ++;
+ }
+ return iqId;
+}
+
+void TlenResetSearchQuery(TlenProtocol *proto) {
+ if (proto->searchQuery != NULL) {
+ mir_free(proto->searchQuery);
+ proto->searchQuery = NULL;
+ }
+ proto->searchQueryLen = 0;
+ proto->searchIndex = 0;
+ proto->searchID = JabberSerialNext(proto);
+}
+
+HANDLE __cdecl TlenProtocol::SearchBasic(const PROTOCHAR* id)
+{
+ char *jid;
+ int iqId = 0;
+ if (!isOnline) return 0;
+ if (id == NULL) return 0;
+ char* id_A = mir_t2a(id);
+ if ((jid=JabberTextEncode(id_A)) != NULL) {
+ searchJID = mir_strdup(id_A);
+ TlenResetSearchQuery(this);
+ JabberStringAppend(&searchQuery, &searchQueryLen, "<i>%s</i>", jid);
+ iqId = TlenRunSearch(this);
+ mir_free(jid);
+ }
+ mir_free(id_A);
+ return (HANDLE)iqId;
+}
+
+HANDLE __cdecl TlenProtocol::SearchByEmail(const PROTOCHAR* email)
+{
+ char *emailEnc;
+ int iqId = 0;
+
+ if (!isOnline) return 0;
+ if (email == NULL) return 0;
+
+ char* email_A = mir_t2a(email);
+ if ((emailEnc=JabberTextEncode(email_A)) != NULL) {
+ TlenResetSearchQuery(this);
+ JabberStringAppend(&searchQuery, &searchQueryLen, "<email>%s</email>", emailEnc);
+ iqId = TlenRunSearch(this);
+ mir_free(emailEnc);
+ }
+ mir_free(email_A);
+ return (HANDLE)iqId;
+}
+
+HANDLE __cdecl TlenProtocol::SearchByName(const PROTOCHAR* nickT, const PROTOCHAR* firstNameT, const PROTOCHAR* lastNameT)
+{
+
+ char* nick = mir_t2a(nickT);
+ char* firstName = mir_t2a(firstNameT);
+ char* lastName = mir_t2a(lastNameT);
+
+ char *p;
+ int iqId = 0;
+
+ if (!isOnline) return 0;
+
+ TlenResetSearchQuery(this);
+
+ if (nick != NULL && nick[0] != '\0') {
+ if ((p=JabberTextEncode(nick)) != NULL) {
+ JabberStringAppend(&searchQuery, &searchQueryLen, "<nick>%s</nick>", p);
+ mir_free(p);
+ }
+ }
+ if (firstName != NULL && firstName[0] != '\0') {
+ if ((p=JabberTextEncode(firstName)) != NULL) {
+ JabberStringAppend(&searchQuery, &searchQueryLen, "<first>%s</first>", p);
+ mir_free(p);
+ }
+ }
+ if (lastName != NULL && lastName[0] != '\0') {
+ if ((p=JabberTextEncode(lastName)) != NULL) {
+ JabberStringAppend(&searchQuery, &searchQueryLen, "<last>%s</last>", p);
+ mir_free(p);
+ }
+ }
+
+ iqId = TlenRunSearch(this);
+ return (HANDLE)iqId;
+}
+
+HWND __cdecl TlenProtocol::CreateExtendedSearchUI(HWND owner)
+{
+ return (HWND) CreateDialog(hInst, MAKEINTRESOURCE(IDD_ADVSEARCH), owner, TlenAdvSearchDlgProc);
+}
+
+HWND __cdecl TlenProtocol::SearchAdvanced(HWND owner)
+{
+ int iqId;
+ if (!isOnline) return 0;
+
+ TlenResetSearchQuery(this);
+ iqId = JabberSerialNext(this);
+ if ((searchQuery = TlenAdvSearchCreateQuery(owner, iqId)) != NULL) {
+ iqId = TlenRunSearch(this);
+ }
+ return (HWND)iqId;
+}
+
+
+static HANDLE AddToListByJID(TlenProtocol *proto, const char *newJid, DWORD flags)
+{
+ HANDLE hContact;
+ char *jid, *nick;
+
+ if ((hContact=JabberHContactFromJID(proto, newJid)) == NULL) {
+ // not already there: add
+ jid = mir_strdup(newJid); _strlwr(jid);
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) proto->m_szModuleName);
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "jid", jid);
+ if ((nick=JabberNickFromJID(newJid)) == NULL)
+ nick = mir_strdup(newJid);
+ DBWriteContactSettingString(hContact, "CList", "MyHandle", nick);
+ mir_free(nick);
+ mir_free(jid);
+
+ // Note that by removing or disable the "NotOnList" will trigger
+ // the plugin to add a particular contact to the roster list.
+ // See DBSettingChanged hook at the bottom part of this source file.
+ // But the add module will delete "NotOnList". So we will not do it here.
+ // Also because we need "MyHandle" and "Group" info, which are set after
+ // PS_ADDTOLIST is called but before the add dialog issue deletion of
+ // "NotOnList".
+ // If temporary add, "NotOnList" won't be deleted, and that's expected.
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ if (flags & PALF_TEMPORARY)
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
+ }
+ else {
+ // already exist
+ // Set up a dummy "NotOnList" when adding permanently only
+ if (!(flags&PALF_TEMPORARY))
+ DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
+ }
+
+ return hContact;
+}
+
+HANDLE __cdecl TlenProtocol::AddToList(int flags, PROTOSEARCHRESULT *psr)
+{
+ HANDLE hContact;
+ JABBER_SEARCH_RESULT *jsr = (JABBER_SEARCH_RESULT*)psr;
+ if (jsr->hdr.cbSize != sizeof(JABBER_SEARCH_RESULT))
+ return (int) NULL;
+ hContact = AddToListByJID(this, jsr->jid, flags); // wParam is flag e.g. PALF_TEMPORARY
+ return hContact;
+}
+
+HANDLE __cdecl TlenProtocol::AddToListByEvent( int flags, int iContact, HANDLE hDbEvent )
+{
+ DBEVENTINFO dbei;
+ HANDLE hContact;
+ char *nick, *firstName, *lastName, *jid;
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ if ((dbei.cbBlob=CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == (DWORD)(-1))
+ return (HANDLE) NULL;
+ if ((dbei.pBlob=(PBYTE) mir_alloc(dbei.cbBlob)) == NULL)
+ return (HANDLE) NULL;
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM) &dbei)) {
+ mir_free(dbei.pBlob);
+ return (HANDLE) NULL;
+ }
+ if (strcmp(dbei.szModule, m_szModuleName)) {
+ mir_free(dbei.pBlob);
+ return (HANDLE) NULL;
+ }
+
+/*
+ // EVENTTYPE_CONTACTS is when adding from when we receive contact list (not used in Jabber)
+ // EVENTTYPE_ADDED is when adding from when we receive "You are added" (also not used in Jabber)
+ // Jabber will only handle the case of EVENTTYPE_AUTHREQUEST
+ // EVENTTYPE_AUTHREQUEST is when adding from the authorization request dialog
+*/
+
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST) {
+ mir_free(dbei.pBlob);
+ return (HANDLE) NULL;
+ }
+
+ nick = (char *)dbei.pBlob + sizeof(DWORD)*2;
+ firstName = nick + strlen(nick) + 1;
+ lastName = firstName + strlen(firstName) + 1;
+ jid = lastName + strlen(lastName) + 1;
+
+ hContact = (HANDLE) AddToListByJID(this, jid, flags);
+ mir_free(dbei.pBlob);
+
+ return hContact;
+}
+
+int __cdecl TlenProtocol::Authorize(HANDLE hDbEvent)
+{
+ DBEVENTINFO dbei;
+ char *nick, *firstName, *lastName, *jid;
+
+ if (!isOnline)
+ return 1;
+
+ memset(&dbei, sizeof(dbei), 0);
+ dbei.cbSize = sizeof(dbei);
+ if (( dbei.cbBlob=CallService( MS_DB_EVENT_GETBLOBSIZE, ( WPARAM )hDbEvent, 0 )) == ( DWORD )( -1 ))
+ return 1;
+ if ((dbei.pBlob=(PBYTE) mir_alloc(dbei.cbBlob)) == NULL)
+ return 1;
+ if ( CallService( MS_DB_EVENT_GET, ( WPARAM )hDbEvent, ( LPARAM )&dbei )){
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST) {
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+ if (strcmp(dbei.szModule, m_szModuleName)) {
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+
+ nick = (char *)dbei.pBlob + sizeof(DWORD)*2;
+ firstName = nick + strlen(nick) + 1;
+ lastName = firstName + strlen(firstName) + 1;
+ jid = lastName + strlen(lastName) + 1;
+
+ JabberSend(this, "<presence to='%s' type='subscribed'/>", jid);
+
+ // Automatically add this user to my roster if option is enabled
+ if (DBGetContactSettingByte(NULL, m_szModuleName, "AutoAdd", TRUE) == TRUE) {
+ HANDLE hContact;
+ JABBER_LIST_ITEM *item;
+
+ if ((item=JabberListGetItemPtr(this, LIST_ROSTER, jid)) == NULL || (item->subscription != SUB_BOTH && item->subscription != SUB_TO)) {
+ JabberLog(this, "Try adding contact automatically jid=%s", jid);
+ if ((hContact=AddToListByJID(this, jid, 0)) != NULL) {
+ // Trigger actual add by removing the "NotOnList" added by AddToListByJID()
+ // See AddToListByJID() and JabberDbSettingChanged().
+ DBDeleteContactSetting(hContact, "CList", "NotOnList");
+ }
+ }
+ }
+
+ mir_free(dbei.pBlob);
+ return 0;
+}
+
+int __cdecl TlenProtocol::AuthDeny(HANDLE hDbEvent, const PROTOCHAR* szReason)
+{
+ DBEVENTINFO dbei;
+ char *nick, *firstName, *lastName, *jid;
+
+ if (!isOnline)
+ return 1;
+
+ memset(&dbei, sizeof(dbei), 0);
+ dbei.cbSize = sizeof(dbei);
+ if ((dbei.cbBlob=CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent/*hContact*/, 0)) == (DWORD)(-1))
+ return 1;
+ if ((dbei.pBlob=(PBYTE) mir_alloc(dbei.cbBlob)) == NULL)
+ return 1;
+ if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent/*hContact*/, (LPARAM) &dbei)) {
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST) {
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+ if (strcmp(dbei.szModule, m_szModuleName)) {
+ mir_free(dbei.pBlob);
+ return 1;
+ }
+
+ nick = (char *)dbei.pBlob + sizeof(DWORD)*2;
+ firstName = nick + strlen(nick) + 1;
+ lastName = firstName + strlen(firstName) + 1;
+ jid = lastName + strlen(lastName) + 1;
+
+ JabberSend(this, "<presence to='%s' type='unsubscribed'/>", jid);
+ JabberSend(this, "<iq type='set'><query xmlns='jabber:iq:roster'><item jid='%s' subscription='remove'/></query></iq>", jid);
+ mir_free(dbei.pBlob);
+ return 0;
+}
+
+static void TlenConnect(TlenProtocol *proto, int initialStatus)
+{
+ if (!proto->isConnected) {
+ ThreadData *thread;
+ int oldStatus;
+
+ thread = (ThreadData *) mir_alloc(sizeof(ThreadData));
+ memset(thread, 0, sizeof(ThreadData));
+ thread->proto = proto;
+ proto->m_iDesiredStatus = initialStatus;
+
+ oldStatus = proto->m_iStatus;
+ proto->m_iStatus = ID_STATUS_CONNECTING;
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, proto->m_iStatus);
+ thread->hThread = (HANDLE) JabberForkThread((void (__cdecl *)(void*))JabberServerThread, 0, thread);
+ }
+}
+
+int __cdecl TlenProtocol::SetStatus(int iNewStatus)
+{
+ int oldStatus;
+ HANDLE s;
+
+ m_iDesiredStatus = iNewStatus;
+
+ if (iNewStatus == ID_STATUS_OFFLINE) {
+ if (threadData) {
+ if (isConnected) {
+ JabberSendPresence(this, ID_STATUS_OFFLINE);
+ }
+
+ // TODO bug? s = proto;
+ s = threadData->s;
+
+ threadData = NULL;
+ if (isConnected) {
+ Sleep(200);
+// JabberSend(s, "</s>");
+ // Force closing connection
+ isConnected = FALSE;
+ isOnline = FALSE;
+ Netlib_CloseHandle(s);
+ }
+ }
+ else {
+ if (m_iStatus != ID_STATUS_OFFLINE) {
+ oldStatus = m_iStatus;
+ m_iStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, m_iStatus);
+ }
+ }
+ }
+ else if (iNewStatus != m_iStatus) {
+ if (!isConnected)
+ TlenConnect(this, iNewStatus);
+ else {
+ // change status
+ oldStatus = m_iStatus;
+ // send presence update
+ JabberSendPresence(this, iNewStatus);
+ ProtoBroadcastAck(m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, m_iStatus);
+ }
+ }
+ return 0;
+}
+
+INT_PTR TlenGetStatus(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ return proto->m_iStatus;
+}
+
+
+int __cdecl TlenProtocol::SetAwayMsg(int iStatus, const PROTOCHAR* msg)
+{
+ char **szMsg;
+ char *newModeMsg;
+
+ JabberLog(this, "SetAwayMsg called, wParam=%d lParam=%s", iStatus, msg);
+
+ newModeMsg = JabberTextEncode(mir_t2a(msg)); //TODO TCHAR
+
+ EnterCriticalSection(&modeMsgMutex);
+
+ switch (iStatus) {
+ case ID_STATUS_ONLINE:
+ szMsg = &modeMsgs.szOnline;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ szMsg = &modeMsgs.szAway;
+ break;
+ case ID_STATUS_NA:
+ szMsg = &modeMsgs.szNa;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ szMsg = &modeMsgs.szDnd;
+ break;
+ case ID_STATUS_FREECHAT:
+ szMsg = &modeMsgs.szFreechat;
+ break;
+ case ID_STATUS_INVISIBLE:
+ szMsg = &modeMsgs.szInvisible;
+ break;
+ default:
+ LeaveCriticalSection(&modeMsgMutex);
+ return 1;
+ }
+
+ if ((*szMsg == NULL && newModeMsg == NULL) ||
+ (*szMsg != NULL && newModeMsg != NULL && !strcmp(*szMsg, newModeMsg))) {
+ // Message is the same, no update needed
+ if (newModeMsg != NULL) mir_free(newModeMsg);
+ }
+ else {
+ // Update with the new mode message
+ if (*szMsg != NULL) mir_free(*szMsg);
+ *szMsg = newModeMsg;
+ // Send a presence update if needed
+ if (iStatus == m_iStatus) {
+ JabberSendPresence(this, m_iStatus);
+ }
+ }
+
+ LeaveCriticalSection(&modeMsgMutex);
+ return 0;
+}
+
+int __cdecl TlenProtocol::GetInfo(HANDLE hContact, int infoType)
+{
+ DBVARIANT dbv;
+ int iqId;
+ char *nick, *pNick;
+
+ if (!isOnline) return 1;
+ if (hContact == NULL) {
+ iqId = JabberSerialNext(this);
+ JabberIqAdd(this, iqId, IQ_PROC_NONE, TlenIqResultVcard);
+ JabberSend(this, "<iq type='get' id='"JABBER_IQID"%d' to='tuba'><query xmlns='jabber:iq:register'></query></iq>", iqId);
+ } else {
+ if (DBGetContactSetting(hContact, m_szModuleName, "jid", &dbv)) return 1;
+ if ((nick=JabberNickFromJID(dbv.pszVal)) != NULL) {
+ if ((pNick=JabberTextEncode(nick)) != NULL) {
+ iqId = JabberSerialNext(this);
+ JabberIqAdd(this, iqId, IQ_PROC_NONE, TlenIqResultVcard);
+ JabberSend(this, "<iq type='get' id='"JABBER_IQID"%d' to='tuba'><query xmlns='jabber:iq:search'><i>%s</i></query></iq>", iqId, pNick);
+ mir_free(pNick);
+ }
+ mir_free(nick);
+ }
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+int __cdecl TlenProtocol::SetApparentMode(HANDLE hContact, int mode)
+{
+ DBVARIANT dbv;
+ int oldMode;
+ char *jid;
+
+ if (!isOnline) return 0;
+ if (!DBGetContactSettingByte(NULL, m_szModuleName, "VisibilitySupport", FALSE)) return 0;
+ if (mode != 0 && mode != ID_STATUS_ONLINE && mode != ID_STATUS_OFFLINE) return 1;
+ oldMode = DBGetContactSettingWord(hContact, m_szModuleName, "ApparentMode", 0);
+ if ((int) mode == oldMode) return 1;
+ DBWriteContactSettingWord(hContact, m_szModuleName, "ApparentMode", (WORD) mode);
+ if (!DBGetContactSetting(hContact, m_szModuleName, "jid", &dbv)) {
+ jid = dbv.pszVal;
+ switch (mode) {
+ case ID_STATUS_ONLINE:
+ if (m_iStatus == ID_STATUS_INVISIBLE || oldMode == ID_STATUS_OFFLINE)
+ JabberSend(this, "<presence to='%s'><show>available</show></presence>", jid);
+ break;
+ case ID_STATUS_OFFLINE:
+ if (m_iStatus != ID_STATUS_INVISIBLE || oldMode == ID_STATUS_ONLINE)
+ JabberSend(this, "<presence to='%s' type='invisible'/>", jid);
+ break;
+ case 0:
+ if (oldMode == ID_STATUS_ONLINE && m_iStatus == ID_STATUS_INVISIBLE)
+ JabberSend(this, "<presence to='%s' type='invisible'/>", jid);
+ else if (oldMode == ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_INVISIBLE)
+ JabberSend(this, "<presence to='%s'><show>available</show></presence>", jid);
+ break;
+ }
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+typedef struct{
+ TlenProtocol *proto;
+ HANDLE hContact;
+} SENDACKTHREADDATA;
+
+static void __cdecl JabberSendMessageAckThread(void *ptr)
+{
+ SENDACKTHREADDATA *data = (SENDACKTHREADDATA *)ptr;
+ SleepEx(10, TRUE);
+ ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+ mir_free(data);
+}
+
+static void __cdecl TlenSendMessageFailedThread(void *ptr)
+{
+ SENDACKTHREADDATA *data = (SENDACKTHREADDATA *)ptr;
+ SleepEx(10, TRUE);
+ ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE) 2, 0);
+ mir_free(data);
+}
+
+static void __cdecl TlenGetAwayMsgThread(void *ptr)
+{
+ DBVARIANT dbv;
+ JABBER_LIST_ITEM *item;
+ SENDACKTHREADDATA *data = (SENDACKTHREADDATA *)ptr;
+ if (!DBGetContactSetting(data->hContact, data->proto->m_szModuleName, "jid", &dbv)) {
+ if ((item=JabberListGetItemPtr(data->proto, LIST_ROSTER, dbv.pszVal)) != NULL) {
+ DBFreeVariant(&dbv);
+ if (item->statusMessage != NULL) {
+ ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE) 1, (LPARAM) item->statusMessage);
+ return;
+ }
+ }
+ else {
+ DBFreeVariant(&dbv);
+ }
+ }
+ ProtoBroadcastAck(data->proto->m_szModuleName, data->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE) 1, (LPARAM) "");
+ mir_free(data);
+}
+
+INT_PTR TlenSendAlert(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ DBVARIANT dbv;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (proto->isOnline && !DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ JabberSend(proto, "<m tp='a' to='%s'/>", dbv.pszVal);
+
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+int __cdecl TlenProtocol::SendMsg(HANDLE hContact, int flags, const char* msg)
+{
+ DBVARIANT dbv;
+ char *msgEnc;
+ JABBER_LIST_ITEM *item;
+ int id;
+ char msgType[16];
+
+ if (!isOnline || DBGetContactSetting(hContact, m_szModuleName, "jid", &dbv)) {
+ SENDACKTHREADDATA *tdata = (SENDACKTHREADDATA*) mir_alloc(sizeof(SENDACKTHREADDATA));
+ tdata->proto = this;
+ tdata->hContact = hContact;
+ JabberForkThread(TlenSendMessageFailedThread, 0, (void *) tdata);
+ return 2;
+ }
+ if (!strcmp(msg, "<alert>")) {
+ SENDACKTHREADDATA *tdata = (SENDACKTHREADDATA*) mir_alloc(sizeof(SENDACKTHREADDATA));
+ tdata->proto = this;
+ tdata->hContact = hContact;
+ JabberSend(this, "<m tp='a' to='%s'/>", dbv.pszVal);
+ JabberForkThread(JabberSendMessageAckThread, 0, (void *) tdata);
+ } else if (!strcmp(msg, "<image>")) {
+ SENDACKTHREADDATA *tdata = (SENDACKTHREADDATA*) mir_alloc(sizeof(SENDACKTHREADDATA));
+ tdata->proto = this;
+ tdata->hContact = hContact;
+ id = JabberSerialNext(this);
+ JabberSend(this, "<message to='%s' type='%s' crc='%x' idt='%d'/>", dbv.pszVal, "pic", 0x757f044, id);
+ JabberForkThread(JabberSendMessageAckThread, 0, (void *) tdata);
+ } else {
+ if ((msgEnc=JabberTextEncode(msg)) != NULL) {
+ if (JabberListExist(this, LIST_CHATROOM, dbv.pszVal) && strchr(dbv.pszVal, '/') == NULL) {
+ strcpy(msgType, "groupchat");
+ } else if (DBGetContactSettingByte(hContact, m_szModuleName, "bChat", FALSE)) {
+ strcpy(msgType, "privchat");
+ } else {
+ strcpy(msgType, "chat");
+ }
+ if (!strcmp(msgType, "groupchat") || DBGetContactSettingByte(NULL, m_szModuleName, "MsgAck", FALSE) == FALSE) {
+ SENDACKTHREADDATA *tdata = (SENDACKTHREADDATA*) mir_alloc(sizeof(SENDACKTHREADDATA));
+ tdata->proto = this;
+ tdata->hContact = hContact;
+ if (!strcmp(msgType, "groupchat")) {
+ JabberSend(this, "<message to='%s' type='%s'><body>%s</body></message>", dbv.pszVal, msgType, msgEnc);
+ } else if (!strcmp(msgType, "privchat")) {
+ JabberSend(this, "<m to='%s'><b n='6' s='10' f='0' c='000000'>%s</b></m>", dbv.pszVal, msgEnc);
+ } else {
+ id = JabberSerialNext(this);
+ JabberSend(this, "<message to='%s' type='%s' id='"JABBER_IQID"%d'><body>%s</body><x xmlns='jabber:x:event'><composing/></x></message>", dbv.pszVal, msgType, id, msgEnc);
+ }
+ JabberForkThread(JabberSendMessageAckThread, 0, (void *) tdata);
+ }
+ else {
+ id = JabberSerialNext(this);
+ if ((item=JabberListGetItemPtr(this, LIST_ROSTER, dbv.pszVal)) != NULL)
+ item->idMsgAckPending = id;
+ JabberSend(this, "<message to='%s' type='%s' id='"JABBER_IQID"%d'><body>%s</body><x xmlns='jabber:x:event'><offline/><delivered/><composing/></x></message>", dbv.pszVal, msgType, id, msgEnc);
+ }
+ }
+ mir_free(msgEnc);
+ }
+ DBFreeVariant(&dbv);
+ return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// JabberGetAvatarInfo - retrieves the avatar info
+
+static INT_PTR TlenGetAvatarInfo(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ BOOL downloadingAvatar = FALSE;
+ char *avatarHash = NULL;
+ JABBER_LIST_ITEM *item = NULL;
+ DBVARIANT dbv;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ PROTO_AVATAR_INFORMATIONT* AI = ( PROTO_AVATAR_INFORMATIONT* )lParam;
+ if (!proto->tlenOptions.enableAvatars) return GAIR_NOAVATAR;
+
+ if (AI->hContact != NULL) {
+ if (!DBGetContactSetting(AI->hContact, proto->m_szModuleName, "jid", &dbv)) {
+ item = JabberListGetItemPtr(proto, LIST_ROSTER, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ if (item != NULL) {
+ downloadingAvatar = item->newAvatarDownloading;
+ avatarHash = item->avatarHash;
+ }
+ }
+ } else {
+ if (proto->threadData != NULL) {
+ avatarHash = proto->threadData->avatarHash;
+ }
+ }
+ if ((avatarHash == NULL || avatarHash[0] == '\0') && !downloadingAvatar) {
+ return GAIR_NOAVATAR;
+ }
+ if (avatarHash != NULL && !downloadingAvatar) {
+ TlenGetAvatarFileName(proto, item, AI->filename, sizeof(AI->filename));
+ AI->format = ( AI->hContact == NULL ) ? proto->threadData->avatarFormat : item->avatarFormat;
+ return GAIR_SUCCESS;
+ }
+ if (( wParam & GAIF_FORCE ) != 0 && AI->hContact != NULL && proto->isOnline) {
+ /* get avatar */
+ return GAIR_WAITFOR;
+ }
+ return GAIR_NOAVATAR;
+}
+
+HANDLE __cdecl TlenProtocol::GetAwayMsg(HANDLE hContact)
+{
+ SENDACKTHREADDATA *tdata = (SENDACKTHREADDATA*) mir_alloc(sizeof(SENDACKTHREADDATA));
+ tdata->proto = this;
+ tdata->hContact = hContact;
+ JabberForkThread((void (__cdecl *)(void*))TlenGetAwayMsgThread, 0, (void *) tdata);
+ return (HANDLE)1;
+}
+
+int __cdecl TlenProtocol::RecvAwayMsg(HANDLE hContact, int mode, PROTORECVEVENT* evt)
+{
+ return 0;
+}
+
+int __cdecl TlenProtocol::SendAwayMsg(HANDLE hContact, HANDLE hProcess, const char* msg)
+{
+ return 0;
+}
+
+HANDLE __cdecl TlenProtocol::FileAllow(HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath)
+{
+ TLEN_FILE_TRANSFER *ft;
+ JABBER_LIST_ITEM *item;
+ char *nick;
+
+ if (!isOnline) return 0;
+
+ ft = (TLEN_FILE_TRANSFER *) hTransfer;
+ ft->szSavePath = mir_strdup(mir_t2a(szPath)); //TODO convert to PROTOCHAR*
+ if ((item=JabberListAdd(this, LIST_FILE, ft->iqId)) != NULL) {
+ item->ft = ft;
+ }
+ nick = JabberNickFromJID(ft->jid);
+ if (ft->newP2P) {
+ JabberSend(this, "<iq to='%s'><query xmlns='p2p'><fs t='%s' e='5' i='%s' v='1'/></query></iq>", ft->jid, ft->jid, ft->iqId);
+ } else {
+ JabberSend(this, "<f t='%s' i='%s' e='5' v='1'/>", nick, ft->iqId);
+ }
+ mir_free(nick);
+ return (HANDLE)hTransfer;
+}
+
+int __cdecl TlenProtocol::FileDeny(HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason)
+{
+ TLEN_FILE_TRANSFER *ft;
+ char *nick;
+
+ if (!isOnline) return 1;
+
+ ft = (TLEN_FILE_TRANSFER *) hTransfer;
+ nick = JabberNickFromJID(ft->jid);
+ if (ft->newP2P) {
+ JabberSend(this, "<f i='%s' e='4' t='%s'/>", ft->iqId, nick);\
+ } else {
+ JabberSend(this, "<f i='%s' e='4' t='%s'/>", ft->iqId, nick);\
+ }
+ mir_free(nick);
+ TlenP2PFreeFileTransfer(ft);
+ return 0;
+}
+
+int __cdecl TlenProtocol::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename) {
+ return 0;
+}
+
+int __cdecl TlenProtocol::FileCancel(HANDLE hContact, HANDLE hTransfer)
+{
+ TLEN_FILE_TRANSFER *ft = (TLEN_FILE_TRANSFER *) hTransfer;
+ JabberLog(this, "Invoking FileCancel()");
+ if (ft->s != NULL) {
+ ft->state = FT_ERROR;
+ Netlib_CloseHandle(ft->s);
+ ft->s = NULL;
+ if (ft->hFileEvent != NULL) {
+ HANDLE hEvent = ft->hFileEvent;
+ ft->hFileEvent = NULL;
+ SetEvent(hEvent);
+ }
+ } else {
+ TlenP2PFreeFileTransfer(ft);
+ }
+ return 0;
+}
+
+HANDLE __cdecl TlenProtocol::SendFile(HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles)
+{
+ TLEN_FILE_TRANSFER *ft;
+ int i, j;
+ struct _stat statbuf;
+ DBVARIANT dbv;
+ char *nick, *p, idStr[10];
+ JABBER_LIST_ITEM *item;
+ int id;
+
+ if (!isOnline) return 0;
+// if (DBGetContactSettingWord(ccs->hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) return 0;
+ if (DBGetContactSetting(hContact, m_szModuleName, "jid", &dbv)) return 0;
+ ft = TlenFileCreateFT(this, dbv.pszVal);
+ for (ft->fileCount=0; ppszFiles[ft->fileCount]; ft->fileCount++);
+ ft->files = (char **) mir_alloc(sizeof(char *) * ft->fileCount);
+ ft->filesSize = (long *) mir_alloc(sizeof(long) * ft->fileCount);
+ ft->allFileTotalSize = 0;
+ for (i=j=0; i<ft->fileCount; i++) {
+ char* ppszFiles_i_A = mir_t2a(ppszFiles[i]);
+ if (_stat(ppszFiles_i_A, &statbuf))
+ JabberLog(this, "'%s' is an invalid filename", ppszFiles[i]);
+ else {
+ ft->filesSize[j] = statbuf.st_size;
+ ft->files[j++] = mir_strdup(ppszFiles_i_A);
+ ft->allFileTotalSize += statbuf.st_size;
+ }
+ mir_free(ppszFiles_i_A);
+ }
+ ft->fileCount = j;
+ ft->szDescription = mir_t2a(szDescription);
+ ft->hContact = hContact;
+ ft->currentFile = 0;
+ DBFreeVariant(&dbv);
+
+ id = JabberSerialNext(this);
+ _snprintf(idStr, sizeof(idStr), "%d", id);
+ if ((item=JabberListAdd(this, LIST_FILE, idStr)) != NULL) {
+ ft->iqId = mir_strdup(idStr);
+ nick = JabberNickFromJID(ft->jid);
+ item->ft = ft;
+ if (tlenOptions.useNewP2P) {
+ JabberSend(this, "<iq to='%s'><query xmlns='p2p'><fs t='%s' e='1' i='%s' c='%d' s='%d' v='%d'/></query></iq>",
+ ft->jid, ft->jid, idStr, ft->fileCount, ft->allFileTotalSize, ft->fileCount);
+
+ ft->newP2P = TRUE;
+ } else {
+ if (ft->fileCount == 1) {
+ char* ppszFiles_0_A = mir_t2a(ppszFiles[0]);
+ if ((p=strrchr(ppszFiles_0_A, '\\')) != NULL) {
+ p++;
+ } else {
+ p = ppszFiles_0_A;
+ }
+ p = JabberTextEncode(p);
+ JabberSend(this, "<f t='%s' n='%s' e='1' i='%s' c='1' s='%d' v='1'/>", nick, p, idStr, ft->allFileTotalSize);
+ mir_free(ppszFiles[0]);
+ mir_free(p);
+ } else {
+ JabberSend(this, "<f t='%s' e='1' i='%s' c='%d' s='%d' v='1'/>", nick, idStr, ft->fileCount, ft->allFileTotalSize);
+ }
+ }
+ mir_free(nick);
+ }
+
+ return (HANDLE) ft;
+}
+
+int __cdecl TlenProtocol::SendContacts(HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList){
+ return 0;
+}
+
+int __cdecl TlenProtocol::SendUrl(HANDLE hContact, int flags, const char* urlt){
+ return 0;
+}
+
+int __cdecl TlenProtocol::RecvMsg(HANDLE hContact, PROTORECVEVENT* evt)
+{
+ return Proto_RecvMessage(hContact, evt);
+}
+
+int __cdecl TlenProtocol::RecvFile(HANDLE hContact, PROTOFILEEVENT* evt)
+{
+ return Proto_RecvFile(hContact, evt);
+}
+
+int __cdecl TlenProtocol::RecvUrl(HANDLE hContact, PROTORECVEVENT*){
+ return 0;
+}
+
+static char* settingToChar( DBCONTACTWRITESETTING* cws )
+{
+ switch( cws->value.type ) {
+ case DBVT_ASCIIZ:
+ return mir_strdup( cws->value.pszVal );
+ case DBVT_UTF8:
+ return mir_utf8decode(mir_strdup(cws->value.pszVal), NULL);
+ }
+ return NULL;
+}
+
+int JabberDbSettingChanged(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ // no action for hContact == NULL or when offline
+ if ((HANDLE) wParam == NULL) return 0;
+ if (!proto->isConnected) return 0;
+
+ if (!strcmp(cws->szModule, "CList")) {
+ HANDLE hContact;
+ DBVARIANT dbv;
+ JABBER_LIST_ITEM *item;
+ char *szProto, *nick, *jid, *group;
+
+ hContact = (HANDLE) wParam;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL || strcmp(szProto, proto->m_szModuleName)) return 0;
+// if (DBGetContactSettingByte(hContact, proto->m_szModuleName, "ChatRoom", 0) != 0) return 0;
+ // A contact's group is changed
+ if (!strcmp(cws->szSetting, "Group")) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, dbv.pszVal)) != NULL) {
+ DBFreeVariant(&dbv);
+ if (!DBGetContactSetting(hContact, "CList", "MyHandle", &dbv)) {
+ nick = JabberTextEncode(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else if (!DBGetContactSetting(hContact, proto->m_szModuleName, "Nick", &dbv)) {
+ nick = JabberTextEncode(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ nick = JabberNickFromJID(item->jid);
+ }
+ if (nick != NULL) {
+ // Note: we need to compare with item->group to prevent infinite loop
+ if (cws->value.type == DBVT_DELETED && item->group != NULL) {
+ JabberLog(proto, "Group set to nothing");
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'></item></query></iq>", nick, item->jid);
+ } else if (cws->value.pszVal != NULL) {
+ char *newGroup = settingToChar(cws);
+ if (item->group == NULL || strcmp(newGroup, item->group)) {
+ JabberLog(proto, "Group set to %s", newGroup);
+ if ((group=TlenGroupEncode(newGroup)) != NULL) {
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'><group>%s</group></item></query></iq>", nick, item->jid, group);
+ mir_free(group);
+ }
+ }
+ mir_free(newGroup);
+ }
+ mir_free(nick);
+ }
+ }
+ else {
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ // A contact is renamed
+ else if (!strcmp(cws->szSetting, "MyHandle")) {
+ char *newNick;
+
+// hContact = (HANDLE) wParam;
+// szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+// if (szProto == NULL || strcmp(szProto, proto->m_szModuleName)) return 0;
+
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ jid = dbv.pszVal;
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, dbv.pszVal)) != NULL) {
+ if (cws->value.type == DBVT_DELETED) {
+ newNick = mir_strdup((char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_NOMYHANDLE));
+ } else if (cws->value.pszVal != NULL) {
+ newNick = settingToChar(cws);
+ } else {
+ newNick = NULL;
+ }
+ // Note: we need to compare with item->nick to prevent infinite loop
+ if (newNick != NULL && (item->nick == NULL || (item->nick != NULL && strcmp(item->nick, newNick)))) {
+ if ((nick=JabberTextEncode(newNick)) != NULL) {
+ JabberLog(proto, "Nick set to %s", newNick);
+ if (item->group != NULL && (group=TlenGroupEncode(item->group)) != NULL) {
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'><group>%s</group></item></query></iq>", nick, jid, group);
+ mir_free(group);
+ } else {
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'></item></query></iq>", nick, jid);
+ }
+ mir_free(nick);
+ }
+ }
+ if (newNick != NULL) mir_free(newNick);
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ // A temporary contact has been added permanently
+ else if (!strcmp(cws->szSetting, "NotOnList")) {
+ char *jid, *nick, *pGroup;
+
+ if (cws->value.type==DBVT_DELETED || (cws->value.type==DBVT_BYTE && cws->value.bVal==0)) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ jid = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ JabberLog(proto, "Add %s permanently to list", jid);
+ if (!DBGetContactSetting(hContact, "CList", "MyHandle", &dbv)) {
+ nick = JabberTextEncode(dbv.pszVal); //Utf8Encode
+ DBFreeVariant(&dbv);
+ }
+ else {
+ nick = JabberNickFromJID(jid);
+ }
+ if (nick != NULL) {
+ JabberLog(proto, "jid=%s nick=%s", jid, nick);
+ if (!DBGetContactSetting(hContact, "CList", "Group", &dbv)) {
+ if ((pGroup=TlenGroupEncode(dbv.pszVal)) != NULL) {
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'><group>%s</group></item></query></iq>", nick, jid, pGroup);
+ JabberSend(proto, "<presence to='%s' type='subscribe'/>", jid);
+ mir_free(pGroup);
+ }
+ DBFreeVariant(&dbv);
+ }
+ else {
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item name='%s' jid='%s'/></query></iq>", nick, jid);
+ JabberSend(proto, "<presence to='%s' type='subscribe'/>", jid);
+ }
+ mir_free(nick);
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+ }
+ mir_free(jid);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int JabberContactDeleted(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ char *szProto;
+ DBVARIANT dbv;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+
+ if (!proto->isOnline) // should never happen
+ return 0;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto == NULL || strcmp(szProto, proto->m_szModuleName))
+ return 0;
+ if (!DBGetContactSetting((HANDLE) wParam, proto->m_szModuleName, "jid", &dbv)) {
+ char *jid, *p, *q;
+
+ jid = dbv.pszVal;
+ if ((p=strchr(jid, '@')) != NULL) {
+ if ((q=strchr(p, '/')) != NULL)
+ *q = '\0';
+ }
+ if (JabberListExist(proto, LIST_ROSTER, jid)) {
+ // Remove from roster, server also handles the presence unsubscription process.
+ JabberSend(proto, "<iq type='set'><query xmlns='jabber:iq:roster'><item jid='%s' subscription='remove'/></query></iq>", jid);
+ }
+
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+int __cdecl TlenProtocol::UserIsTyping(HANDLE hContact, int type)
+{
+ DBVARIANT dbv;
+ JABBER_LIST_ITEM *item;
+
+ if (!isOnline) return 0;
+ if (!DBGetContactSetting(hContact, m_szModuleName, "jid", &dbv)) {
+ if ((item=JabberListGetItemPtr(this, LIST_ROSTER, dbv.pszVal)) != NULL /*&& item->wantComposingEvent == TRUE*/) {
+ switch (type) {
+ case PROTOTYPE_SELFTYPING_OFF:
+ JabberSend(this, "<m tp='u' to='%s'/>", dbv.pszVal);
+ break;
+ case PROTOTYPE_SELFTYPING_ON:
+ JabberSend(this, "<m tp='t' to='%s'/>", dbv.pszVal);
+ break;
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ return 0;
+}
+
+INT_PTR TlenGetMyAvatar(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TCHAR* buf = (TCHAR*)wParam;
+ int size = ( int )lParam;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+
+ if ( buf == NULL || size <= 0 )
+ return -1;
+
+ TlenGetAvatarFileName( proto, NULL, buf, size );
+ //wParam (buf) is output var
+ return 0;
+}
+
+static INT_PTR CALLBACK TlenChangeAvatarDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ {
+ HICON hIcon = GetIcolibIcon(IDI_TLEN);
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hIcon);
+ ReleaseIcolibIcon(hIcon);
+ }
+ CheckDlgButton(hwndDlg, IDC_PUBLICAVATAR, TRUE);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ {
+ int result = LOWORD(wParam);
+ if (IsDlgButtonChecked(hwndDlg, IDC_PUBLICAVATAR)) {
+ result |= 0x10000;
+ }
+ EndDialog(hwndDlg, result);
+ }
+ return TRUE;
+ }
+ break;
+ }
+ return 0;
+}
+
+INT_PTR TlenSetMyAvatar(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TCHAR* szFileName = ( TCHAR* )lParam;
+ TCHAR tFileName[ MAX_PATH ];
+ int fileIn;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!proto->isOnline) return 1;
+ if (szFileName != NULL) {
+ int result = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_USER_CHANGEAVATAR), NULL, TlenChangeAvatarDlgProc, (LPARAM) NULL);
+ TlenGetAvatarFileName( proto, NULL, tFileName, MAX_PATH);
+ if ( CopyFile( szFileName, tFileName, FALSE ) == FALSE ) {
+ return 1;
+ }
+ char* tFileNameA = mir_t2a(tFileName); //TODO - drop io.h
+ fileIn = open( tFileNameA, O_RDWR | O_BINARY, S_IREAD | S_IWRITE );
+ if ( fileIn != -1 ) {
+ long dwPngSize = filelength(fileIn);
+ BYTE* pResult = (BYTE *)mir_alloc(dwPngSize);
+ if (pResult != NULL) {
+ read( fileIn, pResult, dwPngSize );
+ close( fileIn );
+ TlenUploadAvatar(proto, pResult, dwPngSize, (result & 0x10000) != 0);
+ mir_free(pResult);
+ }
+ }
+ mir_free(tFileName);
+ mir_free(tFileNameA);
+ } else {
+ TlenRemoveAvatar(proto);
+ }
+ return 0;
+}
+
+INT_PTR TlenGetAvatarCaps(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ switch (wParam) {
+ case AF_MAXSIZE:
+ {
+ POINT* size = (POINT*)lParam;
+ if ( size )
+ size->x = size->y = 64;
+ }
+ return 0;
+ case AF_PROPORTION:
+ return PIP_SQUARE;
+ case AF_FORMATSUPPORTED:
+ return (lParam == PA_FORMAT_PNG) ? 1 : 0;
+ case AF_ENABLED:
+ return (proto->tlenOptions.enableAvatars && proto->isOnline) ? 1 : 0;
+ case AF_DONTNEEDDELAYS:
+ return 1;
+ case AF_MAXFILESIZE:
+ return 10 * 1024;
+ case AF_DELAYAFTERFAIL:
+ return 0;
+ }
+ return 0;
+}
+
+int __cdecl TlenProtocol::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam)
+{
+ //TlenProtocol *proto = (TlenProtocol *)ptr;
+ switch( iEventType ) {
+ case EV_PROTO_ONLOAD: return TlenOnModulesLoaded(this, 0, 0 );
+ case EV_PROTO_ONOPTIONS: return TlenOptionsInit(this, wParam, lParam );
+ case EV_PROTO_ONEXIT: return TlenPreShutdown(this, 0, 0 );
+ case EV_PROTO_ONRENAME:
+ {
+ CLISTMENUITEM clmi = { 0 };
+ clmi.cbSize = sizeof( CLISTMENUITEM );
+ clmi.flags = CMIM_NAME | CMIF_TCHAR;
+ clmi.ptszName = m_tszUserName;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuRoot, ( LPARAM )&clmi );
+ /* FIXME: Rename network user as well */
+ }
+ }
+ return 1;
+}
+
+// PSS_ADDED
+int __cdecl TlenProtocol::AuthRecv(HANDLE hContact, PROTORECVEVENT* evt)
+{
+ return 1;
+}
+
+// PSS_AUTHREQUEST
+int __cdecl TlenProtocol::AuthRequest(HANDLE hContact, const PROTOCHAR* szMessage)
+{
+ return 1;
+}
+
+HANDLE __cdecl TlenProtocol::ChangeInfo(int iInfoType, void* pInfoData)
+{
+ return NULL;
+}
+
+
+int __cdecl TlenProtocol::RecvContacts(HANDLE hContact, PROTORECVEVENT* evt)
+{
+ return 1;
+}
+
+
+extern INT_PTR CALLBACK TlenAccMgrUIDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+INT_PTR TlenAccMgrUI(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ return (INT_PTR) CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, TlenAccMgrUIDlgProc, (LPARAM) ptr);
+}
+
+void TlenInitServicesVTbl(TlenProtocol *proto) {
+
+ char s[128];
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_GETNAME);
+ CreateServiceFunction_Ex(s, proto, TlenGetName);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_GETAVATARINFO);
+ CreateServiceFunction_Ex(s, proto, TlenGetAvatarInfo);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, "/SendNudge");
+ CreateServiceFunction_Ex(s, proto, TlenSendAlert);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_GETAVATARCAPS);
+ CreateServiceFunction_Ex(s, proto, TlenGetAvatarCaps);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_SETMYAVATART);
+ CreateServiceFunction_Ex(s, proto, TlenSetMyAvatar);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_GETMYAVATART);
+ CreateServiceFunction_Ex(s, proto, TlenGetMyAvatar);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_GETSTATUS);
+ CreateServiceFunction_Ex(s, proto, TlenGetStatus);
+
+ sprintf(s, "%s%s", proto->m_szModuleName, PS_CREATEACCMGRUI);
+ CreateServiceFunction_Ex(s, proto, TlenAccMgrUI);
+
+}
+
+TlenProtocol::TlenProtocol( const char* aProtoName, const TCHAR* aUserName )
+{
+
+ m_iVersion = 2;
+ m_tszUserName = mir_tstrdup(aUserName);
+ m_szModuleName = mir_strdup(aProtoName);
+ m_szProtoName = mir_strdup(aProtoName);
+ _strlwr( m_szProtoName );
+ m_szProtoName[0] = toupper( m_szProtoName[0] );
+ m_iStatus = ID_STATUS_OFFLINE;
+
+ TlenInitServicesVTbl(this);
+
+ InitializeCriticalSection(&modeMsgMutex);
+ InitializeCriticalSection(&csSend);
+
+ char text[_MAX_PATH];
+ sprintf(text, "%s/%s", m_szModuleName, "Nudge");
+ hTlenNudge = CreateHookableEvent(text);
+
+ HookEventObj_Ex(ME_SYSTEM_MODULESLOADED, this, TlenSystemModulesLoaded);
+ HookEventObj_Ex(ME_OPT_INITIALISE, this, TlenOptionsInit);
+ HookEventObj_Ex(ME_DB_CONTACT_SETTINGCHANGED, this, JabberDbSettingChanged);
+ HookEventObj_Ex(ME_DB_CONTACT_DELETED, this, JabberContactDeleted);
+ HookEventObj_Ex(ME_CLIST_PREBUILDCONTACTMENU, this, TlenPrebuildContactMenu);
+// HookEventObj_Ex(ME_SKIN2_ICONSCHANGED, this, TlenIconsChanged);
+ HookEventObj_Ex(ME_SYSTEM_PRESHUTDOWN, this, TlenPreShutdown);
+
+
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, m_szModuleName, "LoginServer", &dbv)) {
+ DBFreeVariant(&dbv);
+ } else {
+ DBWriteContactSettingString(NULL, m_szModuleName, "LoginServer", "tlen.pl");
+ }
+ if (!DBGetContactSetting(NULL, m_szModuleName, "ManualHost", &dbv)) {
+ DBFreeVariant(&dbv);
+ } else {
+ DBWriteContactSettingString(NULL, m_szModuleName, "ManualHost", "s1.tlen.pl");
+ }
+
+ TlenLoadOptions(this);
+
+ JabberWsInit(this);
+ JabberSerialInit(this);
+ JabberIqInit(this);
+ JabberListInit(this);
+
+}
+
+TlenProtocol::~TlenProtocol()
+{
+
+ uninitMenuItems(this);
+ TlenVoiceCancelAll(this);
+ TlenFileCancelAll(this);
+ if (hTlenNudge)
+ DestroyHookableEvent(hTlenNudge);
+ UnhookEvents_Ex(this);
+ JabberListUninit(this);
+ JabberIqUninit(this);
+ JabberSerialUninit(this);
+ DeleteCriticalSection(&modeMsgMutex);
+ DeleteCriticalSection(&csSend);
+ //DestroyServices_Ex(this);
+ JabberWsUninit(this);
+
+ mir_free(modeMsgs.szOnline);
+ mir_free(modeMsgs.szAway);
+ mir_free(modeMsgs.szNa);
+ mir_free(modeMsgs.szDnd);
+ mir_free(modeMsgs.szFreechat);
+ mir_free(modeMsgs.szInvisible);
+
+}
+
+
diff --git a/protocols/Tlen/src/jabber_thread.cpp b/protocols/Tlen/src/jabber_thread.cpp
new file mode 100644
index 0000000000..b9fe951ee1
--- /dev/null
+++ b/protocols/Tlen/src/jabber_thread.cpp
@@ -0,0 +1,1467 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+
+#include "commons.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "resource.h"
+#include "tlen_p2p_old.h"
+#include "tlen_file.h"
+#include "tlen_muc.h"
+#include "tlen_voice.h"
+#include "tlen_avatar.h"
+#include "tlen_presence.h"
+#include "tlen_picture.h"
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+extern void __cdecl TlenProcessP2P(XmlNode *node, ThreadData *info);
+
+
+//static void __cdecl TlenProcessInvitation(struct ThreadData *info);
+static void __cdecl JabberKeepAliveThread(void *ptr);
+static void JabberProcessStreamOpening(XmlNode *node, ThreadData *info);
+static void JabberProcessStreamClosing(XmlNode *node, ThreadData *info);
+static void JabberProcessProtocol(XmlNode *node, ThreadData *info);
+static void JabberProcessMessage(XmlNode *node, ThreadData *info);
+static void JabberProcessIq(XmlNode *node, ThreadData *info);
+static void TlenProcessW(XmlNode *node, ThreadData *info);
+static void TlenProcessM(XmlNode *node, ThreadData *info);
+static void TlenProcessN(XmlNode *node, ThreadData *info);
+static void TlenProcessP(XmlNode *node, ThreadData *info);
+static void TlenProcessV(XmlNode *node, ThreadData *info);
+static void TlenProcessAvatar(XmlNode* node, ThreadData *info);
+static void TlenProcessCipher(XmlNode *node, ThreadData *info);
+
+static VOID NTAPI JabberDummyApcFunc(ULONG_PTR param)
+{
+ return;
+}
+
+static char onlinePassword[128];
+static HANDLE hEventPasswdDlg;
+
+static INT_PTR CALLBACK JabberPasswordDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char text[128];
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ sprintf(text, "%s %s", Translate("Enter password for"), (char *) lParam);
+ SetDlgItemTextA(hwndDlg, IDC_JID, text);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ GetDlgItemTextA(hwndDlg, IDC_PASSWORD, onlinePassword, sizeof(onlinePassword));
+ //EndDialog(hwndDlg, (int) onlinePassword);
+ //return TRUE;
+ // Fall through
+ case IDCANCEL:
+ //EndDialog(hwndDlg, 0);
+ SetEvent(hEventPasswdDlg);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+static VOID NTAPI JabberPasswordCreateDialogApcProc(ULONG_PTR param)
+{
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_PASSWORD), NULL, JabberPasswordDlgProc, (LPARAM) param);
+}
+
+void __cdecl JabberServerThread(ThreadData *info)
+{
+ DBVARIANT dbv;
+ char jidStr[128];
+ char *connectHost;
+ char *buffer;
+ int datalen;
+ XmlState xmlState;
+ HANDLE hContact;
+ int jabberNetworkBufferSize;
+ int oldStatus = ID_STATUS_OFFLINE;
+ int reconnectMaxTime;
+ int numRetry;
+ int reconnectTime;
+ char *str;
+ CLISTMENUITEM clmi;
+ int loginErr = 0;
+ JabberLog(info->proto, "Thread started");
+
+
+ // Normal server connection, we will fetch all connection parameters
+ // e.g. username, password, etc. from the database.
+
+ if (info->proto->threadData != NULL) {
+ // Will not start another connection thread if a thread is already running.
+ // Make APC call to the main thread. This will immediately wake the thread up
+ // in case it is asleep in the reconnect loop so that it will immediately
+ // reconnect.
+ QueueUserAPC(JabberDummyApcFunc, info->proto->threadData->hThread, 0);
+ JabberLog(info->proto, "Thread ended, another normal thread is running");
+ mir_free(info);
+ return;
+ }
+
+ info->proto->threadData = info;
+
+ if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "LoginName", &dbv)) {
+ strncpy(info->username, dbv.pszVal, sizeof(info->username));
+ info->username[sizeof(info->username)-1] = '\0';
+ _strlwr(info->username);
+ DBWriteContactSettingString(NULL, info->proto->m_szModuleName, "LoginName", info->username);
+ DBFreeVariant(&dbv);
+
+ } else {
+ JabberLog(info->proto, "Thread ended, login name is not configured");
+ loginErr = LOGINERR_BADUSERID;
+ }
+
+ if (loginErr == 0) {
+ if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "LoginServer", &dbv)) {
+ strncpy(info->server, dbv.pszVal, sizeof(info->server));
+ info->server[sizeof(info->server)-1] = '\0';
+ _strlwr(info->server);
+ DBWriteContactSettingString(NULL, info->proto->m_szModuleName, "LoginServer", info->server);
+ DBFreeVariant(&dbv);
+ } else {
+ JabberLog(info->proto, "Thread ended, login server is not configured");
+ loginErr = LOGINERR_NONETWORK;
+ }
+ }
+
+ if (loginErr == 0) {
+ if (!info->proto->tlenOptions.savePassword) {
+ // Ugly hack: continue logging on only the return value is &(onlinePassword[0])
+ // because if WM_QUIT while dialog box is still visible, p is returned with some
+ // exit code which may not be NULL.
+ // Should be better with modeless.
+ onlinePassword[0] = (char) -1;
+ hEventPasswdDlg = CreateEvent(NULL, FALSE, FALSE, NULL);
+ QueueUserAPC(JabberPasswordCreateDialogApcProc, hMainThread, (DWORD) jidStr);
+ WaitForSingleObject(hEventPasswdDlg, INFINITE);
+ CloseHandle(hEventPasswdDlg);
+ //if ((p=(char *)DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_PASSWORD), NULL, JabberPasswordDlgProc, (LPARAM) jidStr)) != onlinePassword) {
+ if (onlinePassword[0] != (char) -1) {
+ strncpy(info->password, onlinePassword, sizeof(info->password));
+ info->password[sizeof(info->password)-1] = '\0';
+ } else {
+ JabberLog(info->proto, "Thread ended, password request dialog was canceled");
+ loginErr = LOGINERR_BADUSERID;
+ }
+ } else {
+ if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "Password", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ strncpy(info->password, dbv.pszVal, sizeof(info->password));
+ info->password[sizeof(info->password)-1] = '\0';
+ DBFreeVariant(&dbv);
+ } else {
+ JabberLog(info->proto, "Thread ended, password is not configured");
+ loginErr = LOGINERR_BADUSERID;
+ }
+ }
+ }
+
+ jabberNetworkBufferSize = 2048;
+ if ((buffer=(char *) mir_alloc(jabberNetworkBufferSize+1)) == NULL) { // +1 is for '\0' when debug logging this buffer
+ JabberLog(info->proto, "Thread ended, network buffer cannot be allocated");
+ loginErr = LOGINERR_NONETWORK;
+ }
+
+ if (loginErr != 0) {
+ info->proto->threadData = NULL;
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, loginErr);
+ mir_free(info);
+ return;
+ }
+
+ _snprintf(jidStr, sizeof(jidStr), "%s@%s", info->username, info->server);
+ DBWriteContactSettingString(NULL, info->proto->m_szModuleName, "jid", jidStr);
+
+ if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "ManualHost", &dbv)) {
+ strncpy(info->manualHost, dbv.pszVal, sizeof(info->manualHost));
+ info->manualHost[sizeof(info->manualHost)-1] = '\0';
+ DBFreeVariant(&dbv);
+ }
+ info->port = DBGetContactSettingWord(NULL, info->proto->m_szModuleName, "ManualPort", TLEN_DEFAULT_PORT);
+ info->useEncryption = info->proto->tlenOptions.useEncryption;
+
+ if (info->manualHost[0])
+ connectHost = info->manualHost;
+ else
+ connectHost = info->server;
+
+ JabberLog(info->proto, "Thread server='%s' port='%d'", connectHost, info->port);
+
+
+ if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "AvatarHash", &dbv)) {
+ strcpy(info->proto->threadData->avatarHash, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ info->avatarFormat = DBGetContactSettingDword(NULL, info->proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN);
+
+
+ reconnectMaxTime = 10;
+ numRetry = 0;
+
+ for (;;) { // Reconnect loop
+
+ info->s = JabberWsConnect(info->proto, connectHost, info->port);
+ if (info->s == NULL) {
+ JabberLog(info->proto, "Connection failed (%d)", WSAGetLastError());
+ if (info->proto->threadData == info) {
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NONETWORK);
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+ if (info->proto->tlenOptions.reconnect == TRUE) {
+ reconnectTime = rand() % reconnectMaxTime;
+ JabberLog(info->proto, "Sleeping %d seconds before automatic reconnecting...", reconnectTime);
+ SleepEx(reconnectTime * 1000, TRUE);
+ if (reconnectMaxTime < 10*60) // Maximum is 10 minutes
+ reconnectMaxTime *= 2;
+ if (info->proto->threadData == info) { // Make sure this is still the active thread for the main Jabber connection
+ JabberLog(info->proto, "Reconnecting to the network...");
+ if (numRetry < MAX_CONNECT_RETRIES)
+ numRetry++;
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_CONNECTING + numRetry;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+ continue;
+ }
+ else {
+ JabberLog(info->proto, "Thread ended, connection failed");
+ mir_free(buffer);
+ mir_free(info);
+ return;
+ }
+ }
+ info->proto->threadData = NULL;
+ }
+ JabberLog(info->proto, "Thread ended, connection failed");
+ mir_free(buffer);
+ mir_free(info);
+ return;
+ }
+
+ // Determine local IP
+ /*
+ socket = CallService(MS_NETLIB_GETSOCKET, (WPARAM) proto, 0);
+ struct sockaddr_in saddr;
+ int len;
+
+ len = sizeof(saddr);
+ getsockname(socket, (struct sockaddr *) &saddr, &len);
+ jabberLocalIP = saddr.sin_addr.S_un.S_addr;
+ JabberLog("Local IP = %s", inet_ntoa(saddr.sin_addr));
+ */
+
+ // User may change status to OFFLINE while we are connecting above
+ if (info->proto->m_iDesiredStatus != ID_STATUS_OFFLINE) {
+
+ info->proto->isConnected = TRUE;
+ JabberForkThread(JabberKeepAliveThread, 0, info->proto);
+
+ JabberXmlInitState(&xmlState);
+ JabberXmlSetCallback(&xmlState, 1, ELEM_OPEN, (void (__cdecl *)(XmlNode *,void *))JabberProcessStreamOpening, info);
+ JabberXmlSetCallback(&xmlState, 1, ELEM_CLOSE, (void (__cdecl *)(XmlNode *,void *))JabberProcessStreamClosing, info);
+ JabberXmlSetCallback(&xmlState, 2, ELEM_CLOSE, (void (__cdecl *)(XmlNode *,void *))JabberProcessProtocol, info);
+
+ info->useAES = FALSE;
+
+ if (info->useEncryption) {
+ JabberSend(info->proto, "<s s='1' v='9' t='06000106'>");
+
+ } else {
+ JabberSend(info->proto, "<s v='3'>");
+ }
+
+ JabberLog(info->proto, "Entering main recv loop");
+ datalen = 0;
+
+ for (;;) {
+ int recvResult, bytesParsed;
+
+ if (info->useAES) {
+ recvResult = JabberWsRecvAES(info->proto, buffer+datalen, jabberNetworkBufferSize-datalen, &info->aes_in_context, info->aes_in_iv);
+ } else {
+ recvResult = JabberWsRecv(info->proto, info->s, buffer+datalen, jabberNetworkBufferSize-datalen);
+ }
+
+ if (recvResult <= 0)
+ break;
+ datalen += recvResult;
+
+ buffer[datalen] = '\0';
+ JabberLog(info->proto, "RECV:%s", buffer);
+
+ bytesParsed = JabberXmlParse(&xmlState, buffer, datalen);
+ JabberLog(info->proto, "bytesParsed = %d", bytesParsed);
+ if (bytesParsed > 0) {
+ if (bytesParsed < datalen)
+ memmove(buffer, buffer+bytesParsed, datalen-bytesParsed);
+ datalen -= bytesParsed;
+ }
+ else if (datalen == jabberNetworkBufferSize) {
+ jabberNetworkBufferSize += 2048;
+ JabberLog(info->proto, "Increasing network buffer size to %d", jabberNetworkBufferSize);
+ if ((buffer=(char *) mir_realloc(buffer, jabberNetworkBufferSize+1)) == NULL) {
+ JabberLog(info->proto, "Cannot reallocate more network buffer, go offline now");
+ break;
+ }
+ }
+ else {
+ JabberLog(info->proto, "Unknown state: bytesParsed=%d, datalen=%d, jabberNetworkBufferSize=%d", bytesParsed, datalen, jabberNetworkBufferSize);
+ }
+ }
+
+ JabberXmlDestroyState(&xmlState);
+
+ info->proto->isOnline = FALSE;
+ info->proto->isConnected = FALSE;
+
+ memset(&clmi, 0, sizeof(CLISTMENUITEM));
+ clmi.cbSize = sizeof(CLISTMENUITEM);
+ clmi.flags = CMIM_FLAGS | CMIF_GRAYED;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) info->proto->hMenuMUC, (LPARAM) &clmi);
+ if (info->proto->hMenuChats != NULL){
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) info->proto->hMenuChats, (LPARAM) &clmi);
+ }
+
+ // Set status to offline
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+
+ // Set all contacts to offline
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ str = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (str != NULL && !strcmp(str, info->proto->m_szModuleName)) {
+ if (DBGetContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ DBWriteContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+
+ JabberListWipeSpecial(info->proto);
+ }
+ else {
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+ }
+
+ Netlib_CloseHandle(info->s);
+
+ if (info->proto->tlenOptions.reconnect == FALSE)
+ break;
+
+ if (info->proto->threadData != info) // Make sure this is still the main Jabber connection thread
+ break;
+ reconnectTime = rand() % 10;
+ JabberLog(info->proto, "Sleeping %d seconds before automatic reconnecting...", reconnectTime);
+ SleepEx(reconnectTime * 1000, TRUE);
+ reconnectMaxTime = 20;
+ if (info->proto->threadData != info) // Make sure this is still the main Jabber connection thread
+ break;
+ JabberLog(info->proto, "Reconnecting to the network...");
+ info->proto->m_iDesiredStatus = oldStatus; // Reconnect to my last status
+ oldStatus = info->proto->m_iStatus;
+ info->proto->m_iStatus = ID_STATUS_CONNECTING;
+ numRetry = 1;
+ ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
+ }
+
+ JabberLog(info->proto, "Thread ended: server='%s'", info->server);
+
+ if (info->proto->threadData == info) {
+ info->proto->threadData = NULL;
+ }
+
+ mir_free(buffer);
+ if (info->streamId) mir_free(info->streamId);
+ JabberLog(info->proto, "Exiting ServerThread");
+ mir_free(info);
+}
+
+static void TlenSendAuth(TlenProtocol *proto) {
+ int iqId;
+ char *p;
+ char *str;
+ char text[128];
+ str = TlenPasswordHash(proto->threadData->password);
+ sprintf(text, "%s%s", proto->threadData->streamId, str);
+ mir_free(str);
+ str = JabberSha1(text);
+ if ((p=JabberTextEncode(proto->threadData->username)) != NULL) {
+ iqId = JabberSerialNext(proto->threadData->proto);
+ JabberIqAdd(proto, iqId, IQ_PROC_NONE, JabberIqResultAuth);
+ JabberSend(proto, "<iq type='set' id='"JABBER_IQID"%d'><query xmlns='jabber:iq:auth'><username>%s</username><digest>%s</digest><resource>t</resource><host>tlen.pl</host></query></iq>", iqId, p /*info->username*/, str);
+ mir_free(p);
+ }
+ mir_free(str);
+}
+
+static void JabberProcessStreamOpening(XmlNode *node, ThreadData *info)
+{
+ char *sid, *s;
+
+ if (node->name == NULL || strcmp(node->name, "s"))
+ return;
+
+ if ((sid=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if (info->streamId) mir_free(info->streamId);
+ info->streamId = mir_strdup(sid);
+ }
+ if ((s=JabberXmlGetAttrValue(node, "s")) != NULL && !strcmp(s, "1")) {
+ int i;
+ char *k1, *k2, *k3;
+ unsigned char aes_key[32];
+ char aes_key_str[140], aes_iv_str[40];
+ mpi k1_mpi, k2_mpi, aes_mpi;
+ size_t slen;
+
+ k1=JabberXmlGetAttrValue(node, "k1");
+ k2=JabberXmlGetAttrValue(node, "k2");
+ k3=JabberXmlGetAttrValue(node, "k3");
+
+ memset(&info->aes_in_context, 0, sizeof (aes_context));
+ memset(&info->aes_out_context, 0, sizeof (aes_context));
+ memset(&aes_mpi, 0, sizeof (mpi));
+ mpi_read_string(&aes_mpi, 16, k3);
+ mpi_write_binary(&aes_mpi, info->aes_in_iv, 16);
+ for (i = 0; i < 16; i++) {
+ info->aes_out_iv[i] = rand();
+ aes_key[i] = rand();
+ }
+ memset(&aes_mpi, 0, sizeof (mpi));
+ mpi_read_binary(&aes_mpi, info->aes_out_iv, 16);
+ slen = 40;
+ mpi_write_string(&aes_mpi, 16, aes_iv_str, &slen);
+ aes_setkey_dec(&info->aes_in_context, aes_key, 128);
+ aes_setkey_enc(&info->aes_out_context, aes_key, 128);
+ memset(&aes_mpi, 0, sizeof (mpi));
+ mpi_read_binary(&aes_mpi, aes_key, 16);
+ memset(&k1_mpi, 0, sizeof (mpi));
+ mpi_read_string( &k1_mpi, 16, k1 );
+ memset(&k2_mpi, 0, sizeof (mpi));
+ mpi_read_string( &k2_mpi, 16, k2 );
+ memset(&aes_mpi, 0, sizeof (mpi));
+ mpi_read_binary(&aes_mpi, (unsigned char *)aes_key, 16);
+ mpi_exp_mod( &aes_mpi, &aes_mpi, &k1_mpi, &k2_mpi, NULL );
+ slen = 140;
+ mpi_write_string(&aes_mpi, 16, aes_key_str, &slen);
+ JabberSend(info->proto, "<cipher k1='%s' k2='%s'/>", aes_key_str, aes_iv_str);
+ } else {
+ TlenSendAuth(info->proto);
+ }
+}
+
+static void JabberProcessStreamClosing(XmlNode *node, ThreadData *info)
+{
+ Netlib_CloseHandle(info->proto);
+ if (node->name && !strcmp(node->name, "stream:error") && node->text)
+ MessageBoxA(NULL, Translate(node->text), Translate("Jabber Connection Error"), MB_OK|MB_ICONERROR|MB_SETFOREGROUND);
+}
+
+static void JabberProcessProtocol(XmlNode *node, ThreadData *info)
+{
+ if (!strcmp(node->name, "message"))
+ JabberProcessMessage(node, info);
+ else if (!strcmp(node->name, "presence"))
+ TlenProcessPresence(node, info->proto);
+ else if (!strcmp(node->name, "iq"))
+ JabberProcessIq(node, info);
+ else if (!strcmp(node->name, "f"))
+ TlenProcessF(node, info);
+ else if (!strcmp(node->name, "w"))
+ TlenProcessW(node, info);
+ else if (!strcmp(node->name, "m"))
+ TlenProcessM(node, info);
+ else if (!strcmp(node->name, "n"))
+ TlenProcessN(node, info);
+ else if (!strcmp(node->name, "p"))
+ TlenProcessP(node, info);
+ else if (!strcmp(node->name, "v"))
+ TlenProcessV(node, info);
+ else if (!strcmp(node->name, "avatar"))
+ TlenProcessAvatar(node, info);
+ else if (!strcmp(node->name, "cipher"))
+ TlenProcessCipher(node, info);
+ else
+ JabberLog(info->proto, "Invalid top-level tag (only <message/> <presence/> <iq/> <f/> <w/> <m/> <n/> <p/> <v/> <cipher/> and <avatar/> allowed)");
+
+}
+
+static void TlenProcessCipher(XmlNode *node, ThreadData *info)
+{
+ char *type;
+ type=JabberXmlGetAttrValue(node, "type");
+ info->useAES = TRUE;
+ JabberSend(info->proto, "<cipher type='ok'/>");
+ TlenSendAuth(info->proto);
+}
+
+static void TlenProcessIqGetVersion(TlenProtocol *proto, XmlNode* node)
+{
+ OSVERSIONINFO osvi = { 0 };
+ char mversion[256];
+ char* from, *version, *mver;
+ char* os = NULL;
+ JABBER_LIST_ITEM *item;
+
+ if (proto->m_iStatus == ID_STATUS_INVISIBLE) return;
+ if (!proto->tlenOptions.enableVersion) return;
+ if (( from=JabberXmlGetAttrValue( node, "from" )) == NULL ) return;
+ if (( item=JabberListGetItemPtr( proto, LIST_ROSTER, from )) ==NULL) return;
+ version = JabberTextEncode( TLEN_VERSION_STRING );
+ osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+ if ( GetVersionEx( &osvi )) {
+ switch ( osvi.dwPlatformId ) {
+ case VER_PLATFORM_WIN32_NT:
+ if ( osvi.dwMajorVersion == 5 ) {
+ if ( osvi.dwMinorVersion == 2 ) os = JabberTextEncode( Translate( "Windows Server 2003" ));
+ else if ( osvi.dwMinorVersion == 1 ) os = JabberTextEncode( Translate( "Windows XP" ));
+ else if ( osvi.dwMinorVersion == 0 ) os = JabberTextEncode( Translate( "Windows 2000" ));
+ }
+ else if ( osvi.dwMajorVersion <= 4 ) {
+ os = JabberTextEncode( Translate( "Windows NT" ));
+ }
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if ( osvi.dwMajorVersion == 4 ) {
+ if ( osvi.dwMinorVersion == 0 ) os = JabberTextEncode( Translate( "Windows 95" ));
+ if ( osvi.dwMinorVersion == 10 ) os = JabberTextEncode( Translate( "Windows 98" ));
+ if ( osvi.dwMinorVersion == 90 ) os = JabberTextEncode( Translate( "Windows ME" ));
+ }
+ break;
+ } }
+
+ if ( os == NULL ) os = JabberTextEncode( Translate( "Windows" ));
+
+ strcpy(mversion, "Miranda NG ");
+ CallService( MS_SYSTEM_GETVERSIONTEXT, sizeof( mversion ) - 11, ( LPARAM )mversion + 11 );
+ strcat(mversion, " (Tlen v.");
+ strcat(mversion, TLEN_VERSION_STRING);
+ strcat(mversion, ")");
+ mver = JabberTextEncode( mversion );
+ JabberSend( proto, "<message to='%s' type='iq'><iq type='result'><query xmlns='jabber:iq:version'><name>%s</name><version>%s</version><os>%s</os></query></iq></message>", from, mver?mver:"", version?version:"", os?os:"" );
+ if (!item->versionRequested) {
+ item->versionRequested = TRUE;
+ JabberSend(proto, "<message to='%s' type='iq'><iq type='get'><query xmlns='jabber:iq:version'/></iq></message>", from);
+ }
+
+ if ( mver ) mir_free( mver );
+ if ( version ) mir_free( version );
+ if ( os ) mir_free( os );
+}
+
+// Support for Tlen avatars - avatar token used to access web interface
+static void TlenProcessAvatar(XmlNode* node, ThreadData *info)
+{
+ XmlNode *tokenNode, *aNode;
+ tokenNode = JabberXmlGetChild(node, "token");
+ aNode = JabberXmlGetChild(node, "a");
+ if (tokenNode != NULL) {
+ char *token = tokenNode->text;
+ strcpy(info->avatarToken, token);
+ }
+ if (aNode != NULL) {
+ if (TlenProcessAvatarNode(info->proto, node, NULL)) {
+ }
+ }
+}
+
+static void JabberProcessMessage(XmlNode *node, ThreadData *info)
+{
+ HANDLE hContact;
+ CCSDATA ccs;
+ PROTORECVEVENT recv;
+ XmlNode *bodyNode, *subjectNode, *xNode, *n;
+ char *from, *type, *nick, *p, *localMessage, *idStr;
+ DWORD msgTime;
+ BOOL delivered, composing;
+ int i;
+ JABBER_LIST_ITEM *item;
+ BOOL isChatRoomJid;
+
+ if (!node->name || strcmp(node->name, "message")) return;
+
+ if ((type=JabberXmlGetAttrValue(node, "type")) != NULL && !strcmp(type, "error")) {
+ }
+ else {
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ char *fromJid = JabberLoginFromJID(from);
+ if (info->proto->tlenOptions.ignoreAdvertisements && strstr(from, "b73@tlen.pl") == from) {
+ return;
+ }
+ // If message is from a stranger (not in roster), item is NULL
+ item = JabberListGetItemPtr(info->proto, LIST_ROSTER, fromJid);
+ isChatRoomJid = JabberListExist(info->proto, LIST_CHATROOM, from);
+
+ if (isChatRoomJid && type != NULL && !strcmp(type, "groupchat")) {
+ //JabberGroupchatProcessMessage(node, userdata);
+ } else if (type != NULL && !strcmp(type, "pic")) {
+ TlenProcessPic(node, info->proto);
+ } else if (type != NULL && !strcmp(type, "iq")) {
+ XmlNode *iqNode;
+ // Jabber-compatible iq
+ if ((iqNode=JabberXmlGetChild(node, "iq")) != NULL) {
+ JabberXmlAddAttr(iqNode, "from", from);
+ JabberProcessIq(iqNode, info);
+ }
+ } else {
+ if ((bodyNode=JabberXmlGetChild(node, "body")) != NULL) {
+ if (bodyNode->text != NULL) {
+ if ((subjectNode=JabberXmlGetChild(node, "subject")) != NULL && subjectNode->text != NULL && subjectNode->text[0] != '\0') {
+ p = (char *) mir_alloc(strlen(subjectNode->text)+strlen(bodyNode->text)+5);
+ sprintf(p, "%s\r\n%s", subjectNode->text, bodyNode->text);
+ localMessage = JabberTextDecode(p);
+ mir_free(p);
+ } else {
+ localMessage = JabberTextDecode(bodyNode->text);
+ }
+
+ msgTime = 0;
+ delivered = composing = FALSE;
+ i = 1;
+ while ((xNode=JabberXmlGetNthChild(node, "x", i)) != NULL) {
+ if ((p=JabberXmlGetAttrValue(xNode, "xmlns")) != NULL) {
+ if (!strcmp(p, "jabber:x:delay") && msgTime==0) {
+ if ((p=JabberXmlGetAttrValue(xNode, "stamp")) != NULL) {
+ msgTime = JabberIsoToUnixTime(p);
+ }
+ }
+ else if (!strcmp(p, "jabber:x:event")) {
+ // Check whether any event is requested
+ if (!delivered && (n=JabberXmlGetChild(xNode, "delivered")) != NULL) {
+ delivered = TRUE;
+ idStr = JabberXmlGetAttrValue(node, "id");
+ JabberSend(info->proto, "<message to='%s'><x xmlns='jabber:x:event'><delivered/><id>%s</id></x></message>", from, (idStr != NULL)?idStr:"");
+ }
+ if (item != NULL && JabberXmlGetChild(xNode, "composing") != NULL) {
+ composing = TRUE;
+ if (item->messageEventIdStr)
+ mir_free(item->messageEventIdStr);
+ idStr = JabberXmlGetAttrValue(node, "id");
+ item->messageEventIdStr = (idStr == NULL)?NULL:mir_strdup(idStr);
+ }
+ }
+ }
+ i++;
+ }
+
+ if (item != NULL) {
+ item->wantComposingEvent = composing;
+ if (item->isTyping) {
+ item->isTyping = FALSE;
+ if ((hContact=JabberHContactFromJID(info->proto, fromJid)) != NULL)
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM) hContact, PROTOTYPE_CONTACTTYPING_OFF);
+ }
+ }
+
+ if ((hContact=JabberHContactFromJID(info->proto, fromJid)) == NULL) {
+ // Create a temporary contact
+ if (isChatRoomJid) {
+ if ((p=strchr(from, '/')) != NULL && p[1]!='\0')
+ p++;
+ else
+ p = from;
+ nick = JabberTextEncode(p);
+ hContact = JabberDBCreateContact(info->proto, from, nick, TRUE);
+ }
+ else {
+ nick = JabberLocalNickFromJID(from);
+ hContact = JabberDBCreateContact(info->proto, from, nick, TRUE);
+ }
+ mir_free(nick);
+ }
+
+ if (msgTime == 0) {
+ msgTime = time(NULL);
+ } else {
+ HANDLE hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) hContact, 0);
+ if (hDbEvent != NULL) {
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) &dbei);
+ if (msgTime < dbei.timestamp) {
+ msgTime = dbei.timestamp + 1;
+ }
+ }
+ if (msgTime > (DWORD)time(NULL)) {
+ msgTime = time(NULL);
+ }
+ }
+ recv.flags = 0;
+ recv.timestamp = (DWORD) msgTime;
+ recv.szMessage = localMessage;
+ recv.lParam = 0;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = (LPARAM) &recv;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
+
+ mir_free(localMessage);
+ }
+ }
+ }
+ mir_free(fromJid);
+ }
+ }
+}
+
+static void JabberProcessIq(XmlNode *node, ThreadData *info)
+{
+ HANDLE hContact;
+ XmlNode *queryNode = NULL;
+ char *type, *jid, *nick;
+ char *xmlns = NULL;
+ char *idStr, *str;
+ int id;
+ int i;
+ JABBER_IQ_PFUNC pfunc;
+
+ if (!node->name || strcmp(node->name, "iq")) return;
+ type=JabberXmlGetAttrValue(node, "type");
+// if ((type=JabberXmlGetAttrValue(node, "type")) == NULL) return;
+
+ id = -1;
+ if ((idStr=JabberXmlGetAttrValue(node, "id")) != NULL) {
+ if (!strncmp(idStr, JABBER_IQID, strlen(JABBER_IQID)))
+ id = atoi(idStr+strlen(JABBER_IQID));
+ }
+
+ queryNode = JabberXmlGetChild(node, "query");
+ if (queryNode != NULL) {
+ xmlns = JabberXmlGetAttrValue(queryNode, "xmlns");
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////
+ // MATCH BY ID
+ /////////////////////////////////////////////////////////////////////////
+ if ((pfunc=JabberIqFetchFunc(info->proto, id)) != NULL) {
+ JabberLog(info->proto, "Handling iq request for id=%d", id);
+ pfunc(info->proto, node);
+ /////////////////////////////////////////////////////////////////////////
+ // MORE GENERAL ROUTINES, WHEN ID DOES NOT MATCH
+ /////////////////////////////////////////////////////////////////////////
+ // new p2p connections
+ } else if (xmlns != NULL && !strcmp(xmlns, "p2p")) {
+ if (info->proto->tlenOptions.useNewP2P) {
+ TlenProcessP2P(node, info);
+ }
+ }
+ // RECVED: <iq type='set'><query ...
+ else if (!strcmp(type, "set") && queryNode != NULL && xmlns != NULL) {
+
+ // RECVED: roster push
+ // ACTION: similar to iqIdGetRoster above
+ if (!strcmp(xmlns, "jabber:iq:roster")) {
+ XmlNode *itemNode, *groupNode;
+ JABBER_LIST_ITEM *item;
+ char *name;
+
+ JabberLog(info->proto, "<iq/> Got roster push, query has %d children", queryNode->numChild);
+ for (i=0; i<queryNode->numChild; i++) {
+ itemNode = queryNode->child[i];
+ if (!strcmp(itemNode->name, "item")) {
+ if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
+ if ((str=JabberXmlGetAttrValue(itemNode, "subscription")) != NULL) {
+ // we will not add new account when subscription=remove
+ if (!strcmp(str, "to") || !strcmp(str, "both") || !strcmp(str, "from") || !strcmp(str, "none")) {
+ if ((name=JabberXmlGetAttrValue(itemNode, "name")) != NULL) {
+ nick = JabberTextDecode(name);
+ } else {
+ nick = JabberLocalNickFromJID(jid);
+ }
+ if (nick != NULL) {
+ if ((item=JabberListAdd(info->proto, LIST_ROSTER, jid)) != NULL) {
+ if (item->nick) mir_free(item->nick);
+ item->nick = nick;
+ if ((hContact=JabberHContactFromJID(info->proto, jid)) == NULL) {
+ // Received roster has a new JID.
+ // Add the jid (with empty resource) to Miranda contact list.
+ hContact = JabberDBCreateContact(info->proto, jid, nick, FALSE);
+ }
+ DBWriteContactSettingString(hContact, "CList", "MyHandle", nick);
+ if (item->group) mir_free(item->group);
+ if ((groupNode=JabberXmlGetChild(itemNode, "group")) != NULL && groupNode->text != NULL) {
+ item->group = TlenGroupDecode(groupNode->text);
+ JabberContactListCreateGroup(item->group);
+ DBWriteContactSettingString(hContact, "CList", "Group", item->group);
+ }
+ else {
+ item->group = NULL;
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ if (!strcmp(str, "none") || (!strcmp(str, "from") && strchr(jid, '@') != NULL)) {
+ if (DBGetContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+ else {
+ mir_free(nick);
+ }
+ }
+ }
+ if ((item=JabberListGetItemPtr(info->proto, LIST_ROSTER, jid)) != NULL) {
+ if (!strcmp(str, "both")) item->subscription = SUB_BOTH;
+ else if (!strcmp(str, "to")) item->subscription = SUB_TO;
+ else if (!strcmp(str, "from")) item->subscription = SUB_FROM;
+ else item->subscription = SUB_NONE;
+ JabberLog(info->proto, "Roster push for jid=%s, set subscription to %s", jid, str);
+ // subscription = remove is to remove from roster list
+ // but we will just set the contact to offline and not actually
+ // remove, so that history will be retained.
+ if (!strcmp(str, "remove")) {
+ if ((hContact=JabberHContactFromJID(info->proto, jid)) != NULL) {
+ if (DBGetContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ DBWriteContactSettingWord(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ JabberListRemove(info->proto, LIST_ROSTER, jid);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ // RECVED: <iq type='get'><query ...
+ else if ( !strcmp( type, "get" ) && queryNode != NULL && xmlns != NULL ) {
+ // RECVED: software version query
+ // ACTION: return my software version
+ if ( !strcmp( xmlns, "jabber:iq:version" )) TlenProcessIqGetVersion(info->proto, node);
+ }
+ // RECVED: <iq type='result'><query ...
+ else if ( !strcmp( type, "result") && queryNode != NULL) {
+ if (xmlns != NULL ) {
+ if ( !strcmp(xmlns, "jabber:iq:roster" )) {
+ JabberIqResultRoster(info->proto, node);
+ } else if ( !strcmp( xmlns, "jabber:iq:version" )) {
+ TlenIqResultVersion(info->proto, node);
+ } else if ( !strcmp( xmlns, "jabber:iq:info" )) {
+ TlenIqResultInfo(info->proto, node);
+ }
+ } else {
+ char *from;
+ if (( from=JabberXmlGetAttrValue( node, "from" )) != NULL ) {
+ if ( !strcmp(from, "tcfg" )) {
+ TlenIqResultTcfg(info->proto, node);
+ }
+ }
+ }
+ }
+ // RECVED: <iq type='error'> ...
+ else if (!strcmp(type, "error")) {
+ JABBER_LIST_ITEM *item;
+ // Check for multi-user chat errors
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strstr(from, "@c") != NULL || !strcmp(from, "c")) {
+ TlenMUCRecvError(info->proto, from, node);
+ return;
+ }
+ }
+
+ // Check for file transfer deny by comparing idStr with ft->iqId
+ i = 0;
+ while ((i=JabberListFindNext(info->proto, LIST_FILE, i)) >= 0) {
+ item = JabberListGetItemPtrFromIndex(info->proto,i);
+ if (item->ft->state==FT_CONNECTING && !strcmp(idStr, item->ft->iqId)) {
+ item->ft->state = FT_DENIED;
+ if (item->ft->hFileEvent != NULL)
+ SetEvent(item->ft->hFileEvent); // Simulate the termination of file server connection
+ }
+ i++;
+ }
+ }
+ // RECVED: <iq type='1'>...
+ else if (!strcmp(type, "1")) { // Chat groups list result
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultChatGroups(info->proto, node);
+ }
+ }
+ }
+ else if (!strcmp(type, "2")) { // Chat rooms list result
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultChatRooms(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "3")) { // room search result - result to iq type 3 query
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultRoomSearch(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "4")) { // chat room users list
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strstr(from, "@c") != NULL) {
+ TlenIqResultChatRoomUsers(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "5")) { // room name & group & flags info - sent on joining the room
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strstr(from, "@c") != NULL) {
+ TlenIqResultRoomInfo(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "6")) { // new nick registered
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultUserNicks(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "7")) { // user nicknames list
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultUserNicks(info->proto, node);
+ }
+ }
+ } else if (!strcmp(type, "8")) { // user chat rooms list
+ char *from;
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (strcmp(from, "c") == 0) {
+ TlenIqResultUserRooms(info->proto, node);
+ }
+ }
+ }
+}
+
+/*
+ * Web messages
+ */
+static void TlenProcessW(XmlNode *node, ThreadData *info)
+{
+ HANDLE hContact;
+ CCSDATA ccs;
+ PROTORECVEVENT recv;
+ char *f, *e, *s, *body;
+ char *str, *localMessage;
+ int strSize;
+
+ if (!node->name || strcmp(node->name, "w")) return;
+ if ((body=node->text) == NULL) return;
+
+ if ((f=JabberXmlGetAttrValue(node, "f")) != NULL) {
+
+ char webContactName[128];
+ sprintf(webContactName, Translate("%s Web Messages"), info->proto->m_szProtoName);
+ if ((hContact=JabberHContactFromJID(info->proto, webContactName)) == NULL) {
+ hContact = JabberDBCreateContact(info->proto, webContactName, webContactName, TRUE);
+ }
+
+ s = JabberXmlGetAttrValue(node, "s");
+ e = JabberXmlGetAttrValue(node, "e");
+
+ str = NULL;
+ strSize = 0;
+ JabberStringAppend(&str, &strSize, "%s\r\n%s: ", Translate("Web message"), Translate("From"));
+
+ if (f != NULL)
+ JabberStringAppend(&str, &strSize, "%s", f);
+ JabberStringAppend(&str, &strSize, "\r\n%s: ", Translate("E-mail"));
+ if (e != NULL)
+ JabberStringAppend(&str, &strSize, "%s", e);
+ JabberStringAppend(&str, &strSize, "\r\n\r\n%s", body);
+
+ localMessage = JabberTextDecode(str);
+
+ recv.flags = 0;
+ recv.timestamp = (DWORD) time(NULL);
+ recv.szMessage = localMessage;
+ recv.lParam = 0;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = (LPARAM) &recv;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
+
+ mir_free(localMessage);
+ mir_free(str);
+ }
+}
+
+/*
+ * Typing notification, multi-user conference messages and invitations
+ */
+static void TlenProcessM(XmlNode *node, ThreadData *info)
+{
+ HANDLE hContact;
+ CCSDATA ccs;
+ PROTORECVEVENT recv;
+ char *f;//, *from;//username
+ char *tp;//typing start/stop
+ char *p, *n, *r, *s, *str, *localMessage;
+ int i;
+ XmlNode *xNode, *invNode, *bNode, *subjectNode;
+
+ if (!node->name || strcmp(node->name, "m")) return;
+
+ if ((f=JabberXmlGetAttrValue(node, "f")) != NULL) {
+ char *fLogin = JabberLoginFromJID(f);
+ if ((hContact=JabberHContactFromJID(info->proto, fLogin)) != NULL) {
+ if ((tp=JabberXmlGetAttrValue(node, "tp")) != NULL) {
+ JABBER_LIST_ITEM *item = JabberListGetItemPtr(info->proto, LIST_ROSTER, fLogin);
+ if (!strcmp(tp, "t")) { //contact is writing
+ if (item != NULL ) {
+ item->isTyping = TRUE;
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_INFINITE);
+ }
+ }
+ else if (!strcmp(tp, "u")) {//contact stopped writing
+ if (item != NULL) {
+ item->isTyping = FALSE;
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_OFF);
+ }
+ }
+ else if (!strcmp(tp, "a")) {//alert was received
+ int bAlert = TRUE;
+ if (info->proto->tlenOptions.alertPolicy == TLEN_ALERTS_IGNORE_ALL) {
+ bAlert = FALSE;
+ } else if (info->proto->tlenOptions.alertPolicy == TLEN_ALERTS_IGNORE_NIR) {
+ bAlert = IsAuthorized(info->proto, fLogin);
+ }
+ if (bAlert) {
+ if (info->proto->tlenOptions.useNudge) {
+ NotifyEventHooks(info->proto->hTlenNudge,(WPARAM) hContact,0);
+ } else {
+ if (info->proto->tlenOptions.logAlerts) {
+ TlenLogMessage(info->proto, hContact, 0, Translate("An alert has been received."));
+ }
+ SkinPlaySound("TlenAlertNotify");
+ }
+ }
+ }
+ }
+ }
+ mir_free(fLogin);
+ if ((p=strchr(f, '@')) != NULL) {
+ if ((p=strchr(p, '/')) != NULL && p[1]!='\0') { // message from user
+ time_t timestamp;
+ s = JabberXmlGetAttrValue(node, "s");
+ if (s != NULL) {
+ timestamp = TlenTimeToUTC(atol(s));
+ if (timestamp > time(NULL)) {
+ timestamp = time(NULL);
+ }
+ } else {
+ timestamp = time(NULL);
+ }
+ tp=JabberXmlGetAttrValue(node, "tp");
+ bNode = JabberXmlGetChild(node, "b");
+ f = JabberTextDecode(f);
+ if (bNode != NULL && bNode->text != NULL) {
+ if (tp != NULL && !strcmp(tp, "p")) {
+ /* MUC private message */
+ str = JabberResourceFromJID(f);
+ hContact = JabberDBCreateContact(info->proto, f, str, TRUE);
+ DBWriteContactSettingByte(hContact, info->proto->m_szModuleName, "bChat", TRUE);
+ mir_free(str);
+ localMessage = JabberTextDecode(bNode->text);
+ recv.flags = 0;
+ recv.timestamp = (DWORD) timestamp;
+ recv.szMessage = localMessage;
+ recv.lParam = 0;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = (LPARAM) &recv;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
+ mir_free(localMessage);
+ } else {
+ /* MUC message */
+ TlenMUCRecvMessage(info->proto, f, timestamp, bNode);
+ }
+ }
+ mir_free(f);
+ } else { // message from chat room (system)
+ subjectNode = JabberXmlGetChild(node, "subject");
+ if (subjectNode != NULL) {
+ f = JabberTextDecode(f);
+ localMessage = "";
+ if (subjectNode->text != NULL) {
+ localMessage = subjectNode->text;
+ }
+ localMessage = JabberTextDecode(localMessage);
+ TlenMUCRecvTopic(info->proto, f, localMessage);
+ mir_free(localMessage);
+ mir_free(f);
+ }
+ }
+ }
+ i=1;
+ while ((xNode=JabberXmlGetNthChild(node, "x", i)) != NULL) {
+ invNode=JabberXmlGetChild(xNode, "inv");
+ if (invNode != NULL) {
+ r = JabberTextDecode(f);
+ f = JabberXmlGetAttrValue(invNode, "f");
+ f = JabberTextDecode(f);
+ n = JabberXmlGetAttrValue(invNode, "n");
+ if (n != NULL && strstr(r, n) != r) {
+ n = JabberTextDecode(n);
+ } else {
+ n = mir_strdup(Translate("Private conference"));
+ //n = JabberNickFromJID(r);
+ }
+ TlenMUCRecvInvitation(info->proto, r, n, f, "");
+ mir_free(n);
+ mir_free(r);
+ mir_free(f);
+ break;
+ }
+ i++;
+ }
+ }
+}
+
+static void TlenMailPopup(TlenProtocol *proto, char *title, char *emailInfo)
+{
+ POPUPDATAEX ppd;
+ char * lpzContactName;
+ char * lpzText;
+
+ if (!DBGetContactSettingByte(NULL, proto->m_szModuleName, "MailPopupEnabled", TRUE)) {
+ return;
+ }
+ lpzContactName = title;
+ lpzText = emailInfo;
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = NULL;
+ ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIL));
+ strcpy(ppd.lpzContactName, lpzContactName);
+ strcpy(ppd.lpzText, lpzText);
+ ppd.colorBack = DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupBack", 0);
+ ppd.colorText = DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupText", 0);
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData=NULL;
+ if ( ServiceExists( MS_POPUP_ADDPOPUPEX )) {
+ BYTE delayMode;
+ int delay;
+ delayMode = DBGetContactSettingByte(NULL, proto->m_szModuleName, "MailPopupDelayMode", 0);
+ delay = 0;
+ if (delayMode==1) {
+ delay = DBGetContactSettingDword(NULL, proto->m_szModuleName, "MailPopupDelay", 4);
+ } else if (delayMode==2) {
+ delay = -1;
+ }
+ ppd.iSeconds = delay;
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+
+ }
+ else if ( ServiceExists( MS_POPUP_ADDPOPUP )) {
+ CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0);
+ }
+}
+/*
+ * Incoming e-mail notification
+ */
+static void TlenProcessN(XmlNode *node, ThreadData *info)
+{
+ char *f, *s;
+ char *str, *popupTitle, *popupText;
+ int strSize;
+
+ if (!node->name || strcmp(node->name, "n")) return;
+
+ s = JabberXmlGetAttrValue(node, "s");
+ f = JabberXmlGetAttrValue(node, "f");
+ if (s != NULL && f != NULL) {
+ str = NULL;
+ strSize = 0;
+
+ JabberStringAppend(&str, &strSize, Translate("%s mail"), info->proto->m_szProtoName);
+ popupTitle = JabberTextDecode(str);
+ mir_free(str);
+
+ str = NULL;
+ strSize = 0;
+
+ JabberStringAppend(&str, &strSize, "%s: %s\n", Translate("From"), f);
+ JabberStringAppend(&str, &strSize, "%s: %s", Translate("Subject"), s);
+ popupText = JabberTextDecode(str);
+ TlenMailPopup(info->proto, popupTitle, popupText);
+ SkinPlaySound("TlenMailNotify");
+
+ mir_free(popupTitle);
+ mir_free(popupText);
+ mir_free(str);
+ }
+}
+
+/*
+ * Presence is chat rooms
+ */
+static void TlenProcessP(XmlNode *node, ThreadData *info)
+{
+ char jid[512];
+ char *f, *id, *tp, *a, *n, *k;
+ XmlNode *sNode, *xNode, *iNode, *kNode;
+ int status, flags;
+
+ if (!node->name || strcmp(node->name, "p")) return;
+
+// presence from users in chat room
+ flags = 0;
+ status = ID_STATUS_ONLINE;
+ f = JabberXmlGetAttrValue(node, "f");
+ xNode = JabberXmlGetChild(node, "x");
+ if (xNode != NULL) { // x subtag present (message from chat room) - change user rights only
+ char *temp, *iStr;
+ iNode = JabberXmlGetChild(xNode, "i");
+ if (iNode != NULL) {
+ iStr = JabberXmlGetAttrValue(iNode, "i");
+ temp = (char*)mir_alloc(strlen(f)+strlen(iStr)+2);
+ strcpy(temp, f);
+ strcat(temp, "/");
+ strcat(temp, iStr);
+ f = JabberTextDecode(temp);
+ mir_free(temp);
+ node = iNode;
+ status = 0;
+ } else {
+ f = JabberTextDecode(f);
+ }
+ } else {
+ f = JabberTextDecode(f);
+ }
+ a = JabberXmlGetAttrValue(node, "z");
+ if (a != NULL) {
+ if (atoi(a) &1 ) {
+ flags |= USER_FLAGS_REGISTERED;
+ }
+ }
+ a = JabberXmlGetAttrValue(node, "a");
+ if (a != NULL) {
+ if (atoi(a) == 2) {
+ flags |= USER_FLAGS_ADMIN;
+ }
+ if (atoi(a) == 1) {
+ flags |= USER_FLAGS_OWNER;
+ }
+ if (atoi(a) == 3) {
+ //flags |= USER_FLAGS_MEMBER;
+ }
+ if (atoi(a) == 5) {
+ flags |= USER_FLAGS_GLOBALOWNER;
+ }
+ }
+ sNode = JabberXmlGetChild(node, "s");
+ if (sNode != NULL) {
+ if (!strcmp(sNode->text, "unavailable")) {
+ status = ID_STATUS_OFFLINE;
+ }
+ }
+ kNode = JabberXmlGetChild(node, "kick");
+ k = NULL;
+ if (kNode != NULL) {
+ k = JabberXmlGetAttrValue(kNode, "r");
+ if (k == NULL) {
+ k = "";
+ }
+ k = JabberTextDecode(k);
+ }
+ tp = JabberXmlGetAttrValue(node, "tp");
+ if (tp != NULL && !strcmp(tp, "c")) { // new chat room has just been created
+ id = JabberXmlGetAttrValue(node, "id");
+ if (id != NULL) {
+ n = JabberXmlGetAttrValue(node, "n");
+ if (n != NULL) {
+ n = JabberTextDecode(n);
+ } else {
+ n = mir_strdup(Translate("Private conference"));// JabberNickFromJID(f);
+ }
+ sprintf(jid, "%s/%s", f, info->username);
+// if (!DBGetContactSetting(NULL, info->proto->m_szModuleName, "LoginName", &dbv)) {
+ // always real username
+// sprintf(jid, "%s/%s", f, dbv.pszVal);
+ TlenMUCCreateWindow(info->proto, f, n, 0, NULL, id);
+ TlenMUCRecvPresence(info->proto, jid, ID_STATUS_ONLINE, flags, k);
+// DBFreeVariant(&dbv);
+// }
+ mir_free(n);
+ }
+ } else {
+ TlenMUCRecvPresence(info->proto, f, status, flags, k); // user presence
+ }
+ if (k != NULL) {
+ mir_free(k);
+ }
+ mir_free(f);
+}
+/*
+ * Voice chat
+ */
+static void TlenProcessV(XmlNode *node, ThreadData *info)
+{
+ char jid[128];
+ JABBER_LIST_ITEM *item;
+ char *from, *id, *e, *p;
+// if (!node->name || strcmp(node->name, "v")) return;
+
+ if ((from=JabberXmlGetAttrValue(node, "f")) != NULL) {
+ if (strchr(from, '@') == NULL) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, info->server);
+ } else {
+ _snprintf(jid, sizeof(jid), "%s", from);
+ }
+ if ((e=JabberXmlGetAttrValue(node, "e")) != NULL) {
+ if (!strcmp(e, "1")) {
+ if ((id=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ SkinPlaySound("TlenVoiceNotify");
+ TlenVoiceAccept(info->proto, id, from);
+ }
+ } else if (!strcmp(e, "3")) {
+ // FILE_RECV : e='3' : invalid transfer error
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ if (item->ft != NULL) {
+ HANDLE hEvent = item->ft->hFileEvent;
+ item->ft->hFileEvent = NULL;
+ item->ft->state = FT_ERROR;
+ if (item->ft->s != NULL) {
+ Netlib_CloseHandle(item->ft->s);
+ item->ft->s = NULL;
+ if (hEvent != NULL) {
+ SetEvent(hEvent);
+ }
+ } else {
+ TlenP2PFreeFileTransfer(item->ft);
+ }
+ } else {
+ JabberListRemove(info->proto, LIST_VOICE, p);
+ }
+ }
+ }
+ } else if (!strcmp(e, "4")) {
+ // FILE_SEND : e='4' : File sending request was denied by the remote client
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ if (!strcmp(item->ft->jid, jid)) {
+ TlenVoiceCancelAll(info->proto);
+ //JabberListRemove(info->proto, LIST_VOICE, p);
+ }
+ }
+ }
+ } else if (!strcmp(e, "5")) {
+ // FILE_SEND : e='5' : Voice request was accepted
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ JabberLog(info->proto, "should start voice 1 ? %s ?? %s", jid, item->ft->jid);
+ if (!strcmp(item->ft->jid, jid)) {
+ JabberLog(info->proto, "starting voice 1");
+ TlenVoiceStart(item->ft, 1);
+ }
+ }
+ }
+ } else if (!strcmp(e, "6")) {
+ // FILE_RECV : e='6' : IP and port information to connect to get file
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ if ((p=JabberXmlGetAttrValue(node, "a")) != NULL) {
+ item->ft->hostName = mir_strdup(p);
+ if ((p=JabberXmlGetAttrValue(node, "p")) != NULL) {
+ item->ft->wPort = atoi(p);
+ TlenVoiceStart(item->ft, 0);
+ //JabberForkThread((void (__cdecl *)(void*))TlenVoiceReceiveThread, 0, item->ft);
+ }
+ }
+ }
+ }
+ }
+ else if (!strcmp(e, "7")) {
+ // FILE_RECV : e='7' : IP and port information to connect to send file
+ // in case the conection to the given server was not successful
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ if ((p=JabberXmlGetAttrValue(node, "a")) != NULL) {
+ if (item->ft->hostName != NULL) mir_free(item->ft->hostName);
+ item->ft->hostName = mir_strdup(p);
+ if ((p=JabberXmlGetAttrValue(node, "p")) != NULL) {
+ item->ft->wPort = atoi(p);
+ item->ft->state = FT_SWITCH;
+ SetEvent(item->ft->hFileEvent);
+ }
+ }
+ }
+ }
+ }
+ else if (!strcmp(e, "8")) {
+ // FILE_RECV : e='8' : transfer error
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_VOICE, p)) != NULL) {
+ item->ft->state = FT_ERROR;
+ SetEvent(item->ft->hFileEvent);
+ }
+ }
+ }
+
+ }
+ }
+}
+
+static void __cdecl JabberKeepAliveThread(void *ptr)
+{
+ NETLIBSELECT nls = {0};
+
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ nls.cbSize = sizeof(NETLIBSELECT);
+ nls.dwTimeout = 60000; // 60000 millisecond (1 minute)
+ nls.hExceptConns[0] = proto->threadData->s;
+ for (;;) {
+ if (CallService(MS_NETLIB_SELECT, 0, (LPARAM) &nls) != 0)
+ break;
+ if (proto->tlenOptions.sendKeepAlive)
+ JabberSend(proto, " \t ");
+ }
+ JabberLog(proto, "Exiting KeepAliveThread");
+}
+
diff --git a/protocols/Tlen/src/jabber_util.cpp b/protocols/Tlen/src/jabber_util.cpp
new file mode 100644
index 0000000000..00ce04e579
--- /dev/null
+++ b/protocols/Tlen/src/jabber_util.cpp
@@ -0,0 +1,647 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include <ctype.h>
+#include <win2k.h>
+
+
+HANDLE HookEventObj_Ex(const char *name, TlenProtocol *proto, MIRANDAHOOKOBJ hook)
+{
+ proto->hookNum ++;
+ proto->hHooks = (HANDLE *) mir_realloc(proto->hHooks, sizeof(HANDLE) * (proto->hookNum));
+ proto->hHooks[proto->hookNum - 1] = HookEventObj(name, hook, proto);
+ return proto->hHooks[proto->hookNum - 1] ;
+}
+
+
+HANDLE CreateServiceFunction_Ex(const char *name, TlenProtocol *proto, MIRANDASERVICEOBJ service) {
+ proto->serviceNum++;
+ proto->hServices = (HANDLE *) mir_realloc(proto->hServices, sizeof(HANDLE) * (proto->serviceNum));
+ proto->hServices[proto->serviceNum - 1] = CreateServiceFunctionObj(name, service, proto);
+ return proto->hServices[proto->serviceNum - 1] ;
+}
+
+void UnhookEvents_Ex(TlenProtocol *proto) {
+ unsigned int i;
+ for (i=0; i<proto->hookNum; ++i) {
+ if (proto->hHooks[i] != NULL) {
+ UnhookEvent(proto->hHooks[i]);
+ }
+ }
+ mir_free(proto->hHooks);
+ proto->hookNum = 0;
+ proto->hHooks = NULL;
+}
+
+void DestroyServices_Ex(TlenProtocol *proto) {
+ unsigned int i;
+ for (i=0; i<proto->serviceNum; ++i) {
+ if (proto->hServices[i] != NULL) {
+ DestroyServiceFunction(proto->hServices[i]);
+ }
+ }
+ mir_free(proto->hServices);
+ proto->serviceNum = 0;
+ proto->hServices = NULL;
+}
+
+void JabberSerialInit(TlenProtocol *proto)
+{
+ InitializeCriticalSection(&proto->csSerial);
+ proto->serial = 0;
+}
+
+void JabberSerialUninit(TlenProtocol *proto)
+{
+ DeleteCriticalSection(&proto->csSerial);
+}
+
+
+unsigned int JabberSerialNext(TlenProtocol *proto)
+{
+ unsigned int ret;
+
+ EnterCriticalSection(&proto->csSerial);
+ ret = proto->serial;
+ proto->serial++;
+ LeaveCriticalSection(&proto->csSerial);
+ return ret;
+}
+
+
+void JabberLog(TlenProtocol *proto, const char *fmt, ...)
+{
+#ifdef ENABLE_LOGGING
+ char *str;
+ va_list vararg;
+ int strsize;
+ char *text;
+ char *p, *q;
+ int extra;
+
+ va_start(vararg, fmt);
+ str = (char *) mir_alloc(strsize=2048);
+ while (_vsnprintf(str, strsize, fmt, vararg) == -1)
+ str = (char *) mir_realloc(str, strsize+=2048);
+ va_end(vararg);
+
+ extra = 0;
+ for (p=str; *p != '\0'; p++)
+ if (*p == '\n' || *p == '\r')
+ extra++;
+ text = (char *) mir_alloc(strlen("TLEN")+2+strlen(str)+2+extra);
+ sprintf(text, "[%s]", "TLEN");
+ for (p=str,q=text+strlen(text); *p != '\0'; p++,q++) {
+ if (*p == '\r') {
+ *q = '\\';
+ *(q+1) = 'r';
+ q++;
+ }
+ else if (*p == '\n') {
+ *q = '\\';
+ *(q+1) = 'n';
+ q++;
+ }
+ else
+ *q = *p;
+ }
+ *q = '\n';
+ *(q+1) = '\0';
+ if (proto->hNetlibUser != NULL) {
+ CallService(MS_NETLIB_LOG, (WPARAM) proto->hNetlibUser, (LPARAM) text);
+ }
+ //OutputDebugString(text);
+ mir_free(text);
+ mir_free(str);
+#endif
+}
+
+// Caution: DO NOT use JabberSend() to send binary (non-string) data
+
+int JabberSend(TlenProtocol *proto, const char *fmt, ...)
+{
+ char *str;
+ int size;
+ va_list vararg;
+ int result = 0;
+
+ EnterCriticalSection(&proto->csSend);
+
+ va_start(vararg,fmt);
+ size = 512;
+ str = (char *) mir_alloc(size);
+ while (_vsnprintf(str, size, fmt, vararg) == -1) {
+ size += 512;
+ str = (char *) mir_realloc(str, size);
+ }
+ va_end(vararg);
+
+ JabberLog(proto, "SEND:%s", str);
+ size = (int)strlen(str);
+ if (proto->threadData != NULL) {
+ if (proto->threadData->useAES) {
+ result = JabberWsSendAES(proto, str, size, &proto->threadData->aes_out_context, proto->threadData->aes_out_iv);
+ } else {
+ result = JabberWsSend(proto, proto->threadData->s, str, size);
+ }
+ }
+ LeaveCriticalSection(&proto->csSend);
+
+ mir_free(str);
+ return result;
+}
+
+char *JabberResourceFromJID(const char *jid2)
+{
+ char *p;
+ char *nick;
+ char* jid = mir_strdup(jid2);
+
+ p=strchr(jid, '/');
+ if (p != NULL && p[1] != '\0') {
+ p++;
+ if ((nick=(char *) mir_alloc(1+strlen(jid)-(p-jid))) != NULL) {
+ strncpy(nick, p, strlen(jid)-(p-jid));
+ nick[strlen(jid)-(p-jid)] = '\0';
+ }
+ }
+ else {
+ nick = mir_strdup(jid);
+ }
+
+ mir_free(jid);
+ return nick;
+}
+
+char *JabberNickFromJID(const char *jid2)
+{
+ char *p;
+ char *nick;
+ char* jid = mir_strdup(jid2);
+
+ if ((p=strchr(jid, '@')) == NULL)
+ p = strchr(jid, '/');
+ if (p != NULL) {
+ if ((nick=(char *) mir_alloc((p-jid)+1)) != NULL) {
+ strncpy(nick, jid, p-jid);
+ nick[p-jid] = '\0';
+ }
+ }
+ else {
+ nick = mir_strdup(jid);
+ }
+
+ mir_free(jid);
+ return nick;
+}
+
+char *JabberLoginFromJID(const char *jid2)
+{
+ char *p;
+ char *nick;
+ char* jid = mir_strdup(jid2);
+
+ p = strchr(jid, '/');
+ if (p != NULL) {
+ if ((nick=(char *) mir_alloc((p-jid)+1)) != NULL) {
+ strncpy(nick, jid, p-jid);
+ nick[p-jid] = '\0';
+ }
+ }
+ else {
+ nick = mir_strdup(jid);
+ }
+
+ mir_free(jid);
+ return nick;
+}
+
+char *JabberLocalNickFromJID(const char *jid)
+{
+ char *p;
+ char *localNick;
+
+ p = JabberNickFromJID(jid);
+ localNick = JabberTextDecode(p);
+ mir_free(p);
+ return localNick;
+}
+
+char *JabberSha1(char *str)
+{
+ mir_sha1_ctx sha;
+ DWORD digest[5];
+ char* result;
+
+ if ( str == NULL )
+ return NULL;
+
+ mir_sha1_init( &sha );
+ mir_sha1_append( &sha, (mir_sha1_byte_t* )str, (int)strlen( str ));
+ mir_sha1_finish( &sha, (mir_sha1_byte_t* )digest );
+ if ((result=(char *)mir_alloc(41)) == NULL)
+ return NULL;
+ sprintf(result, "%08x%08x%08x%08x%08x", (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3]), (int)htonl(digest[4]));
+ return result;
+}
+
+char *TlenSha1(char *str, int len)
+{
+ mir_sha1_ctx sha;
+ mir_sha1_byte_t digest[20];
+ char* result;
+ int i;
+
+ if ( str == NULL )
+ return NULL;
+
+ mir_sha1_init( &sha );
+ mir_sha1_append( &sha, (mir_sha1_byte_t* )str, len);
+ mir_sha1_finish( &sha, digest );
+ if (( result=( char* )mir_alloc( 20 )) == NULL )
+ return NULL;
+ for (i=0; i<20; i++)
+ result[i]=digest[4*(i>>2)+(3-(i&0x3))];
+ return result;
+}
+
+char *TlenPasswordHash(const char *str)
+{
+ int magic1 = 0x50305735, magic2 = 0x12345671, sum = 7;
+ char *p, *res;
+
+ if (str == NULL) return NULL;
+ for (p=(char *)str; *p != '\0'; p++) {
+ if (*p != ' ' && *p != '\t') {
+ magic1 ^= (((magic1 & 0x3f) + sum) * ((char) *p)) + (magic1 << 8);
+ magic2 += (magic2 << 8) ^ magic1;
+ sum += ((char) *p);
+ }
+ }
+ magic1 &= 0x7fffffff;
+ magic2 &= 0x7fffffff;
+ res = (char *) mir_alloc(17);
+ sprintf(res, "%08x%08x", magic1, magic2);
+ return res;
+}
+
+char *TlenUrlEncode(const char *str)
+{
+ char *p, *q, *res;
+ unsigned char c;
+
+ if (str == NULL) return NULL;
+ res = (char *) mir_alloc(3*strlen(str) + 1);
+ for (p=(char *)str,q=res; *p != '\0'; p++,q++) {
+ if (*p == ' ') {
+ *q = '+';
+ }
+ else if (*p < 0x20 || *p >= 0x7f || strchr("%&+:'<>\"", *p) != NULL) {
+ // Convert first from CP1252 to ISO8859-2
+ switch ((unsigned char) *p) {
+ case 0xa5: c = (unsigned char) 0xa1; break;
+ case 0x8c: c = (unsigned char) 0xa6; break;
+ case 0x8f: c = (unsigned char) 0xac; break;
+ case 0xb9: c = (unsigned char) 0xb1; break;
+ case 0x9c: c = (unsigned char) 0xb6; break;
+ case 0x9f: c = (unsigned char) 0xbc; break;
+ default: c = (unsigned char) *p; break;
+ }
+ sprintf(q, "%%%02X", c);
+ q += 2;
+ }
+ else {
+ *q = *p;
+ }
+ }
+ *q = '\0';
+ return res;
+}
+
+void TlenUrlDecode(char *str)
+{
+ char *p, *q;
+ unsigned int code;
+
+ if (str == NULL) return;
+ for (p=q=str; *p != '\0'; p++,q++) {
+ if (*p == '+') {
+ *q = ' ';
+ }
+ else if (*p == '%' && *(p+1) != '\0' && isxdigit(*(p+1)) && *(p+2) != '\0' && isxdigit(*(p+2))) {
+ sscanf(p+1, "%2x", &code);
+ *q = (char) code;
+ // Convert from ISO8859-2 to CP1252
+ switch ((unsigned char) *q) {
+ case 0xa1: *q = (char) 0xa5; break;
+ case 0xa6: *q = (char) 0x8c; break;
+ case 0xac: *q = (char) 0x8f; break;
+ case 0xb1: *q = (char) 0xb9; break;
+ case 0xb6: *q = (char) 0x9c; break;
+ case 0xbc: *q = (char) 0x9f; break;
+ }
+ p += 2;
+ }
+ else {
+ *q = *p;
+ }
+ }
+ *q = '\0';
+}
+
+char * TlenGroupDecode(const char *str)
+{
+ char *p, *q;
+ if (str == NULL) return NULL;
+ p = q = JabberTextDecode(str);
+ for (; *p != '\0'; p++) {
+ if (*p == '/') {
+ *p = '\\';
+ }
+ }
+ return q;
+}
+
+char * TlenGroupEncode(const char *str)
+{
+ char *p, *q;
+ if (str == NULL) return NULL;
+ p = q = mir_strdup(str);
+ for (; *p != '\0'; p++) {
+ if (*p == '\\') {
+ *p = '/';
+ }
+ }
+ p = JabberTextEncode(q);
+ mir_free(q);
+ return p;
+}
+
+char *JabberTextEncode(const char *str)
+{
+ char *s1;
+
+ if (str == NULL) return NULL;
+ if ((s1=TlenUrlEncode(str)) == NULL)
+ return NULL;
+ return s1;
+}
+
+char *JabberTextDecode(const char *str)
+{
+ char *s1;
+
+ if (str == NULL) return NULL;
+ s1 = mir_strdup(str);
+ TlenUrlDecode(s1);
+ return s1;
+}
+
+static char b64table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+char *JabberBase64Encode(const char *buffer, int bufferLen)
+{
+ int n;
+ unsigned char igroup[3];
+ char *p, *peob;
+ char *res, *r;
+
+ if (buffer == NULL || bufferLen <= 0) return NULL;
+ if ((res=(char *) mir_alloc((((bufferLen+2)/3)*4) + 1)) == NULL) return NULL;
+
+ for (p=(char*)buffer,peob=p+bufferLen,r=res; p<peob;) {
+ igroup[0] = igroup[1] = igroup[2] = 0;
+ for (n=0; n<3; n++) {
+ if (p >= peob) break;
+ igroup[n] = (unsigned char) *p;
+ p++;
+ }
+ if (n > 0) {
+ r[0] = b64table[ igroup[0]>>2 ];
+ r[1] = b64table[ ((igroup[0]&3)<<4) | (igroup[1]>>4) ];
+ r[2] = b64table[ ((igroup[1]&0xf)<<2) | (igroup[2]>>6) ];
+ r[3] = b64table[ igroup[2]&0x3f ];
+ if (n < 3) {
+ r[3] = '=';
+ if (n < 2)
+ r[2] = '=';
+ }
+ r += 4;
+ }
+ }
+ *r = '\0';
+
+ return res;
+}
+
+static unsigned char b64rtable[256];
+
+char *JabberBase64Decode(const char *str, int *resultLen)
+{
+ char *res;
+ unsigned char *p, *r, igroup[4], a[4];
+ int n, num, count;
+
+ if (str == NULL || resultLen == NULL) return NULL;
+ if ((res=(char *) mir_alloc(((strlen(str)+3)/4)*3)) == NULL) return NULL;
+
+ for (n=0; n<256; n++)
+ b64rtable[n] = (unsigned char) 0x80;
+ for (n=0; n<26; n++)
+ b64rtable['A'+n] = n;
+ for (n=0; n<26; n++)
+ b64rtable['a'+n] = n + 26;
+ for (n=0; n<10; n++)
+ b64rtable['0'+n] = n + 52;
+ b64rtable['+'] = 62;
+ b64rtable['/'] = 63;
+ b64rtable['='] = 0;
+ count = 0;
+ for (p=(unsigned char *)str,r=(unsigned char *)res; *p != '\0';) {
+ for (n=0; n<4; n++) {
+ if ( *p == '\r' || *p == '\n' ) {
+ n--; p++;
+ continue;
+ }
+
+ if ( *p=='\0' ) {
+ if ( n == 0 )
+ goto LBL_Exit;
+ mir_free( res );
+ return NULL;
+ }
+
+ if ( b64rtable[*p] == 0x80 ) {
+ mir_free( res );
+ return NULL;
+ }
+
+ a[n] = *p;
+ igroup[n] = b64rtable[*p];
+ p++;
+ }
+ r[0] = igroup[0]<<2 | igroup[1]>>4;
+ r[1] = igroup[1]<<4 | igroup[2]>>2;
+ r[2] = igroup[2]<<6 | igroup[3];
+ r += 3;
+ num = ( a[2] == '='?1:( a[3] == '='?2:3 ));
+ count += num;
+ if ( num < 3 ) break;
+ }
+LBL_Exit:
+ *resultLen = count;
+ return res;
+}
+
+/*
+ * Apply Polish Daylight Saving Time rules to get "DST-unbiased" timestamp
+ */
+
+time_t TlenTimeToUTC(time_t time) {
+ struct tm *timestamp;
+ timestamp = gmtime(&time);
+ if ( (timestamp->tm_mon > 2 && timestamp->tm_mon < 9) ||
+ (timestamp->tm_mon == 2 && timestamp->tm_mday - timestamp->tm_wday >= 25) ||
+ (timestamp->tm_mon == 9 && timestamp->tm_mday - timestamp->tm_wday < 25)) {
+ //time -= 3600;
+ } else {
+ //time += 3600;
+ }
+ return time;
+}
+
+time_t JabberIsoToUnixTime(char *stamp)
+{
+ struct tm timestamp;
+ char date[9];
+ char *p;
+ int i, y;
+ time_t t;
+
+ if (stamp == NULL) return (time_t) 0;
+
+ p = stamp;
+
+ // Get the date part
+ for (i=0; *p != '\0' && i<8 && isdigit(*p); p++,i++)
+ date[i] = *p;
+
+ // Parse year
+ if (i == 6) {
+ // 2-digit year (1970-2069)
+ y = (date[0]-'0')*10 + (date[1]-'0');
+ if (y < 70) y += 100;
+ }
+ else if (i == 8) {
+ // 4-digit year
+ y = (date[0]-'0')*1000 + (date[1]-'0')*100 + (date[2]-'0')*10 + date[3]-'0';
+ y -= 1900;
+ }
+ else
+ return (time_t) 0;
+ timestamp.tm_year = y;
+ // Parse month
+ timestamp.tm_mon = (date[i-4]-'0')*10 + date[i-3]-'0' - 1;
+ // Parse date
+ timestamp.tm_mday = (date[i-2]-'0')*10 + date[i-1]-'0';
+
+ // Skip any date/time delimiter
+ for (; *p != '\0' && !isdigit(*p); p++);
+
+ // Parse time
+ if (sscanf(p, "%d:%d:%d", &(timestamp.tm_hour), &(timestamp.tm_min), &(timestamp.tm_sec)) != 3)
+ return (time_t) 0;
+
+ timestamp.tm_isdst = 0; // DST is already present in _timezone below
+ _tzset();
+ t = mktime(&timestamp);
+ t -= _timezone;
+ t = TlenTimeToUTC(t);
+
+ if (t >= 0)
+ return t;
+ else
+ return (time_t) 0;
+}
+
+void JabberStringAppend(char **str, int *sizeAlloced, const char *fmt, ...)
+{
+ va_list vararg;
+ char *p;
+ int size, len;
+
+ if (str == NULL) return;
+
+ if (*str == NULL || *sizeAlloced <= 0) {
+ *sizeAlloced = size = 2048;
+ *str = (char *) mir_alloc(size);
+ len = 0;
+ }
+ else {
+ len = (int)strlen(*str);
+ size = *sizeAlloced - (int)strlen(*str);
+ }
+
+ p = *str + len;
+ va_start(vararg, fmt);
+ while (_vsnprintf(p, size, fmt, vararg) == -1) {
+ size += 2048;
+ (*sizeAlloced) += 2048;
+ *str = (char *) mir_realloc(*str, *sizeAlloced);
+ p = *str + len;
+ }
+ va_end(vararg);
+}
+
+int JabberGetPictureType( const char* buf )
+{
+ if ( buf != NULL ) {
+ if ( memcmp( buf, "GIF89", 5 ) == 0 ) return PA_FORMAT_GIF;
+ if ( memcmp( buf, "\x89PNG", 4 ) == 0 ) return PA_FORMAT_PNG;
+ if ( memcmp( buf, "BM", 2 ) == 0 ) return PA_FORMAT_BMP;
+ if ( memcmp( buf, "\xFF\xD8", 2 ) == 0 ) return PA_FORMAT_JPEG;
+ }
+ return PA_FORMAT_UNKNOWN;
+}
+
+BOOL IsAuthorized(TlenProtocol *proto, const char *jid)
+{
+ JABBER_LIST_ITEM *item = JabberListGetItemPtr(proto, LIST_ROSTER, jid);
+ if (item != NULL) {
+ return item->subscription == SUB_BOTH || item->subscription == SUB_FROM;
+ }
+ return FALSE;
+}
+
+
+void TlenLogMessage(TlenProtocol *proto, HANDLE hContact, DWORD flags, const char *message)
+{
+ int size = (int)strlen(message) + 2;
+ char *localMessage = (char *)mir_alloc(size);
+ strcpy(localMessage, message);
+ localMessage[size - 1] = '\0';
+ JabberDBAddEvent(proto, hContact, EVENTTYPE_MESSAGE, flags, (PBYTE)message, (DWORD)size);
+ mir_free(localMessage);
+}
diff --git a/protocols/Tlen/src/jabber_ws.cpp b/protocols/Tlen/src/jabber_ws.cpp
new file mode 100644
index 0000000000..c2cb853b02
--- /dev/null
+++ b/protocols/Tlen/src/jabber_ws.cpp
@@ -0,0 +1,160 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+
+BOOL JabberWsInit(TlenProtocol *proto)
+{
+ NETLIBUSER nlu = {0};
+ NETLIBUSERSETTINGS nlus = {0};
+ TCHAR name[128];
+
+
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_TCHAR; // | NUF_HTTPGATEWAY;
+ mir_sntprintf( name, SIZEOF(name), TranslateT("%s connection"), proto->m_tszUserName);
+ nlu.ptszDescriptiveName = name;
+ nlu.szSettingsModule = proto->m_szModuleName;
+ proto->hNetlibUser = (HANDLE) CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM) &nlu);
+
+ nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_NOOPTIONS | NUF_TCHAR;
+ mir_sntprintf( name, SIZEOF(name), TranslateT("%s SOCKS connection"), proto->m_tszUserName);
+ nlu.ptszDescriptiveName = name;
+ proto->hFileNetlibUser = (HANDLE) CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM) &nlu);
+ nlus.cbSize = sizeof(nlus);
+ nlus.useProxy = 0;
+ CallService(MS_NETLIB_SETUSERSETTINGS, (WPARAM) proto->hFileNetlibUser, (LPARAM) &nlus);
+
+ return (proto->hNetlibUser != NULL)?TRUE:FALSE;
+}
+
+void JabberWsUninit(TlenProtocol *proto)
+{
+ if (proto->hNetlibUser != NULL) Netlib_CloseHandle(proto->hNetlibUser);
+ if (proto->hFileNetlibUser != NULL) Netlib_CloseHandle(proto->hFileNetlibUser);
+ proto->hNetlibUser = NULL;
+ proto->hFileNetlibUser = NULL;
+}
+
+JABBER_SOCKET JabberWsConnect(TlenProtocol *proto, char *host, WORD port)
+{
+ NETLIBOPENCONNECTION nloc = {0};
+
+ nloc.cbSize = sizeof(NETLIBOPENCONNECTION); //NETLIBOPENCONNECTION_V1_SIZE;
+ nloc.szHost = host;
+ nloc.wPort = port;
+ nloc.flags = 0;
+ nloc.timeout = 6;
+ return (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) proto->hNetlibUser, (LPARAM) &nloc);
+}
+
+
+int JabberWsSend(TlenProtocol *proto, JABBER_SOCKET s, char *data, int datalen)
+{
+ int len;
+ if ((len=Netlib_Send(s, data, datalen, /*MSG_NODUMP|*/MSG_DUMPASTEXT)) == SOCKET_ERROR || len != datalen) {
+ JabberLog(proto, "Netlib_Send() failed, error=%d", WSAGetLastError());
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int JabberWsRecv(TlenProtocol *proto, JABBER_SOCKET s, char *data, long datalen)
+{
+ int ret;
+ ret = Netlib_Recv(s, data, datalen, /*MSG_NODUMP|*/MSG_DUMPASTEXT);
+ if (ret == SOCKET_ERROR) {
+ JabberLog(proto, "Netlib_Recv() failed, error=%d", WSAGetLastError());
+ return 0;
+ }
+ if (ret == 0) {
+ JabberLog(proto, "Connection closed gracefully");
+ return 0;
+ }
+ return ret;
+}
+
+
+int JabberWsSendAES(TlenProtocol *proto, char *data, int datalen, aes_context *aes_ctx, unsigned char *aes_iv)
+{
+ int len, sendlen;
+ unsigned char aes_input[16];
+ unsigned char aes_output[256];
+ if (proto->threadData == NULL) {
+ return FALSE;
+ }
+ while (datalen > 0) {
+ len = 0;
+ while (datalen > 0 && len < 256) {
+ int pad = datalen < 16 ? 16 - datalen : 0;
+ memcpy(aes_input, data, datalen < 16 ? datalen : 16);
+ memset(aes_input + 16 - pad, ' ', pad);
+ aes_crypt_cbc(aes_ctx, AES_ENCRYPT, 16, aes_iv, aes_input, aes_output + len);
+ datalen -= 16;
+ data += 16;
+ len += 16;
+ }
+ if (len > 0) {
+ JabberLog(proto, "Sending %d bytes", len);
+ if ((sendlen=Netlib_Send(proto->threadData->s, (char *)aes_output, len, MSG_NODUMP)) == SOCKET_ERROR || len != sendlen) {
+ JabberLog(proto, "Netlib_Send() failed, error=%d", WSAGetLastError());
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+int JabberWsRecvAES(TlenProtocol *proto, char *data, long datalen, aes_context *aes_ctx, unsigned char *aes_iv)
+{
+ int ret, len = 0, maxlen = datalen;
+ unsigned char aes_input[16];
+ unsigned char *aes_output = (unsigned char *)data;
+ if (proto->threadData == NULL) {
+ return 0;
+ }
+ for (maxlen = maxlen & ~0xF; maxlen != 0; maxlen = maxlen & 0xF) {
+ ret = Netlib_Recv(proto->threadData->s, data, maxlen, MSG_NODUMP);
+ if (ret == SOCKET_ERROR) {
+ JabberLog(proto, "Netlib_Recv() failed, error=%d", WSAGetLastError());
+ return 0;
+ }
+ if (ret == 0) {
+ JabberLog(proto, "Connection closed gracefully");
+ return 0;
+ }
+ data += ret;
+ len += ret;
+ maxlen -= ret;
+ }
+
+ ret = len;
+ while (len > 15) {
+ memcpy(aes_input, aes_output, 16);
+ aes_crypt_cbc(aes_ctx, AES_DECRYPT, 16, aes_iv, aes_input, aes_output);
+ aes_output += 16;
+ len -= 16;
+ }
+ return ret;
+}
+
diff --git a/protocols/Tlen/src/jabber_xml.cpp b/protocols/Tlen/src/jabber_xml.cpp
new file mode 100644
index 0000000000..5786404dc6
--- /dev/null
+++ b/protocols/Tlen/src/jabber_xml.cpp
@@ -0,0 +1,568 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include <ctype.h>
+
+static BOOL JabberXmlProcessElem(XmlState *xmlState, XmlElemType elemType, char *elemText, char *elemAttr);
+static void JabberXmlRemoveChild(XmlNode *node, XmlNode *child);
+
+void JabberXmlInitState(XmlState *xmlState)
+{
+ if (xmlState == NULL) return;
+ xmlState->root.name = NULL;
+ xmlState->root.depth = 0;
+ xmlState->root.numAttr = 0;
+ xmlState->root.maxNumAttr = 0;
+ xmlState->root.attr = NULL;
+ xmlState->root.numChild = 0;
+ xmlState->root.maxNumChild = 0;
+ xmlState->root.child = NULL;
+ xmlState->root.text = NULL;
+ xmlState->root.state = NODE_OPEN;
+ xmlState->callback1_open = NULL;
+ xmlState->callback1_close = NULL;
+ xmlState->callback2_open = NULL;
+ xmlState->callback2_close = NULL;
+ xmlState->userdata1_open = NULL;
+ xmlState->userdata1_close = NULL;
+ xmlState->userdata2_open = NULL;
+ xmlState->userdata2_close = NULL;
+}
+
+void JabberXmlDestroyState(XmlState *xmlState)
+{
+ int i;
+ XmlNode *node;
+
+ if (xmlState == NULL) return;
+ // Note: cannot use JabberXmlFreeNode() to free xmlState->root
+ // because it will do mir_free(xmlState->root) which is not freeable.
+ node = &(xmlState->root);
+ // Free all children first
+ for (i=0; i<node->numChild; i++)
+ JabberXmlFreeNode(node->child[i]);
+ if (node->child) mir_free(node->child);
+ // Free all attributes
+ for (i=0; i<node->numAttr; i++) {
+ if (node->attr[i]->name) mir_free(node->attr[i]->name);
+ if (node->attr[i]->value) mir_free(node->attr[i]->value);
+ mir_free(node->attr[i]);
+ }
+ if (node->attr) mir_free(node->attr);
+ // Free string field
+ if (node->text) mir_free(node->text);
+ if (node->name) mir_free(node->name);
+}
+
+BOOL JabberXmlSetCallback(XmlState *xmlState, int depth, XmlElemType type, void (*callback)(XmlNode*, void*), void *userdata)
+{
+ if (depth == 1 && type == ELEM_OPEN) {
+ xmlState->callback1_open = callback;
+ xmlState->userdata1_open = userdata;
+ }
+ else if (depth == 1 && type == ELEM_CLOSE) {
+ xmlState->callback1_close = callback;
+ xmlState->userdata1_close = userdata;
+ }
+ else if (depth == 2 && type == ELEM_OPEN) {
+ xmlState->callback2_open = callback;
+ xmlState->userdata2_open = userdata;
+ }
+ else if (depth == 2 && type == ELEM_CLOSE) {
+ xmlState->callback2_close = callback;
+ xmlState->userdata2_close = userdata;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+#define TAG_MAX_LEN 50
+#define ATTR_MAX_LEN 1024
+int JabberXmlParse(XmlState *xmlState, char *buffer, int datalen)
+{
+ char *p, *q, *r, *eob;
+ char *str;
+ int num;
+ char tag[TAG_MAX_LEN];
+ char attr[ATTR_MAX_LEN];
+ XmlElemType elemType = ELEM_OPEN;
+
+ eob = buffer + datalen;
+ num = 0;
+ // Skip leading whitespaces
+ for (p=buffer; p<eob && isspace(*p); p++,num++);
+ while (num < datalen) {
+ if (*p == '<') { // found starting bracket
+ for (q=p+1; q<eob && *q != '>'; q++);
+ if (q < eob) { // found closing bracket
+ for (r=p+1; *r != '>' && *r != ' ' && *r != '\t'; r++);
+ if (r-(p+1) > TAG_MAX_LEN) {
+// JabberLog("TAG_MAX_LEN too small, ignore current tag");
+ }
+ else {
+ if (*(p+1) == '/') { // closing tag
+ strncpy(tag, p+2, r-(p+2));
+ tag[r-(p+2)] = '\0';
+ elemType = ELEM_CLOSE;
+ }
+ else {
+ if (*(r-1) == '/') { // single open/close tag
+ strncpy(tag, p+1, r-(p+1)-1);
+ tag[r-(p+1)-1] = '\0';
+ elemType = ELEM_OPENCLOSE;
+ }
+ else {
+ strncpy(tag, p+1, r-(p+1));
+ tag[r-(p+1)] = '\0';
+ elemType = ELEM_OPEN;
+ }
+ }
+ for (;r<q && (*r == ' ' || *r == '\t'); r++);
+ if (q-r > ATTR_MAX_LEN) {
+// JabberLog("ATTR_MAX_LEN too small, ignore current tag");
+ }
+ else {
+ strncpy(attr, r, q-r);
+ if ((q-r)>0 && attr[q-r-1] == '/') {
+ attr[q-r-1] = '\0';
+ elemType = ELEM_OPENCLOSE;
+ }
+ else
+ attr[q-r] = '\0';
+ JabberXmlProcessElem(xmlState, elemType, tag, attr);
+ }
+ }
+ num += (q-p+1);
+ p = q + 1;
+ if (elemType == ELEM_CLOSE || elemType == ELEM_OPENCLOSE) {
+ // Skip whitespaces after end tags
+ for (; p<eob && isspace(*p); p++,num++);
+ }
+ }
+ else
+ break;
+ }
+ else { // found inner text
+ for (q=p+1; q<eob && *q != '<'; q++);
+ if (q < eob) { // found starting bracket of the next element
+ str = (char *) mir_alloc(q-p+1);
+ strncpy(str, p, q-p);
+ str[q-p] = '\0';
+ JabberXmlProcessElem(xmlState, ELEM_TEXT, str, NULL);
+ mir_free(str);
+ num += (q-p);
+ p = q;
+ }
+ else
+ break;
+ }
+ }
+
+ return num;
+}
+
+static void JabberXmlParseAttr(XmlNode *node, char *text)
+{
+ char *kstart, *vstart;
+ int klen, vlen;
+ char *p;
+ XmlAttr *a;
+
+ if (node == NULL || text == NULL || strlen(text) <= 0)
+ return;
+
+ for (p=text;;) {
+
+ // Skip leading whitespaces
+ for (;*p != '\0' && (*p == ' ' || *p == '\t'); p++);
+ if (*p == '\0')
+ break;
+
+ // Fetch key
+ kstart = p;
+ for (;*p != '\0' && *p != '=' && *p != ' ' && *p != '\t'; p++);
+ klen = p-kstart;
+
+ if (node->numAttr >= node->maxNumAttr) {
+ node->maxNumAttr = node->numAttr + 20;
+ node->attr = (XmlAttr **) mir_realloc(node->attr, node->maxNumAttr*sizeof(XmlAttr *));
+ }
+ a = node->attr[node->numAttr] = (XmlAttr *) mir_alloc(sizeof(XmlAttr));
+ node->numAttr++;
+
+ // Skip possible whitespaces between key and '='
+ for (;*p != '\0' && (*p == ' ' || *p == '\t'); p++);
+
+ if (*p == '\0') {
+ a->name = (char *) mir_alloc(klen+1);
+ strncpy(a->name, kstart, klen);
+ a->name[klen] = '\0';
+ a->value = mir_strdup("");
+ break;
+ }
+
+ if (*p != '=') {
+ a->name = (char *) mir_alloc(klen+1);
+ strncpy(a->name, kstart, klen);
+ a->name[klen] = '\0';
+ a->value = mir_strdup("");
+ continue;
+ }
+
+ // Found '='
+ p++;
+
+ // Skip possible whitespaces between '=' and value
+ for (;*p != '\0' && (*p == ' ' || *p == '\t'); p++);
+
+ if (*p == '\0') {
+ a->name = (char *) mir_alloc(klen+1);
+ strncpy(a->name, kstart, klen);
+ a->name[klen] = '\0';
+ a->value = mir_strdup("");
+ break;
+ }
+
+ // Fetch value
+ if (*p == '\'' || *p == '"') {
+ p++;
+ vstart = p;
+ for (;*p != '\0' && *p != *(vstart-1); p++);
+ vlen = p-vstart;
+ if (*p != '\0') p++;
+ }
+ else {
+ vstart = p;
+ for (;*p != '\0' && *p != ' ' && *p != '\t'; p++);
+ vlen = p-vstart;
+ }
+
+ a->name = (char *) mir_alloc(klen+1);
+ strncpy(a->name, kstart, klen);
+ a->name[klen] = '\0';
+ a->value = (char *) mir_alloc(vlen+1);
+ strncpy(a->value, vstart, vlen);
+ a->value[vlen] = '\0';
+ }
+}
+
+static BOOL JabberXmlProcessElem(XmlState *xmlState, XmlElemType elemType, char *elemText, char *elemAttr)
+{
+ XmlNode *node, *parentNode, *n;
+ //BOOL activateCallback = FALSE;
+ char *text, *attr;
+
+ if (elemText == NULL) return FALSE;
+
+ if (elemType == ELEM_OPEN && !strcmp(elemText, "?xml")) {
+// JabberLog("XML: skip <?xml> tag");
+ return TRUE;
+ }
+
+ // Find active node
+ node = &(xmlState->root);
+ parentNode = NULL;
+ while (node->numChild>0 && node->child[node->numChild-1]->state == NODE_OPEN) {
+ parentNode = node;
+ node = node->child[node->numChild-1];
+ }
+
+ if (node->state != NODE_OPEN) return FALSE;
+
+ text = mir_strdup(elemText);
+
+ if (elemAttr)
+ attr = mir_strdup(elemAttr);
+ else
+ attr = NULL;
+
+ switch (elemType) {
+ case ELEM_OPEN:
+ if (node->numChild >= node->maxNumChild) {
+ node->maxNumChild = node->numChild + 20;
+ node->child = (XmlNode **) mir_realloc(node->child, node->maxNumChild*sizeof(XmlNode *));
+ }
+ n = node->child[node->numChild] = (XmlNode *) mir_alloc(sizeof(XmlNode));
+ node->numChild++;
+ n->name = text;
+ n->depth = node->depth + 1;
+ n->state = NODE_OPEN;
+ n->numChild = n->maxNumChild = 0;
+ n->child = NULL;
+ n->numAttr = n->maxNumAttr = 0;
+ n->attr = NULL;
+ JabberXmlParseAttr(n, attr);
+ n->text = NULL;
+ if (n->depth == 1 && xmlState->callback1_open != NULL)
+ (*(xmlState->callback1_open))(n, xmlState->userdata1_open);
+ if (n->depth == 2 && xmlState->callback2_open != NULL)
+ (*xmlState->callback2_open)(n, xmlState->userdata2_open);
+ break;
+ case ELEM_OPENCLOSE:
+ if (node->numChild >= node->maxNumChild) {
+ node->maxNumChild = node->numChild + 20;
+ node->child = (XmlNode **) mir_realloc(node->child, node->maxNumChild*sizeof(XmlNode *));
+ }
+ n = node->child[node->numChild] = (XmlNode *) mir_alloc(sizeof(XmlNode));
+ node->numChild++;
+ n->name = text;
+ n->depth = node->depth + 1;
+ n->state = NODE_CLOSE;
+ n->numChild = n->maxNumAttr = 0;
+ n->child = NULL;
+ n->numAttr = n->maxNumAttr = 0;
+ n->attr = NULL;
+ JabberXmlParseAttr(n, attr);
+ n->text = NULL;
+ if (n->depth == 1 && xmlState->callback1_close != NULL) {
+ (*(xmlState->callback1_close))(n, xmlState->userdata1_close);
+ JabberXmlRemoveChild(node, n);
+ }
+ if (n->depth == 2 && xmlState->callback2_close != NULL) {
+ (*xmlState->callback2_close)(n, xmlState->userdata2_close);
+ JabberXmlRemoveChild(node, n);
+ }
+ break;
+ case ELEM_CLOSE:
+ if (node->name != NULL && !strcmp(node->name, text)) {
+ node->state = NODE_CLOSE;
+ if (node->depth == 1 && xmlState->callback1_close != NULL) {
+ (*(xmlState->callback1_close))(node, xmlState->userdata1_close);
+ JabberXmlRemoveChild(parentNode, node);
+ }
+ if (node->depth == 2 && xmlState->callback2_close != NULL) {
+ (*xmlState->callback2_close)(node, xmlState->userdata2_close);
+ JabberXmlRemoveChild(parentNode, node);
+ }
+ mir_free(text);
+ }
+ else {
+// JabberLog("XML: Closing </%s> without opening tag", text);
+ mir_free(text);
+ if (attr) mir_free(attr);
+ return FALSE;
+ }
+ break;
+ case ELEM_TEXT:
+ node->text = text;
+ break;
+ default:
+ mir_free(text);
+ if (attr) mir_free(attr);
+ return FALSE;
+ }
+
+ if (attr) mir_free(attr);
+
+ return TRUE;
+}
+
+char *JabberXmlGetAttrValue(XmlNode *node, char *key)
+{
+ int i;
+
+ if (node == NULL || node->numAttr <= 0 || key == NULL || strlen(key) <= 0)
+ return NULL;
+ for (i=0; i<node->numAttr; i++) {
+ if (node->attr[i]->name && !strcmp(key, node->attr[i]->name))
+ return node->attr[i]->value;
+ }
+ return NULL;
+}
+
+XmlNode *JabberXmlGetChild(XmlNode *node, char *tag)
+{
+ return JabberXmlGetNthChild(node, tag, 1);
+}
+
+XmlNode *JabberXmlGetNthChild(XmlNode *node, char *tag, int nth)
+{
+ int i, num;
+
+ if (node == NULL || node->numChild <= 0 || tag == NULL || strlen(tag) <= 0 || nth < 1)
+ return NULL;
+ num = 1;
+ for (i=0; i<node->numChild; i++) {
+ if (node->child[i]->name && !strcmp(tag, node->child[i]->name)) {
+ if (num == nth) {
+ return node->child[i];
+ }
+ num++;
+ }
+ }
+ return NULL;
+}
+
+XmlNode *JabberXmlGetChildWithGivenAttrValue(XmlNode *node, char *tag, char *attrKey, char *attrValue)
+{
+ int i;
+ char *str;
+
+ if (node == NULL || node->numChild <= 0 || tag == NULL || strlen(tag) <= 0 || attrKey == NULL || strlen(attrKey) <= 0 || attrValue == NULL || strlen(attrValue) <= 0)
+ return NULL;
+ for (i=0; i<node->numChild; i++) {
+ if (node->child[i]->name && !strcmp(tag, node->child[i]->name)) {
+ if ((str=JabberXmlGetAttrValue(node->child[i], attrKey)) != NULL)
+ if (!strcmp(str, attrValue))
+ return node->child[i];
+ }
+ }
+ return NULL;
+}
+
+static void JabberXmlRemoveChild(XmlNode *node, XmlNode *child)
+{
+ int i;
+
+ if (node == NULL || child == NULL || node->numChild <= 0) return;
+ for (i=0; i<node->numChild; i++) {
+ if (node->child[i] == child)
+ break;
+ }
+ if (i < node->numChild) {
+ for (++i; i<node->numChild; i++)
+ node->child[i-1] = node->child[i];
+ node->numChild--;
+ JabberXmlFreeNode(child);
+ }
+}
+
+void JabberXmlFreeNode(XmlNode *node)
+{
+ int i;
+
+ if (node == NULL) return;
+ // Free all children first
+ for (i=0; i<node->numChild; i++)
+ JabberXmlFreeNode(node->child[i]);
+ if (node->child) mir_free(node->child);
+ // Free all attributes
+ for (i=0; i<node->numAttr; i++) {
+ if (node->attr[i]->name) mir_free(node->attr[i]->name);
+ if (node->attr[i]->value) mir_free(node->attr[i]->value);
+ mir_free(node->attr[i]);
+ }
+ if (node->attr) mir_free(node->attr);
+ // Free string field
+ if (node->text) mir_free(node->text);
+ if (node->name) mir_free(node->name);
+ // Free the node itself
+ mir_free(node);
+}
+
+XmlNode *JabberXmlCopyNode(XmlNode *node)
+{
+ XmlNode *n;
+ int i;
+
+ if (node == NULL) return NULL;
+ n = (XmlNode *) mir_alloc(sizeof(XmlNode));
+ // Copy attributes
+ if (node->numAttr > 0) {
+ n->attr = (XmlAttr **) mir_alloc(node->numAttr*sizeof(XmlAttr *));
+ for (i=0; i<node->numAttr; i++) {
+ n->attr[i] = (XmlAttr *) mir_alloc(sizeof(XmlAttr));
+ if (node->attr[i]->name) n->attr[i]->name = mir_strdup(node->attr[i]->name);
+ else n->attr[i]->name = NULL;
+ if (node->attr[i]->value) n->attr[i]->value = mir_strdup(node->attr[i]->value);
+ else n->attr[i]->value = NULL;
+ }
+ }
+ else
+ n->attr = NULL;
+ // Recursively copy children
+ if (node->numChild > 0) {
+ n->child = (XmlNode **) mir_alloc(node->numChild*sizeof(XmlNode *));
+ for (i=0; i<node->numChild; i++)
+ n->child[i] = JabberXmlCopyNode(node->child[i]);
+ }
+ else
+ n->child = NULL;
+ // Copy other fields
+ n->numAttr = node->numAttr;
+ n->maxNumAttr = node->numAttr;
+ n->numChild = node->numChild;
+ n->maxNumChild = node->numChild;
+ n->depth = node->depth;
+ n->state = node->state;
+ n->name = (node->name)?mir_strdup(node->name):NULL;
+ n->text = (node->text)?mir_strdup(node->text):NULL;
+
+ return n;
+}
+
+XmlNode *JabberXmlCreateNode(char *name)
+{
+ XmlNode *n;
+
+ if (name == NULL)
+ return NULL;
+
+ n = (XmlNode *) mir_alloc(sizeof(XmlNode));
+ memset(n, 0, sizeof(XmlNode));
+ n->name = mir_strdup(name);
+ return n;
+}
+
+void JabberXmlAddAttr(XmlNode *n, char *name, char *value)
+{
+ int i;
+
+ if (n == NULL || name == NULL || value == NULL)
+ return;
+
+ i = n->numAttr;
+ (n->numAttr)++;
+ n->attr = (XmlAttr **) mir_realloc(n->attr, sizeof(XmlAttr *) * n->numAttr);
+ n->attr[i] = (XmlAttr *) mir_alloc(sizeof(XmlAttr));
+ n->attr[i]->name = mir_strdup(name);
+ n->attr[i]->value = mir_strdup(value);
+}
+
+XmlNode *JabberXmlAddChild(XmlNode *n, char *name)
+{
+ int i;
+
+ if (n == NULL || name == NULL)
+ return NULL;
+
+ i = n->numChild;
+ n->numChild++;
+ n->child = (XmlNode **) mir_realloc(n->child, sizeof(XmlNode *) * n->numChild);
+ n->child[i] = (XmlNode *) mir_alloc(sizeof(XmlNode));
+ memset(n->child[i], 0, sizeof(XmlNode));
+ n->child[i]->name = mir_strdup(name);
+ return n->child[i];
+}
+
+void JabberXmlAddText(XmlNode *n, char *text)
+{
+ if (n != NULL && text != NULL) {
+ if (n->text) mir_free(n->text);
+ n->text = mir_strdup(text);
+ }
+}
+
diff --git a/protocols/Tlen/src/jabber_xml.h b/protocols/Tlen/src/jabber_xml.h
new file mode 100644
index 0000000000..165a8fadc5
--- /dev/null
+++ b/protocols/Tlen/src/jabber_xml.h
@@ -0,0 +1,79 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _JABBER_XML_H_
+#define _JABBER_XML_H_
+
+typedef enum { ELEM_OPEN, ELEM_CLOSE, ELEM_OPENCLOSE, ELEM_TEXT } XmlElemType;
+typedef enum { NODE_OPEN, NODE_CLOSE } XmlNodeType;
+
+typedef struct tagXmlAttr {
+ char *name;
+ char *value;
+} XmlAttr;
+
+typedef struct tagXmlNode {
+ int depth; // depth of the current node (1=root)
+ char *name; // tag name of the current node
+ int numAttr; // number of attributes
+ int maxNumAttr; // internal use (num of slots currently allocated to attr)
+ XmlAttr **attr; // attribute list
+ int numChild; // number of direct child nodes
+ int maxNumChild; // internal use (num of slots currently allocated to child)
+ struct tagXmlNode **child; // child node list
+ char *text;
+ XmlNodeType state; // internal use by parser
+} XmlNode;
+
+
+typedef struct tagXmlState {
+ XmlNode root; // root is the document (depth = 0);
+ // callback for depth=n element on opening/closing
+ void (*callback1_open)(XmlNode *,void *);
+ void (*callback1_close)(XmlNode *,void *);
+ void (*callback2_open)(XmlNode *,void *);
+ void (*callback2_close)(XmlNode *,void *);
+ void *userdata1_open;
+ void *userdata1_close;
+ void *userdata2_open;
+ void *userdata2_close;
+} XmlState;
+
+void JabberXmlInitState(XmlState *xmlState);
+void JabberXmlDestroyState(XmlState *xmlState);
+BOOL JabberXmlSetCallback(XmlState *xmlState, int depth, XmlElemType type, void (*callback)(XmlNode*, void*), void *userdata);
+int JabberXmlParse(XmlState *xmlState, char *buffer, int datalen);
+char *JabberXmlGetAttrValue(XmlNode *node, char *key);
+XmlNode *JabberXmlGetChild(XmlNode *node, char *tag);
+XmlNode *JabberXmlGetNthChild(XmlNode *node, char *tag, int nth);
+XmlNode *JabberXmlGetChildWithGivenAttrValue(XmlNode *node, char *tag, char *attrKey, char *attrValue);
+void JabberXmlFreeNode(XmlNode *node);
+XmlNode *JabberXmlCopyNode(XmlNode *node);
+
+XmlNode *JabberXmlCreateNode(char *name);
+void JabberXmlAddAttr(XmlNode *n, char *name, char *value);
+XmlNode *JabberXmlAddChild(XmlNode *n, char *name);
+void JabberXmlAddText(XmlNode *n, char *text);
+
+#endif
+
diff --git a/protocols/Tlen/src/resource.h b/protocols/Tlen/src/resource.h
new file mode 100644
index 0000000000..6f3b59b64d
--- /dev/null
+++ b/protocols/Tlen/src/resource.h
@@ -0,0 +1,147 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Tlen.rc
+//
+
+#define IDI_TLEN 100
+#define IDI_MAIL 101
+#define IDI_MUC 102
+#define IDI_CHATS 103
+#define IDI_GRANT 104
+#define IDI_REQUEST 105
+#define IDI_VOICE 106
+#define IDI_MICROPHONE 107
+#define IDI_SPEAKER 108
+#define IDI_IMAGE 109
+
+#define IDD_OPTIONS_BASIC 151
+#define IDD_OPTIONS_VOICE 152
+#define IDD_OPTIONS_POPUPS 153
+#define IDD_OPTIONS_ADVANCED 154
+#define IDD_USER_INFO 155
+#define IDD_USER_VCARD 156
+#define IDD_PASSWORD 157
+#define IDD_ADVSEARCH 158
+#define IDD_VOICE 159
+#define IDD_ACCEPT_VOICE 160
+#define IDD_USER_CHANGEAVATAR 161
+#define IDD_ACCMGRUI 162
+
+#define IDC_TABS 1000
+#define IDC_EDIT_USERNAME 1001
+#define IDC_SAVE 1002
+#define IDC_EDIT_PASSWORD 1003
+#define IDC_EDIT_LOGIN_SERVER 1004
+#define IDC_INFO_JID 1007
+#define IDC_INFO_RESOURCE 1008
+#define IDC_SHOW_OFFLINE 1012
+#define IDC_OFFLINE_MESSAGE 1013
+#define IDC_OFFLINE_MESSAGE_OPTION 1014
+#define IDC_VISIBILITY_SUPPORT 1015
+#define IDC_NUDGE_SUPPORT 1016
+#define IDC_LOG_ALERTS 1017
+
+#define IDC_SUBSCRIPTION 1039
+#define IDC_REGISTERACCOUNT 1040
+#define IDC_SIMPLE 1041
+#define IDC_KEEPALIVE 1042
+#define IDC_HOST 1043
+#define IDC_HOSTPORT 1044
+#define IDC_USE_SSL 1045
+#define IDC_SAVEPASSWORD 1048
+#define IDC_ROSTER_ALERTS 1049
+#define IDC_PASSWORD 1050
+#define IDC_RECONNECT 1050
+#define IDC_JID 1051
+#define IDC_ROSTER_SYNC 1052
+#define IDC_ALERT_POLICY 1053
+#define IDC_MUC_POLICY 1054
+#define IDC_VOICE_POLICY 1055
+#define IDC_IGNORE_ADVERTISEMENTS 1056
+#define IDC_AVATARS 1057
+#define IDC_VERSIONINFO 1058
+#define IDC_IMAGE_POLICY 1059
+#define IDC_CITY 1060
+#define IDC_FULLNAME 1061
+#define IDC_NICKNAME 1062
+#define IDC_FIRSTNAME 1063
+#define IDC_LASTNAME 1064
+#define IDC_BIRTH 1065
+#define IDC_AGE 1065
+#define IDC_OCCUPATION 1066
+#define IDC_EMAIL 1073
+#define IDC_GENDER 1096
+#define IDC_VOICECONVERSATIONS 1097
+#define IDC_PUBLICSTATUS 1098
+#define IDC_VCQUALITY 1100
+#define IDC_VUMETERIN 1101
+#define IDC_VUMETEROUT 1102
+#define IDC_BYTESIN 1103
+#define IDC_BYTESOUT 1104
+#define IDC_MICROPHONE 1105
+#define IDC_SPEAKER 1106
+#define IDC_ACCEPT 1107
+
+#define IDC_FILE_PROXY_TYPE_LABEL 1108
+#define IDC_FILE_PROXY_TYPE 1109
+#define IDC_FILE_PROXY_HOST_LABEL 1110
+#define IDC_FILE_PROXY_HOST 1111
+#define IDC_FILE_PROXY_PORT_LABEL 1112
+#define IDC_FILE_PROXY_PORT 1113
+#define IDC_FILE_PROXY_USE_AUTH 1114
+#define IDC_FILE_PROXY_USER 1115
+#define IDC_FILE_PROXY_USER_LABEL 1116
+#define IDC_FILE_PROXY_PASSWORD_LABEL 1117
+#define IDC_FILE_PROXY_PASSWORD 1118
+#define IDC_FILE_USE_PROXY 1119
+#define IDC_VOICE_DEVICE_IN 1120
+#define IDC_VOICE_DEVICE_OUT 1121
+
+#define IDC_MSG_ACK 1124
+#define IDC_SERVER 1125
+#define IDC_NICK 1129
+#define IDC_LIST 1133
+#define IDC_ENTER 1144
+#define IDC_AGEFROM 1152
+#define IDC_AGETO 1153
+#define IDC_LOOKFOR 1154
+#define IDC_SCHOOL 1155
+#define IDC_FROM 1175
+#define IDC_DELAY 1180
+#define IDC_COLORBKG 1181
+#define IDC_COLORTXT 1182
+#define IDC_PREVIEW 1183
+#define IDC_ENABLEPOPUP 1184
+#define IDC_DELAY_PERMANENT 1185
+#define IDC_DELAY_CUSTOM 1186
+#define IDC_DELAY_POPUP 1187
+#define IDC_TLEN 1190
+#define IDC_GENDER_TEXT 1195
+#define IDC_OCCUPATION_TEXT 1199
+#define IDC_LOOKFOR_TEXT 1200
+#define IDC_GROUP 1203
+#define IDC_SOFTWARE 1204
+#define IDC_VERSION 1205
+#define IDC_SYSTEM 1206
+#define IDC_AVATAR 1210
+#define IDC_SETAVATAR 1211
+#define IDC_DELETEAVATAR 1212
+#define IDC_AVATAR_LIST 1213
+#define IDC_OLD_AVATAR 1214
+#define IDC_BROWSEAVATAR 1215
+#define IDC_PUBLICAVATAR 1216
+
+#define IDC_STATUS 1414
+#define IDC_PLAN 1415
+#define IDC_PERSONALGROUP 1434
+#define IDC_EXTRAGROUP 1435
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 190
+#define _APS_NEXT_COMMAND_VALUE 40017
+#define _APS_NEXT_CONTROL_VALUE 1204
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/Tlen/src/tlen.cpp b/protocols/Tlen/src/tlen.cpp
new file mode 100644
index 0000000000..2feb99495e
--- /dev/null
+++ b/protocols/Tlen/src/tlen.cpp
@@ -0,0 +1,524 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "commons.h"
+#include "jabber.h"
+#include "tlen_muc.h"
+#include "tlen_file.h"
+#include "tlen_voice.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "resource.h"
+#include "tlen_picture.h"
+#include <m_file.h>
+#include <richedit.h>
+#include <ctype.h>
+#include <m_icolib.h>
+#include <m_genmenu.h>
+#include "m_mucc.h"
+
+
+int hLangpack;
+HINSTANCE hInst;
+HANDLE hMainThread;
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ "Tlen Protocol",
+ PLUGIN_MAKE_VERSION(TLEN_MAJOR_VERSION,TLEN_MINOR_VERSION,TLEN_RELEASE_NUM,TLEN_BUILD_NUM),
+ "Tlen protocol plugin for Miranda NG (version: " TLEN_VERSION_STRING ")",
+ "Santithorn Bunchua, Adam Strzelecki, Piotr Piastucki",
+ "the_leech@users.berlios.de",
+ "(c) 2002-2012 Santithorn Bunchua, Piotr Piastucki",
+ "http://miranda-ng.org/",
+ UNICODE_AWARE,
+ {0x748f8934, 0x781a, 0x528d, { 0x52, 0x08, 0x00, 0x12, 0x65, 0x40, 0x4a, 0xb3 }}
+};
+
+// Main jabber server connection thread global variables
+
+int TlenUserInfoInit(void *ptr, WPARAM wParam, LPARAM lParam);
+int TlenSystemModulesLoaded(void *ptr, WPARAM wParam, LPARAM lParam);
+
+BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved)
+{
+#ifdef _DEBUG
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif
+
+ hInst = hModule;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+extern "C" __declspec(dllexport) const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+struct
+{
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+ HANDLE hIconLibItem;
+}
+static iconList[] =
+{
+ { _T("Protocol icon"), "PROTO", IDI_TLEN },
+ { _T("Tlen inbox"), "MAIL", IDI_MAIL },
+ { _T("Group chats"), "MUC", IDI_MUC },
+ { _T("Tlen chats"), "CHATS", IDI_CHATS },
+ { _T("Grant authorization"), "GRANT", IDI_GRANT },
+ { _T("Request authorization"), "REQUEST", IDI_REQUEST },
+ { _T("Voice chat"), "VOICE", IDI_VOICE },
+ { _T("Microphone"), "MICROPHONE", IDI_MICROPHONE },
+ { _T("Speaker"), "SPEAKER", IDI_SPEAKER },
+ { _T("Send image"), "IMAGE", IDI_IMAGE }
+};
+
+static HANDLE GetIconHandle(int iconId) {
+ int i;
+ for (i = 0; i < SIZEOF(iconList); i++)
+ if (iconList[i].defIconID == iconId)
+ return iconList[i].hIconLibItem;
+ return NULL;
+}
+
+HICON GetIcolibIcon(int iconId) {
+ HANDLE handle = GetIconHandle(iconId);
+ if (handle != NULL) {
+ return (HICON) CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)handle);
+ }
+ return NULL;
+}
+
+void ReleaseIcolibIcon(HICON hIcon) {
+ CallService( MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0 );
+}
+
+/*
+static int TlenIconsChanged(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+*/
+
+static void TlenRegisterIcons()
+{
+ SKINICONDESC sid = { 0 };
+ char path[MAX_PATH];
+ TCHAR szSectionName[100];
+ int i;
+ mir_sntprintf(szSectionName, SIZEOF( szSectionName ), _T("%s/%s"), _T("Protocols"), _T("Tlen"));
+
+ GetModuleFileNameA(hInst, path, MAX_PATH);
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.cx = sid.cy = 16;
+ sid.ptszSection = szSectionName;
+ sid.pszDefaultFile = path;
+ sid.flags = SIDF_TCHAR;
+
+ for ( i = 0; i < SIZEOF(iconList); i++ ) {
+ char szSettingName[100];
+ mir_snprintf( szSettingName, sizeof( szSettingName ), "TLEN_%s", iconList[i].szName );
+ sid.pszName = szSettingName;
+ sid.pszDescription = (char*)iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIconLibItem = Skin_AddIcon(&sid);;
+ }
+}
+
+int TlenPrebuildContactMenu(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ DBVARIANT dbv;
+ CLISTMENUITEM clmi = {0};
+ JABBER_LIST_ITEM *item;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ clmi.cbSize = sizeof(CLISTMENUITEM);
+ if ((hContact=(HANDLE) wParam) != NULL && proto->isOnline) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, dbv.pszVal)) != NULL) {
+ if (item->subscription == SUB_NONE || item->subscription == SUB_FROM)
+ clmi.flags = CMIM_FLAGS;
+ else
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactRequestAuth, (LPARAM) &clmi);
+
+ if (item->subscription == SUB_NONE || item->subscription == SUB_TO)
+ clmi.flags = CMIM_FLAGS;
+ else
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactGrantAuth, (LPARAM) &clmi);
+
+ if (item->status != ID_STATUS_OFFLINE)
+ clmi.flags = CMIM_FLAGS;
+ else
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactMUC, (LPARAM) &clmi);
+
+ if (item->status != ID_STATUS_OFFLINE && !TlenVoiceIsInUse(proto))
+ clmi.flags = CMIM_FLAGS;
+ else
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactVoice, (LPARAM) &clmi);
+
+ if (item->status != ID_STATUS_OFFLINE)
+ clmi.flags = CMIM_FLAGS;
+ else
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuPicture, (LPARAM) &clmi);
+
+ DBFreeVariant(&dbv);
+ return 0;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ clmi.flags = CMIM_FLAGS|CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactMUC, (LPARAM) &clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactVoice, (LPARAM) &clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactRequestAuth, (LPARAM) &clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuContactGrantAuth, (LPARAM) &clmi);
+ return 0;
+}
+
+INT_PTR TlenContactMenuHandleRequestAuth(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ DBVARIANT dbv;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if ((hContact=(HANDLE) wParam) != NULL && proto->isOnline) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ JabberSend(proto, "<presence to='%s' type='subscribe'/>", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ return 0;
+}
+
+INT_PTR TlenContactMenuHandleGrantAuth(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ DBVARIANT dbv;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if ((hContact=(HANDLE) wParam) != NULL && proto->isOnline) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ JabberSend(proto, "<presence to='%s' type='subscribed'/>", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ return 0;
+}
+
+INT_PTR TlenContactMenuHandleSendPicture(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if ((hContact=(HANDLE) wParam) != NULL && proto->isOnline) {
+ SendPicture(proto, hContact);
+ }
+ return 0;
+}
+
+INT_PTR TlenMenuHandleInbox(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ char szFileName[ MAX_PATH ];
+ DBVARIANT dbv;
+ NETLIBHTTPREQUEST req;
+ NETLIBHTTPHEADER headers[2];
+ NETLIBHTTPREQUEST *resp;
+ char *login = NULL, *password = NULL;
+ char form[1024];
+ char cookie[1024];
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginName", &dbv)) {
+ login = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "SavePassword", TRUE) == TRUE) {
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "Password", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ password = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ } else if (proto->threadData != NULL && strlen(proto->threadData->password) > 0) {
+ password = mir_strdup(proto->threadData->password);
+ }
+
+ ZeroMemory(&cookie, sizeof(cookie));
+ if (login != NULL && password != NULL) {
+ mir_snprintf( form, SIZEOF(form), "username=%s&password=%s", login, password);
+ headers[0].szName = "Content-Type";
+ headers[0].szValue = "application/x-www-form-urlencoded";
+ ZeroMemory(&req, sizeof(req));
+ req.cbSize = sizeof(req);
+ req.requestType = REQUEST_POST;
+ req.flags = 0;
+ req.headersCount = 1;
+ req.headers = headers;
+ req.pData = form;
+ req.dataLength = (int)strlen(form);
+ req.szUrl = "http://poczta.o2.pl/login.html";
+ resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)proto->hNetlibUser, (LPARAM)&req);
+ if (resp != NULL) {
+ if (resp->resultCode/100 == 2 || resp->resultCode == 302) {
+ int i;
+ for (i=0; i<resp->headersCount; i++ ) {
+ if (strcmpi(resp->headers[i].szName, "Set-Cookie") == 0) {
+ char *start = strstr(resp->headers[i].szValue, "ssid=");
+ if (start != NULL) {
+ char *end = strstr(resp->headers[i].szValue, ";");
+ start = start + 5;
+ if (end == NULL) {
+ end = resp->headers[i].szValue + strlen(resp->headers[i].szValue);
+ }
+ strncpy(cookie, start, (end - start));
+ break;
+ }
+ }
+ }
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
+ }
+ }
+ mir_free(login);
+ mir_free(password);
+ _snprintf(szFileName, sizeof(szFileName), "http://poczta.o2.pl/login.html?sid=%s", cookie);
+ CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) szFileName);
+ return 0;
+}
+
+int TlenOnModulesLoaded(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+
+ char str[128];
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ /* Set all contacts to offline */
+ HANDLE hContact = db_find_first();
+ while (hContact != NULL) {
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto != NULL && !strcmp(szProto, proto->m_szModuleName)) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ TlenMUCInit(proto);
+ sprintf(str, "%s", LPGEN("Incoming mail"));
+ SkinAddNewSoundEx("TlenMailNotify", proto->m_szProtoName, str);
+ sprintf(str, "%s", LPGEN("Alert"));
+ SkinAddNewSoundEx("TlenAlertNotify", proto->m_szProtoName, str);
+ sprintf(str, "%s", LPGEN("Voice chat"));
+ SkinAddNewSoundEx("TlenVoiceNotify", proto->m_szProtoName, str);
+
+ HookEventObj_Ex(ME_USERINFO_INITIALISE, proto, TlenUserInfoInit);
+
+ return 0;
+}
+
+
+int TlenPreShutdown(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ JabberLog(proto, "TLEN TlenPreShutdown");
+ return 0;
+}
+
+
+static void initMenuItems(TlenProtocol *proto)
+{
+
+ char text[_MAX_PATH];
+ CLISTMENUITEM mi, clmi;
+ memset(&mi, 0, sizeof(CLISTMENUITEM));
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ memset(&clmi, 0, sizeof(CLISTMENUITEM));
+ clmi.cbSize = sizeof(CLISTMENUITEM);
+ clmi.flags = CMIM_FLAGS | CMIF_GRAYED;
+
+ mi.pszContactOwner = proto->m_szModuleName;
+ mi.popupPosition = 500090000;
+
+ strcpy(text, proto->m_szModuleName);
+ mi.pszService = text;
+ mi.ptszName = proto->m_tszUserName;
+ mi.position = -1999901009;
+ mi.pszPopupName = (char *)-1;
+ mi.flags = CMIF_ROOTPOPUP | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+ mi.icolibItem = GetIconHandle(IDI_TLEN);
+ proto->hMenuRoot = Menu_AddMainMenuItem(&mi);
+
+ mi.flags = CMIF_CHILDPOPUP | CMIF_ICONFROMICOLIB;
+ //mi.pszPopupName = (char *)proto->hMenuRoot;
+ mi.hParentMenu = (HGENMENU)proto->hMenuRoot;
+
+ proto->hMenuChats = NULL;
+ if (ServiceExists(MS_MUCC_NEW_WINDOW))
+ {
+ sprintf(text, "%s/MainMenuChats", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenMUCMenuHandleChats);
+ mi.pszName = "Tlen Chats";
+ mi.position = 2000050001;
+ mi.icolibItem = GetIconHandle(IDI_CHATS);
+ mi.pszService = text;
+ proto->hMenuChats = Menu_AddMainMenuItem(&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuChats, (LPARAM) &clmi);
+ }
+
+ // "Multi-User Conference"
+ sprintf(text, "%s/MainMenuMUC", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenMUCMenuHandleMUC);
+ mi.pszName = "Multi-User Conference";
+ mi.position = 2000050002;
+ mi.icolibItem = GetIconHandle(IDI_MUC);
+ mi.pszService = text;
+ proto->hMenuMUC = Menu_AddMainMenuItem(&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) proto->hMenuMUC, (LPARAM) &clmi);
+
+ sprintf(text, "%s/MainMenuInbox", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenMenuHandleInbox);
+ mi.pszName = "Tlen Mail";
+ mi.position = 2000050003;
+ mi.icolibItem = GetIconHandle(IDI_MAIL);
+ mi.pszService = text;
+ proto->hMenuInbox = Menu_AddMainMenuItem(&mi);
+
+ mi.hParentMenu = NULL;
+
+
+ // "Send picture"
+ sprintf(text, "%s/SendPicture", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenContactMenuHandleSendPicture);
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.pszName = "Send picture";
+ mi.position = -2000019030;
+ mi.icolibItem = GetIconHandle(IDI_IMAGE);
+ mi.pszService = text;
+ proto->hMenuPicture = Menu_AddContactMenuItem(&mi);
+
+ // "Invite to MUC"
+ sprintf(text, "%s/ContactMenuMUC", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenMUCContactMenuHandleMUC);
+ mi.pszName = "Multi-User Conference";
+ mi.position = -2000019020;
+ mi.icolibItem = GetIconHandle(IDI_MUC);
+ mi.pszService = text;
+ proto->hMenuContactMUC = Menu_AddContactMenuItem(&mi);
+
+ // "Invite to voice chat"
+ sprintf(text, "%s/ContactMenuVoice", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenVoiceContactMenuHandleVoice);
+ mi.pszName = "Voice Chat";
+ mi.position = -2000019010;
+ mi.icolibItem = GetIconHandle(IDI_VOICE);
+ mi.pszService = text;
+ proto->hMenuContactVoice = Menu_AddContactMenuItem(&mi);
+
+ // "Request authorization"
+ sprintf(text, "%s/RequestAuth", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenContactMenuHandleRequestAuth);
+ mi.pszName = "Request authorization";
+ mi.position = -2000001001;
+ mi.icolibItem = GetIconHandle(IDI_REQUEST);
+ mi.pszService = text;
+ proto->hMenuContactRequestAuth = Menu_AddContactMenuItem(&mi);
+
+ // "Grant authorization"
+ sprintf(text, "%s/GrantAuth", proto->m_szModuleName);
+ CreateServiceFunction_Ex(text, proto, TlenContactMenuHandleGrantAuth);
+ mi.pszName = "Grant authorization";
+ mi.position = -2000001000;
+ mi.icolibItem = GetIconHandle(IDI_GRANT);
+ mi.pszService = text;
+ proto->hMenuContactGrantAuth = Menu_AddContactMenuItem(&mi);
+}
+
+void uninitMenuItems(TlenProtocol *proto) {
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)proto->hMenuChats, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)proto->hMenuMUC, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)proto->hMenuInbox, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)proto->hMenuRoot, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)proto->hMenuContactMUC, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)proto->hMenuPicture, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)proto->hMenuContactVoice, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)proto->hMenuContactRequestAuth, (LPARAM) 0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)proto->hMenuContactGrantAuth, (LPARAM) 0);
+}
+
+TlenProtocol* tlenProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
+{
+ TlenProtocol* ppro = new TlenProtocol( pszProtoName, tszUserName );
+
+ return ppro;
+}
+
+int TlenSystemModulesLoaded(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ initMenuItems(proto);
+
+ return 0;
+}
+
+static int tlenProtoUninit( TlenProtocol* ppro )
+{
+ delete ppro;
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ PROTOCOLDESCRIPTOR pd;
+
+ mir_getLP( &pluginInfoEx );
+
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, THREAD_SET_CONTEXT, FALSE, 0);
+
+ srand((unsigned) time(NULL));
+
+ TlenRegisterIcons();
+
+ // Register protocol module
+ ZeroMemory(&pd, sizeof(PROTOCOLDESCRIPTOR));
+ pd.cbSize = sizeof(PROTOCOLDESCRIPTOR);
+ pd.szName = "TLEN";
+ pd.fnInit = ( pfnInitProto )tlenProtoInit;
+ pd.fnUninit = ( pfnUninitProto )tlenProtoUninit;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM) &pd);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
diff --git a/protocols/Tlen/src/tlen_advsearch.cpp b/protocols/Tlen/src/tlen_advsearch.cpp
new file mode 100644
index 0000000000..5a338a3bd6
--- /dev/null
+++ b/protocols/Tlen/src/tlen_advsearch.cpp
@@ -0,0 +1,113 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "resource.h"
+
+static void InitComboBox(HWND hwndCombo, JABBER_FIELD_MAP *fieldMap)
+{
+ int i, n;
+
+ n = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)_T(""));
+ SendMessage(hwndCombo, CB_SETITEMDATA, n, 0);
+ SendMessage(hwndCombo, CB_SETCURSEL, n, 0);
+ for (i=0;;i++) {
+ if (fieldMap[i].name == NULL)
+ break;
+ n = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) TranslateTS(fieldMap[i].name));
+ SendMessage(hwndCombo, CB_SETITEMDATA, n, fieldMap[i].id);
+ }
+}
+
+INT_PTR CALLBACK TlenAdvSearchDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_GENDER), tlenFieldGender);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_LOOKFOR), tlenFieldLookfor);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_STATUS), tlenFieldStatus);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_OCCUPATION), tlenFieldOccupation);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_PLAN), tlenFieldPlan);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void FetchField(HWND hwndDlg, UINT idCtrl, char *fieldName, char **str, int *strSize)
+{
+ char text[512];
+ char *localFieldName, *localText;
+
+ if (hwndDlg == NULL || fieldName == NULL || str == NULL || strSize == NULL)
+ return;
+ GetDlgItemTextA(hwndDlg, idCtrl, text, sizeof(text));
+ if (text[0]) {
+ if ((localFieldName=JabberTextEncode(fieldName)) != NULL) {
+ if ((localText=JabberTextEncode(text)) != NULL) {
+ JabberStringAppend(str, strSize, "<%s>%s</%s>", localFieldName, localText, localFieldName);
+ mir_free(localText);
+ }
+ mir_free(localFieldName);
+ }
+ }
+}
+
+static void FetchCombo(HWND hwndDlg, UINT idCtrl, char *fieldName, char **str, int *strSize)
+{
+ int value;
+ char *localFieldName;
+
+ if (hwndDlg == NULL || fieldName == NULL || str == NULL || strSize == NULL)
+ return;
+ value = (int) SendDlgItemMessage(hwndDlg, idCtrl, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, idCtrl, CB_GETCURSEL, 0, 0), 0);
+ if (value > 0) {
+ if ((localFieldName=JabberTextEncode(fieldName)) != NULL) {
+ JabberStringAppend(str, strSize, "<%s>%d</%s>", localFieldName, value, localFieldName);
+ mir_free(localFieldName);
+ }
+ }
+}
+
+char *TlenAdvSearchCreateQuery(HWND hwndDlg, int iqId)
+{
+ char *str;
+ int strSize;
+
+ if (hwndDlg == NULL) return NULL;
+ str = NULL;
+ FetchField(hwndDlg, IDC_FIRSTNAME, "first", &str, &strSize);
+ FetchField(hwndDlg, IDC_LASTNAME, "last", &str, &strSize);
+ FetchField(hwndDlg, IDC_NICK, "nick", &str, &strSize);
+ FetchField(hwndDlg, IDC_EMAIL, "email", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_GENDER, "s", &str, &strSize);
+ FetchField(hwndDlg, IDC_AGEFROM, "d", &str, &strSize);
+ FetchField(hwndDlg, IDC_AGETO, "u", &str, &strSize);
+ FetchField(hwndDlg, IDC_CITY, "c", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_OCCUPATION, "j", &str, &strSize);
+ FetchField(hwndDlg, IDC_SCHOOL, "e", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_STATUS, "m", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_LOOKFOR, "r", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_PLAN, "p", &str, &strSize);
+ return str;
+}
diff --git a/protocols/Tlen/src/tlen_avatar.cpp b/protocols/Tlen/src/tlen_avatar.cpp
new file mode 100644
index 0000000000..8acf004681
--- /dev/null
+++ b/protocols/Tlen/src/tlen_avatar.cpp
@@ -0,0 +1,427 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include "tlen_avatar.h"
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* TlenGetAvatarFileName() - gets a file name for the avatar image */
+
+void TlenGetAvatarFileName(TlenProtocol *proto, JABBER_LIST_ITEM *item, TCHAR* ptszDest, int cbLen)
+{
+ DWORD dwAttributes;
+ int tPathLen;
+ int format = PA_FORMAT_PNG;
+ TCHAR* tszFileType;
+ TCHAR* tmpPath = Utils_ReplaceVarsT( TEXT("%miranda_avatarcache%") );
+ tPathLen = mir_sntprintf( ptszDest, cbLen, TEXT("%s\\Tlen"), tmpPath );
+ mir_free(tmpPath);
+ dwAttributes = GetFileAttributes( ptszDest );
+ if ( dwAttributes == 0xffffffff || ( dwAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 ) {
+ CallService( MS_UTILS_CREATEDIRTREET, 0, ( LPARAM )ptszDest );
+ }
+ ptszDest[ tPathLen++ ] = '\\';
+ if (item != NULL) {
+ format = item->avatarFormat;
+ } else if (proto->threadData != NULL) {
+ format = proto->threadData->avatarFormat;
+ } else {
+ format = DBGetContactSettingDword(NULL, proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN);
+ }
+ tszFileType = TEXT("png");
+ switch(format) {
+ case PA_FORMAT_JPEG: tszFileType = TEXT("jpg"); break;
+ case PA_FORMAT_ICON: tszFileType = TEXT("ico"); break;
+ case PA_FORMAT_PNG: tszFileType = TEXT("png"); break;
+ case PA_FORMAT_GIF: tszFileType = TEXT("gif"); break;
+ case PA_FORMAT_BMP: tszFileType = TEXT("bmp"); break;
+ }
+ if ( item != NULL ) {
+ char* hash;
+ hash = JabberSha1(item->jid);
+ TCHAR* hashT = mir_a2t(hash);
+ mir_free( hash );
+ mir_sntprintf( ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%s.%s"), hashT, tszFileType );
+ mir_free( hashT );
+ } else {
+ TCHAR* m_tszModuleName = mir_a2t(proto->m_szModuleName);
+ mir_sntprintf( ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%s_avatar.%s"), m_tszModuleName, tszFileType );
+ mir_free( m_tszModuleName );
+ }
+}
+
+static void RemoveAvatar(TlenProtocol *proto, HANDLE hContact) {
+ TCHAR tFileName[ MAX_PATH ];
+ if (hContact == NULL) {
+ proto->threadData->avatarHash[0] = '\0';
+ }
+ TlenGetAvatarFileName( proto, NULL, tFileName, sizeof tFileName );
+ DeleteFile(tFileName);
+ DBDeleteContactSetting(hContact, "ContactPhoto", "File");
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "AvatarHash");
+ DBDeleteContactSetting(hContact, proto->m_szModuleName, "AvatarFormat");
+ ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
+}
+
+static void SetAvatar(TlenProtocol *proto, HANDLE hContact, JABBER_LIST_ITEM *item, char *data, int len, DWORD format) {
+ FILE* out;
+ TCHAR filename[MAX_PATH];
+ char md5[33];
+ mir_md5_state_t ctx;
+ DWORD digest[4];
+
+ if (format == PA_FORMAT_UNKNOWN && len > 4) {
+ format = JabberGetPictureType(data);
+ }
+
+ mir_md5_init( &ctx );
+ mir_md5_append( &ctx, ( BYTE* )data, len);
+ mir_md5_finish( &ctx, ( BYTE* )digest );
+
+ sprintf( md5, "%08x%08x%08x%08x", (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3]));
+ if (item != NULL) {
+ char *hash = item->avatarHash;
+ item->avatarFormat = format;
+ item->avatarHash = mir_strdup(md5);
+ mir_free(hash);
+ } else {
+ proto->threadData->avatarFormat = format;
+ strcpy(proto->threadData->avatarHash, md5);
+ }
+ TlenGetAvatarFileName(proto, item, filename, sizeof filename );
+ DeleteFile(filename);
+ out = _tfopen( filename, TEXT("wb") );
+ if ( out != NULL ) {
+ fwrite( data, len, 1, out );
+ fclose( out );
+ DBWriteContactSettingTString(hContact, "ContactPhoto", "File", filename );
+ DBWriteContactSettingString(hContact, proto->m_szModuleName, "AvatarHash", md5);
+ DBWriteContactSettingDword(hContact, proto->m_szModuleName, "AvatarFormat", format);
+ }
+ ProtoBroadcastAck( proto->m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0);
+}
+
+int TlenProcessAvatarNode(TlenProtocol *proto, XmlNode *avatarNode, JABBER_LIST_ITEM *item) {
+ XmlNode *aNode;
+ char *oldHash = NULL;
+ char *md5 = NULL, *type = NULL;
+ HANDLE hContact;
+ hContact = NULL;
+ if (item != NULL) {
+ if ((hContact=JabberHContactFromJID(proto, item->jid)) == NULL) return 0;
+ }
+ if (item == NULL) {
+ oldHash = proto->threadData->avatarHash;
+ } else {
+ oldHash = item->avatarHash;
+ }
+ if (avatarNode != NULL) {
+ aNode = JabberXmlGetChild(avatarNode, "a");
+ if (aNode != NULL) {
+ type = JabberXmlGetAttrValue(aNode, "type");
+ md5 = JabberXmlGetAttrValue(aNode, "md5");
+ }
+ }
+ if (md5 != NULL) {
+ /* check contact's avatar hash - md5 */
+ if (oldHash == NULL || strcmp(oldHash, md5)) {
+ if (item != NULL) {
+ item->newAvatarDownloading = TRUE;
+ }
+ TlenGetAvatar(proto, hContact);
+ return 1;
+ }
+ } else {
+ /* remove avatar */
+ if (oldHash != NULL) {
+ if (item != NULL) {
+ item->avatarHash = NULL;
+ mir_free(oldHash);
+ item->newAvatarDownloading = FALSE;
+ }
+ RemoveAvatar(proto, hContact);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void TlenProcessPresenceAvatar(TlenProtocol *proto, XmlNode *node, JABBER_LIST_ITEM *item) {
+ HANDLE hContact;
+ if ((hContact=JabberHContactFromJID(proto, item->jid)) == NULL) return;
+ TlenProcessAvatarNode(proto, JabberXmlGetChild(node, "avatar"), item);
+}
+
+
+static char *replaceTokens(const char *base, const char *uri, const char *login, const char* token, int type, int access) {
+ char *result;
+ int i, l, size;
+ l = (int)strlen(uri);
+ size = (int)strlen(base);
+ for (i = 0; i < l; ) {
+ if (!strncmp(uri + i, "^login^", 7)) {
+ size += (int)strlen(login);
+ i += 7;
+ } else if (!strncmp(uri + i, "^type^", 6)) {
+ size++;
+ i += 6;
+ } else if (!strncmp(uri + i, "^token^", 7)) {
+ size += (int)strlen(token);
+ i += 7;
+ } else if (!strncmp(uri + i, "^access^", 8)) {
+ size++;
+ i += 8;
+ } else {
+ size++;
+ i++;
+ }
+ }
+ result = (char *)mir_alloc(size +1);
+ strcpy(result, base);
+ size = (int)strlen(base);
+ for (i = 0; i < l; ) {
+ if (!strncmp(uri + i, "^login^", 7)) {
+ strcpy(result + size, login);
+ size += (int)strlen(login);
+ i += 7;
+ } else if (!strncmp(uri + i, "^type^", 6)) {
+ result[size++] = '0' + type;
+ i += 6;
+ } else if (!strncmp(uri + i, "^token^", 7)) {
+ strcpy(result + size, token);
+ size += (int)strlen(token);
+ i += 7;
+ } else if (!strncmp(uri + i, "^access^", 8)) {
+ result[size++] = '0' + access;
+ i += 8;
+ } else {
+ result[size++] = uri[i++];
+ }
+ }
+ result[size] = '\0';
+ return result;
+}
+
+
+static int getAvatarMutex = 0;
+
+typedef struct {
+ TlenProtocol *proto;
+ HANDLE hContact;
+} TLENGETAVATARTHREADDATA;
+
+static void TlenGetAvatarThread(void *ptr) {
+
+ JABBER_LIST_ITEM *item = NULL;
+ NETLIBHTTPREQUEST req;
+ NETLIBHTTPREQUEST *resp;
+ TLENGETAVATARTHREADDATA *data = (TLENGETAVATARTHREADDATA *)ptr;
+ HANDLE hContact = data->hContact;
+ char *request;
+ char *login = NULL;
+ if (hContact != NULL) {
+ char *jid = JabberJIDFromHContact(data->proto, hContact);
+ login = JabberNickFromJID(jid);
+ item = JabberListGetItemPtr(data->proto, LIST_ROSTER, jid);
+ mir_free(jid);
+ } else {
+ login = mir_strdup(data->proto->threadData->username);
+ }
+ if ((data->proto->threadData != NULL && hContact == NULL) || item != NULL) {
+ DWORD format = PA_FORMAT_UNKNOWN;
+ if (item != NULL) {
+ item->newAvatarDownloading = TRUE;
+ }
+ request = replaceTokens(data->proto->threadData->tlenConfig.mailBase, data->proto->threadData->tlenConfig.avatarGet, login, data->proto->threadData->avatarToken, 0, 0);
+ ZeroMemory(&req, sizeof(req));
+ req.cbSize = sizeof(req);
+ req.requestType = data->proto->threadData->tlenConfig.avatarGetMthd;
+ req.flags = 0;
+ req.headersCount = 0;
+ req.headers = NULL;
+ req.dataLength = 0;
+ req.szUrl = request;
+ resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)data->proto->hNetlibUser, (LPARAM)&req);
+ if (item != NULL) {
+ item->newAvatarDownloading = FALSE;
+ }
+ if (resp != NULL) {
+ if (resp->resultCode/100 == 2) {
+ if (resp->dataLength > 0) {
+ int i;
+ for (i=0; i<resp->headersCount; i++ ) {
+ if (strcmpi(resp->headers[i].szName, "Content-Type") == 0) {
+ if (strcmpi(resp->headers[i].szValue, "image/png") == 0) {
+ format = PA_FORMAT_PNG;
+ } else if (strcmpi(resp->headers[i].szValue, "image/x-png") == 0) {
+ format = PA_FORMAT_PNG;
+ } else if (strcmpi(resp->headers[i].szValue, "image/jpeg") == 0) {
+ format = PA_FORMAT_JPEG;
+ } else if (strcmpi(resp->headers[i].szValue, "image/jpg") == 0) {
+ format = PA_FORMAT_JPEG;
+ } else if (strcmpi(resp->headers[i].szValue, "image/gif") == 0) {
+ format = PA_FORMAT_GIF;
+ } else if (strcmpi(resp->headers[i].szValue, "image/bmp") == 0) {
+ format = PA_FORMAT_BMP;
+ }
+ break;
+ }
+ }
+ SetAvatar(data->proto, hContact, item, resp->pData, resp->dataLength, format);
+ } else {
+ RemoveAvatar(data->proto, hContact);
+ }
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp);
+ }
+ mir_free(request);
+ mir_free(login);
+ }
+ if (hContact == NULL) {
+ getAvatarMutex = 0;
+ }
+ mir_free(data);
+}
+
+void TlenGetAvatar(TlenProtocol *proto, HANDLE hContact) {
+ if (hContact == NULL) {
+ if (getAvatarMutex != 0) {
+ return;
+ }
+ getAvatarMutex = 1;
+ }
+ {
+ TLENGETAVATARTHREADDATA *data = (TLENGETAVATARTHREADDATA *)mir_alloc(sizeof(TLENGETAVATARTHREADDATA));
+ data->proto = proto;
+ data->hContact = hContact;
+ JabberForkThread(TlenGetAvatarThread, 0, data);
+ }
+}
+
+typedef struct {
+ TlenProtocol *proto;
+ NETLIBHTTPREQUEST *req;
+}TLENREMOVEAVATARTHREADDATA;
+
+static void TlenRemoveAvatarRequestThread(void *ptr) {
+ NETLIBHTTPREQUEST *resp;
+ TLENREMOVEAVATARTHREADDATA *data = (TLENREMOVEAVATARTHREADDATA*)ptr;
+ NETLIBHTTPREQUEST *req = (NETLIBHTTPREQUEST *)data->req;
+ resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)data->proto->hNetlibUser, (LPARAM)req);
+ mir_free(req->szUrl);
+ mir_free(req->headers);
+ mir_free(req->pData);
+ mir_free(req);
+ if (resp != NULL) {
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, (WPARAM)0, (LPARAM)resp);
+ RemoveAvatar(data->proto, NULL);
+ }
+ mir_free(data);
+
+}
+
+typedef struct {
+ TlenProtocol *proto;
+ NETLIBHTTPREQUEST *req;
+ char *data;
+ int length;
+}TLENUPLOADAVATARTHREADDATA;
+
+static void TlenUploadAvatarRequestThread(void *ptr) {
+ NETLIBHTTPREQUEST *resp;
+ TLENUPLOADAVATARTHREADDATA * data = (TLENUPLOADAVATARTHREADDATA *) ptr;
+ NETLIBHTTPREQUEST *req = data->req;
+ resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)data->proto->hNetlibUser, (LPARAM)req);
+ if (resp != NULL) {
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, (WPARAM)0, (LPARAM)resp);
+ SetAvatar(data->proto, NULL, NULL, data->data, data->length, PA_FORMAT_PNG);
+ }
+ mir_free(req->szUrl);
+ mir_free(req->headers);
+ mir_free(req->pData);
+ mir_free(req);
+ mir_free(data->data);
+ mir_free(data);
+}
+
+void TlenRemoveAvatar(TlenProtocol *proto) {
+ NETLIBHTTPREQUEST *req;
+ char *request;
+ if (proto->threadData != NULL) {
+ TLENREMOVEAVATARTHREADDATA *data = (TLENREMOVEAVATARTHREADDATA *)mir_alloc(sizeof(TLENREMOVEAVATARTHREADDATA));
+ req = (NETLIBHTTPREQUEST *)mir_alloc(sizeof(NETLIBHTTPREQUEST));
+ data->proto =proto;
+ data->req = req;
+ request = replaceTokens(proto->threadData->tlenConfig.mailBase, proto->threadData->tlenConfig.avatarRemove, "", proto->threadData->avatarToken, 0, 0);
+ ZeroMemory(req, sizeof(NETLIBHTTPREQUEST));
+ req->cbSize = sizeof(NETLIBHTTPREQUEST);
+ req->requestType = proto->threadData->tlenConfig.avatarGetMthd;
+ req->szUrl = request;
+ JabberForkThread(TlenRemoveAvatarRequestThread, 0, data);
+ }
+}
+
+
+void TlenUploadAvatar(TlenProtocol *proto, unsigned char *data, int dataLen, int access) {
+ NETLIBHTTPREQUEST *req;
+ NETLIBHTTPHEADER *headers;
+ TLENUPLOADAVATARTHREADDATA *threadData;
+ char *request;
+ unsigned char *buffer;
+ if (proto->threadData != NULL && dataLen > 0 && data != NULL) {
+ char *mpartHead = "--AaB03x\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"plik.png\"\r\nContent-Type: image/png\r\n\r\n";
+ char *mpartTail = "\r\n--AaB03x--\r\n";
+ int size, sizeHead = (int)strlen(mpartHead), sizeTail = (int)strlen(mpartTail);
+ request = replaceTokens(proto->threadData->tlenConfig.mailBase, proto->threadData->tlenConfig.avatarUpload, "", proto->threadData->avatarToken, 0, access);
+ threadData = (TLENUPLOADAVATARTHREADDATA *)mir_alloc(sizeof(TLENUPLOADAVATARTHREADDATA));
+ threadData->proto = proto;
+ req = (NETLIBHTTPREQUEST *)mir_alloc(sizeof(NETLIBHTTPREQUEST));
+ headers = (NETLIBHTTPHEADER *)mir_alloc(sizeof(NETLIBHTTPHEADER));
+ ZeroMemory(req, sizeof(NETLIBHTTPREQUEST));
+ req->cbSize = sizeof(NETLIBHTTPREQUEST);
+ req->requestType = proto->threadData->tlenConfig.avatarUploadMthd;
+ req->szUrl = request;
+ req->flags = 0;
+ headers[0].szName = "Content-Type";
+ headers[0].szValue = "multipart/form-data; boundary=AaB03x";
+ req->headersCount = 1;
+ req->headers = headers;
+ size = dataLen + sizeHead + sizeTail;
+ buffer = (unsigned char *)mir_alloc(size);
+ memcpy(buffer, mpartHead, sizeHead);
+ memcpy(buffer + sizeHead, data, dataLen);
+ memcpy(buffer + sizeHead + dataLen, mpartTail, sizeTail);
+ req->dataLength = size;
+ req->pData = (char*)buffer;
+ threadData->req = req;
+ threadData->data = (char *) mir_alloc(dataLen);
+ memcpy(threadData->data, data, dataLen);
+ threadData->length = dataLen;
+ JabberForkThread(TlenUploadAvatarRequestThread, 0, threadData);
+ }
+}
+
diff --git a/protocols/Tlen/src/tlen_avatar.h b/protocols/Tlen/src/tlen_avatar.h
new file mode 100644
index 0000000000..0a0694fe11
--- /dev/null
+++ b/protocols/Tlen/src/tlen_avatar.h
@@ -0,0 +1,34 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _TLEN_AVATAR_H_
+#define _TLEN_AVATAR_H_
+
+void TlenProcessPresenceAvatar(TlenProtocol *proto, XmlNode *node, JABBER_LIST_ITEM *item);
+int TlenProcessAvatarNode(TlenProtocol *proto, XmlNode *avatarNode, JABBER_LIST_ITEM *item);
+void TlenGetAvatarFileName(TlenProtocol *proto, JABBER_LIST_ITEM *item, TCHAR* psztDest, int cbLen);
+void TlenGetAvatar(TlenProtocol *proto, HANDLE hContact);
+void TlenUploadAvatar(TlenProtocol *proto, unsigned char *data, int dataLen, int access);
+void TlenRemoveAvatar(TlenProtocol *proto);
+
+#endif // _TLEN_AVATAR_H_
diff --git a/protocols/Tlen/src/tlen_file.cpp b/protocols/Tlen/src/tlen_file.cpp
new file mode 100644
index 0000000000..4a02259245
--- /dev/null
+++ b/protocols/Tlen/src/tlen_file.cpp
@@ -0,0 +1,708 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "jabber_list.h"
+#include "tlen_p2p_old.h"
+
+static void TlenFileReceiveParse(TLEN_FILE_TRANSFER *ft)
+{
+ int i;
+ char *p;
+ TLEN_FILE_PACKET *rpacket, *packet;
+
+ rpacket = NULL;
+ if (ft->state == FT_CONNECTING) {
+ rpacket = TlenP2PPacketReceive(ft->s);
+ if (rpacket != NULL) {
+ p = rpacket->packet;
+ if (rpacket->type == TLEN_FILE_PACKET_FILE_LIST) { // list of files (length & name)
+ ft->fileCount = (int)(*((DWORD*)p));
+ ft->files = (char **) mir_alloc(sizeof(char *) * ft->fileCount);
+ ft->filesSize = (long *) mir_alloc(sizeof(long) * ft->fileCount);
+ ft->currentFile = 0;
+ ft->allFileTotalSize = 0;
+ ft->allFileReceivedBytes = 0;
+ p += sizeof(DWORD);
+ for (i=0;i<ft->fileCount;i++) {
+ ft->filesSize[i] = (long)(*((DWORD*)p));
+ ft->allFileTotalSize += ft->filesSize[i];
+ p += sizeof(DWORD);
+ ft->files[i] = (char *)mir_alloc(256);
+ memcpy(ft->files[i], p, 256);
+ p += 256;
+ }
+ if ((packet=TlenP2PPacketCreate(3*sizeof(DWORD))) == NULL) {
+ ft->state = FT_ERROR;
+ }
+ else {
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_FILE_LIST_ACK);
+ TlenP2PPacketSend(ft->s, packet);
+ TlenP2PPacketFree(packet);
+ ft->state = FT_INITIALIZING;
+ JabberLog(ft->proto, "Change to FT_INITIALIZING");
+ }
+ }
+ TlenP2PPacketFree(rpacket);
+ }
+ else {
+ ft->state = FT_ERROR;
+ }
+ }
+ else if (ft->state == FT_INITIALIZING) {
+ char *fullFileName;
+ if ((packet=TlenP2PPacketCreate(3*sizeof(DWORD))) != NULL) {
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_FILE_REQUEST); // file request
+ TlenP2PPacketPackDword(packet, ft->currentFile);
+ TlenP2PPacketPackDword(packet, 0);
+ TlenP2PPacketPackDword(packet, 0);
+ TlenP2PPacketSend(ft->s, packet);
+ TlenP2PPacketFree(packet);
+
+ fullFileName = (char *) mir_alloc(strlen(ft->szSavePath) + strlen(ft->files[ft->currentFile]) + 2);
+ strcpy(fullFileName, ft->szSavePath);
+ if (fullFileName[strlen(fullFileName)-1] != '\\')
+ strcat(fullFileName, "\\");
+ strcat(fullFileName, ft->files[ft->currentFile]);
+ ft->fileId = _open(fullFileName, _O_BINARY|_O_WRONLY|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITE);
+ ft->fileReceivedBytes = 0;
+ ft->fileTotalSize = ft->filesSize[ft->currentFile];
+ JabberLog(ft->proto, "Saving to [%s] [%d]", fullFileName, ft->filesSize[ft->currentFile]);
+ mir_free(fullFileName);
+ ft->state = FT_RECEIVING;
+ JabberLog(ft->proto, "Change to FT_RECEIVING");
+ }
+ else {
+ ft->state = FT_ERROR;
+ }
+ }
+ else if (ft->state == FT_RECEIVING) {
+ PROTOFILETRANSFERSTATUS pfts;
+ memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
+ pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+ pfts.hContact = ft->hContact;
+ pfts.pszFiles = ft->files;
+ pfts.totalFiles = ft->fileCount;
+ pfts.currentFileNumber = ft->currentFile;
+ pfts.totalBytes = ft->allFileTotalSize;
+ pfts.szWorkingDir = NULL;
+ pfts.szCurrentFile = ft->files[ft->currentFile];
+ pfts.currentFileSize = ft->filesSize[ft->currentFile];
+ pfts.currentFileTime = 0;
+ JabberLog(ft->proto, "Receiving data...");
+ while (ft->state == FT_RECEIVING) {
+ rpacket = TlenP2PPacketReceive(ft->s);
+ if (rpacket != NULL) {
+ p = rpacket->packet;
+ if (rpacket->type == TLEN_FILE_PACKET_FILE_DATA) { // file data
+ int writeSize;
+ writeSize = rpacket->len - 2 * sizeof(DWORD) ; // skip file offset
+ if (_write(ft->fileId, p + 2 * sizeof(DWORD), writeSize) != writeSize) {
+ ft->state = FT_ERROR;
+ }
+ else {
+ ft->fileReceivedBytes += writeSize;
+ ft->allFileReceivedBytes += writeSize;
+ pfts.totalProgress = ft->allFileReceivedBytes;
+ pfts.currentFileProgress = ft->fileReceivedBytes;
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM) &pfts);
+ }
+ }
+ else if (rpacket->type == TLEN_FILE_PACKET_END_OF_FILE) { // end of file
+ _close(ft->fileId);
+ JabberLog(ft->proto, "Finishing this file...");
+ if (ft->currentFile >= ft->fileCount-1) {
+ ft->state = FT_DONE;
+ }
+ else {
+ ft->currentFile++;
+ ft->state = FT_INITIALIZING;
+ JabberLog(ft->proto, "File received, advancing to the next file...");
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+ }
+ }
+ TlenP2PPacketFree(rpacket);
+ }
+ else {
+ ft->state = FT_ERROR;
+ }
+ }
+ }
+}
+
+static void TlenFileReceivingConnection(JABBER_SOCKET hConnection, DWORD dwRemoteIP, void * pExtra)
+{
+ JABBER_SOCKET slisten;
+ TLEN_FILE_TRANSFER *ft;
+
+ TlenProtocol *proto = (TlenProtocol *)pExtra;
+ ft = TlenP2PEstablishIncomingConnection(proto, hConnection, LIST_FILE, TRUE);
+ if (ft != NULL) {
+ slisten = ft->s;
+ ft->s = hConnection;
+ JabberLog(ft->proto, "Set ft->s to %d (saving %d)", hConnection, slisten);
+ JabberLog(ft->proto, "Entering send loop for this file connection... (ft->s is hConnection)");
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenFileReceiveParse(ft);
+ }
+ if (ft->state == FT_DONE)
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ else
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ JabberLog(ft->proto, "Closing connection for this file transfer... (ft->s is now hBind)");
+ ft->s = slisten;
+ JabberLog(ft->proto, "ft->s is restored to %d", ft->s);
+ if (ft->s != hConnection) {
+ Netlib_CloseHandle(hConnection);
+ }
+ if (ft->hFileEvent != NULL)
+ SetEvent(ft->hFileEvent);
+ } else {
+ Netlib_CloseHandle(hConnection);
+ }
+}
+
+
+static void __cdecl TlenFileReceiveThread(TLEN_FILE_TRANSFER *ft)
+{
+ NETLIBOPENCONNECTION nloc;
+ JABBER_SOCKET s;
+ JabberLog(ft->proto, "Thread started: type=file_receive server='%s' port='%d'", ft->hostName, ft->wPort);
+ ft->mode = FT_RECV;
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = ft->hostName;
+ nloc.wPort = ft->wPort;
+ nloc.flags = 0;
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hNetlibUser, (LPARAM) &nloc);
+ if (s != NULL) {
+ ft->s = s;
+ JabberLog(ft->proto, "Entering file receive loop");
+ TlenP2PEstablishOutgoingConnection(ft, TRUE);
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenFileReceiveParse(ft);
+ }
+ if (ft->s) {
+ Netlib_CloseHandle(s);
+ }
+ ft->s = NULL;
+ } else {
+ ft->pfnNewConnectionV2 = TlenFileReceivingConnection;
+ JabberLog(ft->proto, "Connection failed - receiving as server");
+ s = TlenP2PListen(ft);
+ if (s != NULL) {
+ HANDLE hEvent;
+ char *nick;
+ ft->s = s;
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ft->hFileEvent = hEvent;
+ ft->currentFile = 0;
+ ft->state = FT_CONNECTING;
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<f t='%s' i='%s' e='7' a='%s' p='%d'/>", nick, ft->iqId, ft->localName, ft->wLocalPort);
+ mir_free(nick);
+ JabberLog(ft->proto, "Waiting for the file to be received...");
+ WaitForSingleObject(hEvent, INFINITE);
+ ft->hFileEvent = NULL;
+ CloseHandle(hEvent);
+ JabberLog(ft->proto, "Finish all files");
+ Netlib_CloseHandle(s);
+ } else {
+ ft->state = FT_ERROR;
+ }
+ }
+ JabberListRemove(ft->proto, LIST_FILE, ft->iqId);
+ if (ft->state == FT_DONE)
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ else {
+ char *nick;
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<f t='%s' i='%s' e='8'/>", nick, ft->iqId);
+ mir_free(nick);
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ }
+
+ JabberLog(ft->proto, "Thread ended: type=file_receive server='%s'", ft->hostName);
+ TlenP2PFreeFileTransfer(ft);
+}
+
+
+
+static void TlenFileSendParse(TLEN_FILE_TRANSFER *ft)
+{
+ int i;
+ char *p, *t;
+ int currentFile, numRead;
+ char *fileBuffer;
+ TLEN_FILE_PACKET *rpacket, *packet;
+
+
+ if (ft->state == FT_CONNECTING) {
+ char filename[256]; // Must be 256 (0x100)
+ if ((packet=TlenP2PPacketCreate(sizeof(DWORD)+(ft->fileCount*(sizeof(filename)+sizeof(DWORD))))) != NULL) {
+ // Must pause a bit, sending these two packets back to back
+ // will break the session because the receiver cannot take it :)
+ SleepEx(1000, TRUE);
+ TlenP2PPacketSetLen(packet, 0); // Reuse packet
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_FILE_LIST);
+ TlenP2PPacketPackDword(packet, (DWORD) ft->fileCount);
+ for (i=0; i<ft->fileCount; i++) {
+// struct _stat statbuf;
+// _stat(ft->files[i], &statbuf);
+// TlenP2PPacketPackDword(packet, statbuf.st_size);
+ TlenP2PPacketPackDword(packet, ft->filesSize[i]);
+ memset(filename, 0, sizeof(filename));
+ if ((t=strrchr(ft->files[i], '\\')) != NULL)
+ t++;
+ else
+ t = ft->files[i];
+ _snprintf(filename, sizeof(filename)-1, t);
+ TlenP2PPacketPackBuffer(packet, filename, sizeof(filename));
+ }
+ TlenP2PPacketSend(ft->s, packet);
+ TlenP2PPacketFree(packet);
+
+ ft->allFileReceivedBytes = 0;
+ ft->state = FT_INITIALIZING;
+ JabberLog(ft->proto, "Change to FT_INITIALIZING");
+ }
+ else {
+ ft->state = FT_ERROR;
+ }
+ }
+ else if (ft->state == FT_INITIALIZING) { // FT_INITIALIZING
+ rpacket = TlenP2PPacketReceive(ft->s);
+ JabberLog(ft->proto, "FT_INITIALIZING: recv %d", rpacket);
+ if (rpacket == NULL) {
+ ft->state = FT_ERROR;
+ return;
+ }
+ JabberLog(ft->proto, "FT_INITIALIZING: recv type %d", rpacket->type);
+ p = rpacket->packet;
+ // TYPE: TLEN_FILE_PACKET_FILE_LIST_ACK will be ignored
+ // LEN: 0
+ if (rpacket->type == TLEN_FILE_PACKET_FILE_LIST_ACK) {
+
+ }
+ // Then the receiver will request each file
+ // TYPE: TLEN_FILE_PACKET_REQUEST
+ // LEN:
+ // (DWORD) file number
+ // (DWORD) 0
+ // (DWORD) 0
+ else if (rpacket->type == TLEN_FILE_PACKET_FILE_REQUEST) {
+ PROTOFILETRANSFERSTATUS pfts;
+ //struct _stat statbuf;
+
+ currentFile = *((DWORD*)p);
+ if (currentFile != ft->currentFile) {
+ JabberLog(ft->proto, "Requested file (#%d) is invalid (must be %d)", currentFile, ft->currentFile);
+ ft->state = FT_ERROR;
+ }
+ else {
+ // _stat(ft->files[currentFile], &statbuf); // file size in statbuf.st_size
+ JabberLog(ft->proto, "Sending [%s] [%d]", ft->files[currentFile], ft->filesSize[currentFile]);
+ if ((ft->fileId=_open(ft->files[currentFile], _O_BINARY|_O_RDONLY)) < 0) {
+ JabberLog(ft->proto, "File cannot be opened");
+ ft->state = FT_ERROR;
+ }
+ else {
+ memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
+ pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+ pfts.hContact = ft->hContact;
+ pfts.flags = PFTS_SENDING;
+ pfts.pszFiles = ft->files;
+ pfts.totalFiles = ft->fileCount;
+ pfts.currentFileNumber = ft->currentFile;
+ pfts.totalBytes = ft->allFileTotalSize;
+ pfts.szWorkingDir = NULL;
+ pfts.szCurrentFile = ft->files[ft->currentFile];
+ pfts.currentFileSize = ft->filesSize[ft->currentFile]; //statbuf.st_size;
+ pfts.currentFileTime = 0;
+ ft->fileReceivedBytes = 0;
+ if ((packet = TlenP2PPacketCreate(2*sizeof(DWORD)+2048)) == NULL) {
+ ft->state = FT_ERROR;
+ }
+ else {
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_FILE_DATA);
+ fileBuffer = (char *) mir_alloc(2048);
+ JabberLog(ft->proto, "Sending file data...");
+ while ((numRead=_read(ft->fileId, fileBuffer, 2048)) > 0) {
+ TlenP2PPacketSetLen(packet, 0); // Reuse packet
+ TlenP2PPacketPackDword(packet, (DWORD) ft->fileReceivedBytes);
+ TlenP2PPacketPackDword(packet, 0);
+ TlenP2PPacketPackBuffer(packet, fileBuffer, numRead);
+ if (TlenP2PPacketSend(ft->s, packet)) {
+ ft->fileReceivedBytes += numRead;
+ ft->allFileReceivedBytes += numRead;
+ pfts.totalProgress = ft->allFileReceivedBytes;
+ pfts.currentFileProgress = ft->fileReceivedBytes;
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM) &pfts);
+ }
+ else {
+ ft->state = FT_ERROR;
+ break;
+ }
+ }
+ mir_free(fileBuffer);
+ _close(ft->fileId);
+ if (ft->state != FT_ERROR) {
+ if (ft->currentFile >= ft->fileCount-1)
+ ft->state = FT_DONE;
+ else {
+ ft->currentFile++;
+ ft->state = FT_INITIALIZING;
+ JabberLog(ft->proto, "File sent, advancing to the next file...");
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
+ }
+ }
+ JabberLog(ft->proto, "Finishing this file...");
+ TlenP2PPacketSetLen(packet, 0); // Reuse packet
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_END_OF_FILE);
+ TlenP2PPacketPackDword(packet, currentFile);
+ TlenP2PPacketSend(ft->s, packet);
+ TlenP2PPacketFree(packet);
+ }
+ }
+ }
+ TlenP2PPacketFree(rpacket);
+ }
+ else {
+ ft->state = FT_ERROR;
+ }
+ }
+}
+
+static void TlenFileSendingConnection(JABBER_SOCKET hConnection, DWORD dwRemoteIP, void * pExtra)
+{
+ JABBER_SOCKET slisten;
+ TLEN_FILE_TRANSFER *ft;
+ TlenProtocol *proto = (TlenProtocol *)pExtra;
+
+ ft = TlenP2PEstablishIncomingConnection(proto, hConnection, LIST_FILE, TRUE);
+ if (ft != NULL) {
+ slisten = ft->s;
+ ft->s = hConnection;
+ JabberLog(ft->proto, "Set ft->s to %d (saving %d)", hConnection, slisten);
+
+ JabberLog(ft->proto, "Entering send loop for this file connection... (ft->s is hConnection)");
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenFileSendParse(ft);
+ }
+ if (ft->state == FT_DONE)
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ else
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ JabberLog(ft->proto, "Closing connection for this file transfer... (ft->s is now hBind)");
+ ft->s = slisten;
+ JabberLog(ft->proto, "ft->s is restored to %d", ft->s);
+ if (ft->s != hConnection) {
+ Netlib_CloseHandle(hConnection);
+ }
+ if (ft->hFileEvent != NULL)
+ SetEvent(ft->hFileEvent);
+ } else {
+ Netlib_CloseHandle(hConnection);
+ }
+}
+
+int TlenFileCancelAll(TlenProtocol *proto)
+{
+ JABBER_LIST_ITEM *item;
+ HANDLE hEvent;
+ int i = 0;
+
+ while ((i=JabberListFindNext(proto, LIST_FILE, 0)) >=0 ) {
+ if ((item=JabberListGetItemPtrFromIndex(proto, i)) != NULL) {
+ TLEN_FILE_TRANSFER *ft = item->ft;
+ JabberListRemoveByIndex(proto, i);
+ if (ft != NULL) {
+ if (ft->s) {
+ //ProtoBroadcastAck(m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ JabberLog(ft->proto, "Closing ft->s = %d", ft->s);
+ ft->state = FT_ERROR;
+ Netlib_CloseHandle(ft->s);
+ ft->s = NULL;
+ if (ft->hFileEvent != NULL) {
+ hEvent = ft->hFileEvent;
+ ft->hFileEvent = NULL;
+ SetEvent(hEvent);
+ }
+ } else {
+ JabberLog(ft->proto, "freeing ft struct");
+ TlenP2PFreeFileTransfer(ft);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static void __cdecl TlenFileSendingThread(TLEN_FILE_TRANSFER *ft)
+{
+ JABBER_SOCKET s = NULL;
+ HANDLE hEvent;
+ char *nick;
+
+ JabberLog(ft->proto, "Thread started: type=tlen_file_send");
+ ft->mode = FT_SEND;
+ ft->pfnNewConnectionV2 = TlenFileSendingConnection;
+ s = TlenP2PListen(ft);
+ if (s != NULL) {
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ ft->s = s;
+ //JabberLog("ft->s = %d", s);
+ //JabberLog("fileCount = %d", ft->fileCount);
+
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ft->hFileEvent = hEvent;
+ ft->currentFile = 0;
+ ft->state = FT_CONNECTING;
+
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<f t='%s' i='%s' e='6' a='%s' p='%d'/>", nick, ft->iqId, ft->localName, ft->wLocalPort);
+ mir_free(nick);
+ JabberLog(ft->proto, "Waiting for the file to be sent...");
+ WaitForSingleObject(hEvent, INFINITE);
+ ft->hFileEvent = NULL;
+ CloseHandle(hEvent);
+ JabberLog(ft->proto, "Finish all files");
+ Netlib_CloseHandle(s);
+ ft->s = NULL;
+ JabberLog(ft->proto, "ft->s is NULL");
+
+ if (ft->state == FT_SWITCH) {
+ NETLIBOPENCONNECTION nloc;
+ JABBER_SOCKET s;
+ JabberLog(ft->proto, "Sending as client...");
+ ft->state = FT_CONNECTING;
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = ft->hostName;
+ nloc.wPort = ft->wPort;
+ nloc.flags = 0;
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hNetlibUser, (LPARAM) &nloc);
+ if (s != NULL) {
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ ft->s = s;
+ TlenP2PEstablishOutgoingConnection(ft, TRUE);
+ JabberLog(ft->proto, "Entering send loop for this file connection...");
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenFileSendParse(ft);
+ }
+ if (ft->state == FT_DONE)
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ else
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ JabberLog(ft->proto, "Closing connection for this file transfer... ");
+ Netlib_CloseHandle(s);
+ } else {
+ ft->state = FT_ERROR;
+ }
+ }
+ } else {
+ JabberLog(ft->proto, "Cannot allocate port to bind for file server thread, thread ended.");
+ ft->state = FT_ERROR;
+ }
+ JabberListRemove(ft->proto, LIST_FILE, ft->iqId);
+ switch (ft->state) {
+ case FT_DONE:
+ JabberLog(ft->proto, "Finish successfully");
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ break;
+ case FT_DENIED:
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0);
+ break;
+ default: // FT_ERROR:
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<f t='%s' i='%s' e='8'/>", nick, ft->iqId);
+ mir_free(nick);
+ JabberLog(ft->proto, "Finish with errors");
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ break;
+ }
+ JabberLog(ft->proto, "Thread ended: type=file_send");
+ TlenP2PFreeFileTransfer(ft);
+}
+
+
+TLEN_FILE_TRANSFER *TlenFileCreateFT(TlenProtocol *proto, const char *jid) {
+ TLEN_FILE_TRANSFER *ft;
+ ft = (TLEN_FILE_TRANSFER *) mir_alloc(sizeof(TLEN_FILE_TRANSFER));
+ memset(ft, 0, sizeof(TLEN_FILE_TRANSFER));
+ ft->proto = proto;
+ ft->jid = mir_strdup(jid);
+ return ft;
+}
+
+
+/*
+ * File transfer
+ */
+void TlenProcessF(XmlNode *node, ThreadData *info)
+{
+ TLEN_FILE_TRANSFER *ft;
+ char *from, *p, *e;
+ char jid[128], szFilename[MAX_PATH];
+ int numFiles;
+ JABBER_LIST_ITEM *item;
+
+// if (!node->name || strcmp(node->name, "f")) return;
+ if (info == NULL) return;
+
+ if ((from=JabberXmlGetAttrValue(node, "f")) != NULL) {
+
+ if (strchr(from, '@') == NULL) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, info->server);
+ } else {
+ _snprintf(jid, sizeof(jid), "%s", from);
+ }
+ if ((e=JabberXmlGetAttrValue(node, "e")) != NULL) {
+
+ if (!strcmp(e, "1")) {
+ // FILE_RECV : e='1' : File transfer request
+ ft = TlenFileCreateFT(info->proto, jid);
+ ft->hContact = JabberHContactFromJID(info->proto, jid);
+
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL)
+ ft->iqId = mir_strdup(p);
+
+ szFilename[0] = '\0';
+ if ((p=JabberXmlGetAttrValue(node, "c")) != NULL) {
+ numFiles = atoi(p);
+ if (numFiles == 1) {
+ if ((p=JabberXmlGetAttrValue(node, "n")) != NULL) {
+ p = JabberTextDecode(p);
+ strncpy(szFilename, p, sizeof(szFilename));
+ mir_free(p);
+ } else {
+ strcpy(szFilename, Translate("1 File"));
+ }
+ }
+ else if (numFiles > 1) {
+ _snprintf(szFilename, sizeof(szFilename), Translate("%d Files"), numFiles);
+ }
+ }
+
+ if (szFilename[0] != '\0' && ft->iqId != NULL) {
+ TCHAR* filenameT = mir_utf8decodeT((char*)szFilename);
+ PROTORECVFILET pre = {0};
+ pre.flags = PREF_TCHAR;
+ pre.fileCount = 1;
+ pre.timestamp = time(NULL);
+ pre.tszDescription = filenameT;
+ pre.ptszFiles = &filenameT;
+ pre.lParam = (LPARAM)ft;
+ JabberLog(ft->proto, "sending chainrecv");
+ CCSDATA ccs = { ft->hContact, PSR_FILE, 0, (LPARAM)&pre };
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
+ mir_free(filenameT);
+ } else {
+ // malformed <f/> request, reject
+ if (ft->iqId)
+ JabberSend(ft->proto, "<f i='%s' e='4' t='%s'/>", ft->iqId, from);
+ else
+ JabberSend(ft->proto, "<f e='4' t='%s'/>", from);
+ TlenP2PFreeFileTransfer(ft);
+ }
+ }
+ else if (!strcmp(e, "3")) {
+ // FILE_RECV : e='3' : invalid transfer error
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ if (item->ft != NULL) {
+ ProtoBroadcastAck(info->proto->m_szModuleName, item->ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, item->ft, 0);
+ info->proto->FileCancel(NULL, item->ft);
+ }
+ JabberListRemove(info->proto, LIST_FILE, p);
+ }
+ }
+ }
+ else if (!strcmp(e, "4")) {
+ // FILE_SEND : e='4' : File sending request was denied by the remote client
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ if (!strcmp(item->ft->jid, jid)) {
+ ProtoBroadcastAck(info->proto->m_szModuleName, item->ft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, item->ft, 0);
+ JabberListRemove(info->proto, LIST_FILE, p);
+ }
+ }
+ }
+ }
+ else if (!strcmp(e, "5")) {
+ // FILE_SEND : e='5' : File sending request was accepted
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ if (!strcmp(item->ft->jid, jid))
+ JabberForkThread((void (__cdecl *)(void*))TlenFileSendingThread, 0, item->ft);
+ }
+ }
+ }
+ else if (!strcmp(e, "6")) {
+ // FILE_RECV : e='6' : IP and port information to connect to get file
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ if ((p=JabberXmlGetAttrValue(node, "a")) != NULL) {
+ item->ft->hostName = mir_strdup(p);
+ if ((p=JabberXmlGetAttrValue(node, "p")) != NULL) {
+ item->ft->wPort = atoi(p);
+ JabberForkThread((void (__cdecl *)(void*))TlenFileReceiveThread, 0, item->ft);
+ }
+ }
+ }
+ }
+ }
+ else if (!strcmp(e, "7")) {
+ // FILE_RECV : e='7' : IP and port information to connect to send file
+ // in case the conection to the given server was not successful
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ if ((p=JabberXmlGetAttrValue(node, "a")) != NULL) {
+ if (item->ft->hostName != NULL) mir_free(item->ft->hostName);
+ item->ft->hostName = mir_strdup(p);
+ if ((p=JabberXmlGetAttrValue(node, "p")) != NULL) {
+ item->ft->wPort = atoi(p);
+ item->ft->state = FT_SWITCH;
+ SetEvent(item->ft->hFileEvent);
+ }
+ }
+ }
+ }
+ }
+ else if (!strcmp(e, "8")) {
+ // FILE_RECV : e='8' : transfer error
+ if ((p=JabberXmlGetAttrValue(node, "i")) != NULL) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, p)) != NULL) {
+ item->ft->state = FT_ERROR;
+ if (item->ft->hFileEvent != NULL) {
+ SetEvent(item->ft->hFileEvent);
+ } else {
+ ProtoBroadcastAck(info->proto->m_szModuleName, item->ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, item->ft, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/protocols/Tlen/src/tlen_file.h b/protocols/Tlen/src/tlen_file.h
new file mode 100644
index 0000000000..1cd0704ea5
--- /dev/null
+++ b/protocols/Tlen/src/tlen_file.h
@@ -0,0 +1,34 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _TLEN_FILE_H_
+#define _TLEN_FILE_H_
+
+#include <windows.h>
+#include "jabber.h"
+
+extern int TlenFileCancelAll(TlenProtocol *proto);
+extern void TlenProcessF(XmlNode *node, ThreadData *userdata);
+extern TLEN_FILE_TRANSFER *TlenFileCreateFT(TlenProtocol *proto, const char *jid);
+#endif
+
diff --git a/protocols/Tlen/src/tlen_muc.cpp b/protocols/Tlen/src/tlen_muc.cpp
new file mode 100644
index 0000000000..5f3809d806
--- /dev/null
+++ b/protocols/Tlen/src/tlen_muc.cpp
@@ -0,0 +1,1069 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include "jabber_iq.h"
+#include "resource.h"
+#include "tlen_muc.h"
+
+static int TlenMUCHandleEvent(void *ptr, WPARAM wParam, LPARAM lParam);
+static int TlenMUCQueryContacts(TlenProtocol *proto, const char *roomId);
+static int TlenMUCSendInvitation(TlenProtocol *proto, const char *roomID, const char *user);
+static int TlenMUCSendPresence(TlenProtocol *proto, const char *roomID, const char *nick, int desiredStatus);
+static int TlenMUCSendMessage(TlenProtocol *proto, MUCCEVENT *event);
+static int TlenMUCSendTopic(TlenProtocol *proto, MUCCEVENT *event);
+static int TlenMUCSendQuery(TlenProtocol *proto, int type, const char *parent, int page);
+
+static int isSelf(TlenProtocol *proto, const char *roomID, const char *nick)
+{
+ JABBER_LIST_ITEM *item;
+ int result;
+ result=0;
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, roomID);
+ if (item != NULL) {
+ if (item->nick == NULL) {
+ if (!strcmp(nick, proto->threadData->username)) result = 1;
+ } else if (nick[0] == '~') {
+ if (!strcmp(nick+1, item->nick)) {
+ result = 1;
+ }
+ }
+ }
+ return result;
+}
+
+static int stringToHex(const char *str)
+{
+ int i, val;
+ val = 0;
+ for (i=0;i<2;i++) {
+ val <<= 4;
+ if (str[i] >= 'A' && str[i] <= 'F') {
+ val += 10 + str[i]-'A';
+ } else if (str[i] >= '0' && str[i] <= '9') {
+ val += str[i]-'0';
+ }
+ }
+ return val;
+
+}
+static char *getDisplayName(TlenProtocol *proto, const char *id)
+{
+ CONTACTINFO ci;
+ char jid[256];
+ HANDLE hContact;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", id, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ if (((hContact=JabberHContactFromJID(proto, jid)) != NULL) || !strcmp(id, proto->threadData->username)) {
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = hContact;
+ ci.szProto = (char *)proto->m_szModuleName;
+ ci.dwFlag = CNF_DISPLAY;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ if (ci.type == CNFT_ASCIIZ) {
+ if (ci.pszVal) {
+ char* str = mir_t2a(ci.pszVal);
+ mir_free(ci.pszVal);
+ return str;
+ }
+ }
+ }
+ }
+ }
+ return mir_strdup(id);
+}
+
+BOOL TlenMUCInit(TlenProtocol *proto)
+{
+ HookEventObj_Ex(ME_MUCC_EVENT, proto, TlenMUCHandleEvent);
+ return 0;
+}
+static int TlenMUCHandleEvent(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ int id;
+ MUCCEVENT *mucce=(MUCCEVENT *) lParam;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!strcmp(mucce->pszModule, proto->m_szModuleName)) {
+ switch (mucce->iType) {
+ case MUCC_EVENT_INVITE:
+ TlenMUCSendInvitation(proto, mucce->pszID, mucce->pszNick);
+ break;
+ case MUCC_EVENT_MESSAGE:
+ TlenMUCSendMessage(proto, mucce);
+ break;
+ case MUCC_EVENT_TOPIC:
+ TlenMUCSendTopic(proto, mucce);
+ break;
+ case MUCC_EVENT_LEAVE:
+ TlenMUCSendPresence(proto, mucce->pszID, NULL, ID_STATUS_OFFLINE);
+ break;
+ case MUCC_EVENT_QUERY_GROUPS:
+ TlenMUCSendQuery(proto, 1, mucce->pszID, 0);
+ break;
+ case MUCC_EVENT_QUERY_ROOMS:
+ TlenMUCSendQuery(proto, 2, mucce->pszID, mucce->dwData);
+ break;
+ case MUCC_EVENT_QUERY_SEARCH:
+ TlenMUCSendQuery(proto, 3, mucce->pszName, 0);
+ break;
+ case MUCC_EVENT_QUERY_USERS:
+ switch (mucce->dwFlags) {
+ case MUCC_EF_USER_OWNER:
+ id = 1;
+ break;
+ case MUCC_EF_USER_ADMIN:
+ id = 2;
+ break;
+ case MUCC_EF_USER_MEMBER:
+ id = 3;
+ break;
+ case MUCC_EF_USER_BANNED:
+ id = 4;
+ break;
+ case MUCC_EF_USER_MODERATOR:
+ id = 6;
+ break;
+ default:
+ id = 0;
+ }
+ TlenMUCSendQuery(proto, 4, mucce->pszID, id);
+ break;
+ case MUCC_EVENT_REGISTER_NICK:
+ TlenMUCSendQuery(proto, 6, mucce->pszNick, 0);
+ break;
+ case MUCC_EVENT_REMOVE_NICK:
+ TlenMUCSendQuery(proto, 6, mucce->pszNick, 1);
+ break;
+ case MUCC_EVENT_REGISTER_ROOM:
+ id = JabberSerialNext(proto);
+ if (proto->isOnline) {
+ if (mucce->pszNick != NULL) {
+ JabberSend(proto, "<p to='c' tp='c' id='"JABBER_IQID"%d' x='%d' n='%s' p='%s' nick='%s'/>", id, mucce->dwFlags | 0x10, mucce->pszName, mucce->pszID);
+ } else {
+ JabberSend(proto, "<p to='c' tp='c' id='"JABBER_IQID"%d' x='%d' n='%s' p='%s'/>", id, mucce->dwFlags | 0x10, mucce->pszName, mucce->pszID);
+ }
+ }
+ break;
+ case MUCC_EVENT_REMOVE_ROOM:
+ if (proto->isOnline) {
+ JabberSend(proto, "<p to='%s' type='d'/>", mucce->pszID);
+ JabberListRemove(proto, LIST_CHATROOM, mucce->pszID);
+ // TlenMUCSendPresence(mucce->pszID, NULL, ID_STATUS_OFFLINE);
+ }
+ break;
+ case MUCC_EVENT_KICK_BAN:
+ if (proto->isOnline) {
+ char *nick;
+ nick = JabberResourceFromJID(mucce->pszUID);
+ if (!isSelf(proto, mucce->pszID, nick)) {
+ char *reason = JabberTextEncode(mucce->pszText);
+ JabberSend(proto, "<p to='%s'><x><i i='%s' a='4' ex='%d' rs='%s'/></x></p>", mucce->pszID, nick, mucce->dwData, reason);
+ mir_free(reason);
+ }
+ mir_free(nick);
+ }
+ break;
+ case MUCC_EVENT_UNBAN:
+ if (proto->isOnline) {
+ char *nick;
+ nick = JabberResourceFromJID(mucce->pszUID);
+ if (!isSelf(proto, mucce->pszID, nick)) {
+ JabberSend(proto, "<p to='%s'><x><i i='%s' a='0'/></x></p>", mucce->pszID, nick);
+ }
+ mir_free(nick);
+ }
+ break;
+ case MUCC_EVENT_SET_USER_ROLE:
+ if (proto->isOnline) {
+ char *nick;
+ nick = JabberResourceFromJID(mucce->pszUID);
+ if (!isSelf(proto, mucce->pszID, nick)) {
+ if (mucce->dwFlags == MUCC_EF_USER_ADMIN) {
+ id = 2;
+ } else if (mucce->dwFlags == MUCC_EF_USER_MEMBER) {
+ id = 3;
+ } else {
+ id = 0;
+ }
+ JabberSend(proto, "<p to='%s'><x><i i='%s' a='%d' /></x></p>", mucce->pszID, nick, id);
+ }
+ mir_free(nick);
+ }
+ break;
+ case MUCC_EVENT_QUERY_USER_NICKS:
+ TlenMUCSendQuery(proto, 7, mucce->pszID, 0);
+ break;
+ case MUCC_EVENT_QUERY_USER_ROOMS:
+ TlenMUCSendQuery(proto, 8, mucce->pszID, 0);
+ break;
+ case MUCC_EVENT_QUERY_CONTACTS:
+ TlenMUCQueryContacts(proto, mucce->pszID);
+ break;
+ case MUCC_EVENT_JOIN:
+ if (proto->isOnline) {
+ if (mucce->pszID == NULL || strlen(mucce->pszID) == 0) {
+ if (mucce->pszName == NULL || strlen(mucce->pszName) == 0) { // create a new chat room
+ id = JabberSerialNext(proto);
+ JabberSend(proto, "<p to='c' tp='c' id='"JABBER_IQID"%d'/>", id);
+ } else { // find a chat room by name
+ TlenMUCSendQuery(proto, 3, mucce->pszName, 0);
+ }
+ } else { // join existing chat room
+ if (!TlenMUCCreateWindow(proto, mucce->pszID, mucce->pszName, mucce->dwFlags, mucce->pszNick, NULL)) {
+ TlenMUCSendPresence(proto, mucce->pszID, mucce->pszNick, ID_STATUS_ONLINE);
+ }
+ }
+ }
+ break;
+ case MUCC_EVENT_START_PRIV:
+ if (proto->isOnline) {
+ JABBER_LIST_ITEM *item;
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, mucce->pszID);
+ if (item != NULL) {
+ char *nick;
+ nick = JabberResourceFromJID(mucce->pszUID);
+ if (!isSelf(proto, mucce->pszID, nick)) {
+ if (nick[0] == '~' || item->nick != NULL) {
+ char str[256];
+ sprintf(str, "%s/%s", mucce->pszID, nick);
+ hContact = JabberDBCreateContact(proto, str, nick, TRUE); //(char *)mucce->pszUID
+ DBWriteContactSettingByte(hContact, proto->m_szModuleName, "bChat", TRUE);
+ CallService(MS_MSG_SENDMESSAGE, (WPARAM) hContact, (LPARAM) NULL);
+ } else {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ char str[512];
+ _snprintf(str, sizeof(str), "%s@%s", nick, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ hContact = JabberDBCreateContact(proto, str, nick, TRUE);
+ CallService(MS_MSG_SENDMESSAGE, (WPARAM) hContact, (LPARAM) NULL);
+ }
+ }
+ }
+ mir_free(nick);
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int TlenMUCRecvInvitation(TlenProtocol *proto, const char *roomId, const char *roomName, const char *from, const char *reason)
+{
+ char *nick;
+ int ignore, ask, groupChatPolicy;
+ if (roomId == NULL) return 1;
+ groupChatPolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "GroupChatPolicy", 0);
+ ask = TRUE;
+ ignore = FALSE;
+ if (groupChatPolicy == TLEN_MUC_ASK) {
+ ignore = FALSE;
+ ask = TRUE;
+ } else if (groupChatPolicy == TLEN_MUC_IGNORE_ALL) {
+ ignore = TRUE;
+ } else if (groupChatPolicy == TLEN_MUC_IGNORE_NIR) {
+ char jid[256];
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ strcpy(jid, from);
+ }
+ ignore = !IsAuthorized(proto, jid);
+ ask = TRUE;
+ } else if (groupChatPolicy == TLEN_MUC_ACCEPT_IR) {
+ char jid[256];
+ JABBER_LIST_ITEM *item;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ strcpy(jid, from);
+ }
+ item = JabberListGetItemPtr(proto, LIST_ROSTER, jid);
+ ask = !IsAuthorized(proto, jid);
+ ignore = FALSE;
+ } else if (groupChatPolicy == TLEN_MUC_ACCEPT_ALL) {
+ ask = FALSE;
+ ignore = FALSE;
+ }
+ if (!ignore) {
+ if (ask) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = roomId;
+ mucce.pszName = roomName;
+ mucce.iType = MUCC_EVENT_INVITATION;
+ mucce.pszUID = from;
+ nick = getDisplayName(proto, from);
+ mucce.pszNick = nick;
+ mucce.pszText = reason;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ mir_free(nick);
+ } else {
+ if (!TlenMUCCreateWindow(proto, roomId, roomName, 0, NULL, NULL)) {
+ TlenMUCSendPresence(proto, roomId, NULL, ID_STATUS_ONLINE);
+ }
+ }
+ }
+ return 0;
+}
+
+int TlenMUCRecvPresence(TlenProtocol *proto, const char *from, int status, int flags, const char *kick)
+{
+ char str[512];
+// if (JabberListExist(LIST_CHATROOM, from)) {
+ char *nick, *roomId, *userId;
+ MUCCEVENT mucce;
+ roomId = JabberLoginFromJID(from);
+ userId = JabberResourceFromJID(from);
+ nick = getDisplayName(proto, userId);
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = roomId;
+ mucce.iType = MUCC_EVENT_STATUS;
+ mucce.pszUID = userId;//from;
+ mucce.pszNick = nick;
+ mucce.time = time(NULL);
+ mucce.bIsMe = isSelf(proto, roomId, userId);
+ mucce.dwData = status;
+ mucce.dwFlags = 0;
+ if (flags & USER_FLAGS_GLOBALOWNER) mucce.dwFlags |= MUCC_EF_USER_GLOBALOWNER;
+ if (flags & USER_FLAGS_OWNER) mucce.dwFlags |= MUCC_EF_USER_OWNER;
+ if (flags & USER_FLAGS_ADMIN) mucce.dwFlags |= MUCC_EF_USER_ADMIN;
+ if (flags & USER_FLAGS_REGISTERED) mucce.dwFlags |= MUCC_EF_USER_REGISTERED;
+ if (status == ID_STATUS_OFFLINE && mucce.bIsMe && kick != NULL) {
+ mucce.iType = MUCC_EVENT_ERROR;
+ sprintf(str, Translate("You have been kicked. Reason: %s "), kick);
+ mucce.pszText = str;
+ }
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ mir_free(roomId);
+ mir_free(userId);
+ mir_free(nick);
+// }
+ return 0;
+}
+
+int TlenMUCRecvMessage(TlenProtocol *proto, const char *from, long timestamp, XmlNode *bodyNode)
+{
+// if (JabberListExist(LIST_CHATROOM, from)) {
+ char *localMessage;
+ char *nick, *style, *roomId, *userId;
+ int iStyle;
+ MUCCEVENT mucce;
+ roomId = JabberLoginFromJID(from);
+ userId = JabberResourceFromJID(from);
+ nick = getDisplayName(proto, userId);
+ localMessage = JabberTextDecode(bodyNode->text);
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_MESSAGE;
+ mucce.pszID = roomId;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszText = localMessage;
+ mucce.pszUID = userId;//from;
+ mucce.pszNick = nick;
+ mucce.time = timestamp;
+ mucce.bIsMe = isSelf(proto, roomId, userId);
+ mucce.dwFlags = 0;
+ mucce.iFontSize = 0;
+ style = JabberXmlGetAttrValue(bodyNode, "f");
+ if (style != NULL) {
+ iStyle = atoi(style);
+ if (iStyle & 1) mucce.dwFlags |= MUCC_EF_FONT_BOLD;
+ if (iStyle & 2) mucce.dwFlags |= MUCC_EF_FONT_ITALIC;
+ if (iStyle & 4) mucce.dwFlags |= MUCC_EF_FONT_UNDERLINE;
+ }
+ style = JabberXmlGetAttrValue(bodyNode, "c");
+ if (style != NULL && strlen(style) > 5) {
+ iStyle = (stringToHex(style)<<16) | (stringToHex(style+2)<<8) | stringToHex(style+4);
+ } else {
+ iStyle = 0xFFFFFFFF;
+ }
+ mucce.color = (COLORREF) iStyle;
+ style = JabberXmlGetAttrValue(bodyNode, "s");
+ if (style != NULL) {
+ iStyle = atoi(style);
+ } else {
+ iStyle = 0;
+ }
+ mucce.iFontSize = iStyle;
+ style = JabberXmlGetAttrValue(bodyNode, "n");
+ if (style != NULL) {
+ iStyle = atoi(style)-1;
+ } else {
+ iStyle = 0;
+ }
+ mucce.iFont = iStyle;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ mir_free(roomId);
+ mir_free(userId);
+ mir_free(nick);
+ mir_free(localMessage);
+// }
+ return 0;
+}
+int TlenMUCRecvTopic(TlenProtocol *proto, const char *from, const char *subject)
+{
+// if (JabberListExist(LIST_CHATROOM, from)) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_TOPIC;
+ mucce.pszID = from;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszText = subject;
+ mucce.time = time(NULL);
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+// }
+ return 0;
+}
+
+int TlenMUCRecvError(TlenProtocol *proto, const char *from, XmlNode *errorNode)
+{
+ int errCode;
+ char str[512];
+ JABBER_LIST_ITEM *item;
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_ERROR;
+ mucce.pszID = from;
+ mucce.pszModule = proto->m_szModuleName;
+ errCode = atoi(JabberXmlGetAttrValue(errorNode, "code"));
+ switch (errCode) {
+ case 403:
+ sprintf(str, Translate("You cannot join this chat room, because you are banned."));
+ break;
+ case 404:
+ sprintf(str, Translate("Chat room not found."));
+ break;
+ case 407:
+ sprintf(str, Translate("This is a private chat room and you are not one of the members."));
+ break;
+ case 408:
+ sprintf(str, Translate("You cannot send any message unless you join this chat room."));
+ break;
+ case 410:
+ sprintf(str, Translate("Chat room with already created."));
+ break;
+ case 411:
+ sprintf(str, Translate("Nickname '%s' is already registered."),
+ JabberXmlGetAttrValue(errorNode, "n"));
+ break;
+ case 412:
+ sprintf(str, Translate("Nickname already in use, please try another one. Hint: '%s' is free."),
+ JabberXmlGetAttrValue(errorNode, "free"));
+ break;
+ case 413:
+ sprintf(str, Translate("You cannot register more than %s nicknames."),
+ JabberXmlGetAttrValue(errorNode, "num"));
+ break;
+ case 414:
+ sprintf(str, Translate("You cannot create more than %s chat rooms."),
+ JabberXmlGetAttrValue(errorNode, "num"));
+ break;
+ case 415:
+ sprintf(str, Translate("You cannot join more than %s chat rooms."),
+ JabberXmlGetAttrValue(errorNode, "num"));
+ break;
+ case 601:
+ sprintf(str, Translate("Anonymous nicknames are not allowed in this chat room."));
+ break;
+ default:
+ sprintf(str, Translate("Unknown error code : %d"), errCode);
+ break;
+ }
+ mucce.pszText = str;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ if (proto->isOnline) {
+ switch (errCode) {
+ case 412:
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, from);
+ if (item != NULL) {
+ mucce.iType = MUCC_EVENT_JOIN;
+ mucce.dwFlags = MUCC_EF_ROOM_NICKNAMES;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = from;
+ mucce.pszName = item->roomName;
+ mucce.pszNick = JabberXmlGetAttrValue(errorNode, "free");
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ }
+ break;
+ case 601:
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, from);
+ if (item != NULL) {
+ mucce.iType = MUCC_EVENT_JOIN;
+ mucce.dwFlags = 0;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = from;
+ mucce.pszName = item->roomName;
+ mucce.pszNick = NULL;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ }
+ break;
+ }
+ }
+ return 1;
+}
+static int TlenMUCSendInvitation(TlenProtocol *proto, const char *roomID, const char *user)
+{
+ if (!proto->isOnline) {
+ return 1;
+ }
+ JabberSend(proto, "<m to='%s'><x><inv to='%s'><r></r></inv></x></m>", roomID, user);
+ return 0;
+}
+
+static int TlenMUCSendPresence(TlenProtocol *proto, const char *roomID, const char *nick, int desiredStatus)
+{
+ char str[512];
+ char *jid;
+ JABBER_LIST_ITEM *item;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if (nick != NULL) {
+ _snprintf(str, sizeof(str), "%s/%s", roomID, nick);
+ } else {
+ _snprintf(str, sizeof(str), "%s", roomID);
+ }
+ if ((jid = JabberTextEncode(str)) != NULL) {
+ switch (desiredStatus) {
+ case ID_STATUS_ONLINE:
+ JabberSend(proto, "<p to='%s'/>", jid);
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, roomID);
+ if (item != NULL) {
+ if (item->nick != NULL) mir_free(item->nick);
+ item->nick = NULL;
+ if (nick != NULL) {
+ item->nick = mir_strdup(nick);
+ }
+ }
+ break;
+ default:
+ item = JabberListGetItemPtr(proto, LIST_CHATROOM, roomID);
+ if (item != NULL) {
+ JabberSend(proto, "<p to='%s'><s>unavailable</s></p>", jid);
+ JabberListRemove(proto, LIST_CHATROOM, roomID);
+ }
+ break;
+ }
+ mir_free(jid);
+ }
+ return 0;
+}
+
+static int TlenMUCSendMessage(TlenProtocol *proto, MUCCEVENT *event)
+{
+ char *msg, *jid;
+ int style;
+
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if ((msg = JabberTextEncode(event->pszText)) != NULL) {
+ if ((jid = JabberTextEncode(event->pszID)) != NULL) {
+ style = 0;
+ if (event->dwFlags & MUCC_EF_FONT_BOLD) style |=1;
+ if (event->dwFlags & MUCC_EF_FONT_ITALIC) style |=2;
+ if (event->dwFlags & MUCC_EF_FONT_UNDERLINE) style |=4;
+ JabberSend(proto, "<m to='%s'><b n='%d' s='%d' f='%d' c='%06X'>%s</b></m>", jid, event->iFont+1, event->iFontSize, style, event->color, msg);
+ mir_free(jid);
+ }
+ mir_free(msg);
+ }
+ return 0;
+}
+
+static int TlenMUCSendTopic(TlenProtocol *proto, MUCCEVENT *event)
+{
+ char *msg, *jid;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if ((msg = JabberTextEncode(event->pszText)) != NULL) {
+ if ((jid = JabberTextEncode(event->pszID)) != NULL) {
+ JabberSend(proto, "<m to='%s'><subject>%s</subject></m>", jid, msg);
+ mir_free(jid);
+ }
+ mir_free(msg);
+ }
+ return 0;
+}
+
+static int TlenMUCSendQuery(TlenProtocol *proto, int type, const char *parent, int page)
+{
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if (type == 3) { // find chat room by name
+ char serialId[32];
+ JABBER_LIST_ITEM *item;
+ sprintf(serialId, JABBER_IQID"%d", JabberSerialNext(proto));
+ item = JabberListAdd(proto, LIST_SEARCH, serialId);
+ item->roomName = mir_strdup(parent);
+ JabberSend(proto, "<iq to='c' type='3' n='%s' id='%s'/>", parent, serialId);
+ } else {
+ if (parent == NULL) {
+ JabberSend(proto, "<iq to='c' type='%d'/>", type);
+ } else { // 1 - groups, 2 - chat rooms, 7 - user nicks, 8 - user rooms
+ if (type == 1 || (type == 2 && page == 0) || type == 7 || type == 8) {
+ JabberSend(proto, "<iq to='c' type='%d' p='%s'/>", type, parent);
+ } else if (type == 2) {
+ JabberSend(proto, "<iq to='c' type='%d' p='%s' n='%d'/>", type, parent, page);
+ } else if (type == 6) {
+ if (page) {
+ JabberSend(proto, "<iq to='c' type='%d' n='%s' k='u'/>", type, parent);
+ } else {
+ JabberSend(proto, "<iq to='c' type='%d' n='%s'/>", type, parent);
+ }
+ } else if (type == 4) { // list of users, admins etc.
+ JabberSend(proto, "<iq to='%s' type='%d' k='%d'/>", parent, type, page);
+ }
+ }
+ }
+ return 0;
+}
+
+int TlenMUCCreateWindow(TlenProtocol *proto, const char *roomID, const char *roomName, int roomFlags, const char *nick, const char *iqId)
+{
+ JABBER_LIST_ITEM *item;
+ MUCCWINDOW mucw;
+ if (!proto->isOnline || roomID == NULL) {
+ return 1;
+ }
+ if (JabberListExist(proto, LIST_CHATROOM, roomID)) {
+ return 0;
+ }
+ item = JabberListAdd(proto, LIST_CHATROOM, roomID);
+ if (roomName != NULL) {
+ item->roomName = mir_strdup(roomName);
+ }
+ if (nick != NULL) {
+ item->nick = mir_strdup(nick);
+ }
+ mucw.cbSize = sizeof(MUCCWINDOW);
+ mucw.iType = MUCC_WINDOW_CHATROOM;
+ mucw.pszModule = proto->m_szModuleName;
+ mucw.pszModuleName = proto->m_szProtoName;
+ mucw.pszID = roomID;
+ mucw.pszName = roomName;
+ mucw.pszNick = nick;
+ mucw.dwFlags = roomFlags;
+ mucw.pszStatusbarText = "hello";
+ CallService(MS_MUCC_NEW_WINDOW, 0, (LPARAM) &mucw);
+ if (iqId != NULL) {
+ item = JabberListGetItemPtr(proto, LIST_INVITATIONS, iqId);
+ if (item !=NULL) {
+ TlenMUCSendInvitation(proto, roomID, item->nick);
+ }
+ JabberListRemove(proto, LIST_INVITATIONS, iqId);
+ }
+ return 0;
+}
+
+static void TlenMUCFreeQueryResult(MUCCQUERYRESULT *result)
+{ int i;
+ for (i=0; i<result->iItemsNum; i++) {
+ if (result->pItems[i].pszID != NULL) {
+ mir_free((char *) result->pItems[i].pszID);
+ }
+ if (result->pItems[i].pszName != NULL) {
+ mir_free((char *) result->pItems[i].pszName);
+ }
+ if (result->pItems[i].pszNick != NULL) {
+ mir_free((char *) result->pItems[i].pszNick);
+ }
+ if (result->pItems[i].pszText != NULL) {
+ mir_free((char *) result->pItems[i].pszText);
+ }
+ }
+ mir_free((MUCCQUERYITEM *)result->pItems);
+}
+
+void TlenIqResultChatGroups(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *lNode, *itemNode;
+ char *p, *n, *id, *f;
+ int i, j;
+ MUCCQUERYRESULT queryResult;
+
+ if ((lNode=JabberXmlGetChild(iqNode, "l")) == NULL) return;
+ p = JabberXmlGetAttrValue(iqNode, "p");
+ if (p == NULL) {
+ p="";
+ }
+ p = JabberTextDecode(p);
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_GROUPS;
+ queryResult.pszModule = proto->m_szModuleName;
+ queryResult.pszParent = p;
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild);
+ for (i=j=0; i<lNode->numChild; i++) {
+ itemNode = lNode->child[i];
+ if (!strcmp(itemNode->name, "i")) {
+ queryResult.pItems[j].iCount = 0;
+ if ((f = JabberXmlGetAttrValue(itemNode, "f")) != NULL) {
+ queryResult.pItems[j].iCount = !strcmp(f, "3");
+ }
+ n = JabberXmlGetAttrValue(itemNode, "n");
+ id = JabberXmlGetAttrValue(itemNode, "i");
+ if (n != NULL && id != NULL) {
+ queryResult.pItems[j].pszID = JabberTextDecode(id);
+ queryResult.pItems[j].pszName = JabberTextDecode(n);
+ j++;
+ }
+ }
+ }
+ queryResult.iItemsNum = j;
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+ mir_free(p);
+}
+
+void TlenIqResultChatRooms(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *lNode, *itemNode;
+ char *id, *c, *n, *x, *p, *px, *pn;
+ int i, j;
+ MUCCQUERYRESULT queryResult;
+
+ if ((lNode=JabberXmlGetChild(iqNode, "l")) == NULL) return;
+ if ((p = JabberXmlGetAttrValue(iqNode, "p")) == NULL) return;
+ pn = JabberXmlGetAttrValue(lNode, "n");
+ if (pn == NULL) pn = "0";
+ px = JabberXmlGetAttrValue(lNode, "x");
+ if (px == NULL) px = "0";
+ p = JabberTextDecode(p);
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_ROOMS;
+ queryResult.pszModule = proto->m_szModuleName;
+ queryResult.pszParent = p;
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild);
+ queryResult.iPage = atoi(pn);
+ queryResult.iLastPage = atoi(px)&2?1:0;
+ for (i=j=0; i<lNode->numChild; i++) {
+ itemNode = lNode->child[i];
+ if (!strcmp(itemNode->name, "i")) {
+ n = JabberXmlGetAttrValue(itemNode, "n");
+ c = JabberXmlGetAttrValue(itemNode, "c");
+ x = JabberXmlGetAttrValue(itemNode, "x");
+ if ((id=JabberXmlGetAttrValue(itemNode, "i")) != NULL) {
+ queryResult.pItems[j].pszID = JabberTextDecode(id);
+ queryResult.pItems[j].pszName = JabberTextDecode(n);
+ queryResult.pItems[j].iCount = atoi(c);
+ queryResult.pItems[j].dwFlags = atoi(x);
+ j++;
+ }
+ }
+ }
+ queryResult.iItemsNum = j;
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+ mir_free(p);
+}
+void TlenIqResultUserRooms(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *lNode, *itemNode;
+ char *id, *n;
+ int i, j;
+ MUCCQUERYRESULT queryResult;
+ if ((lNode=JabberXmlGetChild(iqNode, "l")) == NULL) return;
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_USER_ROOMS;
+ queryResult.pszModule = proto->m_szModuleName;
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild);
+ for (i=j=0; i<lNode->numChild; i++) {
+ itemNode = lNode->child[i];
+ if (!strcmp(itemNode->name, "i")) {
+ n = JabberXmlGetAttrValue(itemNode, "n");
+ id = JabberXmlGetAttrValue(itemNode, "i");
+ if (n != NULL && id != NULL) {
+ queryResult.pItems[j].pszID = JabberTextDecode(id);
+ queryResult.pItems[j].pszName = JabberTextDecode(n);
+ j++;
+ }
+ }
+ }
+ queryResult.iItemsNum = j;
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+}
+void TlenIqResultUserNicks(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *lNode, *itemNode;
+ char *n;
+ int i, j;
+ MUCCQUERYRESULT queryResult;
+ if ((lNode=JabberXmlGetChild(iqNode, "l")) == NULL) return;
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_USER_NICKS;
+ queryResult.pszModule = proto->m_szModuleName;
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild);
+ for (i=j=0; i<lNode->numChild; i++) {
+ itemNode = lNode->child[i];
+ if (!strcmp(itemNode->name, "i")) {
+ n = JabberXmlGetAttrValue(itemNode, "n");
+ queryResult.pItems[j].pszID = NULL;//JabberTextDecode(n);
+ queryResult.pItems[j].pszName = JabberTextDecode(n);
+ j++;
+ }
+ }
+ queryResult.iItemsNum = j;
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+}
+void TlenIqResultChatRoomUsers(TlenProtocol *proto, XmlNode *iqNode)
+{
+ XmlNode *lNode, *itemNode;
+ char *id, *n;
+ int i, j;
+ MUCCQUERYRESULT queryResult;
+ if ((lNode=JabberXmlGetChild(iqNode, "l")) == NULL) return;
+ if ((id=JabberXmlGetAttrValue(iqNode, "from")) == NULL) return;
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_USERS;
+ queryResult.pszModule = proto->m_szModuleName;
+ queryResult.pszParent = id;
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * lNode->numChild);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * lNode->numChild);
+ for (i=j=0; i<lNode->numChild; i++) {
+ itemNode = lNode->child[i];
+ if (!strcmp(itemNode->name, "i")) {
+ id = JabberXmlGetAttrValue(itemNode, "i");
+ if (id != NULL) {
+ queryResult.pItems[j].pszID = JabberTextDecode(id);
+ n = JabberXmlGetAttrValue(itemNode, "n");
+ if (n != NULL) {
+ queryResult.pItems[j].pszName = JabberTextDecode(n);
+ }
+ n = JabberXmlGetAttrValue(itemNode, "a");
+ if (n != NULL) {
+ queryResult.pItems[j].pszNick = JabberTextDecode(n);
+ }
+ n = JabberXmlGetAttrValue(itemNode, "r");
+ if (n != NULL) {
+ queryResult.pItems[j].pszText = JabberTextDecode(n);
+ }
+ n = JabberXmlGetAttrValue(itemNode, "e");
+ if (n != NULL) {
+ queryResult.pItems[j].iCount = atoi(n);
+ }
+ n = JabberXmlGetAttrValue(itemNode, "s");
+ if (n != NULL) {
+ queryResult.pItems[j].dwFlags = atoi(n);
+ }
+ j++;
+ }
+ }
+ }
+ queryResult.iItemsNum = j;
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+}
+
+void TlenIqResultRoomSearch(TlenProtocol *proto, XmlNode *iqNode)
+{
+ char *iqId, *id;
+ JABBER_LIST_ITEM *item;
+ iqId=JabberXmlGetAttrValue(iqNode, "id");
+ item=JabberListGetItemPtr(proto, LIST_SEARCH, iqId);
+ if ((id=JabberXmlGetAttrValue(iqNode, "i")) != NULL) {
+ MUCCEVENT mucce;
+ id = JabberTextDecode(id);
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_JOIN;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = id;
+ mucce.pszName = id;
+ if (item != NULL) {
+ mucce.pszName = item->roomName;
+ }
+ mucce.pszNick = NULL;
+ mucce.dwFlags = MUCC_EF_ROOM_NICKNAMES;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ mir_free(id);
+ }
+ JabberListRemove(proto, LIST_SEARCH, iqId);
+}
+
+void TlenIqResultRoomInfo(TlenProtocol *proto, XmlNode *iqNode)
+{
+ char *id, *name, *group, *flags;
+ if ((id=JabberXmlGetAttrValue(iqNode, "from")) != NULL) {
+ if ((name=JabberXmlGetAttrValue(iqNode, "n")) != NULL) {
+ MUCCEVENT mucce;
+ group = JabberXmlGetAttrValue(iqNode, "cn");
+ flags = JabberXmlGetAttrValue(iqNode, "x");
+ id = JabberTextDecode(id);
+ name = JabberTextDecode(name);
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_ROOM_INFO;
+ mucce.pszModule = proto->m_szModuleName;
+ mucce.pszID = id;
+ mucce.pszName = name;
+ mucce.dwFlags = atoi(flags);
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) &mucce);
+ mir_free(id);
+ mir_free(name);
+ }
+ }
+}
+
+
+typedef struct {
+ TlenProtocol *proto;
+ char *roomId;
+} MUCSENDQUERYTHREADDATA;
+
+static void __cdecl TlenMUCCSendQueryResultThread(void *ptr)
+{
+ HANDLE hContact;
+ MUCCQUERYRESULT queryResult;
+ DBVARIANT dbv;
+ MUCSENDQUERYTHREADDATA* threadData = (MUCSENDQUERYTHREADDATA*)ptr;
+ queryResult.cbSize = sizeof (MUCCQUERYRESULT);
+ queryResult.iType = MUCC_EVENT_QUERY_CONTACTS;
+ queryResult.pszModule = threadData->proto->m_szModuleName;
+ queryResult.pszParent = threadData->roomId;
+ queryResult.iItemsNum = 0;
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ char *str = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (str != NULL && !strcmp(str, threadData->proto->m_szModuleName)) {
+ if (!DBGetContactSettingByte(hContact, threadData->proto->m_szModuleName, "bChat", FALSE)) {
+ if (!DBGetContactSetting(hContact, threadData->proto->m_szModuleName, "jid", &dbv)) {
+ if (strcmp(dbv.pszVal, "b73@tlen.pl")) {
+ queryResult.iItemsNum++;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ queryResult.pItems = (MUCCQUERYITEM*)mir_alloc(sizeof(MUCCQUERYITEM) * queryResult.iItemsNum);
+ memset(queryResult.pItems, 0, sizeof(MUCCQUERYITEM) * queryResult.iItemsNum);
+ queryResult.iItemsNum = 0;
+ hContact = db_find_first();
+ while (hContact != NULL) {
+ char *baseProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (baseProto != NULL && !strcmp(baseProto, threadData->proto->m_szModuleName)) {
+ if (!DBGetContactSettingByte(hContact, threadData->proto->m_szModuleName, "bChat", FALSE)) {
+ if (!DBGetContactSetting(hContact, threadData->proto->m_szModuleName, "jid", &dbv)) {
+ if (strcmp(dbv.pszVal, "b73@tlen.pl")) {
+ queryResult.pItems[queryResult.iItemsNum].pszID = mir_strdup(dbv.pszVal);
+ queryResult.pItems[queryResult.iItemsNum].pszName = mir_strdup((char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0));
+ queryResult.iItemsNum++;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ CallService(MS_MUCC_QUERY_RESULT, 0, (LPARAM) &queryResult);
+ TlenMUCFreeQueryResult(&queryResult);
+ mir_free(threadData->roomId);
+ mir_free(threadData);
+}
+
+
+static int TlenMUCQueryContacts(TlenProtocol *proto, const char *roomId) {
+
+ MUCSENDQUERYTHREADDATA *threadData = (MUCSENDQUERYTHREADDATA *)mir_alloc(sizeof(MUCSENDQUERYTHREADDATA));
+ threadData->proto = proto;
+ threadData->roomId = mir_strdup(roomId);
+ JabberForkThread(TlenMUCCSendQueryResultThread, 0, (void *)threadData);
+ return 1;
+}
+
+INT_PTR TlenMUCMenuHandleMUC(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ JabberSend(proto, "<p to='c' tp='c' id='"JABBER_IQID"%d'/>", JabberSerialNext(proto));
+ /*
+ MUCCEVENT *mucce;
+ mucce = (MUCCEVENT *) mir_alloc (sizeof(MUCCEVENT));
+ mucce->cbSize = sizeof(MUCCEVENT);
+ mucce->iType = MUCC_EVENT_JOIN;
+ mucce->dwFlags = 0;
+ mucce->pszModule = proto->m_szModuleName;
+ mucce->pszID = NULL;
+ mucce->pszName = NULL;
+ mucce->pszNick = NULL;
+ CallService(MS_MUCC_EVENT, 0, (LPARAM) mucce);
+ mir_free(mucce);
+ */
+ return 0;
+}
+
+INT_PTR TlenMUCMenuHandleChats(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ MUCCWINDOW mucw;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ mucw.cbSize = sizeof(MUCCWINDOW);
+ mucw.iType = MUCC_WINDOW_CHATLIST;
+ mucw.pszModule = proto->m_szModuleName;
+ mucw.pszModuleName = proto->m_szProtoName;
+ CallService(MS_MUCC_NEW_WINDOW, 0, (LPARAM) &mucw);
+ return 0;
+}
+
+INT_PTR TlenMUCContactMenuHandleMUC(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ DBVARIANT dbv;
+ JABBER_LIST_ITEM *item;
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if ((hContact=(HANDLE) wParam) != NULL && proto->isOnline) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ char serialId[32];
+ sprintf(serialId, JABBER_IQID"%d", JabberSerialNext(proto));
+ item = JabberListAdd(proto, LIST_INVITATIONS, serialId);
+ item->nick = mir_strdup(dbv.pszVal);
+ JabberSend(proto, "<p to='c' tp='c' id='%s'/>", serialId);
+ DBFreeVariant(&dbv);
+ }
+ }
+ return 0;
+}
diff --git a/protocols/Tlen/src/tlen_muc.h b/protocols/Tlen/src/tlen_muc.h
new file mode 100644
index 0000000000..8409315ecd
--- /dev/null
+++ b/protocols/Tlen/src/tlen_muc.h
@@ -0,0 +1,45 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _TLEN_MUC_H_
+#define _TLEN_MUC_H_
+
+#include <windows.h>
+#include "m_mucc.h"
+
+#define USER_FLAGS_OWNER 0x01
+#define USER_FLAGS_ADMIN 0x02
+#define USER_FLAGS_REGISTERED 0x04
+#define USER_FLAGS_GLOBALOWNER 0x08
+#define USER_FLAGS_KICKED 0x80
+
+extern BOOL TlenMUCInit(TlenProtocol *proto);
+extern INT_PTR TlenMUCMenuHandleMUC(void *ptr, LPARAM wParam, LPARAM lParam);
+extern INT_PTR TlenMUCMenuHandleChats(void *ptr, LPARAM wParam, LPARAM lParam);
+extern INT_PTR TlenMUCContactMenuHandleMUC(void *ptr, LPARAM wParam, LPARAM lParam);
+extern int TlenMUCCreateWindow(TlenProtocol *proto, const char *roomID, const char *roomName, int roomFlags, const char *nick, const char *iqId);
+extern int TlenMUCRecvInvitation(TlenProtocol *proto, const char *roomJid, const char *roomName, const char *from, const char *reason);
+extern int TlenMUCRecvPresence(TlenProtocol *proto, const char *from, int status, int flags, const char *kick);
+extern int TlenMUCRecvMessage(TlenProtocol *proto, const char *from, long timestamp, XmlNode *bodyNode);
+extern int TlenMUCRecvTopic(TlenProtocol *proto, const char *from, const char *subject);
+extern int TlenMUCRecvError(TlenProtocol *proto, const char *from, XmlNode *errorNode);
+
+#endif
diff --git a/protocols/Tlen/src/tlen_p2p_new.cpp b/protocols/Tlen/src/tlen_p2p_new.cpp
new file mode 100644
index 0000000000..35584f277a
--- /dev/null
+++ b/protocols/Tlen/src/tlen_p2p_new.cpp
@@ -0,0 +1,352 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "tlen_p2p_old.h"
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "jabber_list.h"
+
+
+static void logInfo(const char *filename, const char *fmt, ...) {
+ SYSTEMTIME time;
+ char *str;
+ va_list vararg;
+ int strsize;
+ FILE *flog=fopen(filename,"at");
+ if (flog != NULL) {
+ GetLocalTime(&time);
+ va_start(vararg, fmt);
+ str = (char *) mir_alloc(strsize=2048);
+ while (_vsnprintf(str, strsize, fmt, vararg) == -1)
+ str = (char *) realloc(str, strsize+=2048);
+ va_end(vararg);
+ fprintf(flog,"%04d-%02d-%02d %02d:%02d:%02d,%03d [%s]",time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond,time.wMilliseconds, "INFO");
+ fprintf(flog," %s\n",str);
+ mir_free(str);
+ fclose(flog);
+ }
+}
+
+void __cdecl TlenNewFileReceiveThread(TLEN_FILE_TRANSFER *ft)
+{
+ JabberLog(ft->proto, "P2P receive thread started");
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+// ft->mode = FT_RECV;
+// ft->currentFile = 0;
+// ft->state = FT_CONNECTING;
+ {
+ FILE * fout = fopen("tlen_recv.dxx", "wt");
+ SOCKADDR_IN toad;
+ toad.sin_family = AF_INET;
+ toad.sin_addr.s_addr = inet_addr(ft->hostName);
+ toad.sin_port = htons(ft->wPort);
+ if (fout != NULL) {
+ fprintf(fout, "START:\n");
+ }
+ if (fout != NULL) {
+ fclose(fout);
+ }
+ while (ft->udps != INVALID_SOCKET) {
+ SOCKADDR_IN cad;
+ int alen;
+ int j, n;
+ unsigned char buff[1024];
+ alen = sizeof(struct sockaddr);
+ n=recvfrom(ft->udps, (char*)buff,sizeof(buff),0, (struct sockaddr *) &cad, &alen);
+ if (n<0) {
+ break;
+ }
+ logInfo("tlen_recv.dxx", "UDP");
+ fout = fopen("tlen_recv.dxx", "at");
+ if (fout != NULL) {
+ fprintf(fout, "\n|RECV %d bytes from %s:%d|",n, inet_ntoa(cad.sin_addr), cad.sin_port);
+ for (j = 0; j < n; j++) {
+ fprintf(fout, "%02X-", buff[j]);
+ }
+ }
+ if (n == 1) {
+ alen = sizeof(struct sockaddr);
+ n = sendto(ft->udps, (char*)buff, n, 0,(struct sockaddr *) &toad, alen);
+ if (fout != NULL) {
+ fprintf(fout, "\n|SEND |");
+ for (j = 0; j < n; j++) {
+ fprintf(fout, "%02X-", buff[j]);
+ }
+ }
+ }
+ if (fout != NULL) {
+ fprintf(fout, "\n");
+ fclose(fout);
+ }
+ }
+ }
+ if (ft->udps != INVALID_SOCKET) {
+ closesocket(ft->udps);
+ }
+
+ JabberListRemove(ft->proto, LIST_FILE, ft->iqId);
+ if (ft->state == FT_DONE)
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ else {
+ ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ }
+ JabberLog(ft->proto, "P2P receive thread ended");
+ TlenP2PFreeFileTransfer(ft);
+}
+
+void __cdecl TlenNewFileSendThread(TLEN_FILE_TRANSFER *ft)
+{
+ JabberLog(ft->proto, "P2P send thread started");
+// ft->mode = FT_RECV;
+// ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+// ft->currentFile = 0;
+// ft->state = FT_CONNECTING;
+ {
+ FILE * fout = fopen("tlen_send.gxx", "wt");
+ int step = 0;
+ SOCKADDR_IN toad;
+ toad.sin_family = AF_INET;
+ toad.sin_addr.s_addr = inet_addr(ft->hostName);
+ toad.sin_port = htons(ft->wPort);
+
+ if (fout != NULL) {
+ fprintf(fout, "START:");
+ }
+ if (fout != NULL) {
+ fclose(fout);
+ }
+ for (step = 0; step < 10; step ++) {
+// while (ft->udps != INVALID_SOCKET) {
+ int alen;
+ int j, n;
+ unsigned char buff[1024];
+ alen = sizeof(struct sockaddr);
+ if (step < 3 || step > 5) {
+ buff[0] = 1;
+ n = 1;
+ } else {
+ buff[0] = '$';
+ buff[1] = '^';
+ buff[2] = '&';
+ buff[3] = '%';
+ n = 4;
+ }
+ n=sendto(ft->udps, (char*)buff, n, 0, (struct sockaddr *)&toad, alen);
+ logInfo("tlen_send.dxx", "UDP");
+ if (fout != NULL) {
+ fprintf(fout, "|send: %d %s %d|",n, inet_ntoa(toad.sin_addr), toad.sin_port);
+ for (j = 0; j < n; j++) {
+ fprintf(fout, "%02X-", buff[j]);
+ }
+ }
+ if (fout != NULL) {
+ fprintf(fout, "\n");
+ fclose(fout);
+ }
+ SleepEx(1000, TRUE);
+ }
+ }
+ JabberLog(ft->proto, "P2P send thread ended");
+}
+
+void TlenBindUDPSocket(TLEN_FILE_TRANSFER *ft)
+{
+ JabberLog(ft->proto, "Binding UDP socket");
+ ft->udps = socket(PF_INET, SOCK_DGRAM, 0);
+ if (ft->udps != INVALID_SOCKET) {
+ SOCKADDR_IN sin;
+ int len = sizeof(struct sockaddr);
+ memset((char *)&sin,0,sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);;
+ sin.sin_port = 0;
+ if (bind(ft->udps, (struct sockaddr *)&sin, sizeof(sin)) >= 0) {
+ if (!getsockname((SOCKET)ft->udps,(SOCKADDR *)&sin,&len)) {
+ struct hostent *hp;
+ char host_name[256];
+ gethostname(host_name, sizeof(host_name));
+ hp = gethostbyname(host_name);
+ mir_snprintf(host_name, sizeof(host_name), "%u.%u.%u.%u", (unsigned char)hp->h_addr_list[0][0],
+ (unsigned char)hp->h_addr_list[0][1],
+ (unsigned char)hp->h_addr_list[0][2],
+ (unsigned char)hp->h_addr_list[0][3]);
+
+ ft->wLocalPort = ntohs(sin.sin_port);
+ ft->localName= mir_strdup(host_name);
+ JabberLog(ft->proto, "UDP socket bound to %s:%d", ft->localName, ft->wLocalPort);
+ }
+ }
+ }
+}
+
+
+/*
+aaa sends a file to bbb:
+
+1) aaa wants to SEND bbb a file
+A SEND: <iq to='bbb@tlen.pl'><query xmlns='p2p'><fs t="bbb@tlen.pl" e="1" i="179610858" c="1" s="308278" v="2" /></query></iq>
+B RECV: <iq from='aaa@tlen.pl'><query xmlns='p2p'><fs t="bbb@tlen.pl" e="1" i="179610858" c="1" s="308278" v="2" /></query></iq>
+
+2) bbb ACCEPTs
+B SEND: <iq to='aaa@tlen.pl'><query xmlns='p2p'><fs t="aaa@tlen.pl" e="5" i="179610858" v="2" /></query></iq>
+A RECV: <iq from='bbb@tlen.pl'><query xmlns='p2p'><fs t="aaa@tlen.pl" e="5" i="179610858" v="2" /></query></iq>
+
+3) aaa tries to establish p2p connection:
+A SEND: <iq to='bbb@tlen.pl'><query xmlns='p2p'><dcng n='file_send' k='5' v='2' s='1' i='179610858' ck='rNbjnfRSQwJyaI+oRAXmfQ==' ks='16' iv='MAfaCCrqtuU2Ngw=rNbjnfRSQwJyaI+oRAXmfQ==' mi='24835584'/></query></iq>
+B SEND: <iq from='aaa@tlen.pl'><query xmlns='p2p'><dcng n='file_send' k='5' v='2' s='1' i='179610858' ck='rNbjnfRSQwJyaI+oRAXmfQ==' ks='16' iv='MAfaCCrqtuU2Ngw=rNbjnfRSQwJyaI+oRAXmfQ==' mi='24835584'/></query></iq>
+
+3) bbb sends IP/port details
+B SEND: <iq to='bbb@tlen.pl'><query xmlns='p2p'><dcng la='xx.xx.xx.xx' lp='nnn' pa='xx.xx.xx.xx' pp='nnn' i='179610858' v='2' k='5' s='2'/></query></iq>
+
+*/
+
+void __cdecl TlenProcessP2P(XmlNode *node, ThreadData *info) {
+ XmlNode *queryNode;
+ JABBER_LIST_ITEM *item;
+ char *from;
+
+ if (info == NULL) return;
+
+ queryNode = JabberXmlGetChild(node, "query");
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ XmlNode *fs , *vs, *dcng, *dc;
+ /* file send */
+ fs = JabberXmlGetChild(queryNode, "fs");
+ /* voice send */
+ vs = JabberXmlGetChild(queryNode, "vs");
+ dcng = JabberXmlGetChild(queryNode, "dcng");
+ dc = JabberXmlGetChild(queryNode, "dc");
+ if (fs != NULL) {
+ char *e, *id;
+ /* e - step in the process (starting with 1)*/
+ /* i - id of the file */
+ /* s - size of the file */
+ /* c - number of files */
+ /* v - ??? */
+ e = JabberXmlGetAttrValue(fs, "e");
+ id = JabberXmlGetAttrValue(fs, "i");
+ if (e != NULL) {
+ if (!strcmp(e, "1")) {
+ char *c, *s;
+ TLEN_FILE_TRANSFER * ft = (TLEN_FILE_TRANSFER *) mir_alloc(sizeof(TLEN_FILE_TRANSFER));
+ memset(ft, 0, sizeof(TLEN_FILE_TRANSFER));
+ c = JabberXmlGetAttrValue(fs, "c");
+ s = JabberXmlGetAttrValue(fs, "s");
+ ft->jid = mir_strdup(from);
+ ft->proto = info->proto;
+ ft->hContact = JabberHContactFromJID(info->proto, from);
+ ft->iqId = mir_strdup(id);
+ ft->fileTotalSize = atoi(s);
+ ft->newP2P = TRUE;
+ if ((item=JabberListAdd(ft->proto, LIST_FILE, ft->iqId)) != NULL) {
+ char fileInfo[128];
+ item->ft = ft;
+ mir_snprintf(fileInfo, sizeof(fileInfo), "%s file(s), %s bytes", c, s);
+ TCHAR* filenameT = mir_utf8decodeT((char*)fileInfo);
+ PROTORECVFILET pre = {0};
+ pre.flags = PREF_TCHAR;
+ pre.fileCount = 1;
+ pre.timestamp = time(NULL);
+ pre.tszDescription = filenameT;
+ pre.ptszFiles = &filenameT;
+ pre.lParam = (LPARAM)ft;
+ JabberLog(ft->proto, "sending chainrecv");
+ CCSDATA ccs = { ft->hContact, PSR_FILE, 0, (LPARAM)&pre };
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
+ mir_free(filenameT);
+ }
+ } else if (!strcmp(e, "3")) {
+ /* transfer error */
+ } else if (!strcmp(e, "4")) {
+ /* transfer denied */
+ } else if (!strcmp(e, "5")) {
+ /* transfer accepted */
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) {
+ item->id2 = mir_strdup("84273372");
+ item->ft->id2 = mir_strdup("84273372");
+ JabberSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng n='file_send' k='5' v='2' s='1' i='%s' ck='o7a32V9n2UZYCWpBUhSbFw==' ks='16' iv='MhjWEj9WTsovrQc=o7a32V9n2UZYCWpBUhSbFw==' mi='%s'/></query></iq>", from, item->id2, id);
+ }
+ }
+ }
+ } else if (vs != NULL) {
+
+ } else if (dcng != NULL) {
+ char *s, *id, *id2;
+ JabberLog(info->proto, "DCNG");
+ s = JabberXmlGetAttrValue(dcng, "s");
+ id2 = JabberXmlGetAttrValue(dcng, "i");
+ id = JabberXmlGetAttrValue(dcng, "mi");
+ if (!strcmp(s, "1")) {
+ /* Keys */
+ /* n - name (file_send) */
+ /* k - ??? */
+ /* v - ??? */
+ /* s - step */
+ /* i - id of the file */
+ /* ck - aes key */
+ /* ks - key size (in bytes) */
+ /* iv - aes initial vector */
+ /* mi - p2p connection id */
+ char *n, *k, *v, *ck, *iv;
+ n = JabberXmlGetAttrValue(dcng, "n");
+ k = JabberXmlGetAttrValue(dcng, "k");
+ v = JabberXmlGetAttrValue(dcng, "v");
+ ck = JabberXmlGetAttrValue(dcng, "ck");
+ iv = JabberXmlGetAttrValue(dcng, "iv");
+ if (!strcmp(n, "file_send")) {
+ if ((item=JabberListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) {
+ item->id2 = mir_strdup(id2);
+ item->ft->id2 = mir_strdup(id2);
+ TlenBindUDPSocket(item->ft);
+ JabberSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng la='%s' lp='%d' pa='%s' pp='%d' i='%s' v='2' k='5' s='2'/></query></iq>",
+ item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2);
+ }
+ }
+ } else if (!strcmp(s, "2")) {
+ JabberLog(info->proto, "step = 2");
+ JabberLog(info->proto, "%s",from);
+ JabberLog(info->proto, "%s",id2);
+ /* IP and port */
+ if ((item=JabberListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) {
+ item->ft->hostName = mir_strdup(JabberXmlGetAttrValue(dcng, "pa"));
+ item->ft->wPort = atoi(JabberXmlGetAttrValue(dcng, "pp"));
+ TlenBindUDPSocket(item->ft);
+ JabberSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng la='%s' lp='%d' pa='%s' pp='%d' i='%s' k='5' s='4'/></query></iq>",
+ item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2);
+ JabberForkThread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft);
+ JabberForkThread((void (__cdecl *)(void*))TlenNewFileSendThread, 0, item->ft);
+ }
+ } else if (!strcmp(s, "4")) {
+ /* IP and port */
+ if ((item=JabberListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) {
+ JabberLog(info->proto, "step = 4");
+ item->ft->hostName = mir_strdup(JabberXmlGetAttrValue(dcng, "pa"));
+ item->ft->wPort = atoi(JabberXmlGetAttrValue(dcng, "pp"));
+ JabberForkThread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft);
+ }
+ }
+
+ } else if (dc != NULL) {
+
+ }
+ }
+}
diff --git a/protocols/Tlen/src/tlen_p2p_old.cpp b/protocols/Tlen/src/tlen_p2p_old.cpp
new file mode 100644
index 0000000000..7c1f706d49
--- /dev/null
+++ b/protocols/Tlen/src/tlen_p2p_old.cpp
@@ -0,0 +1,535 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "tlen_p2p_old.h"
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "jabber_list.h"
+
+
+void TlenP2PFreeFileTransfer(TLEN_FILE_TRANSFER *ft)
+{
+ int i;
+ if (ft->jid) mir_free(ft->jid);
+ if (ft->iqId) mir_free(ft->iqId);
+ if (ft->id2) mir_free(ft->id2);
+ if (ft->hostName) mir_free(ft->hostName);
+ if (ft->localName) mir_free(ft->localName);
+ if (ft->szSavePath) mir_free(ft->szSavePath);
+ if (ft->szDescription) mir_free(ft->szDescription);
+ if (ft->filesSize) mir_free(ft->filesSize);
+ if (ft->files) {
+ for (i=0; i<ft->fileCount; i++) {
+ if (ft->files[i]) mir_free(ft->files[i]);
+ }
+ mir_free(ft->files);
+ }
+ mir_free(ft);
+}
+
+TLEN_FILE_PACKET *TlenP2PPacketCreate(int datalen)
+{
+ TLEN_FILE_PACKET *packet;
+
+ if ((packet=(TLEN_FILE_PACKET *) mir_alloc(sizeof(TLEN_FILE_PACKET))) == NULL)
+ return NULL;
+ packet->packet = NULL;
+ if (datalen > 0) {
+ if ((packet->packet=(char *) mir_alloc(datalen)) == NULL) {
+ mir_free(packet);
+ return NULL;
+ }
+ }
+ packet->maxDataLen = datalen;
+ packet->type=0;
+ packet->len=0;
+ return packet;
+}
+
+void TlenP2PPacketFree(TLEN_FILE_PACKET *packet)
+{
+ if (packet != NULL) {
+ if (packet->packet != NULL)
+ mir_free(packet->packet);
+ mir_free(packet);
+ }
+}
+
+void TlenP2PPacketSetType(TLEN_FILE_PACKET *packet, DWORD type)
+{
+ if (packet != NULL) {
+ packet->type = type;
+ }
+}
+
+void TlenP2PPacketSetLen(TLEN_FILE_PACKET *packet, DWORD len)
+{
+ if (packet != NULL) {
+ packet->len = len;
+ }
+}
+
+void TlenP2PPacketPackDword(TLEN_FILE_PACKET *packet, DWORD data)
+{
+ if (packet != NULL && packet->packet != NULL) {
+ if (packet->len + sizeof(DWORD) <= packet->maxDataLen) {
+ (*((DWORD*)((packet->packet)+(packet->len)))) = data;
+ packet->len += sizeof(DWORD);
+ }
+ }
+}
+
+void TlenP2PPacketPackBuffer(TLEN_FILE_PACKET *packet, char *buffer, int len)
+{
+ if (packet != NULL && packet->packet != NULL) {
+ if (packet->len + len <= packet->maxDataLen) {
+ memcpy((packet->packet)+(packet->len), buffer, len);
+ packet->len += len;
+ }
+ }
+}
+
+void TlenP2PInit() {
+}
+
+void TlenP2PUninit() {
+}
+
+int TlenP2PPacketSend(JABBER_SOCKET s, TLEN_FILE_PACKET *packet)
+{
+ DWORD sendResult;
+ if (packet != NULL && packet->packet != NULL) {
+ Netlib_Send(s, (char *)&packet->type, 4, MSG_NODUMP);
+ Netlib_Send(s, (char *)&packet->len, 4, MSG_NODUMP);
+ sendResult=Netlib_Send(s, packet->packet, packet->len, MSG_NODUMP);
+ if (sendResult == SOCKET_ERROR || sendResult != packet->len) return 0;
+ }
+ return 1;
+}
+
+TLEN_FILE_PACKET* TlenP2PPacketReceive(JABBER_SOCKET s)
+{
+ TLEN_FILE_PACKET *packet;
+ DWORD recvResult;
+ DWORD type, len, pos;
+ recvResult = Netlib_Recv(s, (char *)&type, 4, MSG_NODUMP);
+ if (recvResult == 0 || recvResult == SOCKET_ERROR) return NULL;
+ recvResult = Netlib_Recv(s, (char *)&len, 4, MSG_NODUMP);
+ if (recvResult == 0 || recvResult == SOCKET_ERROR) return NULL;
+ packet = TlenP2PPacketCreate(len);
+ TlenP2PPacketSetType(packet, type);
+ TlenP2PPacketSetLen(packet, len);
+ pos = 0;
+ while (len > 0) {
+ recvResult = Netlib_Recv(s, packet->packet+pos, len, MSG_NODUMP);
+ if (recvResult == 0 || recvResult == SOCKET_ERROR) {
+ TlenP2PPacketFree(packet);
+ return NULL;
+ }
+ len -= recvResult;
+ pos += recvResult;
+ }
+ return packet;
+}
+
+void TlenP2PEstablishOutgoingConnection(TLEN_FILE_TRANSFER *ft, BOOL sendAck)
+{
+ char *hash;
+ char str[300];
+ TLEN_FILE_PACKET *packet;
+ TlenProtocol *proto = ft->proto;
+
+ JabberLog(proto, "Establishing outgoing connection.");
+ ft->state = FT_ERROR;
+ if ((packet = TlenP2PPacketCreate(2*sizeof(DWORD) + 20)) != NULL) {
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_CONNECTION_REQUEST);
+ TlenP2PPacketPackDword(packet, 1);
+ TlenP2PPacketPackDword(packet, (DWORD) atoi(ft->iqId));
+ _snprintf(str, sizeof(str), "%08X%s%d", atoi(ft->iqId), proto->threadData->username, atoi(ft->iqId));
+ hash = TlenSha1(str, (int)strlen(str));
+ TlenP2PPacketPackBuffer(packet, hash, 20);
+ mir_free(hash);
+ TlenP2PPacketSend(ft->s, packet);
+ TlenP2PPacketFree(packet);
+ packet = TlenP2PPacketReceive(ft->s);
+ if (packet != NULL) {
+ if (packet->type == TLEN_FILE_PACKET_CONNECTION_REQUEST_ACK) { // acknowledge
+ if ((int)(*((DWORD*)packet->packet)) == atoi(ft->iqId)) {
+ ft->state = FT_CONNECTING;
+ if (sendAck) {
+ ProtoBroadcastAck(proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, ft, 0);
+ }
+ }
+ }
+ TlenP2PPacketFree(packet);
+ }
+ }
+}
+
+TLEN_FILE_TRANSFER* TlenP2PEstablishIncomingConnection(TlenProtocol *proto, JABBER_SOCKET s, JABBER_LIST list, BOOL sendAck)
+{
+ JABBER_LIST_ITEM *item = NULL;
+ TLEN_FILE_PACKET *packet;
+ int i;
+ char str[300];
+ DWORD iqId;
+ // TYPE: 0x1
+ // LEN:
+ // (DWORD) 0x1
+ // (DWORD) id
+ // (BYTE) hash[20]
+ packet = TlenP2PPacketReceive(s);
+ if (packet == NULL || packet->type != TLEN_FILE_PACKET_CONNECTION_REQUEST || packet->len<28) {
+ if (packet != NULL) {
+ TlenP2PPacketFree(packet);
+ }
+ return NULL;
+ }
+ iqId = *((DWORD *)(packet->packet+sizeof(DWORD)));
+ i = 0;
+ while ((i=JabberListFindNext(proto, list, i)) >= 0) {
+ if ((item=JabberListGetItemPtrFromIndex(proto, i)) != NULL) {
+ _snprintf(str, sizeof(str), "%d", iqId);
+ if (!strcmp(item->ft->iqId, str)) {
+ char *hash, *nick;
+ int j;
+ nick = JabberNickFromJID(item->ft->jid);
+ _snprintf(str, sizeof(str), "%08X%s%d", iqId, nick, iqId);
+ mir_free(nick);
+ hash = TlenSha1(str, (int)strlen(str));
+ for (j=0;j<20;j++) {
+ if (hash[j] != packet->packet[2*sizeof(DWORD)+j]) break;
+ }
+ mir_free(hash);
+ if (j == 20) break;
+ }
+ }
+ i++;
+ }
+ TlenP2PPacketFree(packet);
+ if (i >=0) {
+ if ((packet=TlenP2PPacketCreate(sizeof(DWORD))) != NULL) {
+ // Send connection establishment acknowledgement
+ TlenP2PPacketSetType(packet, TLEN_FILE_PACKET_CONNECTION_REQUEST_ACK);
+ TlenP2PPacketPackDword(packet, (DWORD) atoi(item->ft->iqId));
+ TlenP2PPacketSend(s, packet);
+ TlenP2PPacketFree(packet);
+ item->ft->state = FT_CONNECTING;
+ if (sendAck) {
+ ProtoBroadcastAck(item->ft->proto->m_szModuleName, item->ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, item->ft, 0);
+ }
+ return item->ft;
+ }
+ }
+ return NULL;
+}
+
+static void __cdecl TlenFileBindSocks4Thread(TLEN_FILE_TRANSFER* ft)
+{
+ BYTE buf[8];
+ int status;
+
+// JabberLog("Waiting for the file to be sent via SOCKS...");
+ status = Netlib_Recv(ft->s, (char*)buf, 8, MSG_NODUMP);
+// JabberLog("accepted connection !!!");
+ if ( status == SOCKET_ERROR || status < 8 || buf[1] != 90) {
+ status = 1;
+ } else {
+ status = 0;
+ }
+ if (!status) {
+ ft->pfnNewConnectionV2(ft->s, 0, NULL);
+ } else {
+ if (ft->state != FT_SWITCH) {
+ ft->state = FT_ERROR;
+ }
+ }
+ JabberLog(ft->proto, "Closing connection for this file transfer...");
+// Netlib_CloseHandle(ft->s);
+ if (ft->hFileEvent != NULL)
+ SetEvent(ft->hFileEvent);
+
+}
+static void __cdecl TlenFileBindSocks5Thread(TLEN_FILE_TRANSFER* ft)
+{
+ BYTE buf[256];
+ int status;
+
+// JabberLog("Waiting for the file to be sent via SOCKS...");
+ status = Netlib_Recv(ft->s, (char*)buf, sizeof(buf), MSG_NODUMP);
+// JabberLog("accepted connection !!!");
+ if ( status == SOCKET_ERROR || status < 7 || buf[1] != 0) {
+ status = 1;
+ } else {
+ status = 0;
+ }
+ if (!status) {
+ ft->pfnNewConnectionV2(ft->s, 0, NULL);
+ } else {
+ if (ft->state != FT_SWITCH) {
+ ft->state = FT_ERROR;
+ }
+ }
+// JabberLog("Closing connection for this file transfer...");
+// Netlib_CloseHandle(ft->s);
+ if (ft->hFileEvent != NULL)
+ SetEvent(ft->hFileEvent);
+
+}
+
+static JABBER_SOCKET TlenP2PBindSocks4(SOCKSBIND * sb, TLEN_FILE_TRANSFER *ft)
+{ //rfc1928
+ int len;
+ BYTE buf[256];
+ int status;
+ struct in_addr in;
+ NETLIBOPENCONNECTION nloc;
+ JABBER_SOCKET s;
+
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = sb->szHost;
+ nloc.wPort = sb->wPort;
+ nloc.flags = 0;
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hFileNetlibUser, (LPARAM) &nloc);
+ if (s == NULL) {
+// JabberLog("Connection failed (%d), thread ended", WSAGetLastError());
+ return NULL;
+ }
+ buf[0] = 4; //socks4
+ buf[1] = 2; //2-bind, 1-connect
+ *(PWORD)(buf+2) = htons(0); // port
+ *(PDWORD)(buf+4) = INADDR_ANY;
+ if (sb->useAuth) {
+ strcpy((char*)buf+8, sb->szUser);
+ len = (int)strlen(sb->szUser);
+ } else {
+ buf[8] = 0;
+ len = 0;
+ }
+ len += 9;
+ status = Netlib_Send(s, (char*)buf, len, MSG_NODUMP);
+ if (status == SOCKET_ERROR || status < len) {
+// JabberLog("Send failed (%d), thread ended", WSAGetLastError());
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ status = Netlib_Recv(s, (char*)buf, 8, MSG_NODUMP);
+ if (status == SOCKET_ERROR || status < 8 || buf[1] != 90) {
+// JabberLog("SOCKS4 negotiation failed");
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ status = Netlib_Recv(s, (char*)buf, sizeof(buf), MSG_NODUMP);
+ if ( status == SOCKET_ERROR || status < 7 || buf[0] != 5 || buf[1] != 0) {
+// JabberLog("SOCKS5 request failed");
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ in.S_un.S_addr = *(PDWORD)(buf+4);
+ strcpy(sb->szHost, inet_ntoa(in));
+ sb->wPort = htons(*(PWORD)(buf+2));
+ ft->s = s;
+ JabberForkThread((void (__cdecl *)(void*))TlenFileBindSocks4Thread, 0, ft);
+ return s;
+}
+
+static JABBER_SOCKET TlenP2PBindSocks5(SOCKSBIND * sb, TLEN_FILE_TRANSFER *ft)
+{ //rfc1928
+ BYTE buf[512];
+ int len, status;
+ NETLIBOPENCONNECTION nloc;
+ struct in_addr in;
+ JABBER_SOCKET s;
+
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = sb->szHost;
+ nloc.wPort = sb->wPort;
+ nloc.flags = 0;
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hFileNetlibUser, (LPARAM) &nloc);
+ if (s == NULL) {
+ JabberLog(ft->proto, "Connection failed (%d), thread ended", WSAGetLastError());
+ return NULL;
+ }
+ buf[0] = 5; //yep, socks5
+ buf[1] = 1; //one auth method
+ buf[2] = sb->useAuth?2:0; // authorization
+ status = Netlib_Send(s, (char*)buf, 3, MSG_NODUMP);
+ if (status == SOCKET_ERROR || status < 3) {
+ JabberLog(ft->proto, "Send failed (%d), thread ended", WSAGetLastError());
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ status = Netlib_Recv(s, (char*)buf, 2, MSG_NODUMP);
+ if (status == SOCKET_ERROR || status < 2 || (buf[1] != 0 && buf[1] != 2)) {
+ JabberLog(ft->proto, "SOCKS5 negotiation failed");
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ if (buf[1] == 2) { //rfc1929
+ int nUserLen, nPassLen;
+ PBYTE pAuthBuf;
+
+ nUserLen = (int)strlen(sb->szUser);
+ nPassLen = (int)strlen(sb->szPassword);
+ pAuthBuf = (PBYTE)mir_alloc(3+nUserLen+nPassLen);
+ pAuthBuf[0] = 1; //auth version
+ pAuthBuf[1] = nUserLen;
+ memcpy(pAuthBuf+2, sb->szUser, nUserLen);
+ pAuthBuf[2+nUserLen]=nPassLen;
+ memcpy(pAuthBuf+3+nUserLen,sb->szPassword,nPassLen);
+ status = Netlib_Send(s, (char*)pAuthBuf, 3+nUserLen+nPassLen, MSG_NODUMP);
+ mir_free(pAuthBuf);
+ if (status == SOCKET_ERROR || status < 3 + nUserLen+nPassLen) {
+ JabberLog(ft->proto, "Send failed (%d), thread ended", WSAGetLastError());
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ status = Netlib_Recv(s, (char*)buf, sizeof(buf), MSG_NODUMP);
+ if (status == SOCKET_ERROR || status < 2 || buf[1] != 0) {
+ JabberLog(ft->proto, "SOCKS5 sub-negotiation failed");
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ }
+
+ { PBYTE pInit;
+ int nHostLen=4;
+ DWORD hostIP=INADDR_ANY;
+ pInit=(PBYTE)mir_alloc(6+nHostLen);
+ pInit[0]=5; //SOCKS5
+ pInit[1]=2; //bind
+ pInit[2]=0; //reserved
+ pInit[3]=1;
+ *(PDWORD)(pInit+4)=hostIP;
+ *(PWORD)(pInit+4+nHostLen)=htons(0);
+ status = Netlib_Send(s, (char*)pInit, 6+nHostLen, MSG_NODUMP);
+ mir_free(pInit);
+ if (status == SOCKET_ERROR || status < 6 + nHostLen) {
+// JabberLog("Send failed (%d), thread ended", WSAGetLastError());
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ }
+ status = Netlib_Recv(s, (char*)buf, sizeof(buf), MSG_NODUMP);
+ if ( status == SOCKET_ERROR || status < 7 || buf[0] != 5 || buf[1] != 0) {
+// JabberLog("SOCKS5 request failed");
+ Netlib_CloseHandle(s);
+ return NULL;
+ }
+ if (buf[2] == 1) { // domain
+ len = buf[4];
+ memcpy(sb->szHost, buf+5, len);
+ sb->szHost[len]=0;
+ len += 4;
+ } else { // ip address
+ in.S_un.S_addr = *(PDWORD)(buf+4);
+ strcpy(sb->szHost, inet_ntoa(in));
+ len = 8;
+ }
+ sb->wPort = htons(*(PWORD)(buf+len));
+ ft->s = s;
+
+ JabberForkThread((void (__cdecl *)(void*))TlenFileBindSocks5Thread, 0, ft);
+ return s;
+}
+
+
+JABBER_SOCKET TlenP2PListen(TLEN_FILE_TRANSFER *ft)
+{
+ NETLIBBIND nlb = {0};
+ JABBER_SOCKET s = NULL;
+ int useProxy;
+ DBVARIANT dbv;
+ SOCKSBIND sb;
+ struct in_addr in;
+ TlenProtocol *proto = ft->proto;
+ useProxy=0;
+ if (ft->localName != NULL) mir_free(ft->localName);
+ ft->localName = NULL;
+ ft->wPort = 0;
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "UseFileProxy", FALSE)) {
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "FileProxyHost", &dbv)) {
+ strcpy(sb.szHost, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ sb.wPort = DBGetContactSettingWord(NULL, proto->m_szModuleName, "FileProxyPort", 0);
+ sb.useAuth = FALSE;
+ strcpy(sb.szUser, "");
+ strcpy(sb.szPassword, "");
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "FileProxyAuth", FALSE)) {
+ sb.useAuth = TRUE;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "FileProxyUsername", &dbv)) {
+ strcpy(sb.szUser, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "FileProxyPassword", &dbv)) {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM) dbv.pszVal);
+ strcpy(sb.szPassword, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ switch (DBGetContactSettingWord(NULL, proto->m_szModuleName, "FileProxyType", 0)) {
+ case 0: // forwarding
+ useProxy = 1;
+ break;
+ case 1: // socks4
+ s = TlenP2PBindSocks4(&sb, ft);
+ useProxy = 2;
+ break;
+ case 2: // socks5
+ s = TlenP2PBindSocks5(&sb, ft);
+ useProxy = 2;
+ break;
+ }
+ ft->localName = mir_strdup(sb.szHost);
+ ft->wPort = sb.wPort;
+ ft->wLocalPort = sb.wPort;
+ }
+ }
+ if (useProxy<2) {
+ nlb.cbSize = sizeof(NETLIBBIND);
+ nlb.pfnNewConnectionV2 = ft->pfnNewConnectionV2;
+ nlb.wPort = 0; // Use user-specified incoming port ranges, if available
+ nlb.pExtra = proto;
+ JabberLog(ft->proto, "Calling MS_NETLIB_BINDPORT");
+ s = (HANDLE) CallService(MS_NETLIB_BINDPORT, (WPARAM) ft->proto->hNetlibUser, (LPARAM) &nlb);
+ JabberLog(ft->proto, "listening on %d",s);
+ }
+ if (useProxy == 0) {
+ in.S_un.S_addr = htonl(nlb.dwExternalIP);
+ ft->localName = mir_strdup(inet_ntoa(in));
+ ft->wPort = nlb.wPort;
+ ft->wLocalPort = nlb.wExPort;
+ }
+ if (s != NULL) {
+// listenCount++;
+ }
+ return s;
+}
+
+void TlenP2PStopListening(JABBER_SOCKET s) {
+ if (s != NULL) {
+// listenCount--;
+// if (listenCount <= 0) {
+// Netlib_CloseHandle(s);
+// }
+ }
+}
diff --git a/protocols/Tlen/src/tlen_p2p_old.h b/protocols/Tlen/src/tlen_p2p_old.h
new file mode 100644
index 0000000000..4e2305310f
--- /dev/null
+++ b/protocols/Tlen/src/tlen_p2p_old.h
@@ -0,0 +1,70 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+
+#ifndef _TLEN_P2P_OLD_H_
+#define _TLEN_P2P_OLD_H_
+
+enum {
+ TLEN_FILE_PACKET_CONNECTION_REQUEST = 0x01,
+ TLEN_FILE_PACKET_CONNECTION_REQUEST_ACK = 0x02,
+ TLEN_FILE_PACKET_FILE_LIST = 0x32,
+ TLEN_FILE_PACKET_FILE_LIST_ACK = 0x33,
+ TLEN_FILE_PACKET_FILE_REQUEST = 0x34,
+ TLEN_FILE_PACKET_FILE_DATA = 0x35,
+ TLEN_FILE_PACKET_END_OF_FILE = 0x37,
+ TLEN_VOICE_PACKET = 0x96
+};
+
+typedef struct {
+ unsigned int maxDataLen;
+ char *packet;
+ DWORD type;
+ DWORD len;
+} TLEN_FILE_PACKET;
+
+typedef struct {
+ char szHost[256];
+ int wPort;
+ int useAuth;
+ char szUser[256];
+ char szPassword[256];
+}SOCKSBIND;
+
+extern void TlenP2PFreeFileTransfer(TLEN_FILE_TRANSFER *ft);
+extern TLEN_FILE_PACKET *TlenP2PPacketCreate(int datalen);
+extern void TlenP2PPacketFree(TLEN_FILE_PACKET *packet);
+extern void TlenP2PPacketSetType(TLEN_FILE_PACKET *packet, DWORD type);
+extern void TlenP2PPacketSetLen(TLEN_FILE_PACKET *packet, DWORD len);
+extern void TlenP2PPacketPackDword(TLEN_FILE_PACKET *packet, DWORD data);
+extern void TlenP2PPacketPackBuffer(TLEN_FILE_PACKET *packet, char *buffer, int len);
+extern int TlenP2PPacketSend(JABBER_SOCKET s, TLEN_FILE_PACKET *packet);
+extern TLEN_FILE_PACKET* TlenP2PPacketReceive(JABBER_SOCKET s);
+extern void TlenP2PEstablishOutgoingConnection(TLEN_FILE_TRANSFER *ft, BOOL sendAck);
+extern TLEN_FILE_TRANSFER* TlenP2PEstablishIncomingConnection(TlenProtocol *proto, JABBER_SOCKET s, JABBER_LIST list, BOOL sendAck);
+extern JABBER_SOCKET TlenP2PListen(TLEN_FILE_TRANSFER *ft);
+extern void TlenP2PStopListening(JABBER_SOCKET s);
+
+void __cdecl TlenProcessP2P(XmlNode *node, void *userdata);
+
+
+#endif
diff --git a/protocols/Tlen/src/tlen_picture.cpp b/protocols/Tlen/src/tlen_picture.cpp
new file mode 100644
index 0000000000..1120b23839
--- /dev/null
+++ b/protocols/Tlen/src/tlen_picture.cpp
@@ -0,0 +1,320 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2009 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include "tlen_file.h"
+#include "tlen_p2p_old.h"
+
+typedef struct {
+ TlenProtocol *proto;
+ JABBER_LIST_ITEM *item;
+} TLENPSREQUESTTHREADDATA;
+
+static void LogPictureMessage(TlenProtocol *proto, const char *jid, const char *filename, BOOL isSent)
+{
+ char message[1024];
+ const char *msg = isSent ? "Image sent file://%s" : "Image received file://%s";
+ _snprintf(message, sizeof(message), Translate(msg), filename);
+ TlenLogMessage(proto, JabberHContactFromJID(proto, jid), isSent ? DBEF_SENT : 0, message);
+}
+
+static void TlenPsPostThread(void *ptr) {
+ TLENPSREQUESTTHREADDATA *data = (TLENPSREQUESTTHREADDATA *)ptr;
+ TlenProtocol *proto = data->proto;
+ JABBER_LIST_ITEM *item = data->item;
+ JABBER_SOCKET socket = JabberWsConnect(proto, "ps.tlen.pl", 443);
+ BOOL bSent = FALSE;
+ if (socket != NULL) {
+ char header[512];
+ DWORD ret;
+ item->ft->s = socket;
+ item->ft->hFileEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ _snprintf(header, sizeof(header), "<pic auth='%s' t='p' to='%s' size='%d' idt='%s'/>", proto->threadData->username, item->ft->jid, item->ft->fileTotalSize, item->jid);
+ JabberWsSend(proto, socket, header, (int)strlen(header));
+ ret = WaitForSingleObject(item->ft->hFileEvent, 1000 * 60 * 5);
+ if (ret == WAIT_OBJECT_0) {
+ FILE *fp = fopen( item->ft->files[0], "rb" );
+ if (fp) {
+ int i;
+ char header[512];
+ char fileBuffer[2048];
+ _snprintf(header, sizeof(header), "<pic st='%s' idt='%s'/>", item->ft->iqId, item->jid);
+ JabberWsSend(proto, socket, header, (int)strlen(header));
+ JabberLog(proto, "Sending picture data...");
+ for (i = item->ft->filesSize[0]; i > 0; ) {
+ int toread = min(2048, i);
+ int readcount = (int)fread(fileBuffer, (size_t)1, (size_t)toread, fp);
+ i -= readcount;
+ if (readcount > 0) {
+ JabberWsSend(proto, socket, fileBuffer, readcount);
+ }
+ if (toread != readcount) {
+ break;
+ }
+ }
+ fclose(fp);
+ SleepEx(3000, TRUE);
+ bSent = TRUE;
+ } else {
+ /* picture not found */
+ }
+ } else {
+ /* 5 minutes passed */
+ }
+ Netlib_CloseHandle(socket);
+ if (bSent) {
+ JabberSend(proto, "<message to='%s' idt='%s' rt='%s' pid='1001' type='pic' />", item->ft->jid, item->jid, item->ft->id2);
+ LogPictureMessage(proto, item->ft->jid, item->ft->files[0], TRUE);
+ }
+ TlenP2PFreeFileTransfer(item->ft);
+ JabberListRemove(proto, LIST_PICTURE, item->jid);
+ } else {
+ /* cannot connect to ps server */
+ }
+ mir_free(data);
+}
+
+static void TlenPsPost(TlenProtocol *proto, JABBER_LIST_ITEM *item) {
+ TLENPSREQUESTTHREADDATA *threadData = (TLENPSREQUESTTHREADDATA *)mir_alloc(sizeof(TLENPSREQUESTTHREADDATA));
+ threadData->proto = proto;
+ threadData->item = item;
+ JabberForkThread(TlenPsPostThread, 0, threadData);
+}
+
+static void TlenPsGetThread(void *ptr) {
+ TLENPSREQUESTTHREADDATA *data = (TLENPSREQUESTTHREADDATA *)ptr;
+ TlenProtocol *proto = data->proto;
+ JABBER_LIST_ITEM *item = data->item;
+ FILE *fp;
+ fp = fopen( item->ft->files[0], "wb" );
+ if (fp) {
+ JABBER_SOCKET socket = JabberWsConnect(proto, "ps.tlen.pl", 443);
+ if (socket != NULL) {
+ XmlState xmlState;
+ char header[512];
+ char fileBuffer[2048];
+ JabberXmlInitState(&xmlState);
+ _snprintf(header, sizeof(header), "<pic auth='%s' t='g' to='%s' pid='1001' idt='%s' rt='%s'/>", proto->threadData->username, item->ft->jid, item->jid, item->ft->id2);
+ JabberWsSend(proto, socket, header, (int)strlen(header));
+ JabberLog(proto, "Reveiving picture data...");
+ {
+ int totalcount = 0;
+ int size = item->ft->filesSize[0];
+ BOOL bHeader = TRUE;
+ while (TRUE) {
+ int readcount = JabberWsRecv(proto, socket, fileBuffer, 2048 - totalcount);
+ if (readcount == 0) {
+ break;
+ }
+ totalcount += readcount;
+ if (bHeader) {
+ char * tagend = (char*)memchr(fileBuffer, '/', totalcount);
+ tagend = (char*)memchr(tagend + 1, '>', totalcount - (tagend - fileBuffer) - 1);
+ if (tagend != NULL) {
+ int parsed = JabberXmlParse(&xmlState, fileBuffer, tagend - fileBuffer + 1);
+ if (parsed == 0) {
+ continue;
+ }
+ bHeader = FALSE;
+ totalcount -= parsed;
+ memmove(fileBuffer, fileBuffer+parsed, totalcount);
+ }
+ }
+ if (!bHeader) {
+ if (totalcount > 0) {
+ fwrite(fileBuffer, 1, totalcount, fp);
+ size -= totalcount;
+ totalcount = 0;
+ }
+ if (size == 0) {
+ break;
+ }
+ }
+ }
+ }
+ Netlib_CloseHandle(socket);
+ JabberLog(proto, "Picture received...");
+ LogPictureMessage(proto, item->ft->jid, item->ft->files[0], FALSE);
+ } else {
+ /* cannot connect to ps server */
+ }
+ fclose(fp);
+ } else {
+ /* cannot create file */
+ }
+ TlenP2PFreeFileTransfer(item->ft);
+ JabberListRemove(proto, LIST_PICTURE, item->jid);
+ mir_free(data);
+}
+
+static void TlenPsGet(TlenProtocol *proto, JABBER_LIST_ITEM *item) {
+ TLENPSREQUESTTHREADDATA *threadData = (TLENPSREQUESTTHREADDATA *)mir_alloc(sizeof(TLENPSREQUESTTHREADDATA));
+ threadData->proto = proto;
+ threadData->item = item;
+ JabberForkThread(TlenPsGetThread, 0, threadData);
+}
+
+void TlenProcessPic(XmlNode *node, TlenProtocol *proto) {
+ JABBER_LIST_ITEM *item = NULL;
+ char *crc, *crc_c, *idt, *size, *from, *fromRaw, *rt;
+ from = JabberXmlGetAttrValue(node, "from");
+ fromRaw = JabberLoginFromJID(from);
+ idt = JabberXmlGetAttrValue(node, "idt");
+ size = JabberXmlGetAttrValue(node, "size");
+ crc_c = JabberXmlGetAttrValue(node, "crc_c");
+ crc = JabberXmlGetAttrValue(node, "crc");
+ rt = JabberXmlGetAttrValue(node, "rt");
+ if (idt != NULL) {
+ item = JabberListGetItemPtr(proto, LIST_PICTURE, idt);
+ }
+ if (item != NULL) {
+ if (!strcmp(from, "ps")) {
+ char *st = JabberXmlGetAttrValue(node, "st");
+ if (st != NULL) {
+ item->ft->iqId = mir_strdup(st);
+ item->ft->id2 = mir_strdup(rt);
+ if (item->ft->hFileEvent != NULL) {
+ SetEvent(item->ft->hFileEvent);
+ item->ft->hFileEvent = NULL;
+ }
+ }
+ } else if (!strcmp(item->ft->jid, fromRaw)) {
+ if (crc_c != NULL) {
+ if (!strcmp(crc_c, "n")) {
+ /* crc_c = n, picture transfer accepted */
+ TlenPsPost(proto, item);
+ } else if (!strcmp(crc_c, "f")) {
+ /* crc_c = f, picture cached, no need to transfer again */
+ LogPictureMessage(proto, item->ft->jid, item->ft->files[0], TRUE);
+ TlenP2PFreeFileTransfer(item->ft);
+ JabberListRemove(proto, LIST_PICTURE, idt);
+ }
+ } else if (rt != NULL) {
+ item->ft->id2 = mir_strdup(rt);
+ TlenPsGet(proto, item);
+ }
+ }
+ } else if (crc != NULL) {
+ BOOL bAccept = proto->tlenOptions.imagePolicy == TLEN_IMAGES_ACCEPT_ALL || (proto->tlenOptions.imagePolicy == TLEN_IMAGES_IGNORE_NIR && IsAuthorized(proto, from));
+ if (bAccept) {
+ FILE* fp;
+ char fileName[MAX_PATH];
+ char *ext = JabberXmlGetAttrValue(node, "ext");
+ char *tmpPath = Utils_ReplaceVars( "%miranda_userdata%" );
+ int tPathLen = mir_snprintf( fileName, MAX_PATH, "%s\\Images\\Tlen", tmpPath );
+ long oldSize = 0, lSize = atol(size);
+ DWORD dwAttributes = GetFileAttributesA( fileName );
+ if ( dwAttributes == 0xffffffff || ( dwAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 ) {
+ CallService( MS_UTILS_CREATEDIRTREE, 0, ( LPARAM )fileName );
+ }
+ mir_free(tmpPath);
+ fileName[ tPathLen++ ] = '\\';
+ mir_snprintf( fileName + tPathLen, MAX_PATH - tPathLen, "%s.%s", crc, ext );
+ fp = fopen( fileName, "rb" );
+ if (fp) {
+ fseek(fp, 0, SEEK_END);
+ oldSize = ftell(fp);
+ fclose(fp);
+ }
+ if (oldSize != lSize) {
+ item = JabberListAdd(proto, LIST_PICTURE, idt);
+ item->ft = TlenFileCreateFT(proto, from);
+ item->ft->files = (char **) mir_alloc(sizeof(char *));
+ item->ft->filesSize = (long *) mir_alloc(sizeof(long));
+ item->ft->files[0] = mir_strdup(fileName);
+ item->ft->filesSize[0] = lSize;
+ item->ft->fileTotalSize = item->ft->filesSize[0];
+ JabberSend(proto, "<message type='pic' to='%s' crc_c='n' idt='%s'/>", from, idt);
+ } else {
+ JabberSend(proto, "<message type='pic' to='%s' crc_c='f' idt='%s'/>", from, idt);
+ LogPictureMessage(proto, from, fileName, FALSE);
+ }
+ }
+ }
+ mir_free(fromRaw);
+}
+
+BOOL SendPicture(TlenProtocol *proto, HANDLE hContact) {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ char *jid = dbv.pszVal;
+ char szFilter[512];
+ char *szFileName = (char*) mir_alloc(_MAX_PATH);
+ OPENFILENAMEA ofn = {0};
+ CallService( MS_UTILS_GETBITMAPFILTERSTRINGS, ( WPARAM ) sizeof( szFilter ), ( LPARAM )szFilter );
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = NULL;
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.lpstrFile = szFileName;
+ ofn.nMaxFile = _MAX_PATH;
+ ofn.Flags = OFN_FILEMUSTEXIST;
+ szFileName[0] = '\0';
+ if ( GetOpenFileNameA( &ofn )) {
+ long size;
+ FILE* fp = fopen( szFileName, "rb" );
+ if (fp) {
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ if (size > 0 && size < 256*1024) {
+ JABBER_LIST_ITEM *item;
+ mir_sha1_ctx sha;
+ DWORD digest[5];
+ int i;
+ char idStr[10];
+ char fileBuffer[2048];
+ int id = JabberSerialNext(proto);
+ _snprintf(idStr, sizeof(idStr), "%d", id);
+ item = JabberListAdd(proto, LIST_PICTURE, idStr);
+ item->ft = TlenFileCreateFT(proto, jid);
+ item->ft->files = (char **) mir_alloc(sizeof(char *));
+ item->ft->filesSize = (long *) mir_alloc(sizeof(long));
+ item->ft->files[0] = szFileName;
+ item->ft->filesSize[0] = size;
+ item->ft->fileTotalSize = size;
+ fseek(fp, 0, SEEK_SET);
+ mir_sha1_init( &sha );
+ for (i = item->ft->filesSize[0]; i > 0; ) {
+ int toread = min(2048, i);
+ int readcount = (int)fread(fileBuffer, (size_t)1, (size_t)toread, fp);
+ i -= readcount;
+ if (readcount > 0) {
+ mir_sha1_append( &sha, (mir_sha1_byte_t* )fileBuffer, readcount);
+ }
+ if (toread != readcount) {
+ break;
+ }
+ }
+ mir_sha1_finish( &sha, (mir_sha1_byte_t* )digest );
+ JabberSend(proto, "<message type='pic' to='%s' crc='%08x%08x%08x%08x%08x' idt='%s' size='%d' ext='%s'/>", jid,
+ (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3]), (int)htonl(digest[4]), idStr, item->ft->filesSize[0], "jpg");
+ } else {
+ /* file too big */
+ }
+ fclose(fp);
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ return FALSE;
+}
diff --git a/protocols/Tlen/src/tlen_picture.h b/protocols/Tlen/src/tlen_picture.h
new file mode 100644
index 0000000000..ef98b02405
--- /dev/null
+++ b/protocols/Tlen/src/tlen_picture.h
@@ -0,0 +1,33 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2009 Piotr Piastucki
+
+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.
+
+*/
+#ifndef _TLEN_PICTURE_H
+#define _TLEN_PICTURE_H
+
+#include <windows.h>
+#include "jabber.h"
+
+void TlenProcessPic(XmlNode *node, TlenProtocol *proto);
+BOOL SendPicture(TlenProtocol *, HANDLE hContact);
+
+#endif /* _TLEN_PICTURE_H */
+
diff --git a/protocols/Tlen/src/tlen_presence.cpp b/protocols/Tlen/src/tlen_presence.cpp
new file mode 100644
index 0000000000..7dc15f41f6
--- /dev/null
+++ b/protocols/Tlen/src/tlen_presence.cpp
@@ -0,0 +1,318 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2009 Piotr Piastucki
+
+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 "jabber.h"
+#include "jabber_list.h"
+#include "tlen_avatar.h"
+
+void TlenProcessPresence(XmlNode *node, TlenProtocol *proto)
+{
+ HANDLE hContact;
+ XmlNode *showNode, *statusNode;
+ JABBER_LIST_ITEM *item;
+ char *from, *type, *nick, *show;
+ int status, laststatus = ID_STATUS_OFFLINE;
+ char *p;
+
+ if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
+ if (JabberListExist(proto, LIST_CHATROOM, from)); //JabberGroupchatProcessPresence(node, userdata);
+
+ else {
+ type = JabberXmlGetAttrValue(node, "type");
+ item = JabberListGetItemPtr(proto, LIST_ROSTER, from);
+ if (item != NULL) {
+ if (proto->tlenOptions.enableAvatars) {
+ TlenProcessPresenceAvatar(proto, node, item);
+ }
+ }
+ if (type == NULL || (!strcmp(type, "available"))) {
+ if ((nick=JabberLocalNickFromJID(from)) != NULL) {
+ if ((hContact=JabberHContactFromJID(proto, from)) == NULL)
+ hContact = JabberDBCreateContact(proto, from, nick, FALSE);
+ if (!JabberListExist(proto, LIST_ROSTER, from)) {
+ JabberLog(proto, "Receive presence online from %s (who is not in my roster)", from);
+ JabberListAdd(proto, LIST_ROSTER, from);
+ }
+ status = ID_STATUS_ONLINE;
+ if ((showNode=JabberXmlGetChild(node, "show")) != NULL) {
+ if ((show=showNode->text) != NULL) {
+ if (!strcmp(show, "away")) status = ID_STATUS_AWAY;
+ else if (!strcmp(show, "xa")) status = ID_STATUS_NA;
+ else if (!strcmp(show, "dnd")) status = ID_STATUS_DND;
+ else if (!strcmp(show, "chat")) status = ID_STATUS_FREECHAT;
+ else if (!strcmp(show, "unavailable")) {
+ // Always show invisible (on old Tlen client) as invisible (not offline)
+ status = ID_STATUS_OFFLINE;
+ }
+ }
+ }
+
+ statusNode = JabberXmlGetChild(node, "status");
+ if (statusNode)
+ p = JabberTextDecode(statusNode->text);
+ else
+ p = NULL;
+ JabberListAddResource(proto, LIST_ROSTER, from, status, statusNode?p:NULL);
+ if (p) {
+ DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
+ mir_free(p);
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "StatusMsg");
+ }
+ // Determine status to show for the contact and request version information
+ if (item != NULL) {
+ laststatus = item->status;
+ item->status = status;
+ }
+ if (strchr(from, '@') != NULL || DBGetContactSettingByte(NULL, proto->m_szModuleName, "ShowTransport", TRUE) == TRUE) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", (WORD) status);
+ }
+ if (item != NULL) {
+ if (!item->infoRequested) {
+ int iqId = JabberSerialNext(proto);
+ item->infoRequested = TRUE;
+ JabberSend( proto, "<iq type='get' id='"JABBER_IQID"%d'><query xmlns='jabber:iq:info' to='%s'></query></iq>", iqId, from);
+ }
+ if (proto->tlenOptions.enableVersion && !item->versionRequested) {
+ item->versionRequested = TRUE;
+ if (proto->m_iStatus != ID_STATUS_INVISIBLE) {
+ JabberSend( proto, "<message to='%s' type='iq'><iq type='get'><query xmlns='jabber:iq:version'/></iq></message>", from );
+ }
+ }
+ }
+ JabberLog(proto, "%s (%s) online, set contact status to %d", nick, from, status);
+ mir_free(nick);
+ }
+ }
+ else if (!strcmp(type, "unavailable")) {
+ if (!JabberListExist(proto, LIST_ROSTER, from)) {
+ JabberLog(proto, "Receive presence offline from %s (who is not in my roster)", from);
+ JabberListAdd(proto, LIST_ROSTER, from);
+ }
+ else {
+ JabberListRemoveResource(proto, LIST_ROSTER, from);
+ }
+ status = ID_STATUS_OFFLINE;
+ statusNode = JabberXmlGetChild(node, "status");
+ if (statusNode) {
+ if (proto->tlenOptions.offlineAsInvisible) {
+ status = ID_STATUS_INVISIBLE;
+ }
+ p = JabberTextDecode(statusNode->text);
+ JabberListAddResource(proto, LIST_ROSTER, from, status, p);
+ if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
+ if (p) {
+ DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
+ } else {
+ DBDeleteContactSetting(hContact, "CList", "StatusMsg");
+ }
+ }
+ if (p) mir_free(p);
+ }
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
+ // Determine status to show for the contact based on the remaining resources
+ item->status = status;
+ item->versionRequested = FALSE;
+ item->infoRequested = FALSE;
+ }
+ if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
+ if (strchr(from, '@') != NULL || DBGetContactSettingByte(NULL, proto->m_szModuleName, "ShowTransport", TRUE) == TRUE) {
+ if (DBGetContactSettingWord(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
+ DBWriteContactSettingWord(hContact, proto->m_szModuleName, "Status", (WORD) status);
+ }
+ if (item != NULL && item->isTyping) {
+ item->isTyping = FALSE;
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM) hContact, PROTOTYPE_CONTACTTYPING_OFF);
+ }
+ JabberLog(proto, "%s offline, set contact status to %d", from, status);
+ }
+ }
+ else if (!strcmp(type, "subscribe")) {
+ if (strchr(from, '@') == NULL) {
+ // automatically send authorization allowed to agent/transport
+ JabberSend(proto, "<presence to='%s' type='subscribed'/>", from);
+ }
+ else if ((nick=JabberNickFromJID(from)) != NULL) {
+ JabberLog(proto, "%s (%s) requests authorization", nick, from);
+ JabberDBAddAuthRequest(proto, from, nick);
+ mir_free(nick);
+ }
+ }
+ else if (!strcmp(type, "subscribed")) {
+ if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
+ if (item->subscription == SUB_FROM) item->subscription = SUB_BOTH;
+ else if (item->subscription == SUB_NONE) {
+ item->subscription = SUB_TO;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void JabberSendPresenceTo(TlenProtocol *proto, int status, char *to)
+{
+ char *showBody, *statusMsg, *presenceType;
+ char *ptr = NULL;
+
+ if (!proto->isOnline) return;
+
+ // Send <presence/> update for status (we won't handle ID_STATUS_OFFLINE here)
+ // Note: jabberModeMsg is already encoded using JabberTextEncode()
+ EnterCriticalSection(&proto->modeMsgMutex);
+
+ showBody = NULL;
+ statusMsg = NULL;
+ presenceType = NULL;
+ switch (status) {
+ case ID_STATUS_ONLINE:
+ showBody = "available";
+ statusMsg = proto->modeMsgs.szOnline;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ showBody = "away";
+ statusMsg = proto->modeMsgs.szAway;
+ break;
+ case ID_STATUS_NA:
+ showBody = "xa";
+ statusMsg = proto->modeMsgs.szNa;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ showBody = "dnd";
+ statusMsg = proto->modeMsgs.szDnd;
+ break;
+ case ID_STATUS_FREECHAT:
+ showBody = "chat";
+ statusMsg = proto->modeMsgs.szFreechat;
+ break;
+ case ID_STATUS_INVISIBLE:
+ presenceType = "invisible";
+ statusMsg = proto->modeMsgs.szInvisible;
+ break;
+ case ID_STATUS_OFFLINE:
+ presenceType = "unavailable";
+ if (DBGetContactSettingByte(NULL, proto->m_szModuleName, "LeaveOfflineMessage", FALSE)) {
+ int offlineMessageOption = DBGetContactSettingWord(NULL, proto->m_szModuleName, "OfflineMessageOption", 0);
+ if (offlineMessageOption == 0) {
+ switch (proto->m_iStatus) {
+ case ID_STATUS_ONLINE:
+ ptr = mir_strdup(proto->modeMsgs.szOnline);
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ ptr = mir_strdup(proto->modeMsgs.szAway);
+ break;
+ case ID_STATUS_NA:
+ ptr = mir_strdup(proto->modeMsgs.szNa);
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ ptr = mir_strdup(proto->modeMsgs.szDnd);
+ break;
+ case ID_STATUS_FREECHAT:
+ ptr = mir_strdup(proto->modeMsgs.szFreechat);
+ break;
+ case ID_STATUS_INVISIBLE:
+ ptr = mir_strdup(proto->modeMsgs.szInvisible);
+ break;
+ }
+ } else if (offlineMessageOption == 99) {
+
+ } else if (offlineMessageOption < 7) {
+ DBVARIANT dbv;
+ const char *statusNames[] = {"OnDefault", "AwayDefault", "NaDefault", "DndDefault", "FreeChatDefault", "InvDefault"};
+ if (!DBGetContactSetting(NULL, "SRAway", statusNames[offlineMessageOption-1], &dbv)) {
+ int i;
+ char substituteStr[128];
+ ptr = mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ for (i=0;ptr[i];i++) {
+ if (ptr[i] != '%') continue;
+ if (!_strnicmp(ptr+i,"%time%",6))
+ GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_NOSECONDS,NULL,NULL,substituteStr,sizeof(substituteStr));
+ else if (!_strnicmp(ptr+i,"%date%",6))
+ GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,NULL,NULL,substituteStr,sizeof(substituteStr));
+ else continue;
+ if (strlen(substituteStr)>6) ptr=(char*)mir_realloc(ptr,strlen(ptr)+1+strlen(substituteStr)-6);
+ MoveMemory(ptr+i+strlen(substituteStr),ptr+i+6,strlen(ptr)-i-5);
+ CopyMemory(ptr+i,substituteStr,strlen(substituteStr));
+ }
+ }
+ }
+ }
+ statusMsg = ptr;
+ break;
+ default:
+ // Should not reach here
+ break;
+ }
+ proto->m_iStatus = status;
+ if (presenceType) {
+ if (statusMsg)
+ JabberSend(proto, "<presence type='%s'><status>%s</status></presence>", presenceType, statusMsg);
+ else
+ JabberSend(proto, "<presence type='%s'></presence>", presenceType);
+ } else {
+ if (statusMsg)
+ JabberSend(proto, "<presence><show>%s</show><status>%s</status></presence>", showBody, statusMsg);
+ else
+ JabberSend(proto, "<presence><show>%s</show></presence>", showBody);
+ }
+ if (ptr) {
+ mir_free(ptr);
+ }
+ LeaveCriticalSection(&proto->modeMsgMutex);
+}
+
+
+
+void JabberSendPresence(TlenProtocol *proto, int statusIn)
+{
+ int statusOut;
+ switch (statusIn) {
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_OFFLINE:
+ case ID_STATUS_NA:
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_INVISIBLE:
+ statusOut = statusIn;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ default:
+ statusOut = ID_STATUS_AWAY;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ statusOut = ID_STATUS_DND;
+ break;
+ }
+ JabberSendPresenceTo(proto, statusOut, NULL);
+}
+
+
diff --git a/protocols/Tlen/src/tlen_presence.h b/protocols/Tlen/src/tlen_presence.h
new file mode 100644
index 0000000000..caf92ddab5
--- /dev/null
+++ b/protocols/Tlen/src/tlen_presence.h
@@ -0,0 +1,29 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2009 Piotr Piastucki
+
+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.
+
+*/
+#ifndef _TLEN_PRESENCE_H
+#define _TLEN_PRESENCE_H
+
+void TlenProcessPresence(XmlNode *node, TlenProtocol *proto);
+
+#endif /* _TLEN_PRESENCE_H */
+
diff --git a/protocols/Tlen/src/tlen_userinfo.cpp b/protocols/Tlen/src/tlen_userinfo.cpp
new file mode 100644
index 0000000000..38463f746c
--- /dev/null
+++ b/protocols/Tlen/src/tlen_userinfo.cpp
@@ -0,0 +1,335 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2002-2004 Santithorn Bunchua
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include <commctrl.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "jabber_list.h"
+#include "resource.h"
+#include "tlen_avatar.h"
+
+JABBER_FIELD_MAP tlenFieldGender[] = {
+ { 1, _T("Male") },
+ { 2, _T("Female") },
+ { 0, NULL }
+};
+JABBER_FIELD_MAP tlenFieldLookfor[] = {
+ { 1, _T("Somebody to talk") },
+ { 2, _T("Friendship") },
+ { 3, _T("Flirt/romance") },
+ { 4, _T("Love") },
+ { 5, _T("Nothing") },
+ { 0, NULL }
+};
+JABBER_FIELD_MAP tlenFieldStatus[] = {
+ { 1, _T("All") },
+ { 2, _T("Available") },
+ { 3, _T("Free for chat") },
+ { 0, NULL }
+};
+JABBER_FIELD_MAP tlenFieldOccupation[] = {
+ { 1, _T("Student") },
+ { 2, _T("College student") },
+ { 3, _T("Farmer") },
+ { 4, _T("Manager") },
+ { 5, _T("Specialist") },
+ { 6, _T("Clerk") },
+ { 7, _T("Unemployed") },
+ { 8, _T("Pensioner") },
+ { 9, _T("Housekeeper") },
+ { 10, _T("Teacher") },
+ { 11, _T("Doctor") },
+ { 12, _T("Other") },
+ { 0, NULL }
+};
+JABBER_FIELD_MAP tlenFieldPlan[] = {
+ { 1, _T("I'd like to go downtown") },
+ { 2, _T("I'd like to go to the cinema") },
+ { 3, _T("I'd like to take a walk") },
+ { 4, _T("I'd like to go to the disco") },
+ { 5, _T("I'd like to go on a blind date") },
+ { 6, _T("Waiting for suggestion") },
+ { 0, NULL }
+};
+
+static INT_PTR CALLBACK TlenUserInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static void InitComboBox(HWND hwndCombo, JABBER_FIELD_MAP *fieldMap)
+{
+ int i, n;
+
+ n = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)_T(""));
+ SendMessage(hwndCombo, CB_SETITEMDATA, n, 0);
+ SendMessage(hwndCombo, CB_SETCURSEL, n, 0);
+ for (i=0;;i++) {
+ if (fieldMap[i].name == NULL)
+ break;
+ n = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) TranslateTS(fieldMap[i].name));
+ SendMessage(hwndCombo, CB_SETITEMDATA, n, fieldMap[i].id);
+ }
+}
+
+static void FetchField(HWND hwndDlg, UINT idCtrl, char *fieldName, char **str, int *strSize)
+{
+ char text[512];
+ char *localFieldName, *localText;
+
+ if (hwndDlg == NULL || fieldName == NULL || str == NULL || strSize == NULL)
+ return;
+ GetDlgItemTextA(hwndDlg, idCtrl, text, sizeof(text));
+ if (text[0]) {
+ if ((localFieldName=JabberTextEncode(fieldName)) != NULL) {
+ if ((localText=JabberTextEncode(text)) != NULL) {
+ JabberStringAppend(str, strSize, "<%s>%s</%s>", localFieldName, localText, localFieldName);
+ mir_free(localText);
+ }
+ mir_free(localFieldName);
+ }
+ }
+}
+
+static void FetchCombo(HWND hwndDlg, UINT idCtrl, char *fieldName, char **str, int *strSize)
+{
+ int value;
+ char *localFieldName;
+
+ if (hwndDlg == NULL || fieldName == NULL || str == NULL || strSize == NULL)
+ return;
+ value = (int) SendDlgItemMessage(hwndDlg, idCtrl, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, idCtrl, CB_GETCURSEL, 0, 0), 0);
+ if (value > 0) {
+ if ((localFieldName=JabberTextEncode(fieldName)) != NULL) {
+ JabberStringAppend(str, strSize, "<%s>%d</%s>", localFieldName, value, localFieldName);
+ mir_free(localFieldName);
+ }
+ }
+}
+
+
+int TlenUserInfoInit(void *ptr, WPARAM wParam, LPARAM lParam)
+{
+ char *szProto;
+ HANDLE hContact;
+ OPTIONSDIALOGPAGE odp = {0};
+ TlenProtocol *proto = (TlenProtocol *)ptr;
+
+ if (!CallService(MS_PROTO_ISPROTOCOLLOADED, 0, (LPARAM) proto->m_szModuleName))
+ return 0;
+ hContact = (HANDLE) lParam;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ((szProto != NULL && !strcmp(szProto, proto->m_szModuleName)) || !lParam) {
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.flags = ODPF_TCHAR;
+ odp.pfnDlgProc = TlenUserInfoDlgProc;
+ odp.position = -2000000000;
+ odp.pszTemplate = ((HANDLE)lParam != NULL) ? MAKEINTRESOURCEA(IDD_USER_INFO):MAKEINTRESOURCEA(IDD_USER_VCARD);
+ odp.ptszTitle = (hContact != NULL) ? LPGENT("Account") : proto->m_tszUserName;
+ odp.dwInitParam = (LPARAM)proto;
+ UserInfo_AddPage(wParam, &odp);
+
+ }
+ if (!lParam && proto->isOnline) {
+ CCSDATA ccs = {0};
+ proto->GetInfo(0, (LPARAM) &ccs);
+ }
+ return 0;
+}
+
+typedef struct {
+ TlenProtocol *proto;
+ HANDLE hContact;
+}TLENUSERINFODLGDATA;
+
+
+static INT_PTR CALLBACK TlenUserInfoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TLENUSERINFODLGDATA *data = (TLENUSERINFODLGDATA *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+
+ data = (TLENUSERINFODLGDATA*)mir_alloc(sizeof(TLENUSERINFODLGDATA));
+ data->hContact = (HANDLE) lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)data);
+ // lParam is hContact
+ TranslateDialogDefault(hwndDlg);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_GENDER), tlenFieldGender);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_OCCUPATION), tlenFieldOccupation);
+ InitComboBox(GetDlgItem(hwndDlg, IDC_LOOKFOR), tlenFieldLookfor);
+
+ return TRUE;
+ case WM_TLEN_REFRESH:
+ {
+ DBVARIANT dbv;
+ char *jid;
+ int i;
+ JABBER_LIST_ITEM *item;
+
+ SetDlgItemText(hwndDlg, IDC_INFO_JID, _T(""));
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, _T(""));
+ SetFocus(GetDlgItem(hwndDlg, IDC_STATIC));
+
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "FirstName", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_FIRSTNAME, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_FIRSTNAME, _T(""));
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "LastName", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_LASTNAME, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_LASTNAME, _T(""));
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "Nick", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_NICKNAME, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_NICKNAME, _T(""));
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "e-mail", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_EMAIL, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_EMAIL, _T(""));
+ if (!DBGetContactSetting(data->hContact, data->proto->m_szModuleName, "Age", &dbv)) {
+ SetDlgItemInt(hwndDlg, IDC_AGE, dbv.wVal, FALSE);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_AGE, _T(""));
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "City", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_CITY, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_CITY, _T(""));
+ if (!DBGetContactSettingTString(data->hContact, data->proto->m_szModuleName, "School", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_SCHOOL, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else SetDlgItemText(hwndDlg, IDC_SCHOOL, _T(""));
+ switch (DBGetContactSettingByte(data->hContact, data->proto->m_szModuleName, "Gender", '?')) {
+ case 'M':
+ SendDlgItemMessage(hwndDlg, IDC_GENDER, CB_SETCURSEL, 1, 0);
+ SetDlgItemText(hwndDlg, IDC_GENDER_TEXT, TranslateTS(tlenFieldGender[0].name));
+ break;
+ case 'F':
+ SendDlgItemMessage(hwndDlg, IDC_GENDER, CB_SETCURSEL, 2, 0);
+ SetDlgItemText(hwndDlg, IDC_GENDER_TEXT, TranslateTS(tlenFieldGender[1].name));
+ break;
+ default:
+ SendDlgItemMessage(hwndDlg, IDC_GENDER, CB_SETCURSEL, 0, 0);
+ SetDlgItemText(hwndDlg, IDC_GENDER_TEXT, _T(""));
+ break;
+ }
+ i = DBGetContactSettingWord(data->hContact, data->proto->m_szModuleName, "Occupation", 0);
+ if (i>0 && i<13) {
+ SetDlgItemText(hwndDlg, IDC_OCCUPATION_TEXT, TranslateTS(tlenFieldOccupation[i-1].name));
+ SendDlgItemMessage(hwndDlg, IDC_OCCUPATION, CB_SETCURSEL, i, 0);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_OCCUPATION_TEXT, _T(""));
+ SendDlgItemMessage(hwndDlg, IDC_OCCUPATION, CB_SETCURSEL, 0, 0);
+ }
+ i = DBGetContactSettingWord(data->hContact, data->proto->m_szModuleName, "LookingFor", 0);
+ if (i>0 && i<6) {
+ SetDlgItemText(hwndDlg, IDC_LOOKFOR_TEXT, TranslateTS(tlenFieldLookfor[i-1].name));
+ SendDlgItemMessage(hwndDlg, IDC_LOOKFOR, CB_SETCURSEL, i, 0);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_LOOKFOR_TEXT, _T(""));
+ SendDlgItemMessage(hwndDlg, IDC_LOOKFOR, CB_SETCURSEL, 0, 0);
+ }
+ i = DBGetContactSettingWord(data->hContact, data->proto->m_szModuleName, "VoiceChat", 0);
+ CheckDlgButton(hwndDlg, IDC_VOICECONVERSATIONS, i);
+ i = DBGetContactSettingWord(data->hContact, data->proto->m_szModuleName, "PublicStatus", 0);
+ CheckDlgButton(hwndDlg, IDC_PUBLICSTATUS, i);
+ if (!DBGetContactSetting(data->hContact, data->proto->m_szModuleName, "jid", &dbv)) {
+ jid = JabberTextDecode(dbv.pszVal);
+ SetDlgItemTextA(hwndDlg, IDC_INFO_JID, jid);
+ mir_free(jid);
+ jid = dbv.pszVal;
+ if (data->proto->isOnline) {
+ if ((item=JabberListGetItemPtr(data->proto, LIST_ROSTER, jid)) != NULL) {
+ switch (item->subscription) {
+ case SUB_BOTH:
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, TranslateT("both"));
+ break;
+ case SUB_TO:
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, TranslateT("to"));
+ break;
+ case SUB_FROM:
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, TranslateT("from"));
+ break;
+ default:
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, TranslateT("none"));
+ break;
+ }
+ SetDlgItemTextA(hwndDlg, IDC_SOFTWARE, item->software);
+ SetDlgItemTextA(hwndDlg, IDC_VERSION, item->version);
+ SetDlgItemTextA(hwndDlg, IDC_SYSTEM, item->system);
+ } else {
+ SetDlgItemText(hwndDlg, IDC_SUBSCRIPTION, TranslateT("not on roster"));
+ }
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_INFOCHANGED:
+ {
+ HANDLE hContact = (HANDLE) ((LPPSHNOTIFY) lParam)->lParam;
+ SendMessage(hwndDlg, WM_TLEN_REFRESH, 0, (LPARAM) hContact);
+ }
+ break;
+ case PSN_PARAMCHANGED:
+ {
+ data->proto = ( TlenProtocol* )(( LPPSHNOTIFY )lParam )->lParam;
+ SendMessage(hwndDlg, WM_TLEN_REFRESH, 0, 0);
+ }
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SAVE && HIWORD(wParam) == BN_CLICKED) {
+ char *str = NULL;
+ int strSize;
+ JabberStringAppend(&str, &strSize, "<iq type='set' id='"JABBER_IQID"%d' to='tuba'><query xmlns='jabber:iq:register'>", JabberSerialNext(data->proto));
+ FetchField(hwndDlg, IDC_FIRSTNAME, "first", &str, &strSize);
+ FetchField(hwndDlg, IDC_LASTNAME, "last", &str, &strSize);
+ FetchField(hwndDlg, IDC_NICKNAME, "nick", &str, &strSize);
+ FetchField(hwndDlg, IDC_EMAIL, "email", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_GENDER, "s", &str, &strSize);
+ FetchField(hwndDlg, IDC_AGE, "b", &str, &strSize);
+ FetchField(hwndDlg, IDC_CITY, "c", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_OCCUPATION, "j", &str, &strSize);
+ FetchField(hwndDlg, IDC_SCHOOL, "e", &str, &strSize);
+ FetchCombo(hwndDlg, IDC_LOOKFOR, "r", &str, &strSize);
+ JabberStringAppend(&str, &strSize, "<g>%d</g>", IsDlgButtonChecked(hwndDlg, IDC_VOICECONVERSATIONS) ? 1 : 0);
+ JabberStringAppend(&str, &strSize, "<v>%d</v>", IsDlgButtonChecked(hwndDlg, IDC_PUBLICSTATUS) ? 1 : 0);
+ JabberStringAppend(&str, &strSize, "</query></iq>");
+ JabberSend(data->proto, "%s", str);
+ mir_free(str);
+ data->proto->GetInfo(NULL, 0);
+ }
+ break;
+ case WM_DESTROY:
+ mir_free(data);
+ break;
+ }
+ return FALSE;
+}
diff --git a/protocols/Tlen/src/tlen_voice.cpp b/protocols/Tlen/src/tlen_voice.cpp
new file mode 100644
index 0000000000..c476d55116
--- /dev/null
+++ b/protocols/Tlen/src/tlen_voice.cpp
@@ -0,0 +1,1121 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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 "jabber.h"
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <math.h>
+#include <m_button.h>
+//#include <win2k.h>
+#include "resource.h"
+#include "jabber_list.h"
+#include "tlen_voice.h"
+#include "tlen_p2p_old.h"
+#include "tlen_file.h"
+
+static int MODE_FREQUENCY[]= {0, 0, 8000, 11025, 22050, 44100};
+static int MODE_FRAME_SIZE[]= {0, 0, 5, 5, 10, 25};
+static int FRAMES_AVAILABLE_MAX_LIMIT = 2;
+static int VU_METER_HEIGHT = 64;
+static int VU_METER_WIDTH = 20;
+static int VU_METER_LEVELS = 16;
+static HBITMAP vuMeterBitmaps[100];
+
+static void TlenVoiceReceiveParse(TLEN_FILE_TRANSFER *ft);
+static void TlenVoiceSendParse(TLEN_FILE_TRANSFER *ft);
+static void TlenVoiceReceivingConnection(HANDLE hNewConnection, DWORD dwRemoteIP, void * pExtra);
+
+static void CALLBACK TlenVoicePlaybackCallback(HWAVEOUT hwo, UINT uMsg, DWORD* dwInstance, DWORD dwParam1, DWORD dwParam2)
+{
+ if (uMsg == WOM_DONE) {
+ TLEN_VOICE_CONTROL *control = (TLEN_VOICE_CONTROL *) dwInstance;
+ waveOutUnprepareHeader(hwo, (WAVEHDR *) dwParam1, sizeof(WAVEHDR));
+ if (control->proto->framesAvailableForPlayback > 0) {
+ control->proto->framesAvailableForPlayback--;
+ }
+// playbackControl->waveHeaders[playbackControl->waveHeadersPos].dwFlags = WHDR_DONE;
+// playbackControl->waveHeaders[playbackControl->waveHeadersPos].lpData = (char *) (playbackControl->waveData + playbackControl->waveHeadersPos * playbackControl->waveFrameSize);
+// playbackControl->waveHeaders[playbackControl->waveHeadersPos].dwBufferLength = playbackControl->waveFrameSize * 2;
+// waveOutPrepareHeader(playbackControl->hWaveOut, &playbackControl->waveHeaders[playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+// waveOutWrite(playbackControl->hWaveOut, &playbackControl->waveHeaders[playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+
+ }
+}
+
+static DWORD WINAPI TlenVoiceRecordingThreadProc(TLEN_VOICE_CONTROL *control)
+{
+ MSG msg;
+ HWAVEIN hWaveIn;
+ WAVEHDR *hWaveHdr;
+ control->isRunning = 1;
+ control->stopThread = 0;
+ while (TRUE) {
+ GetMessage(&msg,NULL,0,0);
+ if (msg.message == MM_WIM_DATA) {
+// JabberLog("recording thread running...%d", msg.message);
+ hWaveIn = (HWAVEIN) msg.wParam;
+ hWaveHdr = (WAVEHDR *) msg.lParam;
+ waveInUnprepareHeader(hWaveIn, hWaveHdr, sizeof(WAVEHDR));
+ if (hWaveHdr->dwBytesRecorded>0 && !control->bDisable) {
+ control->recordingData = (short *)hWaveHdr->lpData;
+ TlenVoiceSendParse(control->ft);
+ }
+ if (!control->stopThread) {
+ waveInPrepareHeader(hWaveIn, &control->waveHeaders[control->waveHeadersPos], sizeof(WAVEHDR));
+ waveInAddBuffer(hWaveIn, &control->waveHeaders[control->waveHeadersPos], sizeof(WAVEHDR));
+ control->waveHeadersPos = (control->waveHeadersPos +1) % control->waveHeadersNum;
+ }
+ }
+ else if (msg.message == MM_WIM_CLOSE) {
+ break;
+ }
+ }
+ control->isRunning = 0;
+ JabberLog(control->proto, "recording thread ended...");
+ return 0;
+}
+
+
+/*static void CALLBACK TlenVoiceRecordingCallback(HWAVEIN hwi, UINT uMsg, DWORD* dwInstance, DWORD dwParam1, DWORD dwParam2)
+{
+ if (uMsg == WIM_DATA) {
+ TLEN_VOICE_CONTROL *control = (TLEN_VOICE_CONTROL *) dwInstance;
+ if (control->waveHeaders[control->waveHeadersPos].dwBytesRecorded>0) {
+ control->recordingData = (short *)control->waveHeaders[control->waveHeadersPos].lpData;
+ TlenVoiceSendParse(control->ft);
+ }
+ waveInAddBuffer(control->hWaveIn, &control->waveHeaders[control->waveHeadersPos], sizeof(WAVEHDR));
+ control->waveHeadersPos = (control->waveHeadersPos +1) % control->waveHeadersNum;
+ }
+}*/
+
+static int TlenVoicePlaybackStart(TLEN_VOICE_CONTROL *control)
+{
+ WAVEFORMATEX wfm;
+ MMRESULT mmres;
+ int i, j;
+ int iNumDevs, iSelDev;
+ WAVEOUTCAPS wic;
+
+ memset(&wfm, 0, sizeof(wfm));
+ wfm.cbSize = sizeof(WAVEFORMATEX);
+ wfm.nChannels = 1;
+ wfm.wBitsPerSample = 16;
+ wfm.nSamplesPerSec = MODE_FREQUENCY[control->codec];
+ wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nChannels * wfm.wBitsPerSample/8;
+ wfm.nBlockAlign = 2 * wfm.nChannels;
+ wfm.wFormatTag = WAVE_FORMAT_PCM;
+
+ control->waveMode = 0;
+ control->waveFrameSize = MODE_FRAME_SIZE[control->codec] * 160 * wfm.nChannels;// * wfm.wBitsPerSample / 8;
+ control->waveHeadersPos = 0;
+ control->waveHeadersNum = FRAMES_AVAILABLE_MAX_LIMIT + 2;
+
+ j = DBGetContactSettingWord(NULL, control->proto->m_szModuleName, "VoiceDeviceOut", 0);
+ iSelDev = WAVE_MAPPER;
+ if (j != 0) {
+ iNumDevs = waveOutGetNumDevs();
+ for (i = 0; i < iNumDevs; i++) {
+ if (!waveOutGetDevCaps(i, &wic, sizeof(WAVEOUTCAPS))) {
+ if (wic.dwFormats != 0) {
+ j--;
+ if (j == 0) {
+ iSelDev = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!waveOutGetDevCaps(iSelDev, &wic, sizeof(WAVEOUTCAPS))) {
+ JabberLog(control->proto, "Playback device ID #%u: %s\r\n", iSelDev, wic.szPname);
+ }
+
+ mmres = waveOutOpen(&control->hWaveOut, iSelDev, &wfm, (DWORD) &TlenVoicePlaybackCallback, (DWORD) control, CALLBACK_FUNCTION);
+ if (mmres != MMSYSERR_NOERROR) {
+ JabberLog(control->proto, "TlenVoiceStart FAILED!");
+ return 1;
+ }
+ control->waveData = (short *)mir_alloc(control->waveHeadersNum * control->waveFrameSize * 2);
+ memset(control->waveData, 0, control->waveHeadersNum * control->waveFrameSize * 2);
+ control->waveHeaders = (WAVEHDR *)mir_alloc(control->waveHeadersNum * sizeof(WAVEHDR));
+ JabberLog(control->proto, "TlenVoiceStart OK!");
+ return 0;
+}
+
+
+static int TlenVoiceRecordingStart(TLEN_VOICE_CONTROL *control)
+{
+ WAVEFORMATEX wfm;
+ MMRESULT mmres;
+ int i, j;
+ int iNumDevs, iSelDev;
+ WAVEINCAPS wic;
+
+ memset(&wfm, 0, sizeof(wfm));
+ wfm.cbSize = sizeof(WAVEFORMATEX);
+ wfm.nChannels = 1;
+ wfm.wBitsPerSample = 16;
+ wfm.nSamplesPerSec = MODE_FREQUENCY[control->codec];
+ wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nChannels * wfm.wBitsPerSample/8;
+ wfm.nBlockAlign = 2 * wfm.nChannels;
+ wfm.wFormatTag = WAVE_FORMAT_PCM;
+
+
+ control->waveMode = 0;
+// control->isRunning = 1;
+ control->waveFrameSize = MODE_FRAME_SIZE[control->codec] * 160 * wfm.nChannels;// * wfm.wBitsPerSample / 8;
+ control->waveHeadersPos = 0;
+ control->waveHeadersNum = 2;
+
+ control->hThread = CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)TlenVoiceRecordingThreadProc,
+ control,
+ 0,
+ (LPDWORD)&control->threadID);
+
+
+ SetThreadPriority(control->hThread, THREAD_PRIORITY_ABOVE_NORMAL);
+
+ j = DBGetContactSettingWord(NULL, control->proto->m_szModuleName, "VoiceDeviceIn", 0);
+ iSelDev = WAVE_MAPPER;
+ if (j != 0) {
+ iNumDevs = waveInGetNumDevs();
+ for (i = 0; i < iNumDevs; i++) {
+ if (!waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS))) {
+ if (wic.dwFormats != 0) {
+ j--;
+ if (j == 0) {
+ iSelDev = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!waveInGetDevCaps(iSelDev, &wic, sizeof(WAVEINCAPS))) {
+ JabberLog(control->proto, "Recording device ID #%u: %s\r\n", iSelDev, wic.szPname);
+ }
+
+ mmres = waveInOpen(&control->hWaveIn, iSelDev, &wfm, (DWORD) control->threadID, 0, CALLBACK_THREAD);
+// mmres = waveInOpen(&control->hWaveIn, 3, &wfm, (DWORD) &TlenVoiceRecordingCallback, (DWORD) control, CALLBACK_FUNCTION);
+ if (mmres != MMSYSERR_NOERROR) {
+ PostThreadMessage(control->threadID, WIM_CLOSE, 0, 0);
+ JabberLog(control->proto, "TlenVoiceStart FAILED %d!", mmres);
+ return 1;
+ }
+ control->waveData = (short *)mir_alloc(control->waveHeadersNum * control->waveFrameSize * 2);
+ memset(control->waveData, 0, control->waveHeadersNum * control->waveFrameSize * 2);
+ control->waveHeaders = (WAVEHDR *)mir_alloc(control->waveHeadersNum * sizeof(WAVEHDR));
+ for (i=0;i<control->waveHeadersNum;i++) {
+ control->waveHeaders[i].dwFlags = 0;//WHDR_DONE;
+ control->waveHeaders[i].lpData = (char *) (control->waveData + i * control->waveFrameSize);
+ control->waveHeaders[i].dwBufferLength = control->waveFrameSize *2;
+ mmres = waveInPrepareHeader(control->hWaveIn, &control->waveHeaders[i], sizeof(WAVEHDR));
+ if (mmres != MMSYSERR_NOERROR) {
+ waveInClose(control->hWaveIn);
+// PostThreadMessage(control->threadID, WIM_CLOSE, 0, 0);
+ JabberLog(control->proto, "TlenVoiceStart FAILED #2!");
+ return 1;
+ }
+ }
+ for (i=0;i<control->waveHeadersNum;i++) {
+ waveInAddBuffer(control->hWaveIn, &control->waveHeaders[i], sizeof(WAVEHDR));
+ }
+ waveInStart(control->hWaveIn);
+ JabberLog(control->proto, "TlenVoiceRStart OK!");
+ return 0;
+}
+
+
+static TLEN_VOICE_CONTROL *TlenVoiceCreateVC(TlenProtocol *proto, int codec)
+{
+ TLEN_VOICE_CONTROL *vc;
+ vc = (TLEN_VOICE_CONTROL *) mir_alloc(sizeof (TLEN_VOICE_CONTROL));
+ memset(vc, 0, sizeof(TLEN_VOICE_CONTROL));
+ vc->gsmstate = gsm_create();
+ vc->codec = codec;
+ vc->proto = proto;
+ return vc;
+}
+static void TlenVoiceFreeVc(TLEN_VOICE_CONTROL *vc)
+{
+ int i;
+ JabberLog(vc->proto, "-> TlenVoiceFreeVc");
+ vc->stopThread = 1;
+ PostThreadMessage(vc->threadID, MM_WIM_CLOSE, 0, 0);
+ while (vc->isRunning) {
+ Sleep(50);
+ }
+ if (vc->hThread != NULL) CloseHandle(vc->hThread);
+ if (vc->hWaveIn) {
+ for (i=0;i<vc->waveHeadersNum;i++) {
+ while (waveInUnprepareHeader(vc->hWaveIn, &vc->waveHeaders[i], sizeof(WAVEHDR)) == WAVERR_STILLPLAYING) {
+ Sleep(50);
+ }
+ }
+ while (waveInClose(vc->hWaveIn) == WAVERR_STILLPLAYING) {
+ Sleep(50);
+ }
+ }
+ if (vc->hWaveOut) {
+ for (i=0;i<vc->waveHeadersNum;i++) {
+ while (waveOutUnprepareHeader(vc->hWaveOut, &vc->waveHeaders[i], sizeof(WAVEHDR)) == WAVERR_STILLPLAYING) {
+ Sleep(50);
+ }
+ }
+ while (waveOutClose(vc->hWaveOut) == WAVERR_STILLPLAYING) {
+ Sleep(50);
+ }
+ }
+ if (vc->waveData) mir_free(vc->waveData);
+ if (vc->waveHeaders) mir_free(vc->waveHeaders);
+ if (vc->gsmstate) gsm_release(vc->gsmstate);
+ JabberLog(vc->proto, "<- TlenVoiceFreeVc");
+ mir_free(vc);
+}
+
+static void TlenVoiceCrypt(char *buffer, int len)
+{
+ int i, j, k;
+ j = 0x71;
+ for (i=0;i<len;i++) {
+ k = j;
+ j = j << 6;
+ j += k;
+ j = k + (j << 1);
+ j += 0xBB;
+ buffer[i]^=j;
+ }
+}
+
+void __cdecl TlenVoiceReceiveThread(TLEN_FILE_TRANSFER *ft)
+{
+ NETLIBOPENCONNECTION nloc;
+ JABBER_SOCKET s;
+
+ JabberLog(ft->proto, "Thread started: type=file_receive server='%s' port='%d'", ft->hostName, ft->wPort);
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = ft->hostName;
+ nloc.wPort = ft->wPort;
+ nloc.flags = 0;
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Connecting..."));
+// ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hNetlibUser, (LPARAM) &nloc);
+ if (s != NULL) {
+ ft->s = s;
+ JabberLog(ft->proto, "Entering file receive loop");
+ TlenP2PEstablishOutgoingConnection(ft, FALSE);
+ if (ft->state != FT_ERROR) {
+ ft->proto->playbackControl = NULL;
+ ft->proto->recordingControl = TlenVoiceCreateVC(ft->proto, 3);
+ ft->proto->recordingControl->ft = ft;
+ TlenVoiceRecordingStart(ft->proto->recordingControl);
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenVoiceReceiveParse(ft);
+ }
+ TlenVoiceFreeVc(ft->proto->recordingControl);
+ ft->proto->playbackControl = NULL;
+ ft->proto->recordingControl = NULL;
+ }
+ if (ft->s) {
+ Netlib_CloseHandle(s);
+ }
+ ft->s = NULL;
+ } else {
+ JabberLog(ft->proto, "Connection failed - receiving as server");
+ ft->pfnNewConnectionV2 = TlenVoiceReceivingConnection;
+ s = TlenP2PListen(ft);
+ if (s != NULL) {
+ HANDLE hEvent;
+ char *nick;
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Waiting for connection..."));
+ ft->s = s;
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ft->hFileEvent = hEvent;
+ ft->currentFile = 0;
+ ft->state = FT_CONNECTING;
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<v t='%s' i='%s' e='7' a='%s' p='%d'/>", nick, ft->iqId, ft->localName, ft->wLocalPort);
+ mir_free(nick);
+ JabberLog(ft->proto, "Waiting for the file to be received...");
+ WaitForSingleObject(hEvent, INFINITE);
+ ft->hFileEvent = NULL;
+ CloseHandle(hEvent);
+ JabberLog(ft->proto, "Finish all files");
+ Netlib_CloseHandle(s);
+ } else {
+ ft->state = FT_ERROR;
+ }
+ }
+ JabberListRemove(ft->proto, LIST_VOICE, ft->iqId);
+ if (ft->state == FT_DONE) {
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Finished..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ } else {
+ char *nick;
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<f t='%s' i='%s' e='8'/>", nick, ft->iqId);
+ mir_free(nick);
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Error..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ }
+ JabberLog(ft->proto, "Thread ended: type=file_receive server='%s'", ft->hostName);
+
+ TlenP2PFreeFileTransfer(ft);
+}
+
+static void TlenVoiceReceivingConnection(JABBER_SOCKET hConnection, DWORD dwRemoteIP, void * pExtra)
+{
+ JABBER_SOCKET slisten;
+ TLEN_FILE_TRANSFER *ft;
+ TlenProtocol *proto = (TlenProtocol *)pExtra;
+
+ ft = TlenP2PEstablishIncomingConnection(proto, hConnection, LIST_VOICE, FALSE);
+ if (ft != NULL) {
+ slisten = ft->s;
+ ft->s = hConnection;
+ JabberLog(ft->proto, "Set ft->s to %d (saving %d)", hConnection, slisten);
+ JabberLog(ft->proto, "Entering send loop for this file connection... (ft->s is hConnection)");
+ proto->playbackControl = NULL;
+ proto->recordingControl = TlenVoiceCreateVC(proto, 3);
+ proto->recordingControl->ft = ft;
+ TlenVoiceRecordingStart(proto->recordingControl);
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenVoiceReceiveParse(ft);
+ }
+ TlenVoiceFreeVc(proto->recordingControl);
+ proto->playbackControl = NULL;
+ proto->recordingControl = NULL;
+ if (ft->state == FT_DONE) {
+ SetDlgItemText(proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Finished..."));
+// ProtoBroadcastAck(proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ } else {
+// ProtoBroadcastAck(proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Error..."));
+ }
+ JabberLog(ft->proto, "Closing connection for this file transfer... (ft->s is now hBind)");
+ ft->s = slisten;
+ JabberLog(ft->proto, "ft->s is restored to %d", ft->s);
+ }
+ Netlib_CloseHandle(hConnection);
+ if (ft != NULL && ft->hFileEvent != NULL)
+ SetEvent(ft->hFileEvent);
+}
+
+static void TlenVoiceReceiveParse(TLEN_FILE_TRANSFER *ft)
+{
+ char *statusTxt;
+ int i, j;
+ char *p;
+ float val;
+ TLEN_FILE_PACKET *packet;
+ packet = TlenP2PPacketReceive(ft->s);
+ if (packet != NULL) {
+ statusTxt = " Unknown packet ";
+ p = packet->packet;
+ if (packet->type == TLEN_VOICE_PACKET) {
+ short *out;
+ int codec, chunkNum;
+ statusTxt = " OK ";
+ TlenVoiceCrypt(packet->packet+4, packet->len-4);
+ codec = *((int *)packet->packet);
+ if (codec<2 || codec>5) {
+ statusTxt = " Unknown codec ";
+ } else {
+ if (ft->proto->playbackControl == NULL) {
+ ft->proto->playbackControl = TlenVoiceCreateVC(ft->proto, codec);
+ TlenVoicePlaybackStart(ft->proto->playbackControl);
+ ft->proto->framesAvailableForPlayback = 0;
+ ft->proto->availOverrunValue = 0;
+ } else if (ft->proto->playbackControl->codec != codec) {
+ TlenVoiceFreeVc(ft->proto->playbackControl);
+ ft->proto->playbackControl = TlenVoiceCreateVC(ft->proto, codec);
+ TlenVoicePlaybackStart(ft->proto->playbackControl);
+ ft->proto->framesAvailableForPlayback = 0;
+ ft->proto->availOverrunValue = 0;
+ }
+ if (!ft->proto->playbackControl->bDisable) {
+ ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos].dwFlags = WHDR_DONE;
+ ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos].lpData = (char *) (ft->proto->playbackControl->waveData + ft->proto->playbackControl->waveHeadersPos * ft->proto->playbackControl->waveFrameSize);
+ ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos].dwBufferLength = ft->proto->playbackControl->waveFrameSize * 2;
+ /*
+ if (availPlayback == 0) {
+ statusTxt = "!! Buffer is empty !!";
+ availPlayback++;
+ waveOutPrepareHeader(playbackControl->hWaveOut, &playbackControl->waveHeaders[playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+ waveOutWrite(playbackControl->hWaveOut, &playbackControl->waveHeaders[playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+ playbackControl->waveHeadersPos = (playbackControl->waveHeadersPos +1) % playbackControl->waveHeadersNum;
+ playbackControl->waveHeaders[playbackControl->waveHeadersPos].dwFlags = WHDR_DONE;
+ playbackControl->waveHeaders[playbackControl->waveHeadersPos].lpData = (char *) (playbackControl->waveData + playbackControl->waveHeadersPos * playbackControl->waveFrameSize);
+ playbackControl->waveHeaders[playbackControl->waveHeadersPos].dwBufferLength = playbackControl->waveFrameSize * 2;
+ }
+ */
+ chunkNum = min(MODE_FRAME_SIZE[codec], (int)(packet->len - 4) / 33);
+ out = (short *)ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos].lpData;
+ for (i=0; i<chunkNum; i++) {
+ for (j=0;j<33;j++) {
+ ft->proto->playbackControl->gsmstate->gsmFrame[j] = packet->packet[i*33 +j +4];
+ }
+ gsm_decode(ft->proto->playbackControl->gsmstate, out);
+ out += 160;
+ }
+ out = (short *)ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos].lpData;
+ val = 0;
+ for (i=0; i<MODE_FRAME_SIZE[codec] * 160; i+=MODE_FRAME_SIZE[codec]) {
+ val += out[i]*out[i];
+ }
+ j = (int)((log10(val) - 4) * 2.35);
+ if (j > VU_METER_LEVELS - 1 ) {
+ j = VU_METER_LEVELS - 1;
+ } else if (j<0) {
+ j = 0;
+ }
+ ft->proto->playbackControl->vuMeter = j;
+ ft->proto->playbackControl->bytesSum += 8 + packet->len;
+ /* Simple logic to avoid huge delays. If a delay is detected a frame is not played */
+ j = ft->proto->availOverrunValue > 0 ? -1 : 0;
+ while (ft->proto->framesAvailableForPlayback > FRAMES_AVAILABLE_MAX_LIMIT) {
+ j = 1;
+ SleepEx(5, FALSE);
+ }
+ ft->proto->availOverrunValue += j;
+ /* 40 frames - 800ms/8kHz */
+ if (ft->proto->availOverrunValue < 40) {
+ ft->proto->framesAvailableForPlayback++;
+ waveOutPrepareHeader(ft->proto->playbackControl->hWaveOut, &ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+ waveOutWrite(ft->proto->playbackControl->hWaveOut, &ft->proto->playbackControl->waveHeaders[ft->proto->playbackControl->waveHeadersPos], sizeof(WAVEHDR));
+ ft->proto->playbackControl->waveHeadersPos = (ft->proto->playbackControl->waveHeadersPos +1) % ft->proto->playbackControl->waveHeadersNum;
+ } else {
+ ft->proto->availOverrunValue -= 10;
+ statusTxt = "!! Skipping frame !!";
+ }
+ }
+ }
+ }
+ {
+ char ttt[2048];
+ sprintf(ttt, "%s %d %d ", statusTxt, ft->proto->framesAvailableForPlayback, ft->proto->availOverrunValue);
+ SetDlgItemTextA(ft->proto->voiceDlgHWND, IDC_STATUS, ttt);
+ }
+ TlenP2PPacketFree(packet);
+ }
+ else {
+ if (ft->proto->playbackControl != NULL) {
+ TlenVoiceFreeVc(ft->proto->playbackControl);
+ ft->proto->playbackControl = NULL;
+ }
+ ft->state = FT_ERROR;
+ }
+}
+
+
+void __cdecl TlenVoiceSendingThread(TLEN_FILE_TRANSFER *ft)
+{
+ JABBER_SOCKET s = NULL;
+ HANDLE hEvent;
+ char *nick;
+
+ JabberLog(ft->proto, "Thread started: type=voice_send");
+ ft->pfnNewConnectionV2 = TlenVoiceReceivingConnection;
+ s = TlenP2PListen(ft);
+ if (s != NULL) {
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Waiting for connection..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ ft->s = s;
+ //JabberLog("ft->s = %d", s);
+ //JabberLog("fileCount = %d", ft->fileCount);
+
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ft->hFileEvent = hEvent;
+ ft->currentFile = 0;
+ ft->state = FT_CONNECTING;
+
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<v t='%s' i='%s' e='6' a='%s' p='%d'/>", nick, ft->iqId, ft->localName, ft->wLocalPort);
+ mir_free(nick);
+ JabberLog(ft->proto, "Waiting for the voice data to be sent...");
+ WaitForSingleObject(hEvent, INFINITE);
+ ft->hFileEvent = NULL;
+ CloseHandle(hEvent);
+ JabberLog(ft->proto, "Finish voice");
+ Netlib_CloseHandle(s);
+ ft->s = NULL;
+ JabberLog(ft->proto, "ft->s is NULL");
+
+ if (ft->state == FT_SWITCH) {
+ NETLIBOPENCONNECTION nloc;
+ JABBER_SOCKET s;
+ JabberLog(ft->proto, "Sending as client...");
+ ft->state = FT_CONNECTING;
+ nloc.cbSize = NETLIBOPENCONNECTION_V1_SIZE;//sizeof(NETLIBOPENCONNECTION);
+ nloc.szHost = ft->hostName;
+ nloc.wPort = ft->wPort;
+ nloc.flags = 0;
+ s = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) ft->proto->hNetlibUser, (LPARAM) &nloc);
+ if (s != NULL) {
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Connecting..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, ft, 0);
+ ft->s = s;
+ TlenP2PEstablishOutgoingConnection(ft, FALSE);
+ if (ft->state != FT_ERROR) {
+ JabberLog(ft->proto, "Entering send loop for this file connection...");
+ ft->proto->playbackControl = NULL;
+ ft->proto->recordingControl = TlenVoiceCreateVC(ft->proto, 3);
+ ft->proto->recordingControl->ft = ft;
+ TlenVoiceRecordingStart(ft->proto->recordingControl);
+ while (ft->state != FT_DONE && ft->state != FT_ERROR) {
+ TlenVoiceReceiveParse(ft);
+ }
+ }
+ JabberLog(ft->proto, "Closing connection for this file transfer... ");
+ Netlib_CloseHandle(s);
+ } else {
+ ft->state = FT_ERROR;
+ }
+ }
+ } else {
+ JabberLog(ft->proto, "Cannot allocate port to bind for file server thread, thread ended.");
+ ft->state = FT_ERROR;
+ }
+ JabberListRemove(ft->proto, LIST_VOICE, ft->iqId);
+ switch (ft->state) {
+ case FT_DONE:
+ JabberLog(ft->proto, "Finish successfully");
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Finished..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
+ break;
+ case FT_DENIED:
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Denied..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0);
+ break;
+ default: // FT_ERROR:
+ nick = JabberNickFromJID(ft->jid);
+ JabberSend(ft->proto, "<v t='%s' i='%s' e='8'/>", nick, ft->iqId);
+ mir_free(nick);
+ JabberLog(ft->proto, "Finish with errors");
+ SetDlgItemText(ft->proto->voiceDlgHWND, IDC_STATUS, TranslateT("...Error..."));
+ //ProtoBroadcastAck(ft->proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ break;
+ }
+ JabberLog(ft->proto, "Thread ended: type=voice_send");
+ TlenP2PFreeFileTransfer(ft);
+}
+
+static void TlenVoiceSendParse(TLEN_FILE_TRANSFER *ft)
+{
+ int codec, i;
+ TLEN_FILE_PACKET *packet;
+
+ codec = ft->proto->recordingControl->codec;
+ if ((packet=TlenP2PPacketCreate(sizeof(DWORD)+MODE_FRAME_SIZE[codec]*33)) != NULL) {
+ short *in;
+ float val;
+ in = ft->proto->recordingControl->recordingData;
+ TlenP2PPacketSetType(packet, 0x96);
+ packet->packet[0] = codec;
+ TlenP2PPacketPackDword(packet, codec);
+ val = 0;
+ for (i=0; i<MODE_FRAME_SIZE[codec] * 160; i+=MODE_FRAME_SIZE[codec]) {
+ val += in[i]*in[i];
+ }
+ i = (int)((log10(val) - 4) * 2.35);
+ if (i > VU_METER_LEVELS - 1 ) {
+ i = VU_METER_LEVELS - 1;
+ } else if (i<0) {
+ i = 0;
+ }
+ ft->proto->recordingControl->vuMeter = i;
+ for (i=0; i<MODE_FRAME_SIZE[codec]; i++) {
+ gsm_encode(ft->proto->recordingControl->gsmstate, in + i * 160);
+ TlenP2PPacketPackBuffer(packet, (char*)ft->proto->recordingControl->gsmstate->gsmFrame, 33);
+ }
+ TlenVoiceCrypt(packet->packet+4, packet->len-4);
+ if (!TlenP2PPacketSend(ft->s, packet)) {
+ ft->state = FT_ERROR;
+ }
+ ft->proto->recordingControl->bytesSum += 8 + packet->len;
+ TlenP2PPacketFree(packet);
+ } else {
+ ft->state = FT_ERROR;
+ }
+}
+
+int TlenVoiceCancelAll(TlenProtocol *proto)
+{
+ JABBER_LIST_ITEM *item;
+ HANDLE hEvent;
+ int i = 0;
+
+ while ((i=JabberListFindNext(proto, LIST_VOICE, 0)) >=0 ) {
+ if ((item=JabberListGetItemPtrFromIndex(proto, i)) != NULL) {
+ TLEN_FILE_TRANSFER *ft = item->ft;
+ JabberListRemoveByIndex(proto, i);
+ if (ft != NULL) {
+ if (ft->s) {
+ //ProtoBroadcastAck(proto->m_szModuleName, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
+ JabberLog(proto, "Closing ft->s = %d", ft->s);
+ ft->state = FT_ERROR;
+ Netlib_CloseHandle(ft->s);
+ ft->s = NULL;
+ if (ft->hFileEvent != NULL) {
+ hEvent = ft->hFileEvent;
+ ft->hFileEvent = NULL;
+ SetEvent(hEvent);
+ }
+ } else {
+ JabberLog(proto, "freeing (V) ft struct");
+ TlenP2PFreeFileTransfer(ft);
+ }
+ }
+ }
+ }
+ if (proto->voiceDlgHWND != NULL) {
+ EndDialog(proto->voiceDlgHWND, 0);
+ }
+ return 0;
+}
+
+INT_PTR TlenVoiceContactMenuHandleVoice(void *ptr, LPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact;
+ DBVARIANT dbv;
+ JABBER_LIST_ITEM *item;
+ TLEN_FILE_TRANSFER *ft;
+ TlenProtocol *proto =(TlenProtocol *)ptr;
+ if (!proto->isOnline) {
+ return 1;
+ }
+ if ((hContact=(HANDLE) wParam) != NULL) {
+ if (!DBGetContactSetting(hContact, proto->m_szModuleName, "jid", &dbv)) {
+ char serialId[32];
+ sprintf(serialId, "%d", JabberSerialNext(proto));
+ if ((item = JabberListAdd(proto, LIST_VOICE, serialId)) != NULL) {
+ ft = TlenFileCreateFT(proto, dbv.pszVal);
+ ft->iqId = mir_strdup(serialId);
+ item->ft = ft;
+// JabberSend(ft->proto, "<iq to='%s'><query xmlns='voip'><voip k='1' s='1' v='1' i='51245604'/></query></iq>", ft->jid);
+// Sleep(5000);
+ TlenVoiceStart(ft, 2);
+ JabberSend(ft->proto, "<v t='%s' e='1' i='%s' v='1'/>", ft->jid, serialId);
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ return 0;
+}
+
+int TlenVoiceIsInUse(TlenProtocol *proto) {
+ if (JabberListFindNext(proto, LIST_VOICE, 0) >= 0 || proto->voiceDlgHWND != NULL) {
+ JabberLog(proto, "voice in use ? %d", proto->voiceDlgHWND);
+ return 1;
+ }
+ return 0;
+}
+
+static HBITMAP TlenVoiceMakeBitmap(int w, int h, int bpp, void *ptr)
+{
+ BITMAPINFO bmih;
+ HBITMAP hbm;
+ HDC hdc;
+ bmih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmih.bmiHeader.biWidth = w&0xFFFFFFFC;
+ bmih.bmiHeader.biHeight = h;//&0xFFFFFFFC;
+ bmih.bmiHeader.biPlanes = 1; // musi byc 1
+ bmih.bmiHeader.biBitCount = bpp;
+ bmih.bmiHeader.biCompression = BI_RGB;
+ bmih.bmiHeader.biSizeImage = 0;
+ bmih.bmiHeader.biXPelsPerMeter = 0;
+ bmih.bmiHeader.biYPelsPerMeter = 0;
+ bmih.bmiHeader.biClrUsed = 0;
+ bmih.bmiHeader.biClrImportant = 0;
+ hdc = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
+ hbm = CreateDIBitmap(hdc, (PBITMAPINFOHEADER) &bmih, CBM_INIT, ptr, &bmih, DIB_RGB_COLORS);
+ ReleaseDC(NULL,hdc);
+ return hbm;
+}
+
+static void TlenVoiceInitVUMeters()
+{
+ int i, v, y, x, x0, col, col0;
+ unsigned char *pBits;
+ int ledWidth, ledHeight;
+ ledWidth = 9;
+ ledHeight = 6;
+ VU_METER_HEIGHT = ledHeight;
+ VU_METER_WIDTH = (VU_METER_LEVELS-1) * ledWidth;
+ VU_METER_WIDTH = (VU_METER_WIDTH + 3) & (~3);
+ pBits = (unsigned char *)mir_alloc(3*VU_METER_WIDTH*VU_METER_HEIGHT);
+ memset(pBits, 0x80, 3*VU_METER_WIDTH*VU_METER_HEIGHT);
+ for (i=0;i<VU_METER_LEVELS;i++) {
+ for (v=0;v<VU_METER_LEVELS-1;v++) {
+ if (v >= i) {
+ if (v < 10) col0 = 0x104010;
+ else if (v<13) col0 = 0x404010;
+ else col0 = 0x401010;
+ } else {
+ if (v < 10) col0 = 0x00f000;
+ else if (v<13) col0 = 0xf0f000;
+ else col0 = 0xf00000;
+ }
+ x0 = v * ledWidth;
+ for (y=1;y<VU_METER_HEIGHT-1;y++) {
+ col = col0;
+ for (x=1;x<ledWidth;x++) {
+ pBits[3*(x+x0+y*VU_METER_WIDTH)] = col &0xFF;
+ pBits[3*(x+x0+y*VU_METER_WIDTH)+1] = (col>>8) &0xFF;
+ pBits[3*(x+x0+y*VU_METER_WIDTH)+2] = (col>>16) &0xFF;
+ }
+ }
+ }
+ vuMeterBitmaps[i] = TlenVoiceMakeBitmap(VU_METER_WIDTH, VU_METER_HEIGHT, 24, pBits);
+ }
+ mir_free(pBits);
+}
+
+static INT_PTR CALLBACK TlenVoiceDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hDC, hMemDC;
+ int v;
+ static int counter;
+ TlenProtocol *proto = (TlenProtocol *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ proto = (TlenProtocol *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)proto);
+ proto->voiceDlgHWND = hwndDlg;
+ TranslateDialogDefault(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_ADDSTRING, 0, (LPARAM) TranslateT("8000 Hz / 13.8 kbps"));
+ SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_ADDSTRING, 0, (LPARAM) TranslateT("11025 Hz / 19.1 kbps"));
+ SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_ADDSTRING, 0, (LPARAM) TranslateT("22050 Hz / 36.8 kbps"));
+ SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_ADDSTRING, 0, (LPARAM) TranslateT("44100 Hz / 72 kbps"));
+ SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_SETCURSEL, 1, 0);
+ SendDlgItemMessage(hwndDlg, IDC_MICROPHONE, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_SPEAKER, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_MICROPHONE, BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_SPEAKER, BUTTONSETASPUSHBTN, TRUE, 0);
+ {
+ HICON hIcon = GetIcolibIcon(IDI_MICROPHONE);
+ SendDlgItemMessage(hwndDlg, IDC_MICROPHONE, BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
+ ReleaseIcolibIcon(hIcon);
+ hIcon = GetIcolibIcon(IDI_SPEAKER);
+ SendDlgItemMessage(hwndDlg, IDC_SPEAKER, BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
+ ReleaseIcolibIcon(hIcon);
+ }
+ CheckDlgButton(hwndDlg, IDC_MICROPHONE, TRUE);
+ CheckDlgButton(hwndDlg, IDC_SPEAKER, TRUE);
+ TlenVoiceInitVUMeters();
+ SetDlgItemText(hwndDlg, IDC_STATUS, TranslateT("...???..."));
+ counter = 0;
+ SetTimer(hwndDlg, 1, 100, NULL);
+ return FALSE;
+ case WM_TIMER:
+ if (proto->recordingControl != NULL && !proto->recordingControl->bDisable) {
+ v = proto->recordingControl->vuMeter % VU_METER_LEVELS;
+ if (proto->recordingControl->vuMeter >0) {
+ proto->recordingControl->vuMeter--;
+ }
+ } else {
+ v = 0;
+ }
+ hDC = GetDC(GetDlgItem(hwndDlg, IDC_VUMETERIN));
+ if (NULL != (hMemDC = CreateCompatibleDC( hDC ))) {
+ SelectObject( hMemDC, vuMeterBitmaps[v]) ;
+ BitBlt( hDC, 0, 0, VU_METER_WIDTH, VU_METER_HEIGHT, hMemDC, 0, 0, SRCCOPY ) ;
+ DeleteDC(hMemDC);
+ }
+ ReleaseDC(GetDlgItem(hwndDlg, IDC_PLAN), hDC);
+ if (proto->playbackControl != NULL && !proto->playbackControl->bDisable) {
+ v = proto->playbackControl->vuMeter % VU_METER_LEVELS;
+ if (proto->playbackControl->vuMeter >0) {
+ proto->playbackControl->vuMeter--;
+ }
+ } else {
+ v = 0;
+ }
+ hDC = GetDC(GetDlgItem(hwndDlg, IDC_VUMETEROUT));
+ if (NULL != (hMemDC = CreateCompatibleDC( hDC ))) {
+ SelectObject( hMemDC, vuMeterBitmaps[v]) ;
+ BitBlt( hDC, 0, 0, VU_METER_WIDTH, VU_METER_HEIGHT, hMemDC, 0, 0, SRCCOPY ) ;
+ DeleteDC(hMemDC);
+ }
+ ReleaseDC(GetDlgItem(hwndDlg, IDC_PLAN), hDC);
+ counter ++;
+ if (counter %10 == 0) {
+ char str[50];
+ float fv;
+ if (proto->recordingControl != NULL) {
+ fv = (float)proto->recordingControl->bytesSum;
+ proto->recordingControl->bytesSum = 0;
+ } else {
+ fv = 0;
+ }
+ sprintf(str, "%.1f kB/s", fv / 1024);
+ SetDlgItemTextA(hwndDlg, IDC_BYTESOUT, str);
+ if (proto->playbackControl != NULL) {
+ fv = (float)proto->playbackControl->bytesSum;
+ proto->playbackControl->bytesSum = 0;
+ } else {
+ fv = 0;
+ }
+ sprintf(str, "%.1f kB/s", fv / 1024);
+ SetDlgItemTextA(hwndDlg, IDC_BYTESIN, str);
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ case IDC_VCQUALITY:
+ if (HIWORD(wParam) == CBN_SELCHANGE) {
+ if (proto->recordingControl != NULL) {
+ int codec;
+ codec = SendDlgItemMessage(hwndDlg, IDC_VCQUALITY, CB_GETCURSEL, 0, 0) + 2;
+ if (codec != proto->recordingControl->codec && codec > 1 && codec < 6) {
+ TLEN_FILE_TRANSFER *ft = proto->recordingControl->ft;
+ TlenVoiceFreeVc(proto->recordingControl);
+ proto->recordingControl = TlenVoiceCreateVC(ft->proto, codec);
+ proto->recordingControl->ft = ft;
+ TlenVoiceRecordingStart(proto->recordingControl);
+ }
+ }
+ }
+ case IDC_MICROPHONE:
+ if (proto->recordingControl != NULL) {
+ proto->recordingControl->bDisable = !IsDlgButtonChecked(hwndDlg, IDC_MICROPHONE);
+ }
+ break;
+ case IDC_SPEAKER:
+ if (proto->playbackControl != NULL) {
+ proto->playbackControl->bDisable = !IsDlgButtonChecked(hwndDlg, IDC_SPEAKER);
+ }
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ proto->voiceDlgHWND = NULL;
+ break;
+
+ }
+ return FALSE;
+}
+
+static void __cdecl TlenVoiceDlgThread(void *ptr)
+{
+
+ TLEN_FILE_TRANSFER *ft = (TLEN_FILE_TRANSFER *)ptr;
+ TlenProtocol * proto = ft->proto;
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_VOICE), NULL, TlenVoiceDlgProc, (LPARAM) proto);
+ TlenVoiceCancelAll(proto);
+}
+
+int TlenVoiceStart(TLEN_FILE_TRANSFER *ft, int mode)
+{
+
+ JabberLog(ft->proto, "starting voice %d", mode);
+ if (mode == 0) {
+ JabberForkThread((void (__cdecl *)(void*))TlenVoiceReceiveThread, 0, ft);
+ } else if (mode == 1) {
+ JabberForkThread((void (__cdecl *)(void*))TlenVoiceSendingThread, 0, ft);
+ } else {
+ JabberForkThread((void (__cdecl *)(void*))TlenVoiceDlgThread, 0, ft);
+ }
+ return 0;
+}
+
+static char *getDisplayName(TlenProtocol *proto, const char *id)
+{
+ char jid[256];
+ HANDLE hContact;
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", id, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ if ((hContact=JabberHContactFromJID(proto, jid)) != NULL) {
+ return mir_strdup((char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0));
+ }
+ }
+ return mir_strdup(id);
+}
+
+typedef struct {
+ TlenProtocol *proto;
+ JABBER_LIST_ITEM *item;
+}ACCEPTDIALOGDATA;
+
+static INT_PTR CALLBACK TlenVoiceAcceptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ACCEPTDIALOGDATA * data;
+ char *str;
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ data = (ACCEPTDIALOGDATA *) lParam;
+ str = getDisplayName(data->proto, data->item->nick);
+ SetDlgItemTextA(hwndDlg, IDC_FROM, str);
+ mir_free(str);
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_ACCEPT:
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+ case IDCANCEL:
+ case IDCLOSE:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ }
+ return FALSE;
+}
+
+static void __cdecl TlenVoiceAcceptDlgThread(void *ptr)
+{
+
+ ACCEPTDIALOGDATA *data = (ACCEPTDIALOGDATA *)ptr;
+ int result = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ACCEPT_VOICE), NULL, TlenVoiceAcceptDlgProc, (LPARAM) data);
+ if (result && data->proto->isOnline) {
+ data->item->ft = TlenFileCreateFT(data->proto, data->item->nick);
+ data->item->ft->iqId = mir_strdup(data->item->jid);
+ TlenVoiceStart(data->item->ft, 2);
+ JabberSend(data->proto, "<v t='%s' i='%s' e='5' v='1'/>", data->item->nick, data->item->jid);
+ } else {
+ if (data->proto->isOnline) {
+ JabberSend(data->proto, "<v t='%s' i='%s' e='4' />", data->item->nick, data->item->jid);
+ }
+ JabberListRemove(data->proto, LIST_VOICE, data->item->jid);
+ }
+ mir_free(data);
+}
+
+int TlenVoiceAccept(TlenProtocol *proto, const char *id, const char *from)
+{
+ JABBER_LIST_ITEM * item;
+ if (!TlenVoiceIsInUse(proto)) {
+ if ((item = JabberListAdd(proto, LIST_VOICE, id)) != NULL) {
+ int ask, ignore, voiceChatPolicy;
+ ask = TRUE;
+ ignore = FALSE;
+ voiceChatPolicy = DBGetContactSettingWord(NULL, proto->m_szModuleName, "VoiceChatPolicy", 0);
+ if (voiceChatPolicy == TLEN_MUC_ASK) {
+ ignore = FALSE;
+ ask = TRUE;
+ } else if (voiceChatPolicy == TLEN_MUC_IGNORE_ALL) {
+ ignore = TRUE;
+ } else if (voiceChatPolicy == TLEN_MUC_IGNORE_NIR) {
+ char jid[256];
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ strcpy(jid, from);
+ }
+ ignore = !IsAuthorized(proto, jid);
+ ask = TRUE;
+ } else if (voiceChatPolicy == TLEN_MUC_ACCEPT_IR) {
+ char jid[256];
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL, proto->m_szModuleName, "LoginServer", &dbv)) {
+ _snprintf(jid, sizeof(jid), "%s@%s", from, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ strcpy(jid, from);
+ }
+ ask = !IsAuthorized(proto, jid);
+ ignore = FALSE;
+ } else if (voiceChatPolicy == TLEN_MUC_ACCEPT_ALL) {
+ ask = FALSE;
+ ignore = FALSE;
+ }
+ if (ignore) {
+ if (proto->isOnline) {
+ JabberSend(proto, "<v t='%s' i='%s' e='4' />", from, id);
+ }
+ JabberListRemove(proto, LIST_VOICE, id);
+ } else {
+ item->nick = mir_strdup(from);
+ if (ask) {
+ ACCEPTDIALOGDATA *data = (ACCEPTDIALOGDATA *)mir_alloc(sizeof(ACCEPTDIALOGDATA));
+ data->proto = proto;
+ data->item = item;
+ JabberForkThread((void (__cdecl *)(void*))TlenVoiceAcceptDlgThread, 0, data);
+ } else if (proto->isOnline) {
+ item->ft = TlenFileCreateFT(proto, from);
+ item->ft->iqId = mir_strdup(id);
+ TlenVoiceStart(item->ft, 2);
+ JabberSend(proto, "<v t='%s' i='%s' e='5' v='1'/>", item->nick, item->jid);
+ }
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int TlenVoiceBuildInDeviceList(TlenProtocol *proto, HWND hWnd)
+{ int i, j, iNumDevs;
+ WAVEINCAPS wic;
+ iNumDevs = waveInGetNumDevs();
+ SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)TranslateT("Default"));
+ for (i = j = 0; i < iNumDevs; i++) {
+ if (!waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS))) {
+ if (wic.dwFormats != 0) {
+ SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)wic.szPname);
+ j++;
+ }
+ }
+ }
+ i = DBGetContactSettingWord(NULL, proto->m_szModuleName, "VoiceDeviceIn", 0);
+ if (i>j) i = 0;
+ SendMessage(hWnd, CB_SETCURSEL, i, 0);
+ return 0;
+}
+
+int TlenVoiceBuildOutDeviceList(TlenProtocol *proto, HWND hWnd)
+{ int i, j, iNumDevs;
+ WAVEOUTCAPS woc;
+ iNumDevs = waveInGetNumDevs();
+ SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)TranslateT("Default"));
+ for (i = j = 0; i < iNumDevs; i++) {
+ if (!waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS))) {
+ if (woc.dwFormats != 0) {
+ SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)woc.szPname);
+ j++;
+ }
+ }
+ }
+ i = DBGetContactSettingWord(NULL, proto->m_szModuleName, "VoiceDeviceOut", 0);
+ if (i>j) i = 0;
+ SendMessage(hWnd, CB_SETCURSEL, i, 0);
+ return 0;
+}
diff --git a/protocols/Tlen/src/tlen_voice.h b/protocols/Tlen/src/tlen_voice.h
new file mode 100644
index 0000000000..0018bb6e17
--- /dev/null
+++ b/protocols/Tlen/src/tlen_voice.h
@@ -0,0 +1,70 @@
+/*
+
+Tlen Protocol Plugin for Miranda NG
+Copyright (C) 2004-2007 Piotr Piastucki
+
+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.
+
+*/
+
+#ifndef _TLEN_VOICE_H_
+#define _TLEN_VOICE_H_
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "jabber.h"
+extern "C" {
+ #include "codec/gsm.h"
+}
+
+typedef struct TLEN_VOICE_CONTROL_STRUCT {
+ int waveMode;
+ int codec;
+ int bDisable;
+
+ short *recordingData;
+ short *waveData;
+ WAVEHDR *waveHeaders;
+ int waveFrameSize;
+ int waveHeadersPos;
+ int waveHeadersNum;
+
+// HANDLE hEvent;
+ HANDLE hThread;
+ DWORD threadID;
+ HWAVEOUT hWaveOut;
+ HWAVEIN hWaveIn;
+ int isRunning;
+ int stopThread;
+ gsm_state *gsmstate;
+ TLEN_FILE_TRANSFER *ft;
+ int vuMeter;
+ int bytesSum;
+ TlenProtocol *proto;
+} TLEN_VOICE_CONTROL;
+
+
+extern void __cdecl TlenVoiceSendingThread(TLEN_FILE_TRANSFER *ft);
+extern void __cdecl TlenVoiceReceiveThread(TLEN_FILE_TRANSFER *ft);
+extern int TlenVoiceIsInUse(TlenProtocol *proto);
+extern INT_PTR TlenVoiceContactMenuHandleVoice(void *ptr, LPARAM wParam, LPARAM lParam);
+extern int TlenVoiceCancelAll(TlenProtocol *proto);
+extern int TlenVoiceStart(TLEN_FILE_TRANSFER *ft, int mode) ;
+extern int TlenVoiceAccept(TlenProtocol *proto, const char *id, const char *from);
+extern int TlenVoiceBuildInDeviceList(TlenProtocol *proto, HWND hWnd);
+extern int TlenVoiceBuildOutDeviceList(TlenProtocol *proto, HWND hWnd);
+#endif
+
diff --git a/protocols/Tlen/tlen_10.vcxproj b/protocols/Tlen/tlen_10.vcxproj
new file mode 100644
index 0000000000..4e5b9c1a8c
--- /dev/null
+++ b/protocols/Tlen/tlen_10.vcxproj
@@ -0,0 +1,366 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>Tlen</ProjectName>
+ <ProjectGuid>{F3208C96-3C21-46AA-8695-C794E28CDC34}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/jabber.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../../plugins/ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JABBER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderFile>jabber.h</PrecompiledHeaderFile>
+ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <BaseAddress>0x32500000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release/jabber.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../../plugins/ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JABBER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderFile>jabber.h</PrecompiledHeaderFile>
+ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win64%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <BaseAddress>0x32500000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/jabber.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../../plugins/ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JABBER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderFile>jabber.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x32500000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/jabber.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../../plugins/ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JABBER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Precise</FloatingPointModel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderFile>jabber.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>
+ </AssemblerListingLocation>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <GenerateMapFile>false</GenerateMapFile>
+ <MapFileName>
+ </MapFileName>
+ <BaseAddress>0x32500000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\crypto\aes.c" />
+ <ClCompile Include="src\crypto\bignum.c" />
+ <ClCompile Include="src\codec\gsm_codec.c" />
+ <ClCompile Include="src\codec\gsm_long.c" />
+ <ClCompile Include="src\codec\gsm_lpc.c" />
+ <ClCompile Include="src\codec\gsm_preprocess.c" />
+ <ClCompile Include="src\codec\gsm_rpe.c" />
+ <ClCompile Include="src\codec\gsm_short.c" />
+ <ClCompile Include="src\jabber_iq.cpp" />
+ <ClCompile Include="src\jabber_iqid.cpp" />
+ <ClCompile Include="src\jabber_list.cpp" />
+ <ClCompile Include="src\jabber_misc.cpp" />
+ <ClCompile Include="src\jabber_opt.cpp" />
+ <ClCompile Include="src\jabber_svc.cpp" />
+ <ClCompile Include="src\jabber_thread.cpp" />
+ <ClCompile Include="src\jabber_util.cpp" />
+ <ClCompile Include="src\jabber_ws.cpp" />
+ <ClCompile Include="src\jabber_xml.cpp" />
+ <ClCompile Include="src\crypto\padlock.c" />
+ <ClCompile Include="src\tlen.cpp" />
+ <ClCompile Include="src\tlen_advsearch.cpp" />
+ <ClCompile Include="src\tlen_avatar.cpp" />
+ <ClCompile Include="src\tlen_file.cpp" />
+ <ClCompile Include="src\tlen_muc.cpp" />
+ <ClCompile Include="src\tlen_p2p_new.cpp" />
+ <ClCompile Include="src\tlen_p2p_old.cpp" />
+ <ClCompile Include="src\tlen_picture.cpp" />
+ <ClCompile Include="src\tlen_presence.cpp" />
+ <ClCompile Include="src\tlen_userinfo.cpp" />
+ <ClCompile Include="src\tlen_voice.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\tlen.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\commons.h" />
+ <ClInclude Include="src\crypto\polarssl\aes.h" />
+ <ClInclude Include="src\crypto\polarssl\bignum.h" />
+ <ClInclude Include="src\crypto\polarssl\bn_mul.h" />
+ <ClInclude Include="src\crypto\polarssl\config.h" />
+ <ClInclude Include="src\codec\gsm.h" />
+ <ClInclude Include="src\jabber.h" />
+ <ClInclude Include="src\jabber_iq.h" />
+ <ClInclude Include="src\jabber_list.h" />
+ <ClInclude Include="src\jabber_xml.h" />
+ <ClInclude Include="src\crypto\polarssl\padlock.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\tlen_avatar.h" />
+ <ClInclude Include="src\tlen_file.h" />
+ <ClInclude Include="src\tlen_muc.h" />
+ <ClInclude Include="src\tlen_p2p_old.h" />
+ <ClInclude Include="src\tlen_picture.h" />
+ <ClInclude Include="src\tlen_presence.h" />
+ <ClInclude Include="src\tlen_voice.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\auth_grant.ico" />
+ <None Include="res\auth_request.ico" />
+ <None Include="res\groupchats.ico" />
+ <None Include="res\image.ico" />
+ <None Include="res\mail.ico" />
+ <None Include="res\microphone.ico" />
+ <None Include="res\speaker.ico" />
+ <None Include="res\tlen.ico" />
+ <None Include="res\tlenbig.ico" />
+ <None Include="res\tlenchats.ico" />
+ <None Include="res\tlensmall.ico" />
+ <None Include="res\voicechat.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Tlen/tlen_10.vcxproj.filters b/protocols/Tlen/tlen_10.vcxproj.filters
new file mode 100644
index 0000000000..2893437d57
--- /dev/null
+++ b/protocols/Tlen/tlen_10.vcxproj.filters
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="src\crypto\aes.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\crypto\bignum.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_codec.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_long.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_lpc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_preprocess.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_rpe.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\codec\gsm_short.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\crypto\padlock.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_iq.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_iqid.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_list.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_misc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_opt.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_svc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_thread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_ws.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\jabber_xml.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_advsearch.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_avatar.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_file.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_muc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_p2p_new.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_p2p_old.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_picture.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_presence.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_userinfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tlen_voice.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\crypto\polarssl\aes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\crypto\polarssl\bignum.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\crypto\polarssl\bn_mul.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\crypto\polarssl\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\codec\gsm.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\jabber_iq.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\jabber.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\jabber_list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_voice.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_presence.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_picture.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_p2p_old.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_muc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_file.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\tlen_avatar.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\crypto\polarssl\padlock.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\jabber_xml.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\commons.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\auth_grant.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\auth_request.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\groupchats.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\image.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\mail.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\microphone.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\speaker.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tlen.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tlenbig.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tlenchats.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tlensmall.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\voicechat.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{35b6da69-06c9-4f34-901c-823e97f865fd}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{a2b613e9-0050-4e07-8d72-9fbd35d80c8d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{c8abc1f0-582c-43c8-bbe4-043b9c119339}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\tlen.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Tlen/tlen_czaty/mucc.vcxproj b/protocols/Tlen/tlen_czaty/mucc.vcxproj
new file mode 100644
index 0000000000..d74899057f
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/mucc.vcxproj
@@ -0,0 +1,479 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>TlenCzaty</ProjectName>
+ <ProjectGuid>{BD1D155A-7A47-4414-80A3-CCCC3C5C583B}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">tlen_czaty</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">tlen_czaty</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">tlen_czaty</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">tlen_czaty</TargetName>
+ <IgnoreImportLibrary>false</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release/mucc.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MUCC_EXPORTS;UNICODE;_UNICODE;_X64;X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0415</Culture>
+ </ResourceCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <ProgramDatabaseFile>$(TargetDir)tlen_czaty.pdb</ProgramDatabaseFile>
+ <BaseAddress>0x32600000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>$(OutDir)$(TargetName).bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/mucc.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MUCC_EXPORTS;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0415</Culture>
+ </ResourceCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <ProgramDatabaseFile>$(TargetDir)tlen_czaty.pdb</ProgramDatabaseFile>
+ <BaseAddress>0x32600000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>$(OutDir)$(TargetName).bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/mucc.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MUCC_EXPORTS;UNICODE;_UNICODE;X64;_X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0415</Culture>
+ </ResourceCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)tlen_czaty.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>$(OutDir)$(TargetName).bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/mucc.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MUCC_EXPORTS;UNICODE;_UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0415</Culture>
+ </ResourceCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)tlen_czaty.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>$(OutDir)$(TargetName).bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\AdminWindow.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatContainer.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatEvent.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatGroup.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatRoom.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatUser.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ChatWindow.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\FontList.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\HelperDialog.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\ManagerWindow.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\mucc.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\mucc_services.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\Options.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="src\Utils.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\AdminWindow.h" />
+ <ClInclude Include="src\ChatContainer.h" />
+ <ClInclude Include="src\ChatEvent.h" />
+ <ClInclude Include="src\ChatGroup.h" />
+ <ClInclude Include="src\ChatRoom.h" />
+ <ClInclude Include="src\ChatUser.h" />
+ <ClInclude Include="src\ChatWindow.h" />
+ <ClInclude Include="src\FontList.h" />
+ <ClInclude Include="src\HelperDialog.h" />
+ <ClInclude Include="src\ManagerWindow.h" />
+ <ClInclude Include="src\mucc.h" />
+ <ClInclude Include="src\mucc_services.h" />
+ <ClInclude Include="src\Options.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\Utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\admin.ico" />
+ <None Include="res\administration.ico" />
+ <None Include="res\blank.ico" />
+ <None Include="res\bold.ico" />
+ <None Include="res\chat.ico" />
+ <None Include="res\glowner.ico" />
+ <None Include="res\invite.ico" />
+ <None Include="res\italic.ico" />
+ <None Include="res\message.ico" />
+ <None Include="res\moderator.ico" />
+ <None Include="res\next.ico" />
+ <None Include="res\options.ico" />
+ <None Include="res\owner.ico" />
+ <None Include="res\prev.ico" />
+ <None Include="res\r_anon.ico" />
+ <None Include="res\r_memb.ico" />
+ <None Include="res\r_mod.ico" />
+ <None Include="res\registered.ico" />
+ <None Include="res\search.ico" />
+ <None Include="res\smile.ico" />
+ <None Include="res\tlensmall.ico" />
+ <None Include="res\underline.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\mucc.rc">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Tlen/tlen_czaty/mucc.vcxproj.filters b/protocols/Tlen/tlen_czaty/mucc.vcxproj.filters
new file mode 100644
index 0000000000..792e83ddef
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/mucc.vcxproj.filters
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="src\AdminWindow.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\mucc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatContainer.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatEvent.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatGroup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatRoom.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatUser.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ChatWindow.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\FontList.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\HelperDialog.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\ManagerWindow.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\mucc_services.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\Utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\Options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\AdminWindow.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatContainer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatEvent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatGroup.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatRoom.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatUser.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ChatWindow.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\FontList.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\HelperDialog.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\ManagerWindow.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\mucc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\mucc_services.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\admin.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\administration.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\chat.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\blank.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\bold.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\invite.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\glowner.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\italic.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\message.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\moderator.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\next.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\options.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\owner.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\prev.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\r_anon.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\r_memb.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\r_mod.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\registered.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\search.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\smile.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\tlensmall.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\underline.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{acd9ca44-7d7e-4add-a4c6-16614bbf78b6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{b4f7b43d-0f34-4a03-ba3f-90d6ff3b78c8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{170ec188-279a-4f4d-8cf7-5deaccc50346}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\mucc.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Tlen/tlen_czaty/res/admin.ico b/protocols/Tlen/tlen_czaty/res/admin.ico
new file mode 100644
index 0000000000..9699f55d6f
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/admin.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/administration.ico b/protocols/Tlen/tlen_czaty/res/administration.ico
new file mode 100644
index 0000000000..e57884857e
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/administration.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/blank.ico b/protocols/Tlen/tlen_czaty/res/blank.ico
new file mode 100644
index 0000000000..7845f62fed
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/blank.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/bold.ico b/protocols/Tlen/tlen_czaty/res/bold.ico
new file mode 100644
index 0000000000..01d5adda1d
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/bold.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/chat.ico b/protocols/Tlen/tlen_czaty/res/chat.ico
new file mode 100644
index 0000000000..0b388d8f9d
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/chat.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/delete.ico b/protocols/Tlen/tlen_czaty/res/delete.ico
new file mode 100644
index 0000000000..59408c5337
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/delete.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/glowner.ico b/protocols/Tlen/tlen_czaty/res/glowner.ico
new file mode 100644
index 0000000000..86fdf534e9
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/glowner.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/invite.ico b/protocols/Tlen/tlen_czaty/res/invite.ico
new file mode 100644
index 0000000000..bf7dbc4d7a
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/invite.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/italic.ico b/protocols/Tlen/tlen_czaty/res/italic.ico
new file mode 100644
index 0000000000..d34418be24
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/italic.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/message.ico b/protocols/Tlen/tlen_czaty/res/message.ico
new file mode 100644
index 0000000000..40d183b7b3
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/message.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/mucc.rc b/protocols/Tlen/tlen_czaty/res/mucc.rc
new file mode 100644
index 0000000000..27c5224948
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/mucc.rc
@@ -0,0 +1,579 @@
+#include "..\src/resource.h"
+#include "..\..\src/commons.h"
+#ifdef __MINGW32__
+ #define WINVER 0x500
+ #define _WIN32_IE 0x500
+ #include <windows.h>
+ #ifndef IDC_STATIC
+ #define IDC_STATIC (-1)
+#endif
+#else
+// #define APSTUDIO_READONLY_SYMBOLS
+// #include "winres.h"
+// #undef APSTUDIO_READONLY_SYMBOLS
+ #include <windows.h>
+ #ifndef IDC_STATIC
+ #define IDC_STATIC (-1)
+ #endif
+#endif
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif
+#ifdef APSTUDIO_INVOKED
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+IDR_CHATOPTIONS MENU DISCARDABLE
+BEGIN
+ POPUP "", MENUBREAK
+ BEGIN
+ POPUP "Log Appearance"
+ BEGIN
+ MENUITEM "Show Nicknames", ID_OPTIONMENU_SHOWNICKNAMES
+ MENUITEM "Show Message On A New Line", ID_OPTIONMENU_MSGINNEWLINE
+ END
+ POPUP "Timestamp Settings"
+ BEGIN
+ MENUITEM "Show Date", ID_OPTIONMENU_SHOWDATE
+ MENUITEM "Show Timestamp", ID_OPTIONMENU_SHOWTIMESTAMP
+ MENUITEM "Show Seconds", ID_OPTIONMENU_SHOWSECONDS
+ MENUITEM "Use Long Date Format", ID_OPTIONMENU_USELONGDATE
+
+ END
+ POPUP "Text Formatting Filter"
+ BEGIN
+ MENUITEM "Font Name", ID_OPTIONMENU_FORMATFONT
+ MENUITEM "Font Size", ID_OPTIONMENU_FORMATSIZE
+ MENUITEM "Font Style", ID_OPTIONMENU_FORMATSTYLE
+ MENUITEM "Font Color", ID_OPTIONMENU_FORMATCOLOR
+ END
+ POPUP "Event Filter"
+ BEGIN
+ MENUITEM "Messages", ID_OPTIONMENU_LOGMESSAGES
+ MENUITEM "User Has Joined", ID_OPTIONMENU_LOGJOINED
+ MENUITEM "User Has Left", ID_OPTIONMENU_LOGLEFT
+ MENUITEM "Topic Changes", ID_OPTIONMENU_LOGTOPIC
+ END
+ POPUP "Window Flashing"
+ BEGIN
+ MENUITEM "Messages", ID_OPTIONMENU_FLASHMESSAGES
+ MENUITEM "User Has Joined", ID_OPTIONMENU_FLASHJOINED
+ MENUITEM "User Has Left", ID_OPTIONMENU_FLASHLEFT
+ MENUITEM "Topic Changes", ID_OPTIONMENU_FLASHTOPIC
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Save Settings As Default", ID_OPTIONMENU_SAVEDEFAULT
+ MENUITEM SEPARATOR
+ MENUITEM "User Administration", ID_ADMINMENU_ADMIN, GRAYED
+ MENUITEM "Destroy Chat Room", ID_ADMINMENU_DESTROY, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Save Log", ID_ADMINMENU_SAVELOG
+ END
+ POPUP "", MENUBREAK
+ BEGIN
+ MENUITEM "Message", ID_USERMENU_MESSAGE
+ MENUITEM SEPARATOR
+ POPUP "Kick && Ban", GRAYED
+ BEGIN
+ MENUITEM "No Ban", ID_USERMENU_KICK_NO_BAN
+ MENUITEM "Ban For 1 Minute", ID_USERMENU_KICK_BAN_1_MIN
+ MENUITEM "Ban For 5 Minutes", ID_USERMENU_KICK_BAN_5_MIN
+ MENUITEM "Ban For 15 Minutes", ID_USERMENU_KICK_BAN_15_MIN
+ MENUITEM "Ban For 30 Minutes", ID_USERMENU_KICK_BAN_15_MIN
+ MENUITEM "Ban For 1 Hour", ID_USERMENU_KICK_BAN_1_H
+ MENUITEM "Ban For 6 Hours", ID_USERMENU_KICK_BAN_6_H
+ MENUITEM "Ban For 1 Day", ID_USERMENU_KICK_BAN_1_D
+ MENUITEM "Ban For 3 Days", ID_USERMENU_KICK_BAN_3_D
+ MENUITEM "Ban For 1 Week", ID_USERMENU_KICK_BAN_1_W
+ MENUITEM "Ban For 2 Weeks", ID_USERMENU_KICK_BAN_2_W
+ MENUITEM "Ban For 4 Weeks", ID_USERMENU_KICK_BAN_4_W
+ END
+ POPUP "Change User Role", GRAYED
+ BEGIN
+ MENUITEM "No Role", ID_USERMENU_RIGHTS_NO
+ MENUITEM "Member", ID_USERMENU_RIGHTS_MEMBER
+
+ MENUITEM "Admin", ID_USERMENU_RIGHTS_ADMIN
+ END
+ MENUITEM "User Administration", ID_USERMENU_ADMINISTRATION, GRAYED
+ END
+ POPUP "", MENUBREAK
+ BEGIN
+ MENUITEM "Unban", ID_USERMENU_UNBAN
+ END
+END
+
+IDR_CONTEXT MENU DISCARDABLE
+BEGIN
+ POPUP "Log"
+ BEGIN
+ MENUITEM "&Copy", IDM_COPY
+ MENUITEM "Co&py All", IDM_COPYALL
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_SELECTALL
+ MENUITEM SEPARATOR
+ MENUITEM "C&lear Log", IDM_CLEAR
+ END
+ POPUP "LogLink"
+ BEGIN
+ MENUITEM "Open in &new window", IDM_OPENNEW
+ MENUITEM "&Open in existing window", IDM_OPENEXISTING
+ MENUITEM "&Copy link", IDM_COPYLINK
+ END
+ POPUP "Message"
+ BEGIN
+ MENUITEM "Undo", IDM_UNDO
+ MENUITEM "Redo", IDM_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cut", IDM_CUT
+ MENUITEM "Copy", IDM_COPY
+ MENUITEM "Paste", IDM_PASTE
+ MENUITEM "Delete", IDM_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_SELECTALL
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTIONS DIALOGEX 0, 0, 320, 260
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Fonts",IDC_FONTSGB,169,10,143,182
+ LTEXT "Background color",IDC_STATIC,175,23,100,8
+ CONTROL "",IDC_COLORBKG,"ColourPicker",WS_TABSTOP,277,21,29,12
+ LTEXT "Input area background",IDC_STATIC,175,38,100,8
+ CONTROL "",IDC_COLORINPUT,"ColourPicker",WS_TABSTOP,277,36,29,12
+ LTEXT "User list background",IDC_STATIC,175,53,100,8
+ CONTROL "",IDC_COLORLIST,"ColourPicker",WS_TABSTOP,277,51,29,12
+ LISTBOX IDC_FONTLIST,175,69,131,95,LBS_OWNERDRAWVARIABLE |
+ LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "",IDC_COLORTXT,"ColourPicker",WS_TABSTOP,175,170,55,15
+ PUSHBUTTON "Choose font",IDC_CHOOSEFONT,251,170,55,15
+ GROUPBOX "Options",IDC_OPTIONSGB,5,10,158,182
+ CONTROL "",IDC_TREELIST,"SysTreeView32",TVS_HASBUTTONS |
+ TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP,11,
+ 23,146,162,WS_EX_STATICEDGE
+ GROUPBOX "Other",IDC_SIMPLE,5,193,310,57
+ CONTROL "Use tabbed mode",IDC_USETABS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,206,140,10
+ CONTROL "Enable IEView",IDC_ENABLEIEVIEW,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,219,140,10
+ CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,232,140,10
+ LTEXT "Limit log history to (events):",IDC_STATIC,153,234,110,8
+ EDITTEXT IDC_LOGLIMIT,263,232,40,14,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_LOGLIMITSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,390,218,11,14
+END
+
+IDD_CHATMANAGER DIALOGEX 0, 0, 473, 234
+STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER |
+ WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Chats"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Tab1",IDC_TABS,"SysTabControl32",TCS_BUTTONS |
+ TCS_FIXEDWIDTH | 0x8,214,7,252,20
+ PUSHBUTTON "Close",IDCLOSE,416,215,50,14
+ CONTROL "Tree1",IDC_GROUP,"SysTreeView32",TVS_HASBUTTONS |
+ TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP |
+ TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS,5,20,203,209,
+ WS_EX_STATICEDGE
+ LTEXT "Groups",IDC_STATIC,7,9,24,8
+END
+
+IDD_GROUPCHAT_CONTAINER DIALOGEX 0, 0, 300, 200
+STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER |
+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Tlen Group Chat"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "",IDC_TABS,"SysTabControl32", WS_CLIPSIBLINGS | TCS_MULTILINE | TCS_FOCUSNEVER | 0x8,0,0,300,200
+END
+
+IDD_GROUPCHAT_LOG DIALOGEX 0, 0, 294, 178
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
+/*
+STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER |
+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+ */
+//EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_VSPLIT,"Static",SS_ENHMETAFILE,237,20,3,117
+ CONTROL "",IDC_HSPLIT,"Static",SS_ENHMETAFILE,156,285,2,0
+ CONTROL "",IDC_LOG,"RichEdit20A",WS_VSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS | 0x844,
+ 3,21,233,117,WS_EX_STATICEDGE
+ CONTROL "",IDC_TREELIST,"SysTreeView32",TVS_DISABLEDRAGDROP |
+ TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT,5,
+ 20,203,209,WS_EX_STATICEDGE
+ EDITTEXT IDC_EDIT,3,158,285,13,ES_MULTILINE | ES_AUTOVSCROLL |
+ NOT WS_BORDER | WS_VSCROLL | ES_WANTRETURN,WS_EX_STATICEDGE
+ CONTROL "Topic",IDC_TOPIC_BUTTON,"MButtonClass",WS_DISABLED |
+ WS_TABSTOP,3,3,34,12,0x18000000L
+ CONTROL "",IDC_BOLD,"MButtonClass",WS_TABSTOP,3,140,16,16,
+ 0x18000000L
+ CONTROL "",IDC_ITALIC,"MButtonClass",WS_TABSTOP,21,140,16,16,
+ 0x18000000L
+ CONTROL "",IDC_UNDERLINE,"MButtonClass",WS_TABSTOP,39,140,16,16,
+ 0x18000000L
+ CONTROL "",IDC_COLOR,"ColourPicker",WS_TABSTOP,57,140,16,16
+ COMBOBOX IDC_FONTSIZE,154,142,27,80,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "",IDC_SMILEYBTN,"MButtonClass", WS_TABSTOP,185,140,16,16,
+ 0x18000000L
+ CONTROL "Invite",IDC_INVITE,"MButtonClass",WS_TABSTOP,259,141,16,
+ 16,0x18000000L
+ EDITTEXT IDC_TOPIC,70,19,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT
+ WS_BORDER
+ CONTROL "",IDC_OPTIONS,"MButtonClass",WS_TABSTOP,208,140,16,16,
+ 0x18000000L
+ COMBOBOX IDC_FONT,77,142,74,90,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ PUSHBUTTON "Close",IDCANCEL,0,0,20,20,NOT WS_VISIBLE
+ //,NOT WS_VISIBLE
+END
+
+IDD_HELPER_JOIN DIALOGEX 0, 0, 186, 79
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Join Tlen Multi-User Conference Room"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Room:",IDC_ROOM_LABEL,10,13,43,8
+ EDITTEXT IDC_ROOM,54,12,119,12,ES_AUTOHSCROLL
+ LTEXT "Nickname:",IDC_NICK_LABEL,10,30,40,8
+ EDITTEXT IDC_NICK,54,29,119,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Join",IDOK,75,59,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,59,50,14
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,50,172,4
+END
+
+IDD_HELPER_INVITE DIALOG DISCARDABLE 0, 0, 186, 79
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Invite a User"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "User:",IDC_STATIC,10,13,43,8
+ COMBOBOX IDC_USER,54,10,119,120,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Reason:",IDC_STATIC,10,30,40,8
+ EDITTEXT IDC_REASON,54,29,119,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Invite",IDC_INVITE,75,59,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,59,50,14
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,50,172,4
+END
+
+IDD_HELPER_INVITE_ACCEPT DIALOG DISCARDABLE 0, 0, 232, 112
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Multi-User Conference Invitation"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "&Accept",IDC_ACCEPT,124,93,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,178,93,50,14
+ LTEXT "From:",IDC_STATIC,33,24,63,8
+ LTEXT "Room:",IDC_STATIC,33,38,63,8
+ LTEXT "Reason:",IDC_STATIC,33,52,63,8
+ LTEXT "Nickname:",IDC_STATIC,33,76,62,8
+ LTEXT "The following invitation to join a multi-user conference is received.",
+ IDC_STATIC,3,4,225,8
+ EDITTEXT IDC_FROM,99,22,105,12,ES_AUTOHSCROLL | ES_READONLY
+ EDITTEXT IDC_ROOM,99,36,105,12,ES_AUTOHSCROLL | ES_READONLY
+ EDITTEXT IDC_REASON,99,50,105,12,ES_AUTOHSCROLL | ES_READONLY
+ EDITTEXT IDC_NICK,99,74,105,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,3,65,225,4
+END
+
+IDD_HELPER_TOPIC DIALOGEX 0, 0, 223, 44
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Change Chat Room Topic"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "New topic:",IDC_STATIC,10,8,43,8
+ EDITTEXT IDC_TOPIC,54,7,160,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,108,26,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,164,26,50,14
+END
+
+IDD_USER_ADMIN DIALOG DISCARDABLE 0, 0, 300, 180
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Chat Room Administration"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Tab1",IDC_TABS,"SysTabControl32",TCS_BUTTONS |
+ TCS_FIXEDWIDTH | 0x8,0,5,220,20
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,20,300,4
+ PUSHBUTTON "Close",IDCANCEL,230,162,60,16
+
+END
+
+IDD_USER_KICK DIALOGEX 0, 30, 300, 130
+STYLE WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Nickname:",IDC_STATIC,30,6,70,10
+ EDITTEXT IDC_NICK,100,6,100,12,ES_AUTOHSCROLL | WS_TABSTOP
+ LTEXT "Ban for:",IDC_STATIC,30,35,70,10
+ COMBOBOX IDC_KICK_OPTIONS,100,35,90,150,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Reason:",IDC_STATIC,30,51,70,10
+ EDITTEXT IDC_REASON,100,51,100,12,ES_AUTOHSCROLL | WS_TABSTOP
+ CONTROL "Kick && Ban",IDOK,"MButtonClass",WS_TABSTOP,210,65,60,16
+
+ LTEXT "User role:",IDC_STATIC,30,90,70,10
+ COMBOBOX IDC_ROLE_OPTIONS,100,90,90,60,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Set Role",IDC_SET_ROLE,"MButtonClass",WS_TABSTOP,210,104,60,16
+
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,128,300,4
+END
+
+IDD_USER_ROLE DIALOGEX 0, 30, 300, 130
+STYLE WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Nickname:",IDC_STATIC,30,25,70,10
+ EDITTEXT IDC_NICK,100,25,100,12,ES_AUTOHSCROLL | WS_TABSTOP
+ LTEXT "User role:",IDC_STATIC,30,41,70,10
+ COMBOBOX IDC_OPTIONS,100,41,90,60,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Set Role",IDOK,"MButtonClass",WS_TABSTOP,120,90,60,16
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,128,300,4
+END
+
+IDD_USER_BROWSER DIALOGEX 0, 30, 300, 130
+STYLE WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_OPTIONS,50,0,90,60,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Show",IDC_SHOW,"MButtonClass",WS_TABSTOP,160,0,50,14
+ CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE |
+ LVS_OWNERDRAWFIXED | WS_TABSTOP,0,20,299,110,
+ WS_EX_CLIENTEDGE
+END
+
+IDD_OPT_POPUPS DIALOG DISCARDABLE 0, 0, 317, 141
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ GROUPBOX "Delay",IDC_STATIC,160,46,137,55
+ CONTROL "&From PopUp plugin",IDC_DELAY_POPUP,"Button",
+ BS_AUTORADIOBUTTON,167,60,125,10
+ CONTROL "&Custom",IDC_DELAY_CUSTOM,"Button",BS_AUTORADIOBUTTON,
+ 167,73,98,10
+ CONTROL "P&ermanent",IDC_DELAY_PERMANENT,"Button",
+ BS_AUTORADIOBUTTON,167,87,123,10
+ EDITTEXT IDC_DELAY,270,71,21,14,ES_AUTOHSCROLL | ES_NUMBER
+ GROUPBOX "Colours",IDC_STATIC,15,46,137,55
+ LTEXT "Background",IDC_STATIC,53,63,95,8
+ LTEXT "Text",IDC_STATIC,53,82,96,8
+ CONTROL "",IDC_COLORBKG,"ColourPicker",WS_TABSTOP,23,61,24,12
+ GROUPBOX "General Options",IDC_STATIC,15,15,282,26
+ CONTROL "",IDC_COLORTXT,"ColourPicker",WS_TABSTOP,23,79,24,12
+ PUSHBUTTON "Preview",IDC_PREVIEW,132,112,50,14
+ CONTROL "Enable incoming mail notification",IDC_ENABLEPOPUP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,26,130,10
+END
+
+IDD_TAB_CHATROOMS DIALOGEX 216, 28, 247, 180
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ CONTROL "List1",IDC_ROOM,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE |
+ LVS_OWNERDRAWFIXED | WS_TABSTOP,0,26,247,154,
+ WS_EX_CLIENTEDGE
+ CONTROL "prev",IDC_PREV,"MButtonClass",WS_TABSTOP,5,6,20,16
+ CONTROL "next",IDC_NEXT,"MButtonClass",WS_TABSTOP,35,6,20,16
+ CONTROL "find",IDC_SEARCH,"MButtonClass",WS_TABSTOP,65,6,20,16
+END
+
+IDD_TAB_MYROOMS DIALOGEX 216, 28, 244, 180
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ CONTROL "Create",IDC_REGISTER,"MButtonClass",WS_TABSTOP,186,62,
+ 50,14,0x18000000L
+ EDITTEXT IDC_NAME,84,20,149,14,ES_AUTOHSCROLL
+ LTEXT "Room name:",IDC_STATIC,14,23,60,8
+ CONTROL "Permanent",IDC_CHECK_PERMANENT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,111,40,89,10
+ CONTROL "Nicknames",IDC_CHECK_NICKNAMES,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,52,89,10
+ CONTROL "Public",IDC_CHECK_PUBLIC,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,40,89,10
+ CONTROL "Members only",IDC_CHECK_MEMBERS,"Button",
+ BS_AUTOCHECKBOX,111,52,89,10
+ LTEXT "Chat rooms:",IDC_STATIC,2,90,100,8
+ /*
+ CONTROL "Tree1",IDC_LIST,"SysTreeView32",TVS_DISABLEDRAGDROP |
+ TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | TVS_FULLROWSELECT |
+ TVS_NONEVENHEIGHT,0,100,177,80,WS_EX_STATICEDGE
+ */
+ CONTROL "Refresh",IDC_REFRESH,"MButtonClass",WS_TABSTOP,186,160,
+ 50,14,0x18000000L
+ GROUPBOX "New chat room",IDC_STATIC,0,5,244,78
+ CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE |
+ LVS_NOCOLUMNHEADER | LVS_OWNERDRAWFIXED | WS_TABSTOP,0,100,177,80,
+ WS_EX_CLIENTEDGE
+END
+
+IDD_TAB_MYNICKNAMES DIALOG DISCARDABLE 216, 28, 244, 180
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Register",IDC_REGISTER,"MButtonClass",WS_TABSTOP,186,62,
+ 50,14,0x18000000L
+ EDITTEXT IDC_NICK,84,20,149,14,ES_AUTOHSCROLL
+ LTEXT "Nickname:",IDC_STATIC,14,23,60,8
+ LTEXT "Nicknames:",IDC_STATIC,2,90,100,8
+ CONTROL "Remove",IDC_REMOVE,"MButtonClass",WS_TABSTOP,186,110,50,
+ 14,0x18000000L
+ CONTROL "Refresh",IDC_REFRESH,"MButtonClass",WS_TABSTOP,186,160,
+ 50,14,0x18000000L
+ GROUPBOX "New nickname",IDC_STATIC,0,5,244,78
+ CONTROL "List1",IDC_LIST,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE |
+ LVS_NOCOLUMNHEADER | LVS_OWNERDRAWFIXED | WS_TABSTOP,0,100,177,80,
+ WS_EX_CLIENTEDGE
+ /*
+ CONTROL "Tree1",IDC_LIST,"SysTreeView32",TVS_DISABLEDRAGDROP |
+ TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | TVS_FULLROWSELECT |
+ TVS_NONEVENHEIGHT,0,100,177,80,WS_EX_STATICEDGE
+ */
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MUCC_FILEVERSION_STRING
+ PRODUCTVERSION MUCC_FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "041504e3"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "http://miranda-ng.org/\0"
+ VALUE "FileDescription", "Group Chats GUI Plugin for Miranda NG\0"
+ VALUE "FileVersion", MUCC_VERSION_STRING
+ VALUE "InternalName", "tlen_chat\0"
+ VALUE "LegalCopyright", "Copyright (c) 2004-2006 Piotr Piastucki\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "tlen_chat.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Tlen Chat Plugin\0"
+ VALUE "ProductVersion", MUCC_VERSION_STRING
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x415, 1251
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_CHAT ICON DISCARDABLE "res\\chat.ico"
+IDI_BLANK ICON DISCARDABLE "res\\blank.ico"
+IDI_ITALIC ICON DISCARDABLE "res\\italic.ico"
+IDI_BOLD ICON DISCARDABLE "res\\bold.ico"
+IDI_UNDERLINE ICON DISCARDABLE "res\\underline.ico"
+IDI_OPTIONS ICON DISCARDABLE "res\\options.ico"
+IDI_OWNER ICON DISCARDABLE "res\\owner.ico"
+IDI_GLOBALOWNER ICON DISCARDABLE "res\\glowner.ico"
+IDI_ADMIN ICON DISCARDABLE "res\\admin.ico"
+IDI_REGISTERED ICON DISCARDABLE "res\\registered.ico"
+IDI_R_MODERATED ICON DISCARDABLE "res\\r_mod.ico"
+IDI_R_MEMBERS ICON DISCARDABLE "res\\r_memb.ico"
+IDI_R_ANONYMOUS ICON DISCARDABLE "res\\r_anon.ico"
+IDI_SEARCH ICON DISCARDABLE "res\\search.ico"
+IDI_PREV ICON DISCARDABLE "res\\prev.ico"
+IDI_NEXT ICON DISCARDABLE "res\\next.ico"
+IDI_INVITE ICON DISCARDABLE "res\\invite.ico"
+IDI_ADMINISTRATION ICON DISCARDABLE "res\\administration.ico"
+IDI_SMILEY ICON DISCARDABLE "res\\smile.ico"
+IDI_MESSAGE ICON DISCARDABLE "res\\message.ico"
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/Tlen/tlen_czaty/res/next.ico b/protocols/Tlen/tlen_czaty/res/next.ico
new file mode 100644
index 0000000000..d817b06cc6
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/next.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/options.ico b/protocols/Tlen/tlen_czaty/res/options.ico
new file mode 100644
index 0000000000..2fd2d902d9
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/options.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/owner.ico b/protocols/Tlen/tlen_czaty/res/owner.ico
new file mode 100644
index 0000000000..27bea391f0
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/owner.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/prev.ico b/protocols/Tlen/tlen_czaty/res/prev.ico
new file mode 100644
index 0000000000..2f171e5783
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/prev.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/r_anon.ico b/protocols/Tlen/tlen_czaty/res/r_anon.ico
new file mode 100644
index 0000000000..b5ebd0289e
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/r_anon.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/r_memb.ico b/protocols/Tlen/tlen_czaty/res/r_memb.ico
new file mode 100644
index 0000000000..418fd9abf5
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/r_memb.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/r_mod.ico b/protocols/Tlen/tlen_czaty/res/r_mod.ico
new file mode 100644
index 0000000000..3b9fa47f60
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/r_mod.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/registered.ico b/protocols/Tlen/tlen_czaty/res/registered.ico
new file mode 100644
index 0000000000..3a5182b5d6
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/registered.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/save.ico b/protocols/Tlen/tlen_czaty/res/save.ico
new file mode 100644
index 0000000000..48b0581fd5
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/save.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/search.ico b/protocols/Tlen/tlen_czaty/res/search.ico
new file mode 100644
index 0000000000..065468e272
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/search.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/sendmail.ico b/protocols/Tlen/tlen_czaty/res/sendmail.ico
new file mode 100644
index 0000000000..0b60bf950e
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/sendmail.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/smile.ico b/protocols/Tlen/tlen_czaty/res/smile.ico
new file mode 100644
index 0000000000..d4aea87249
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/smile.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/tlenbig.ico b/protocols/Tlen/tlen_czaty/res/tlenbig.ico
new file mode 100644
index 0000000000..4d09293560
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/tlenbig.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/tlensmall.ico b/protocols/Tlen/tlen_czaty/res/tlensmall.ico
new file mode 100644
index 0000000000..5204d39d21
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/tlensmall.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/res/underline.ico b/protocols/Tlen/tlen_czaty/res/underline.ico
new file mode 100644
index 0000000000..7709f5f7f4
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/res/underline.ico
Binary files differ
diff --git a/protocols/Tlen/tlen_czaty/src/AdminWindow.cpp b/protocols/Tlen/tlen_czaty/src/AdminWindow.cpp
new file mode 100644
index 0000000000..5df8a2abf0
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/AdminWindow.cpp
@@ -0,0 +1,490 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "AdminWindow.h"
+#include "Utils.h"
+
+
+static INT_PTR CALLBACK UserKickDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ const char *banOptions[]={"No ban", "1 minute", "5 minutes", "15 minutes", "30 minutes",
+ "1 hour", "6 hours", "1 day", "3 days", "1 week", "2 weeks", "4 weeks"};
+ const int banTime[] = {0, 1, 5, 15, 30, 60, 360, 1440, 4320, 10080, 20160, 40320};
+ const char *roleOptions[]={"No role", "Member", "Admin", "Moderator"};
+ const int roleMask[] = {0, MUCC_EF_USER_MEMBER, MUCC_EF_USER_ADMIN, MUCC_EF_USER_MODERATOR};
+ AdminWindow *adminWindow;
+ adminWindow = (AdminWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ adminWindow = (AdminWindow *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) adminWindow);
+ adminWindow->setKickTabHWND(hwndDlg);
+ for (i=0;i<12;i++) {
+ SendDlgItemMessage(hwndDlg, IDC_KICK_OPTIONS, CB_ADDSTRING, 0, (LPARAM) banOptions[i]);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_KICK_OPTIONS, CB_SETCURSEL, 0, 0);
+ for (i=0;i<3;i++) {
+ SendDlgItemMessage(hwndDlg, IDC_ROLE_OPTIONS, CB_ADDSTRING, 0, (LPARAM) roleOptions[i]);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_ROLE_OPTIONS, CB_SETCURSEL, 0, 0);
+ SetDlgItemTextA(hwndDlg, IDC_NICK, adminWindow->getNick());
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ {
+ char nick[256], reason[256];
+ GetDlgItemTextA(hwndDlg, IDC_NICK, nick, sizeof(nick));
+ GetDlgItemTextA(hwndDlg, IDC_REASON, reason, sizeof(reason));
+ if (strlen(nick)>0) {
+ int iSel = SendDlgItemMessage(hwndDlg, IDC_KICK_OPTIONS, CB_GETCURSEL, 0, 0);
+ if (iSel >= 0 && iSel < 12) {
+ adminWindow->getParent()->kickAndBan(nick, banTime[iSel] * 60, reason);
+ }
+ }
+ }
+// EndDialog(hwndDlg, 1);
+// return TRUE;
+ break;
+ case IDC_SET_ROLE:
+ {
+ char nick[256];
+ GetDlgItemTextA(hwndDlg, IDC_NICK, nick, sizeof(nick));
+ if (strlen(nick)>0) {
+ int iSel = SendDlgItemMessage(hwndDlg, IDC_ROLE_OPTIONS, CB_GETCURSEL, 0, 0);
+ if (iSel >= 0 && iSel < 3) {
+ adminWindow->getParent()->setRights(nick, roleMask[iSel]);
+ }
+ }
+ }
+ break;
+// EndDialog(hwndDlg, 1);
+// return TRUE;
+ case IDCANCEL:
+// EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+// EndDialog(hwndDlg, 0);
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK UserBrowserDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{ int i;
+ const char *browseOptions[]={"Banned", "Owners", "Administrators", "Members", "Moderators"};
+ const int browserFlags[]={MUCC_EF_USER_BANNED, MUCC_EF_USER_OWNER, MUCC_EF_USER_ADMIN, MUCC_EF_USER_MEMBER, MUCC_EF_USER_MODERATOR};
+ LVCOLUMN lvCol;
+ HWND lv;
+ AdminWindow *adminWindow;
+ adminWindow = (AdminWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ adminWindow = (AdminWindow *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) adminWindow);
+ adminWindow->setBrowserTabHWND(hwndDlg);
+ lv = GetDlgItem(hwndDlg, IDC_LIST);
+ ListView_SetExtendedListViewStyle(lv, LVS_EX_FULLROWSELECT);
+ lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+ lvCol.pszText = TranslateT("Login");
+ lvCol.cx = 80;
+ lvCol.iSubItem = 0;
+ ListView_InsertColumn(lv, 0, &lvCol);
+ lvCol.pszText = TranslateT("Nick name");
+ lvCol.cx = 80;
+ lvCol.iSubItem = 1;
+ ListView_InsertColumn(lv, 1, &lvCol);
+ lvCol.pszText = TranslateT("When");
+ lvCol.cx = 95;
+ lvCol.iSubItem = 2;
+ ListView_InsertColumn(lv, 2, &lvCol);
+ lvCol.pszText = TranslateT("Admin");
+ lvCol.cx = 80;
+ lvCol.iSubItem = 2;
+ ListView_InsertColumn(lv, 3, &lvCol);
+ lvCol.pszText = TranslateT("Reason");
+ lvCol.cx = 70;
+ lvCol.iSubItem = 2;
+ ListView_InsertColumn(lv, 5, &lvCol);
+ lvCol.pszText = TranslateT("Remaining");
+ lvCol.cx = 80;
+ lvCol.iSubItem = 2;
+ ListView_InsertColumn(lv, 4, &lvCol);
+ for (i=0;i<(adminWindow->getParent()->getRoomFlags() & MUCC_EF_ROOM_MEMBERS_ONLY ? 4 : 3);i++) {
+ SendDlgItemMessage(hwndDlg, IDC_OPTIONS, CB_ADDSTRING, 0, (LPARAM) browseOptions[i]);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_OPTIONS, CB_SETCURSEL, 0, 0);
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_SHOW:
+ int iSel;
+ iSel = SendDlgItemMessage(hwndDlg, IDC_OPTIONS, CB_GETCURSEL, 0, 0);
+ if (iSel< 5) {
+ adminWindow->queryUsers(browserFlags[iSel]);
+ }
+ break;
+// return TRUE;
+ case IDCANCEL:
+// EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+// EndDialog(hwndDlg, 0);
+ break;
+ case WM_MEASUREITEM:
+ if (wParam == IDC_LIST) {
+ MEASUREITEMSTRUCT *lpMis = (MEASUREITEMSTRUCT *) lParam;
+ lpMis->itemHeight = 16;//GetSystemMetrics(SM_CYSMICON);
+ return TRUE;
+ }
+ break;
+ case WM_DRAWITEM:
+ if (wParam == IDC_LIST) {
+ RECT rc;
+ int x, w;
+ TCHAR text[256];
+ DRAWITEMSTRUCT *lpDis = (DRAWITEMSTRUCT *) lParam;
+ switch (lpDis->itemAction) {
+ default:
+ case ODA_SELECT:
+ case ODA_DRAWENTIRE:
+ if (lpDis->itemState & ODS_SELECTED) {
+ HBRUSH hBrush = CreateSolidBrush(RGB(0xC2, 0xC8, 0xDA));//0xDAC8C2);
+ FillRect(lpDis->hDC, &(lpDis->rcItem), hBrush);//(HBRUSH) (COLOR_HIGHLIGHT+1));
+ DeleteObject(hBrush);
+ SetTextColor(lpDis->hDC, 0);
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ else {
+ FillRect(lpDis->hDC, &(lpDis->rcItem), (HBRUSH) (COLOR_WINDOW+1));
+ SetTextColor(lpDis->hDC, RGB(0, 0, 0));//GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ x = lpDis->rcItem.left + 1;
+ for (int col=0;col<6;col++) {
+ w = ListView_GetColumnWidth(GetDlgItem(hwndDlg, IDC_LIST), col);
+ rc.left = x;
+ rc.top = lpDis->rcItem.top;
+ rc.bottom = lpDis->rcItem.bottom;
+ rc.right = x+w-2;
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), lpDis->itemID, col, text, sizeof(text)/sizeof(TCHAR));
+ if (_tcslen(text) == 0) {
+ _tcscpy(text, _TEXT("-"));
+ }
+ DrawText(lpDis->hDC, text, (int)_tcslen(text), &rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ x+=w;
+ }
+ break;
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ LPNMHDR pNmhdr;
+ pNmhdr = (LPNMHDR)lParam;
+ if (pNmhdr->idFrom == IDC_LIST && adminWindow->getBrowserMode() == MUCC_EF_USER_BANNED) {
+ switch (pNmhdr->code) {
+ case NM_RCLICK:
+ {
+ LVHITTESTINFO hti;
+ int hitItem;
+ hti.pt.x=(short)LOWORD(GetMessagePos());
+ hti.pt.y=(short)HIWORD(GetMessagePos());
+ ScreenToClient(pNmhdr->hwndFrom, &hti.pt);
+ if ((hitItem = ListView_HitTest(pNmhdr->hwndFrom,&hti)) !=-1) {
+ LVITEM lvi = {0};
+ HMENU hMenu;
+ int iSelection;
+ TCHAR nick[256];
+ lvi.mask = TVIF_TEXT;
+ lvi.iItem = hitItem;
+ lvi.iSubItem = 0;
+ lvi.pszText = nick;
+ lvi.cchTextMax = sizeof(nick)/sizeof(TCHAR);
+ ListView_GetItem(pNmhdr->hwndFrom, &lvi);
+ hMenu=GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_CHATOPTIONS)), 3);
+ TranslateMenu(hMenu);
+ iSelection = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_TOPALIGN | TPM_LEFTALIGN, (short)LOWORD(GetMessagePos()), (short)HIWORD(GetMessagePos()), 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ if (iSelection == ID_USERMENU_UNBAN) {
+ char* lps1 = Utils::mucc_mir_t2a(nick);
+ adminWindow->getParent()->unban(lps1);
+ Utils::mucc_mir_free(lps1);
+ }
+ }
+
+ }
+ break;
+ }
+ }
+
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK AdminDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+ TCITEM tci;
+ HWND tc;
+ AdminWindow *adminWindow;
+ adminWindow = (AdminWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ adminWindow = (AdminWindow *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) adminWindow);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) muccIcon[MUCC_IDI_ADMINISTRATION]);
+
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_USER_KICK), hwndDlg, UserKickDlgProc, (LPARAM) adminWindow);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ ShowWindow(hwnd, SW_SHOW);
+
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_USER_BROWSER), hwndDlg, UserBrowserDlgProc, (LPARAM) adminWindow);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ adminWindow->setCurrentTab(0);
+ adminWindow->setHWND(hwndDlg);
+
+ tc = GetDlgItem(hwndDlg, IDC_TABS);
+ tci.mask = TCIF_TEXT;
+ tci.pszText = TranslateT("Administration");
+ TabCtrl_InsertItem(tc, 0, &tci);
+ tci.pszText = TranslateT("Browser");
+ TabCtrl_InsertItem(tc, 1, &tci);
+
+ return FALSE;
+ case WM_NOTIFY:
+ switch (wParam) {
+ case IDC_TABS:
+ switch (((LPNMHDR) lParam)->code) {
+ case TCN_SELCHANGE:
+ switch (adminWindow->getCurrentTab()) {
+ case 0:
+ ShowWindow(adminWindow->getKickTabHWND(), SW_HIDE);
+ break;
+ case 1:
+ ShowWindow(adminWindow->getBrowserTabHWND(), SW_HIDE);
+ break;
+ }
+ adminWindow->setCurrentTab(TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TABS)));
+ switch (adminWindow->getCurrentTab()) {
+ case 0:
+ ShowWindow(adminWindow->getKickTabHWND(), SW_SHOW);
+ break;
+ case 1:
+ ShowWindow(adminWindow->getBrowserTabHWND(), SW_SHOW);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ delete adminWindow;
+ // EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ delete adminWindow;
+ // EndDialog(hwndDlg, 0);
+ break;
+ }
+ return FALSE;
+}
+
+
+
+AdminWindow::AdminWindow(ChatWindow *parent, const char *nick, int mode) {
+ this->parent = parent;
+ hWnd = NULL;
+ browserMode = 0;
+ this->nick = NULL;
+ Utils::copyString(&this->nick, nick);
+}
+
+AdminWindow::~AdminWindow() {
+
+ if (hWnd != NULL) {
+ EndDialog(hWnd, 0);
+ }
+ if (parent != NULL) {
+ parent->setAdminWindow(NULL);
+ }
+ if (nick != NULL) {
+ delete nick;
+ }
+}
+
+void AdminWindow::start() {
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_USER_ADMIN), NULL, AdminDlgProc, (LPARAM) this);
+}
+
+void AdminWindow::setHWND(HWND hWnd) {
+ this->hWnd = hWnd;
+}
+
+void AdminWindow::setCurrentTab(int t) {
+ currentTab = t;
+}
+
+int AdminWindow::getCurrentTab() {
+ return currentTab;
+}
+
+
+void AdminWindow::setKickTabHWND(HWND hWnd) {
+ hKickTabWnd = hWnd;
+}
+
+void AdminWindow::setBrowserTabHWND(HWND hWnd) {
+ hBrowserTabWnd = hWnd;
+}
+
+HWND AdminWindow::getKickTabHWND() {
+ return hKickTabWnd;
+}
+
+HWND AdminWindow::getBrowserTabHWND() {
+ return hBrowserTabWnd;
+}
+
+void AdminWindow::queryUsers(int queryType) {
+ MUCCEVENT muce;
+ EnableWindow(GetDlgItem(getBrowserTabHWND(), IDC_SHOW), FALSE);
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_USERS;
+ muce.pszModule = parent->getModule();
+ muce.pszID = parent->getRoomId();
+ muce.dwFlags = queryType;
+ browserMode = queryType;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+}
+
+ChatWindow * AdminWindow::getParent() {
+ return parent;
+}
+
+void AdminWindow::queryResultUsers(MUCCQUERYRESULT *queryResult) {
+ ListView_DeleteAllItems(GetDlgItem(getBrowserTabHWND(), IDC_LIST));
+ for (int i=0;i<queryResult->iItemsNum;i++) {
+
+ char timestampStr[100];
+ DBTIMETOSTRING dbtts;
+ LVITEM lvItem;
+
+ lvItem.mask = LVIF_TEXT;// | LVIF_PARAM;
+ lvItem.iSubItem = 0;
+ lvItem.iItem = ListView_GetItemCount(GetDlgItem(getBrowserTabHWND(), IDC_LIST));
+ lvItem.pszText = Utils::mucc_mir_a2t(queryResult->pItems[i].pszID);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+// lvItem.lParam = (LPARAM) room;
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+ lvItem.iSubItem = 1;
+ lvItem.pszText = Utils::mucc_mir_a2t(queryResult->pItems[i].pszName);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ ListView_SetItemText(GetDlgItem(getBrowserTabHWND(), IDC_LIST), lvItem.iItem, lvItem.iSubItem, lvItem.pszText);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+ lvItem.iSubItem = 2;
+ dbtts.cbDest = 90;
+ dbtts.szDest = timestampStr;
+ dbtts.szFormat = (char *)"d t";
+ timestampStr[0]='\0';
+ if (queryResult->pItems[i].dwFlags) {
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRING, (WPARAM)queryResult->pItems[i].dwFlags, (LPARAM) & dbtts);
+ }
+ lvItem.pszText = Utils::mucc_mir_a2t(timestampStr);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ ListView_SetItemText(GetDlgItem(getBrowserTabHWND(), IDC_LIST), lvItem.iItem, lvItem.iSubItem, lvItem.pszText);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+ lvItem.iSubItem = 3;
+ lvItem.pszText = Utils::mucc_mir_a2t(queryResult->pItems[i].pszNick);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ ListView_SetItemText(GetDlgItem(getBrowserTabHWND(), IDC_LIST), lvItem.iItem, lvItem.iSubItem, lvItem.pszText);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+ lvItem.iSubItem = 4;
+ timestampStr[0] = '\0';
+ if (queryResult->pItems[i].iCount > 0) {
+ int days = queryResult->pItems[i].iCount / (60*60*24);
+ int hours = (queryResult->pItems[i].iCount % (60*60*24)) / (60*60);
+ int minutes = (queryResult->pItems[i].iCount % (60*60)) / 60;
+ int seconds = queryResult->pItems[i].iCount % 60;
+ if (days != 0) {
+ sprintf(timestampStr, "%dd%dh%dm%ds", days, hours, minutes, seconds);
+ } else if (hours != 0) {
+ sprintf(timestampStr, "%dh%dm%ds", hours, minutes, seconds);
+ } else if (minutes != 0) {
+ sprintf(timestampStr, "%dm%ds", minutes, seconds);
+ } else {
+ sprintf(timestampStr, "%ds", seconds);
+ }
+ }
+ lvItem.pszText = Utils::mucc_mir_a2t(timestampStr);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ ListView_SetItemText(GetDlgItem(getBrowserTabHWND(), IDC_LIST), lvItem.iItem, lvItem.iSubItem, lvItem.pszText);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+ lvItem.iSubItem = 5;
+ lvItem.pszText = Utils::mucc_mir_a2t(queryResult->pItems[i].pszText);
+ if (lvItem.pszText == NULL) lvItem.pszText = _TEXT("");
+ ListView_InsertItem(GetDlgItem(getBrowserTabHWND(), IDC_LIST), &lvItem);
+ ListView_SetItemText(GetDlgItem(getBrowserTabHWND(), IDC_LIST), lvItem.iItem, lvItem.iSubItem, lvItem.pszText);
+ Utils::mucc_mir_free(lvItem.pszText);
+
+/*
+ ptr = new HelperContact(queryResult->pItems[i].pszID, queryResult->pItems[i].pszName);
+ if (lastptr != NULL) {
+ lastptr->setNext(ptr);
+ } else {
+ contactList=ptr;
+ }
+ lastptr=ptr;
+
+ */
+ }
+ EnableWindow(GetDlgItem(getBrowserTabHWND(), IDC_SHOW), TRUE);
+}
+
+const char *AdminWindow::getNick() {
+ return nick;
+}
+
+int AdminWindow::getBrowserMode() {
+ return browserMode;
+}
diff --git a/protocols/Tlen/tlen_czaty/src/AdminWindow.h b/protocols/Tlen/tlen_czaty/src/AdminWindow.h
new file mode 100644
index 0000000000..2e3e4f5496
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/AdminWindow.h
@@ -0,0 +1,63 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+
+class AdminWindow;
+#ifndef ADMINWINDOW_INCLUDED
+#define ADMINWINDOW_INCLUDED
+
+#include "mucc.h"
+#include "ChatWindow.h"
+
+class AdminWindow {
+private:
+ HWND hWnd;
+ HWND hKickTabWnd, hBrowserTabWnd;
+ int currentTab;
+ int browserMode;
+ ChatWindow *parent;
+ char *nick;
+public:
+ enum BROWSER_MODE {
+ BROWSE_BANNED = 1,
+ BROWSE_OWNERS = 2,
+ BROWSE_ADMINS = 3,
+ BROWSE_MEMBERS = 4,
+ BROWSE_MODERATORS = 5
+ };
+ AdminWindow (ChatWindow *parent, const char *nick, int mode);
+ ~AdminWindow();
+ void start();
+ void setHWND(HWND);
+ void setKickTabHWND(HWND);
+ void setBrowserTabHWND(HWND);
+ HWND getKickTabHWND();
+ HWND getBrowserTabHWND();
+ int getCurrentTab();
+ int getBrowserMode();
+ void setCurrentTab(int);
+ void queryUsers(int);
+ ChatWindow* getParent();
+ const char *getNick();
+ void queryResultUsers(MUCCQUERYRESULT *queryResult);
+};
+
+#endif
+
diff --git a/protocols/Tlen/tlen_czaty/src/ChatContainer.cpp b/protocols/Tlen/tlen_czaty/src/ChatContainer.cpp
new file mode 100644
index 0000000000..eb3a6512fd
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatContainer.cpp
@@ -0,0 +1,480 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatContainer.h"
+#include "Utils.h"
+#include "Options.h"
+
+#define DM_CREATECHILD (WM_USER+10)
+#define DM_ADDCHILD (WM_USER+11)
+#define DM_ACTIVATECHILD (WM_USER+12)
+#define DM_CHANGECHILDDATA (WM_USER+13)
+#define DM_REMOVECHILD (WM_USER+14)
+
+#define DM_SETUNREAD (WM_USER+15)
+#define DM_FLASHWINDOW (WM_USER+16)
+
+#define TIMERID_FLASHWND 1
+#define TIMEOUT_FLASHWND 900
+
+ChatContainer * ChatContainer::list = NULL;
+bool ChatContainer::released = false;
+CRITICAL_SECTION ChatContainer::mutex;
+
+//BOOL CALLBACK ContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static void __cdecl StartThread(void *vContainer);
+
+void ChatContainer::release() {
+ released = true;
+ for (ChatContainer *ptr2, *ptr = list; ptr != NULL; ptr=ptr2) {
+ ptr2 = ptr->getNext();
+ SendMessage(ptr->getHWND(), WM_CLOSE, 0, 0);
+ }
+ DeleteCriticalSection(&mutex);
+}
+
+void ChatContainer::init() {
+ released = false;
+ InitializeCriticalSection(&mutex);
+}
+
+int ChatContainer::getDefaultOptions() {
+ return FLAG_USE_TABS;
+}
+
+ChatContainer * ChatContainer::getWindow() {
+ ChatContainer *ptr;
+ EnterCriticalSection(&mutex);
+ if (list == NULL || !(Options::getChatContainerOptions() & ChatContainer::FLAG_USE_TABS)) {
+ ptr = new ChatContainer();
+ } else {
+ ptr = list;
+ }
+ LeaveCriticalSection(&mutex);
+ return ptr;
+}
+
+ChatContainer::ChatContainer() {
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hWnd = NULL;
+ prev = next =NULL;
+ active = NULL;
+ childCount = 0;
+ nFlash = 0;
+ nFlashMax = 3;
+ Utils::forkThread((void (__cdecl *)(void *))StartThread, 0, (void *) this);
+ WaitForSingleObject(hEvent, INFINITE);
+ EnterCriticalSection(&mutex);
+ setNext(list);
+ if (next != NULL) {
+ next->setPrev(this);
+ }
+ list = this;
+ LeaveCriticalSection(&mutex);
+}
+
+ChatContainer::~ChatContainer() {
+ if (!released) {
+ EnterCriticalSection(&mutex);
+ if (getPrev() != NULL) {
+ getPrev()->setNext(next);
+ } else if (list == this) {
+ list = getNext();
+ }
+ if (getNext() != NULL) {
+ getNext()->setPrev(prev);
+ }
+ LeaveCriticalSection(&mutex);
+ }
+ if (hEvent != NULL) {
+ CloseHandle(hEvent);
+ }
+}
+
+void ChatContainer::setHWND(HWND hWnd) {
+ this->hWnd = hWnd;
+}
+
+HWND ChatContainer::getHWND() {
+ return hWnd;
+}
+
+HANDLE ChatContainer::getEvent() {
+ return hEvent;
+}
+
+ChatContainer * ChatContainer::getNext() {
+ return next;
+}
+
+void ChatContainer::setNext(ChatContainer * next) {
+ this->next = next;
+}
+
+ChatContainer * ChatContainer::getPrev() {
+ return prev;
+}
+
+void ChatContainer::setPrev(ChatContainer * prev) {
+ this->prev = prev;
+}
+
+void ChatContainer::show(bool bShow) {
+ ShowWindow(hWnd, bShow ? SW_SHOW : SW_HIDE);
+}
+
+ChatWindow * ChatContainer::getActive() {
+ return active;
+}
+
+int ChatContainer::getFlash() {
+ return nFlash;
+}
+
+int ChatContainer::getFlashMax() {
+ return nFlashMax;
+}
+
+int ChatContainer::getFlashTimeout() {
+ return TIMEOUT_FLASHWND;
+}
+
+void ChatContainer::setFlash(int n) {
+ nFlash = n;
+}
+
+void ChatContainer::activateChild(ChatWindow *window) {
+ RECT rcChild;
+ getChildWindowRect(&rcChild);
+ if (window != NULL) {
+ SetWindowPos(window->getHWND(), HWND_TOP, rcChild.left, rcChild.top, rcChild.right-rcChild.left, rcChild.bottom - rcChild.top, SWP_NOSIZE);
+ }
+ if (window != active) {
+ ChatWindow *prev = active;
+ active = window;
+ SendMessage(hWnd, WM_SIZE, 0, 0);
+ ShowWindow(active->getHWND(), SW_SHOW);
+// SendMessage(active->getHWND(), DM_UPDATETITLE, 0, 0);
+ if (prev != NULL) {
+ ShowWindow(prev->getHWND(), SW_HIDE);
+ }
+ SetWindowTextA(hWnd, window->getRoomName());
+ }
+ TCITEM tci;
+ tci.mask = TCIF_IMAGE;
+ tci.iImage = -1;
+ TabCtrl_SetItem(GetDlgItem(hWnd, IDC_TABS), getChildTab(window), &tci);
+ SendMessage(active->getHWND(), WM_ACTIVATE, WA_ACTIVE, 0);
+ SetFocus(active->getHWND());
+}
+
+
+void ChatContainer::addChild(ChatWindow *child) {
+ TCITEM tci;
+ int tabId;
+ HWND hwndTabs = GetDlgItem(hWnd, IDC_TABS);
+ childCount++;
+ tci.mask = TCIF_TEXT | TCIF_PARAM;
+ LPTSTR lps1 = Utils::mucc_mir_a2t(child->getRoomName());
+ tci.pszText = lps1;
+ tci.lParam = (LPARAM) child;
+ tabId = TabCtrl_InsertItem(hwndTabs, childCount-1, &tci);
+ TabCtrl_SetCurSel(hwndTabs, tabId);
+ Utils::mucc_mir_free(lps1);
+ activateChild(child);
+ SendMessage(hWnd, WM_SIZE, 0, 0);
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hWnd);
+}
+
+void ChatContainer::changeChildData(ChatWindow *child) {
+ int tabId;
+ HWND hwndTabs = GetDlgItem(hWnd, IDC_TABS);
+ tabId = getChildTab(child);
+ if (tabId >=0) {
+ TCITEM tci;
+ tci.mask = TCIF_TEXT;
+ LPTSTR lps1 = Utils::mucc_mir_a2t(child->getRoomName());
+ tci.pszText = lps1;
+ TabCtrl_SetItem(hwndTabs, childCount-1, &tci);
+ Utils::mucc_mir_free(lps1);
+ }
+ if (child == active) {
+ SetWindowTextA(hWnd, child->getRoomName());
+ }
+}
+
+
+void ChatContainer::removeChild(ChatWindow *child) {
+ HWND hwndTabs = GetDlgItem(hWnd, IDC_TABS);
+ int iSel = getChildTab(child);
+ if (iSel >= 0) {
+ TabCtrl_DeleteItem(hwndTabs, iSel);
+ }
+ childCount--;
+ if (childCount > 0) {
+ TCITEM tci;
+ if (iSel == childCount) iSel--;
+ TabCtrl_SetCurSel(hwndTabs, iSel);
+ tci.mask = TCIF_PARAM;
+ if (TabCtrl_GetItem(hwndTabs, iSel, &tci)) {
+ child = (ChatWindow *)tci.lParam;
+ activateChild(child);
+ }
+ } else {//if (!released) {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+}
+
+void ChatContainer::setUnread(ChatWindow *child, int unread) {
+ if (!unread || child != active) {
+ TCITEM tci;
+ tci.mask = TCIF_IMAGE;
+ if (unread) {
+ tci.iImage = 0;
+ } else {
+ tci.iImage = -1;
+ }
+ TabCtrl_SetItem(GetDlgItem(hWnd, IDC_TABS), getChildTab(child), &tci);
+ }
+}
+
+
+void ChatContainer::getChildWindowRect(RECT *rcChild)
+{
+ RECT rc, rcTabs; //rcStatus,
+ HWND hwndTabs = GetDlgItem(hWnd, IDC_TABS);
+ int l = TabCtrl_GetItemCount(hwndTabs);
+ GetClientRect(hWnd, &rc);
+ GetClientRect(hwndTabs, &rcTabs);
+ TabCtrl_AdjustRect(hwndTabs, FALSE, &rcTabs);
+// GetWindowRect(dat->hwndStatus, &rcStatus);
+ rcChild->left = 0;
+ rcChild->right = rc.right;
+ if (l > 1) {
+ rcChild->top = rcTabs.top - 1;
+ } else {
+ rcChild->top = 0;
+ }
+ rcChild->bottom = rc.bottom - rc.top;// - (rcStatus.bottom - rcStatus.top);
+}
+
+ChatWindow * ChatContainer::getChildFromTab(int tabId) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(GetDlgItem(hWnd, IDC_TABS), tabId, &tci);
+ return (ChatWindow *)tci.lParam;
+}
+
+int ChatContainer::getChildTab(ChatWindow *child) {
+ TCITEM tci;
+ int l, i;
+ HWND hwndTabs = GetDlgItem(hWnd, IDC_TABS);
+ l = TabCtrl_GetItemCount(hwndTabs);
+ for (i = 0; i < l; i++) {
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTabs, i, &tci);
+ if (child == (ChatWindow *) tci.lParam) {
+ return i;
+ }
+ }
+ return -1;
+
+}
+
+HWND ChatContainer::remoteCreateChild(DLGPROC proc, ChatWindow *ptr) {
+ return (HWND) SendMessage(hWnd, DM_CREATECHILD, (WPARAM)proc, (LPARAM) ptr);
+}
+
+void ChatContainer::remoteAddChild(ChatWindow *ptr) {
+ SendMessage(hWnd, DM_ADDCHILD, (WPARAM)0, (LPARAM) ptr);
+}
+
+void ChatContainer::remoteChangeChildData(ChatWindow *ptr) {
+ SendMessage(hWnd, DM_CHANGECHILDDATA, (WPARAM)0, (LPARAM) ptr);
+}
+
+void ChatContainer::remoteRemoveChild(ChatWindow *ptr) {
+ SendMessage(hWnd, DM_REMOVECHILD, (WPARAM)0, (LPARAM) ptr);
+}
+
+void ChatContainer::remoteSetUnread(ChatWindow *ptr, int unread) {
+ SendMessage(hWnd, DM_SETUNREAD, (WPARAM)unread, (LPARAM) ptr);
+}
+
+void ChatContainer::remoteFlashWindow() {
+ SendMessage(hWnd, DM_FLASHWINDOW, 0, 0);
+}
+
+INT_PTR CALLBACK ContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ChatContainer *container;
+ container = (ChatContainer *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (container == NULL && msg != WM_INITDIALOG) return FALSE;
+ switch (msg) {
+ case WM_INITDIALOG:
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) muccIcon[MUCC_IDI_CHAT]);
+ container = (ChatContainer *) lParam;
+ container->setHWND(hwndDlg);
+ TabCtrl_SetImageList(GetDlgItem(hwndDlg, IDC_TABS), hImageList);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) container);
+ ShowWindow(hwndDlg, SW_SHOW);
+ SetEvent(container->getEvent());
+ return TRUE;
+ case WM_GETMINMAXINFO:
+ MINMAXINFO *mmi;
+ RECT rcChild, rcWindow;
+ mmi = (MINMAXINFO *) lParam;
+ GetWindowRect(hwndDlg, &rcWindow);
+ container->getChildWindowRect(&rcChild);
+ mmi->ptMinTrackSize.x = 380;
+ mmi->ptMinTrackSize.y = 130 + (rcWindow.bottom - rcWindow.top) - (rcChild.bottom - rcChild.top);
+ return FALSE;
+ case WM_SIZE:
+ if (IsIconic(hwndDlg) || wParam == SIZE_MINIMIZED) break;
+ {
+ RECT rc, rcChild, rcWindow;
+ GetClientRect(hwndDlg, &rc);
+ HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
+ MoveWindow(hwndTabs, 0, 0, (rc.right - rc.left), (rc.bottom - rc.top) - 0, FALSE);
+ RedrawWindow(hwndTabs, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE);
+ container->getChildWindowRect(&rcChild);
+ if ((rcChild.bottom-rcChild.top) < 130 || (rcChild.right-rcChild.left) < 380) {
+ GetWindowRect(hwndDlg, &rcWindow);
+ if ((rcChild.bottom-rcChild.top) < 130) {
+ rcWindow.bottom = rcWindow.top + 130 + (rcWindow.bottom - rcWindow.top) - (rcChild.bottom - rcChild.top);
+ }
+ if ((rcChild.right-rcChild.left) < 380) {
+ rcWindow.right = rcWindow.left + 380;
+ }
+ MoveWindow(hwndDlg, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
+ container->getChildWindowRect(&rcChild);
+ }
+ if (container->getActive() != NULL) {
+ MoveWindow(container->getActive()->getHWND(), rcChild.left, rcChild.top, rcChild.right-rcChild.left, rcChild.bottom - rcChild.top, TRUE);
+ }
+ }
+ return TRUE;
+ case DM_CREATECHILD:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_GROUPCHAT_LOG), hwndDlg, (DLGPROC) wParam, (LPARAM) lParam));
+ return TRUE;
+ case DM_ADDCHILD:
+ container->addChild((ChatWindow *) lParam);
+ return TRUE;
+ case DM_REMOVECHILD:
+ container->removeChild((ChatWindow *) lParam);
+ return TRUE;
+ case DM_CHANGECHILDDATA:
+ container->removeChild((ChatWindow *) lParam);
+ return TRUE;
+ case DM_SETUNREAD:
+ container->setUnread((ChatWindow *) lParam, (int)wParam);
+ return TRUE;
+ case DM_FLASHWINDOW:
+ if (GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) {
+ container->setFlash(0);
+ SetTimer(hwndDlg, TIMERID_FLASHWND, container->getFlashTimeout(), NULL);
+ }
+ return TRUE;
+ case WM_NOTIFY:
+ {
+ NMHDR* pNMHDR = (NMHDR*) lParam;
+ switch (pNMHDR->code) {
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci = {0};
+ HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
+ int iSel = TabCtrl_GetCurSel(hwndTabs);
+ tci.mask = TCIF_PARAM;
+ if (TabCtrl_GetItem(hwndTabs, iSel, &tci)) {
+ ChatWindow * chatWindow = (ChatWindow *) tci.lParam;
+ container->activateChild(chatWindow);
+ }
+ }
+ break;
+ case NM_CLICK:
+ {
+ FILETIME ft;
+ TCHITTESTINFO thinfo;
+ int tabId;
+ HWND hwndTabs = GetDlgItem(hwndDlg, IDC_TABS);
+ GetSystemTimeAsFileTime(&ft);
+ GetCursorPos(&thinfo.pt);
+ ScreenToClient(hwndTabs, &thinfo.pt);
+ tabId = TabCtrl_HitTest(hwndTabs, &thinfo);
+ if (tabId != -1 && tabId == container->lastClickTab &&
+ (ft.dwLowDateTime - container->lastClickTime) < (GetDoubleClickTime() * 10000)) {
+ SendMessage(container->getChildFromTab(tabId)->getHWND(), WM_CLOSE, 0, 0);
+ container->lastClickTab = -1;
+ } else {
+ container->lastClickTab = tabId;
+ }
+ container->lastClickTime = ft.dwLowDateTime;
+ }
+ break;
+ }
+
+ }
+ break;
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE)
+ break;
+ case WM_MOUSEACTIVATE:
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
+ FlashWindow(hwndDlg, FALSE);
+ }
+ /*
+ if (container->getActive() != NULL) {
+ container->setUnread(container->getActive(), 0);
+ SendMessage(container->getActive()->getHWND(), WM_ACTIVATE, WA_ACTIVE, 0);
+ }*/
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ return FALSE;
+ case WM_TIMER:
+ if (wParam == TIMERID_FLASHWND) {
+ if ((container->getFlash() > container->getFlashMax()) || (GetActiveWindow() == hwndDlg) || (GetForegroundWindow() == hwndDlg)) {
+ KillTimer(hwndDlg, TIMERID_FLASHWND);
+ FlashWindow(hwndDlg, FALSE);
+ } else if (container->getFlash() < container->getFlashMax()) {
+ FlashWindow(hwndDlg, TRUE);
+ container->setFlash(container->getFlash()+1);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)0);
+ delete container;
+ return TRUE;
+
+ }
+ return FALSE;
+}
+
+
+static void __cdecl StartThread(void *vContainer) {
+ OleInitialize(NULL);
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GROUPCHAT_CONTAINER), NULL, ContainerDlgProc, (LPARAM) vContainer);
+ //MessageBox(NULL, "ChatContainer dies.", "MW", MB_OK);
+ OleUninitialize();
+
+}
diff --git a/protocols/Tlen/tlen_czaty/src/ChatContainer.h b/protocols/Tlen/tlen_czaty/src/ChatContainer.h
new file mode 100644
index 0000000000..43b21014f0
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatContainer.h
@@ -0,0 +1,100 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+
+class ChatContainer;
+
+#ifndef CHATCONTAINER_INCLUDED
+#define CHATCONTAINER_INCLUDED
+#include "mucc.h"
+#include "ChatEvent.h"
+#include "ChatUser.h"
+#include "AdminWindow.h"
+
+class ChatContainerChild {
+public:
+ ChatWindow *window;
+ ChatContainerChild *next;
+ ChatContainerChild *prev;
+};
+
+class ChatContainer{
+
+private:
+ static ChatContainer * list;
+ static bool released;
+ static CRITICAL_SECTION mutex;
+ HWND hWnd;
+ HANDLE hEvent;
+ int childCount;
+ int width, height;
+ int nFlash, nFlashMax;
+ ChatContainer *next, *prev;
+ ChatWindow * active;
+ ChatContainer();
+protected:
+ friend INT_PTR CALLBACK ContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ void addChild(ChatWindow *);
+ void activateChild(ChatWindow *);
+ void changeChildData(ChatWindow *);
+ void removeChild(ChatWindow *);
+ void setUnread(ChatWindow *child, int unread);
+ void getChildWindowRect(RECT *rcChild);
+ ChatWindow * getChildFromTab(int tabId);
+ int getChildTab(ChatWindow *);
+ int getChildCount();
+ void setChildCount(int);
+ ChatWindow * getActive();
+ ChatContainerChild *getChildren();
+ ChatContainer * getNext();
+ void setNext(ChatContainer *);
+ ChatContainer * getPrev();
+ void setPrev(ChatContainer *);
+ int lastClickTime;
+ int lastClickTab;
+ HANDLE getEvent();
+ void setHWND(HWND);
+ int getFlash();
+ int getFlashMax();
+ int getFlashTimeout();
+ void setFlash(int);
+public:
+ enum FLAGS {
+ FLAG_USE_TABS = 0x00000001,
+ };
+
+ ~ChatContainer();
+ static void init();
+ static void release();
+ static ChatContainer * getWindow();
+ static int getDefaultOptions();
+ void show(bool bShow);
+ HWND getHWND();
+
+ HWND remoteCreateChild(DLGPROC proc, ChatWindow *);
+ void remoteAddChild(ChatWindow *);
+ void remoteChangeChildData(ChatWindow *);
+ void remoteRemoveChild(ChatWindow *);
+ void remoteSetUnread(ChatWindow *ptr, int unread);
+ void remoteFlashWindow();
+};
+
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ChatEvent.cpp b/protocols/Tlen/tlen_czaty/src/ChatEvent.cpp
new file mode 100644
index 0000000000..98da308382
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatEvent.cpp
@@ -0,0 +1,174 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatEvent.h"
+#include "Options.h"
+#include "Utils.h"
+#include <string.h>
+
+ChatEvent::ChatEvent() {
+
+ next = prev = NULL;
+ event.cbSize = sizeof(MUCCEVENT);
+ event.iType = 0;
+ event.pszID = NULL;
+ event.pszModule = NULL;
+ event.pszName = NULL;
+ event.pszNick = NULL;
+ event.pszText = NULL;
+ event.pszUID = NULL;
+}
+
+ChatEvent::ChatEvent(const MUCCEVENT *e) {
+
+ event.cbSize = sizeof(MUCCEVENT);
+ event.iType = e->iType;
+ event.bIsMe = e->bIsMe;
+ event.color = e->color;
+ event.dwData = e->dwData;
+ event.dwFlags = e->dwFlags;
+ event.iFont = e->iFont;
+ event.iFontSize = e->iFontSize;
+ event.time = e->time;
+ event.pszID = NULL;
+ event.pszModule = NULL;
+ event.pszName = NULL;
+ event.pszNick = NULL;
+ event.pszText = NULL;
+ event.pszUID = NULL;
+// Utils::copyString((char **)&(event.pszID), e->pszID);
+// Utils::copyString((char **)&(event.pszModule), e->pszModule);
+// Utils::copyString((char **)&(event.pszName), e->pszName);
+ if (e->iType == MUCC_EVENT_STATUS || e->iType == MUCC_EVENT_MESSAGE) {
+ Utils::copyString((char **)&(event.pszNick), e->pszNick);
+ }
+ if (e->iType == MUCC_EVENT_ERROR || e->iType == MUCC_EVENT_MESSAGE || e->iType == MUCC_EVENT_TOPIC) {
+ Utils::copyString((char **)&(event.pszText), e->pszText);
+ }
+// Utils::copyString((char **)&(event.pszUID), e->pszUID);
+ next = prev = NULL;
+}
+
+ChatEvent::~ChatEvent() {
+
+ if (event.pszID != NULL) {
+ delete (char *)event.pszID;
+ }
+ if (event.pszModule != NULL) {
+ delete (char *)event.pszModule;
+ }
+ if (event.pszName != NULL) {
+ delete (char *)event.pszName;
+ }
+ if (event.pszNick != NULL) {
+ delete (char *)event.pszNick;
+ }
+ if (event.pszText != NULL) {
+ delete (char *)event.pszText;
+ }
+ if (event.pszUID != NULL) {
+ delete (char *)event.pszUID;
+ }
+ if (next != NULL) {
+ next->setPrev(prev);
+ }
+ if (prev != NULL) {
+ prev->setNext(next);
+ }
+}
+
+ChatEvent * ChatEvent::getNext() {
+ return next;
+}
+
+ChatEvent * ChatEvent::getPrev() {
+ return prev;
+}
+
+void ChatEvent::setNext(ChatEvent *next) {
+ this->next = next;
+}
+
+void ChatEvent::setPrev(ChatEvent * prev) {
+ this->prev = prev;
+}
+
+const MUCCEVENT * ChatEvent::getEvent() {
+ return &event;
+}
+
+ChatEventList::ChatEventList() {
+ eventListEnd = &eventListRoot;
+ setMaxSize(DEFAULT_MAX_SIZE);
+ currentSize = 0;
+}
+
+ChatEventList::~ChatEventList() {
+ while (eventListRoot.getNext() != NULL) {
+ delete eventListRoot.getNext();
+ }
+}
+
+int ChatEventList::addEvent(const MUCCEVENT *muccevent) {
+ int trimmed = 0;
+ ChatEvent *event = new ChatEvent(muccevent);
+ event->setPrev(eventListEnd);
+ eventListEnd->setNext(event);
+ eventListEnd=event;
+ currentSize++;
+ if (currentSize>hiMaxSize) {
+ while (currentSize>loMaxSize && eventListRoot.getNext() != NULL) {
+ delete eventListRoot.getNext();
+ currentSize--;
+ trimmed = 1;
+ }
+ }
+ return trimmed;
+}
+
+ChatEvent * ChatEventList::getEvents() {
+ return eventListRoot.getNext();
+}
+
+void ChatEventList::setMaxSize(int s) {
+ loMaxSize = s;
+ if (s>200) {
+ hiMaxSize = s + s/10;
+ } else {
+ hiMaxSize = s + 20;
+ }
+}
+
+void ChatEventList::clear() {
+ ChatEvent *event = eventListRoot.getNext();
+ eventListRoot.setNext(NULL);
+ eventListEnd = &eventListRoot;
+ currentSize = 0;
+ if (event != NULL) {
+ event->setPrev(NULL);
+ while (event->getNext() != NULL) {
+ delete event->getNext();
+ }
+ delete event;
+ }
+}
+
+
diff --git a/protocols/Tlen/tlen_czaty/src/ChatEvent.h b/protocols/Tlen/tlen_czaty/src/ChatEvent.h
new file mode 100644
index 0000000000..c90c5b48ee
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatEvent.h
@@ -0,0 +1,60 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef CHATEVENT_INCLUDED
+#define CHATEVENT_INCLUDED
+#include "mucc.h"
+
+class ChatEvent {
+private:
+ ChatEvent * prev;
+ ChatEvent * next;
+ MUCCEVENT event;
+public:
+ ChatEvent();
+ ChatEvent(const MUCCEVENT *);
+ ~ChatEvent();
+ ChatEvent * getPrev();
+ ChatEvent * getNext();
+ void setPrev(ChatEvent *);
+ void setNext(ChatEvent *);
+ const MUCCEVENT *getEvent();
+};
+
+class ChatEventList {
+private:
+ ChatEvent eventListRoot;
+ ChatEvent * eventListEnd;
+ int loMaxSize;
+ int hiMaxSize;
+ int currentSize;
+public:
+ enum {
+ DEFAULT_MAX_SIZE = 100
+ };
+ ChatEventList();
+ ~ChatEventList();
+ ChatEvent * getEvents();
+ int addEvent(const MUCCEVENT *);
+ void clear();
+ void setMaxSize(int s);
+};
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ChatGroup.cpp b/protocols/Tlen/tlen_czaty/src/ChatGroup.cpp
new file mode 100644
index 0000000000..535985a85d
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatGroup.cpp
@@ -0,0 +1,99 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatGroup.h"
+#include "Utils.h"
+
+ChatGroup::ChatGroup() {
+ prev = next = NULL;
+ parent = child =NULL;
+ name = NULL;
+ id = 0;
+}
+
+ChatGroup::~ChatGroup() {
+ if (name != NULL) delete name;
+ if (id != NULL) delete id;
+}
+ChatGroup * ChatGroup::getNext() {
+ return next;
+}
+
+void ChatGroup::setNext(ChatGroup *next) {
+ this->next = next;
+}
+
+ChatGroup * ChatGroup::getPrev() {
+ return prev;
+}
+
+void ChatGroup::setPrev(ChatGroup *prev) {
+ this->prev = prev;
+}
+
+ChatGroup * ChatGroup::getChild() {
+ return child;
+}
+
+void ChatGroup::addChild(ChatGroup *child) {
+ ChatGroup *group;
+ for (group=getChild();group != NULL && group->getNext() != NULL;group=group->getNext()) {
+ }
+ if (group == NULL) this->child = child;
+ else {
+ group->setNext(child);
+ }
+ child->setPrev(group);
+ child->setNext(NULL);
+}
+
+ChatGroup * ChatGroup::getListNext() {
+ return listNext;
+}
+
+void ChatGroup::setListNext(ChatGroup *next) {
+ this->listNext = next;
+}
+
+const char *ChatGroup::getId() {
+ return id;
+}
+
+void ChatGroup::setId(const char *id) {
+ Utils::copyString(&this->id, id);
+}
+
+HTREEITEM ChatGroup::getTreeItem() {
+ return hItem;
+}
+
+void ChatGroup::setTreeItem(HTREEITEM hItem) {
+ this->hItem=hItem;
+}
+
+const char *ChatGroup::getName() {
+ return name;
+}
+
+void ChatGroup::setName(const char *name) {
+ Utils::copyString(&this->name, name);
+}
+
diff --git a/protocols/Tlen/tlen_czaty/src/ChatGroup.h b/protocols/Tlen/tlen_czaty/src/ChatGroup.h
new file mode 100644
index 0000000000..8f92066707
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatGroup.h
@@ -0,0 +1,55 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef CHATGROUP_INCLUDED
+#define CHATGROUP_INCLUDED
+#include "mucc.h"
+
+class ChatGroup {
+private:
+ HTREEITEM hItem;
+ ChatGroup * parent;
+ ChatGroup * child;
+ ChatGroup * prev;
+ ChatGroup * next;
+ ChatGroup * listNext;
+ char * name;
+ char * id;
+public:
+ ChatGroup();
+ ~ChatGroup();
+ ChatGroup * getPrev();
+ ChatGroup * getNext();
+ ChatGroup * getListNext();
+ ChatGroup * getChild();
+ ChatGroup * getParent();
+ HTREEITEM getTreeItem();
+ const char * getName();
+ const char * getId();
+ void setPrev(ChatGroup *);
+ void setNext(ChatGroup *);
+ void setListNext(ChatGroup *);
+ void addChild(ChatGroup *);
+ void setParent(ChatGroup *);
+ void setName(const char *);
+ void setTreeItem(HTREEITEM );
+ void setId(const char *);
+};
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ChatRoom.cpp b/protocols/Tlen/tlen_czaty/src/ChatRoom.cpp
new file mode 100644
index 0000000000..e575bdd759
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatRoom.cpp
@@ -0,0 +1,68 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatRoom.h"
+#include "Utils.h"
+
+
+ChatRoom::ChatRoom() {
+ next = prev = NULL;
+ name = NULL;
+ id = NULL;
+}
+
+ChatRoom::~ChatRoom() {
+ if (name != NULL) delete name;
+ if (id != NULL) delete id;
+}
+
+void ChatRoom::setId(const char *id) {
+ Utils::copyString(&this->id, id);
+}
+
+void ChatRoom::setName(const char *name) {
+ Utils::copyString(&this->name, name);
+}
+
+const char* ChatRoom::getId() {
+ return id;
+}
+
+const char* ChatRoom::getName() {
+ return name;
+}
+
+ChatRoom *ChatRoom::getNext() {
+ return next;
+}
+
+void ChatRoom::setNext(ChatRoom *next) {
+ this->next = next;
+}
+
+void ChatRoom::setFlags(int flags) {
+ this->flags = flags;
+}
+
+int ChatRoom::getFlags() {
+ return flags;
+}
+
diff --git a/protocols/Tlen/tlen_czaty/src/ChatRoom.h b/protocols/Tlen/tlen_czaty/src/ChatRoom.h
new file mode 100644
index 0000000000..e883ccd84a
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatRoom.h
@@ -0,0 +1,51 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef CHATROOM_INCLUDED
+#define CHATROOM_INCLUDED
+#include "mucc.h"
+
+
+class ChatRoom {
+private:
+ HTREEITEM hItem;
+ ChatRoom * prev;
+ ChatRoom * next;
+ char * name;
+ char * id;
+ int flags;
+public:
+ ChatRoom();
+ ~ChatRoom();
+ ChatRoom * getPrev();
+ ChatRoom * getNext();
+ HTREEITEM getTreeItem();
+ const char * getName();
+ const char * getId();
+ int getFlags();
+ void setPrev(ChatRoom *);
+ void setNext(ChatRoom *);
+ void setName(const char *);
+ void setTreeItem(HTREEITEM );
+ void setId(const char *);
+ void setFlags(int);
+};
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ChatUser.cpp b/protocols/Tlen/tlen_czaty/src/ChatUser.cpp
new file mode 100644
index 0000000000..3f306d4523
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatUser.cpp
@@ -0,0 +1,83 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatUser.h"
+#include "Utils.h"
+
+ChatUser::ChatUser() {
+ id = NULL;
+ nick = NULL;
+ hTreeItem = NULL;
+ me = 0;
+}
+
+ChatUser::~ChatUser() {
+ if (id != NULL) delete id;
+ if (nick != NULL) delete nick;
+}
+
+void ChatUser::setNick(const char *nick) {
+ Utils::copyString(&this->nick, nick);
+}
+
+void ChatUser::setId(const char *id) {
+ Utils::copyString(&this->id, id);
+}
+
+const char *ChatUser::getNick() {
+ return nick;
+}
+
+const char *ChatUser::getId() {
+ return id;
+}
+
+void ChatUser::setNext(ChatUser *next) {
+ this->next = next;
+}
+
+ChatUser * ChatUser::getNext() {
+ return next;
+}
+
+void ChatUser::setFlags(int flags) {
+ this->flags = flags;
+}
+
+int ChatUser::getFlags() {
+ return flags;
+}
+
+void ChatUser::setMe(int me) {
+ this->me = me;
+}
+
+int ChatUser::isMe() {
+ return me;
+}
+
+void ChatUser::setHTreeItem(HTREEITEM hti) {
+ hTreeItem = hti;
+}
+
+HTREEITEM ChatUser::getHTreeItem() {
+ return hTreeItem;
+}
diff --git a/protocols/Tlen/tlen_czaty/src/ChatUser.h b/protocols/Tlen/tlen_czaty/src/ChatUser.h
new file mode 100644
index 0000000000..5fa95c2291
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatUser.h
@@ -0,0 +1,49 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef CHATUSER_INCLUDED
+#define CHATUSER_INCLUDED
+#include "mucc.h"
+
+class ChatUser {
+private:
+ char * nick;
+ char * id;
+ int flags;
+ int me;
+ ChatUser * next;
+ HTREEITEM hTreeItem;
+public:
+ ChatUser();
+ ~ChatUser();
+ void setNick(const char *);
+ void setId(const char *);
+ const char * getNick();
+ const char * getId();
+ void setNext(ChatUser *);
+ int getFlags();
+ void setFlags(int );
+ HTREEITEM getHTreeItem();
+ void setHTreeItem(HTREEITEM);
+ ChatUser * getNext();
+ void setMe(int);
+ int isMe();
+};
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ChatWindow.cpp b/protocols/Tlen/tlen_czaty/src/ChatWindow.cpp
new file mode 100644
index 0000000000..b5db25ea9f
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatWindow.cpp
@@ -0,0 +1,2109 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ChatWindow.h"
+#include "HelperDialog.h"
+#include "Utils.h"
+#include "Options.h"
+#include "m_smileyadd.h"
+#include "m_ieview.h"
+//#include "m_chat.h"
+
+static int logPixelSY;
+static INT_PTR CALLBACK LogDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static void JabberStringAppend(char **str, int *sizeAlloced, const char *fmt, ...);
+static char *JabberRtfEscape(char *str);
+//static DWORD CALLBACK Log_StreamCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb);
+
+COLORREF ChatWindow::colorListBg, ChatWindow::colorListText, ChatWindow::colorListGroupText;
+HFONT ChatWindow::hListGroupFont=NULL;
+HFONT ChatWindow::hListFont=NULL;
+
+ChatWindow * ChatWindow::list = NULL;
+bool ChatWindow::released = false;
+CRITICAL_SECTION ChatWindow::mutex;
+
+static WNDPROC oldSplitterWndProc, oldEditWndProc;
+static HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
+
+void ChatWindow::release() {
+ released = true;
+ for (ChatWindow *ptr2, *ptr = list; ptr != NULL; ptr=ptr2) {
+ ptr2 = ptr->getNext();
+ //SendMessage(ptr->getHWND(), WM_CLOSE, 0, 0);
+ }
+ DeleteCriticalSection(&mutex);
+ DestroyCursor(hCurSplitNS);
+ DestroyCursor(hCurSplitWE);
+ DestroyCursor(hCurHyperlinkHand);
+}
+
+void ChatWindow::init() {
+ hCurSplitNS = LoadCursor(NULL, IDC_SIZENS);
+ hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE);
+ hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND);
+ if (hCurHyperlinkHand == NULL) {
+ hCurHyperlinkHand = LoadCursor(NULL, IDC_ARROW);
+ }
+ released = false;
+ InitializeCriticalSection(&mutex);
+}
+
+/* chat.dll mod*/
+/*
+static bool gcRegistered = false;
+
+static void __stdcall StartThread(void *vChat) { //__cdecl
+ ChatWindow *chat = (ChatWindow *)vChat;
+ if (!gcRegistered) {
+ gcRegistered = true;
+ GCREGISTER gcr = {0};
+ gcr.cbSize = sizeof(GCREGISTER);
+ gcr.dwFlags = 0;
+ gcr.iMaxText = 0;
+ gcr.nColors = 0;
+ gcr.pColors = 0;
+ gcr.pszModuleDispName = chat->getModule();
+ gcr.pszModule = chat->getModule();
+ if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr)) {
+ MessageBox(NULL, "cannot register", "CHAT", MB_OK);
+ }
+ }
+ GCWINDOW gcw = {0};
+ gcw.cbSize = sizeof(GCWINDOW);
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = chat->getModule();
+ gcw.pszName = chat->getRoomName();
+ gcw.pszID = chat->getRoomId();
+ gcw.pszStatusbarText = "status";
+ gcw.bDisableNickList = FALSE;
+ gcw.dwItemData = (DWORD) chat;
+ if (CallService(MS_GC_NEWCHAT, 0, (LPARAM) &gcw)) {
+ MessageBox(NULL, "cannot create", "CHAT", MB_OK);
+ }
+
+ GCDEST gcdest;
+ GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
+ const char *groupNames[] = {"Global Owners", "Owners", "Admins", "Moderators", "Users"};
+ gcdest.pszModule = (char *)chat->getModule();
+ gcdest.pszID = (char *)chat->getRoomId();
+ gcevent.bAddToLog = FALSE;
+ gcevent.time = 0;
+ gcdest.iType = GC_EVENT_ADDGROUP;
+ for (int i=0;i<5;i++) {
+ gcevent.pszStatus = Translate(groupNames[i]);
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gcevent);
+ }
+
+
+ gcdest.iType = GC_EVENT_CONTROL;
+ CallService(MS_GC_EVENT, WINDOW_INITDONE, (LPARAM)&gcevent);
+ CallService(MS_GC_EVENT, WINDOW_ONLINE, (LPARAM)&gcevent);
+}
+*/
+
+ChatWindow::ChatWindow(MUCCWINDOW *mucw) {
+ prev = next = NULL;
+ adminWindow = NULL;
+ hWnd = NULL;
+ hWndLog = NULL;
+ module = roomId = roomName = topic = NULL;
+ hSplitterPos = 0;
+ vSplitterPos = 0;
+ wasFirstMessage = 0;
+ isEmpty = true;
+ isStarted = 0;
+ options = Options::getChatWindowOptions();
+ bBold = bItalic = bUnderline = 0;
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hEditFont = NULL;
+ userMe = NULL;
+ users = NULL;
+ for (int i=0;i<5;i++) {
+ hUserGroups[i] = NULL;
+ }
+ setModule(mucw->pszModule);
+ setRoomId(mucw->pszID);
+ setRoomName(mucw->pszName);
+ EnterCriticalSection(&mutex);
+ setNext(list);
+ if (next!=NULL) {
+ next->setPrev(this);
+ }
+ list = this;
+ LeaveCriticalSection(&mutex);
+ container = ChatContainer::getWindow();
+ hWnd = container->remoteCreateChild(LogDlgProc, this);
+ container->remoteAddChild(this);
+ /* chat.dll mod*/
+/* CallFunctionAsync(StartThread, (void *)this);*/
+}
+
+ChatWindow::~ChatWindow () {
+ if (!released) {
+ EnterCriticalSection(&mutex);
+ if (getPrev() != NULL) {
+ getPrev()->setNext(next);
+ } else if (list == this) {
+ list = getNext();
+ }
+ if (getNext() != NULL) {
+ getNext()->setPrev(prev);
+ }
+ LeaveCriticalSection(&mutex);
+ }
+ if (adminWindow != NULL) {
+ delete adminWindow;
+ }
+ if (hEvent != NULL) {
+ CloseHandle(hEvent);
+ }
+ while (users != NULL) {
+ ChatUser *user = users;
+ users = users->getNext();
+ delete user;
+ }
+ if (module != NULL) {
+ delete module;
+ }
+ if (roomId != NULL) {
+ delete roomId;
+ }
+ if (roomName != NULL) {
+ delete roomName;
+ }
+ if (topic != NULL) {
+ delete topic;
+ }
+ container->remoteRemoveChild(this);
+};
+
+
+void ChatWindow::setPrev(ChatWindow *prev) {
+ this->prev = prev;
+}
+
+ChatWindow * ChatWindow::getPrev() {
+ return prev;
+}
+
+void ChatWindow::setNext(ChatWindow *next) {
+ this->next = next;
+}
+
+ChatWindow * ChatWindow::getNext() {
+ return next;
+}
+
+void ChatWindow::setHWND(HWND hWnd) {
+ this->hWnd = hWnd;
+}
+
+HWND ChatWindow::getHWND() {
+ return hWnd;
+}
+
+void ChatWindow::setHWNDLog(HWND hWnd) {
+ this->hWndLog = hWnd;
+}
+
+HWND ChatWindow::getHWNDLog() {
+ return hWndLog;
+}
+
+HANDLE ChatWindow::getEvent() {
+ return hEvent;
+}
+
+ChatContainer * ChatWindow::getContainer() {
+ return container;
+}
+
+void ChatWindow::setAdminWindow(AdminWindow *aw) {
+ this->adminWindow = aw;
+}
+
+AdminWindow* ChatWindow::getAdminWindow() {
+ return adminWindow;
+}
+
+void ChatWindow::setModule(const char *module) {
+ Utils::copyString(&this->module, module);
+}
+
+const char * ChatWindow::getModule() {
+ return module;
+}
+
+void ChatWindow::setRoomId(const char *roomId) {
+ Utils::copyString(&this->roomId, roomId);
+}
+
+const char * ChatWindow::getRoomId() {
+ return roomId;
+}
+
+void ChatWindow::setRoomName(const char *roomName) {
+// char str[300];
+ Utils::copyString(&this->roomName, roomName);
+// sprintf(str, "%s %08X", roomName, roomFlags);
+// SetWindowText(hWnd, str);
+ SetWindowTextA(hWnd, roomName);
+}
+
+void ChatWindow::setRoomFlags(int flags) {
+// char str[300];
+ roomFlags = flags;
+// sprintf(str, "%s %08X", roomName, roomFlags);
+// SetWindowText(hWnd, str);
+}
+
+int ChatWindow::getRoomFlags() {
+ return roomFlags;
+}
+
+const char * ChatWindow::getRoomName() {
+ return roomName;
+}
+
+void ChatWindow::setOptions(int options) {
+ if (options != this->options) {
+ this->options = options;
+ rebuildLog();
+ }
+}
+
+int ChatWindow::getOptions() {
+ return options;
+}
+
+static void __cdecl StartAdminThread(void *vChat) {
+ ChatWindow *chat = (ChatWindow *)vChat;
+ chat->getAdminWindow()->start();
+}
+
+void ChatWindow::startAdminDialog(int mode) {
+ if (adminWindow == NULL) {
+ ChatUser *user = getSelectedUser();
+ if (user != NULL) {
+ adminWindow = new AdminWindow(this, user->getId(), mode);
+ } else {
+ adminWindow = new AdminWindow(this, "", mode);
+ }
+ Utils::forkThread((void (__cdecl *)(void *))StartAdminThread, 0, (void *) this);
+ }
+}
+void ChatWindow::addUser(ChatUser *user) {
+ user->setNext(users);
+ users = user;
+}
+void ChatWindow::removeUser(ChatUser *user) {
+ ChatUser *user2;
+ for (user2=users;user2 != NULL;user2=user2->getNext()) {
+ if (user2->getNext() == user) break;
+ }
+ if (user2 != NULL) {
+ user2->setNext(user->getNext());
+ } else if (users == user) {
+ users = user->getNext();
+ }
+}
+
+ChatUser * ChatWindow::getMe() {
+ return userMe;
+}
+
+ChatUser * ChatWindow::findUser(const char *userId) {
+ ChatUser *user;
+ for (user=users;user != NULL;user=user->getNext()) {
+ if (!(strcmp(user->getId(), userId))) break;
+ }
+ return user;
+}
+
+ChatUser * ChatWindow::findUserByNick(const char *nick) {
+ ChatUser *user;
+ for (user=users;user != NULL;user=user->getNext()) {
+ if (!(strcmp(user->getNick(), nick))) break;
+ }
+ return user;
+}
+
+ChatUser *ChatWindow::getSelectedUser() {
+ HTREEITEM hTreeItem = TreeView_GetSelection(GetDlgItem(hWnd, IDC_TREELIST));
+ if (hTreeItem != NULL) {
+ TVITEM tvi;
+ tvi.mask = TVIF_PARAM;
+ tvi.hItem = hTreeItem;
+ TreeView_GetItem(GetDlgItem(hWnd, IDC_TREELIST), &tvi);
+ return (ChatUser *) tvi.lParam;
+ }
+ return NULL;
+}
+
+int ChatWindow::startPriv() {
+ ChatUser *user = getSelectedUser();
+ if (user != NULL) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_START_PRIV;
+ mucce.pszModule = getModule();
+ mucce.pszID = getRoomId();
+ mucce.pszUID = user->getId();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&mucce);
+ }
+ return 0;
+}
+
+int ChatWindow::unban(const char *id) {
+ if (id != NULL) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_UNBAN;
+ mucce.pszModule = getModule();
+ mucce.pszID = getRoomId();
+ mucce.pszUID = id;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&mucce);
+ }
+ return 0;
+}
+
+
+int ChatWindow::kickAndBan(const char *id, int time, const char *reason) {
+ if (id != NULL) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_KICK_BAN;
+ mucce.pszModule = getModule();
+ mucce.pszID = getRoomId();
+ mucce.pszUID = id;
+ mucce.dwData = time;
+ mucce.pszText = reason;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&mucce);
+ }
+ return 0;
+}
+
+int ChatWindow::kickAndBan(int time) {
+ ChatUser *user = getSelectedUser();
+ if (user != NULL) {
+ kickAndBan(user->getId(), time, "");
+ }
+ return 0;
+}
+
+int ChatWindow::setRights(const char *id, int flags) {
+ if (id != NULL) {
+ MUCCEVENT mucce;
+ mucce.cbSize = sizeof(MUCCEVENT);
+ mucce.iType = MUCC_EVENT_SET_USER_ROLE;
+ mucce.pszModule = getModule();
+ mucce.pszID = getRoomId();
+ mucce.pszUID = id;
+ mucce.dwFlags = flags;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&mucce);
+ }
+ return 0;
+}
+
+int ChatWindow::setRights(int flags) {
+ ChatUser *user = getSelectedUser();
+ if (user != NULL) {
+ setRights(user->getId(), flags);
+ }
+ return 0;
+}
+
+int ChatWindow::getUserGroup(ChatUser *user) {
+ int group = 4;
+ if (user->getFlags()&MUCC_EF_USER_GLOBALOWNER) {
+ group = 0;
+ } else if (user->getFlags()&MUCC_EF_USER_OWNER) {
+ group = 1;
+ } else if (user->getFlags()&MUCC_EF_USER_ADMIN) {
+ group = 2;
+ } else if (user->getFlags()&MUCC_EF_USER_MODERATOR) {
+ group = 3;
+ }
+ return group;
+}
+
+int ChatWindow::changePresence(const MUCCEVENT *event) {
+ int i, group, bLogEvent = FALSE;
+ const char *groupNames[] = {"Global Owners", "Owners", "Admins", "Moderators", "Users"};
+ ChatUser *user = findUser(event->pszUID);
+ if (event->dwData == ID_STATUS_ONLINE || (user != NULL && event->dwData != ID_STATUS_OFFLINE)) {
+ if (user == NULL) {
+ user = new ChatUser();
+ user->setId(event->pszUID);
+ user->setNick(event->pszNick);
+ user->setFlags(event->dwFlags);
+ user->setMe(event->bIsMe);
+ addUser(user);
+ if (user->isMe()) {
+ userMe = user;
+ }
+ bLogEvent = TRUE;
+ } else {
+ group = getUserGroup(user);
+ user->setFlags(event->dwFlags);
+ TreeView_DeleteItem(GetDlgItem(hWnd, IDC_TREELIST), user->getHTreeItem());
+ if (TreeView_GetChild(GetDlgItem(hWnd, IDC_TREELIST), getTreeItem(group)) == NULL) {
+ TreeView_DeleteItem(GetDlgItem(hWnd, IDC_TREELIST), getTreeItem(group));
+ setTreeItem(group, NULL);
+ }
+ }
+ if (user->isMe()) {
+ if (user->getFlags() & MUCC_EF_USER_OWNER || user->getFlags() & MUCC_EF_USER_ADMIN) {
+ EnableWindow(GetDlgItem(hWnd, IDC_TOPIC_BUTTON), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hWnd, IDC_TOPIC_BUTTON), FALSE);
+ }
+ }
+ group = getUserGroup(user);
+ TVINSERTSTRUCT tvis;
+ if (getTreeItem(group) == NULL) {
+ for (i=group-1; i >= 0; i--) {
+ if (getTreeItem(i) != NULL) break;
+ }
+ tvis.hParent = NULL;
+ if (i >= 0) {
+ tvis.hInsertAfter = getTreeItem(i);
+ } else {
+ tvis.hInsertAfter = TVI_FIRST;
+ }
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_CHILDREN;
+ tvis.item.lParam = (LPARAM) NULL;
+ tvis.item.cChildren = 1;
+ LPTSTR lps1 = Utils::mucc_mir_a2t(Translate(groupNames[group]));
+ tvis.item.pszText = lps1;
+ //tvis.item.state = INDEXTOSTATEIMAGEMASK(1);
+ //tvis.item.stateMask = TVIS_STATEIMAGEMASK ;
+ setTreeItem(group, TreeView_InsertItem(GetDlgItem(hWnd, IDC_TREELIST), &tvis));
+ Utils::mucc_mir_free(lps1);
+ }
+ tvis.hParent = getTreeItem(group);
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM;
+ LPTSTR lps2 = Utils::mucc_mir_a2t(user->getNick());
+ tvis.item.pszText = lps2;
+ tvis.item.lParam = (LPARAM) user;
+ user->setHTreeItem(TreeView_InsertItem(GetDlgItem(hWnd, IDC_TREELIST), &tvis));
+ TreeView_Expand(GetDlgItem(hWnd, IDC_TREELIST), getTreeItem(group), TVE_EXPAND);
+ Utils::mucc_mir_free(lps2);
+ }
+ else {
+ if (user != NULL) {
+ group = getUserGroup(user);
+ TreeView_DeleteItem(GetDlgItem(hWnd, IDC_TREELIST), user->getHTreeItem());
+ if (TreeView_GetChild(GetDlgItem(hWnd, IDC_TREELIST), getTreeItem(group)) == NULL) {
+ TreeView_DeleteItem(GetDlgItem(hWnd, IDC_TREELIST), getTreeItem(group));
+ setTreeItem(group, NULL);
+ }
+ removeUser(user);
+ delete user;
+ bLogEvent = TRUE;
+ }
+ }
+ if (bLogEvent && wasFirstMessage) {
+ logEvent(event);
+ }
+ return 1;
+}
+int ChatWindow::changeTopic(const MUCCEVENT *event) {
+
+ SetDlgItemTextA(hWnd, IDC_TOPIC, event->pszText);
+//if (wasFirstMessage) {
+ logEvent(event);
+// }
+ return 1;
+}
+
+int ChatWindow::changeRoomInfo(const MUCCEVENT *event) {
+
+ Utils::log("setting room info !");
+ setRoomName(event->pszName);
+ setRoomFlags(event->dwFlags);
+ return 1;
+}
+
+const char * ChatWindow::getFontName(int index) {
+ const char *fontNames[] = {"Arial",
+ "Comic Sans MS",
+ "Courier New",
+ "Impact",
+ "Lucida Console",
+ "MS Sans Serif",
+ "Tahoma",
+ "Times New Roman",
+ "Trebuchet MS",
+ "Verdana"};
+ if (index>9 || index<0) index = 0;
+ return fontNames[index];
+}
+int ChatWindow::getFontNameNum() {
+ return 10;
+}
+int ChatWindow::getFontSize(int index) {
+ return index+7;
+}
+int ChatWindow::getFontSizeNum() {
+ return 10;
+}
+
+void ChatWindow::refreshSettings() {
+ SendDlgItemMessage(hWnd, IDC_LOG, EM_SETBKGNDCOLOR , 0, Options::getLogBgColor());
+ SendDlgItemMessage(hWnd, IDC_TREELIST, TVM_SETBKCOLOR, 0, Options::getListBgColor());
+ eventList.setMaxSize(Options::getLogLimit());
+}
+
+void ChatWindow::refreshSettings(int force) {
+
+ if (hListFont != NULL && !force) {
+ return;
+ }
+ EnterCriticalSection(&mutex);
+ if (hListFont != NULL) {
+ DeleteObject(hListFont);
+ }
+ if (hListGroupFont != NULL) {
+ DeleteObject(hListGroupFont);
+ }
+ Font * font = Options::getFont(Options::FONT_USERLIST);
+ colorListText = font->getColor();
+ hListFont = CreateFontA(font->getSize(), 0, 0, 0,
+ font->getStyle() & Font::BOLD ? FW_BOLD : FW_NORMAL,
+ font->getStyle() & Font::ITALIC ? 1 : 0,
+ font->getStyle() & Font::UNDERLINE ? 1 : 0, 0,
+ font->getCharSet(),
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,
+ font->getFace());
+ font = Options::getFont(Options::FONT_USERLISTGROUP);
+ colorListGroupText = font->getColor();
+ hListGroupFont = CreateFontA(font->getSize(), 0, 0, 0,
+ font->getStyle() & Font::BOLD ? FW_BOLD : FW_NORMAL,
+ font->getStyle() & Font::ITALIC ? 1 : 0,
+ font->getStyle() & Font::UNDERLINE ? 1 : 0, 0,
+ font->getCharSet(),
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN,
+ font->getFace());
+
+ for (ChatWindow *ptr=list; ptr != NULL; ptr=ptr->getNext()) {
+ ptr->refreshSettings();
+ InvalidateRect(ptr->getHWND(), NULL, FALSE);
+ }
+ LeaveCriticalSection(&mutex);
+}
+HFONT ChatWindow::getListFont() {
+ return hListFont;
+}
+
+HFONT ChatWindow::getListGroupFont() {
+ return hListGroupFont;
+}
+
+COLORREF ChatWindow::getListTextColor() {
+ return colorListText;
+}
+
+COLORREF ChatWindow::getListGroupTextColor() {
+ return colorListGroupText;
+}
+
+HTREEITEM ChatWindow::getTreeItem(int index) {
+ return hUserGroups[index];
+}
+
+void ChatWindow::setTreeItem(int index, HTREEITEM hTreeItem) {
+ hUserGroups[index]=hTreeItem;
+}
+
+int ChatWindow::getDefaultOptions() {
+ return FLAG_SHOW_NICKNAMES | FLAG_SHOW_TIMESTAMP | FLAG_FORMAT_ALL | FLAG_LOG_MESSAGES | FLAG_OPT_SENDONENTER;
+}
+
+void ChatWindow::clearLog() {
+ if (getHWNDLog() != NULL) {
+ IEVIEWEVENT iee;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.iType = IEE_CLEAR_LOG;
+ iee.dwFlags = IEEF_NO_UNICODE;
+ iee.hwnd = hWndLog;
+ iee.hContact = NULL;
+ iee.codepage = CP_ACP;
+ iee.pszProto = getModule();
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+ } else {
+ SetDlgItemTextA(getHWND(), IDC_LOG, "");
+ }
+ isEmpty = true;
+ eventList.clear();
+}
+
+void ChatWindow::rebuildLog() {
+ int nMin, nMax;
+ HWND hwndLog;
+ if (getHWNDLog() != NULL) {
+ IEVIEWEVENT iee;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.iType = IEE_CLEAR_LOG;
+ iee.dwFlags = IEEF_NO_UNICODE;
+ iee.hwnd = hWndLog;
+ iee.hContact = NULL;
+ iee.codepage = CP_ACP;
+ iee.pszProto = getModule();
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+ } else {
+ SetDlgItemTextA(getHWND(), IDC_LOG, "");
+ }
+ isEmpty = true;
+ for (ChatEvent* event=eventList.getEvents(); event != NULL; event=event->getNext()) {
+ appendMessage(event->getEvent());
+ }
+ if (getHWNDLog() == NULL) {
+ if (ServiceExists(MS_SMILEYADD_REPLACESMILEYS)) PostMessage(getHWND(), WM_TLEN_SMILEY, 0, 0);
+ hwndLog = GetDlgItem(getHWND(), IDC_LOG);
+ int len = GetWindowTextLengthA(hwndLog);
+ SendMessage(hwndLog, EM_SETSEL, len - 1, len - 1);
+ GetScrollRange(hwndLog, SB_VERT, &nMin, &nMax);
+ SetScrollPos(hwndLog, SB_VERT, nMax, TRUE);
+ PostMessage(hwndLog, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nMax), (LPARAM) NULL);
+ }
+}
+
+int ChatWindow::logEvent(const MUCCEVENT *event) {
+ /* chat.dll mod*/
+ /*
+ if (event->iType == MUCC_EVENT_MESSAGE) {
+ GCDEST gcdest;
+ GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
+ gcdest.pszModule = (char *)this->getModule();
+ gcdest.pszID = (char *)this->getRoomId();
+ gcdest.iType = GC_EVENT_MESSAGE;
+ gcevent.pszText = event->pszText;
+ gcevent.pszNick = event->pszNick;
+ gcevent.pszUID = event->pszUID;
+ gcevent.bIsMe = event->bIsMe;
+ gcevent.bAddToLog = TRUE;
+ gcevent.time = event->time;
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gcevent);
+
+ }
+ if (event->iType == MUCC_EVENT_STATUS) {
+ const char *groupNames[] = {"Global Owners", "Owners", "Admins", "Moderators", "Users"};
+ GCDEST gcdest;
+ GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
+ gcdest.pszModule = (char *)this->getModule();
+ gcdest.pszID = (char *)this->getRoomId();
+ gcevent.pszText = event->pszText;
+ gcevent.pszNick = event->pszNick;
+ int group = 4;
+ if (event->dwFlags&MUCC_EF_USER_GLOBALOWNER) {
+ group = 0;
+ } else if (event->dwFlags&MUCC_EF_USER_OWNER) {
+ group = 1;
+ } else if (event->dwFlags&MUCC_EF_USER_ADMIN) {
+ group = 2;
+ } else if (event->dwFlags&MUCC_EF_USER_MODERATOR) {
+ group = 3;
+ }
+ gcevent.pszStatus = Translate(groupNames[group]);
+ gcevent.pszUID = event->pszUID;
+ gcevent.bIsMe = event->bIsMe;
+ gcevent.bAddToLog = TRUE;
+ gcevent.time = event->time;
+ if (event->dwData == ID_STATUS_ONLINE) {
+ gcdest.iType = GC_EVENT_JOIN;
+ } else {
+ gcdest.iType = GC_EVENT_PART;
+ }
+ CallService(MS_GC_EVENT, 0, (LPARAM)&gcevent);
+ }
+ */
+ /* chat.dll mod*/
+
+ int nMin, nMax;
+ HWND hwndLog;
+ if (event->iType != MUCC_EVENT_ERROR) {
+ if (eventList.addEvent(event)) {
+ rebuildLog();
+ return 1;
+ }
+ }
+ if (event->iType == MUCC_EVENT_MESSAGE) {
+ wasFirstMessage = 1;
+ appendMessage(event);
+ container->remoteSetUnread(this, 1);
+ } else {
+ appendMessage(event);
+ }
+ if (event->iType == MUCC_EVENT_MESSAGE && getOptions() & FLAG_FLASH_MESSAGES) {
+ container->remoteFlashWindow();
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_ONLINE && getOptions() & FLAG_FLASH_JOINED) {
+ container->remoteFlashWindow();
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_OFFLINE && getOptions() & FLAG_FLASH_LEFT) {
+ container->remoteFlashWindow();
+ } else if (event->iType == MUCC_EVENT_TOPIC && getOptions() & FLAG_FLASH_TOPIC) {
+ container->remoteFlashWindow();
+ }
+ if (getHWNDLog() == NULL) {
+ if (ServiceExists(MS_SMILEYADD_REPLACESMILEYS)) PostMessage(getHWND(), WM_TLEN_SMILEY, 0, 0);
+ hwndLog = GetDlgItem(getHWND(), IDC_LOG);
+ int len = GetWindowTextLengthA(hwndLog);
+ SendMessage(hwndLog, EM_SETSEL, len - 1, len - 1);
+ GetScrollRange(hwndLog, SB_VERT, &nMin, &nMax);
+ SetScrollPos(hwndLog, SB_VERT, nMax, TRUE);
+ PostMessage(hwndLog, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nMax), (LPARAM) NULL);
+ }
+ return 1;
+}
+
+void ChatWindow::createRTFHeader() {
+ char *rtf;
+ int i, msgSize;
+ //, , iFontSize, bItalic, bBold, bUnderline;
+ rtf = NULL;
+ JabberStringAppend(&rtf, &msgSize, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+
+ for (i=0;i<FontList::getFontNum();i++) {
+ Font *font = FontList::getFont(i);
+ JabberStringAppend(&rtf, &msgSize, "{\\f%u\\fnil\\fcharset%u %s;}", font->getCharSet(), font->getFace());
+ }
+ JabberStringAppend(&rtf, &msgSize, "}{\\colortbl ");
+ for (i=0;i<FontList::getFontNum();i++) {
+ Font *font = FontList::getFont(i);
+ DWORD color = font->getColor();
+ JabberStringAppend(&rtf, &msgSize, "\\red%d\\green%d\\blue%d;", color&0xFF, (color>>8)&0xFF, (color>>16)&0xFF);
+ }
+ JabberStringAppend(&rtf, &msgSize, "}");
+}
+
+
+int ChatWindow::appendMessage(const MUCCEVENT *event) {
+ char timestampStr[100], str[512];
+ char *rtf, *escapedStr = NULL, *escapedNick = NULL;
+ Font *fontTimestamp, *fontName, *fontMessage; //*fontColon,
+ int msgSize;
+ DWORD color;
+ int iFontSize, bItalic, bBold, bUnderline;
+ HWND hwndLog;
+ DBTIMETOSTRING dbtts;
+ CHARRANGE sel;
+ SETTEXTEX stt;
+ //tm *ltime;
+
+ if (event->iType != MUCC_EVENT_STATUS && event->iType != MUCC_EVENT_STATUS && event->iType != MUCC_EVENT_ERROR
+ && event->iType != MUCC_EVENT_TOPIC && event->iType != MUCC_EVENT_MESSAGE) {
+ return 0;
+ }
+ if (event->iType == MUCC_EVENT_MESSAGE && !(getOptions() & FLAG_LOG_MESSAGES)) {
+ return 0;
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_ONLINE && !(getOptions() & FLAG_LOG_JOINED)) {
+ return 0;
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_OFFLINE && !(getOptions() & FLAG_LOG_LEFT)) {
+ return 0;
+ } else if (event->iType == MUCC_EVENT_TOPIC && !(getOptions() & FLAG_LOG_TOPIC)) {
+ return 0;
+ }
+
+ if (getHWNDLog() != NULL) {
+ IEVIEWEVENTDATA ied;
+ IEVIEWEVENT iee;
+ IEVIEWWINDOW iew;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.dwFlags = IEEF_NO_UNICODE;
+ iee.hwnd = hWndLog;
+ iee.hContact = NULL;
+ iee.iType = IEE_LOG_MEM_EVENTS;
+ iee.codepage = CP_ACP;
+ iee.pszProto = getModule();
+ iee.eventData = &ied;
+ iee.count = 1;
+
+ ied.cbSize = sizeof(IEVIEWEVENTDATA);
+ if (event->iType == MUCC_EVENT_MESSAGE) {
+ ied.iType = IEED_MUCC_EVENT_MESSAGE;
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_ONLINE) {
+ ied.iType = IEED_MUCC_EVENT_JOINED;
+ } else if (event->iType == MUCC_EVENT_STATUS && event->dwData == ID_STATUS_OFFLINE) {
+ ied.iType = IEED_MUCC_EVENT_LEFT;
+ } else if (event->iType == MUCC_EVENT_TOPIC) {
+ ied.iType = IEED_MUCC_EVENT_TOPIC;
+ } else if (event->iType == MUCC_EVENT_ERROR) {
+ ied.iType = IEED_MUCC_EVENT_ERROR;
+ }
+ ied.dwFlags = getOptions() & FLAG_FORMAT_ALL;
+ ied.next = NULL;
+ ied.color = event->color;
+ ied.fontSize = event->iFontSize;
+ ied.fontStyle = event->dwFlags;
+ ied.fontName = getFontName(event->iFont);
+ ied.pszNick = event->pszNick;
+ ied.pszText = event->pszText;
+ ied.time = event->time;
+ ied.dwData = getOptions(); // event->dwData;
+ ied.bIsMe = event->bIsMe;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+
+ iew.cbSize = sizeof(IEVIEWWINDOW);
+ iew.iType = IEW_SCROLLBOTTOM;
+ iew.hwnd = hWndLog;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&iew);
+ return 1;
+ }
+ rtf = NULL;
+ fontTimestamp = FontList::getFont(FontList::FONT_TIMESTAMP);
+// fontColon = FontList::getFont(FontList::FONT_COLON);
+ if (event->iType == MUCC_EVENT_MESSAGE) {
+ escapedStr=JabberRtfEscape((char *)event->pszText);
+ escapedNick=JabberRtfEscape((char *)event->pszNick);
+ if (event->bIsMe) {
+ fontName = FontList::getFont(FontList::FONT_MYNAME);
+ fontMessage = FontList::getFont(FontList::FONT_OUTMESSAGE);
+ } else {
+ fontName = FontList::getFont(FontList::FONT_OTHERSNAMES);
+ fontMessage = FontList::getFont(FontList::FONT_INMESSAGE);
+ }
+ } else {
+ fontName = FontList::getFont(FontList::FONT_ERROR);
+ if (event->iType == MUCC_EVENT_ERROR) {
+ escapedStr = JabberRtfEscape((char *)event->pszText);
+ fontMessage = FontList::getFont(FontList::FONT_ERROR);
+ } else if (event->iType == MUCC_EVENT_STATUS) {
+ if (event->dwData == ID_STATUS_ONLINE) {
+ fontMessage = FontList::getFont(FontList::FONT_JOINED);
+ _snprintf(str, sizeof(str), Translate("%s has joined."), event->pszNick);
+ } else {
+ fontMessage = FontList::getFont(FontList::FONT_LEFT);
+ _snprintf(str, sizeof(str), Translate("%s has left."), event->pszNick);
+ }
+ escapedStr = JabberRtfEscape(str);
+ } else if (event->iType == MUCC_EVENT_TOPIC) {
+ fontMessage = FontList::getFont(FontList::FONT_TOPIC);
+ _snprintf(str, sizeof(str), Translate("The topic is %s."), event->pszText);
+ escapedStr = JabberRtfEscape(str);
+ }
+ }
+ //ltime = localtime(&event->time);
+ JabberStringAppend(&rtf, &msgSize, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+ JabberStringAppend(&rtf, &msgSize, "{\\f0\\fnil\\fcharset%u %s;}", fontTimestamp->getCharSet(), fontTimestamp->getFace());
+ JabberStringAppend(&rtf, &msgSize, "{\\f1\\fnil\\fcharset%u %s;}", fontName->getCharSet(), fontName->getFace());
+ if (event->iType == MUCC_EVENT_MESSAGE && getOptions()&FLAG_FORMAT_FONT) {
+ JabberStringAppend(&rtf, &msgSize, "{\\f2\\fnil\\fcharset%u %s;}", fontMessage->getCharSet(), getFontName(event->iFont));
+ } else {
+ JabberStringAppend(&rtf, &msgSize, "{\\f2\\fnil\\fcharset%u %s;}", fontMessage->getCharSet(), fontMessage->getFace());
+ }
+ JabberStringAppend(&rtf, &msgSize, "}{\\colortbl ");
+ color = fontTimestamp->getColor();
+ JabberStringAppend(&rtf, &msgSize, "\\red%d\\green%d\\blue%d;", color&0xFF, (color>>8)&0xFF, (color>>16)&0xFF);
+ color = fontName->getColor();
+ JabberStringAppend(&rtf, &msgSize, "\\red%d\\green%d\\blue%d;", color&0xFF, (color>>8)&0xFF, (color>>16)&0xFF);
+ if (event->iType == MUCC_EVENT_MESSAGE && getOptions()&FLAG_FORMAT_COLOR && event->color != 0xFFFFFFFF) {
+ color = event->color;
+ } else {
+ color = fontMessage->getColor();
+ }
+ JabberStringAppend(&rtf, &msgSize, "\\red%d\\green%d\\blue%d;", color&0xFF, (color>>8)&0xFF, (color>>16)&0xFF);
+ JabberStringAppend(&rtf, &msgSize, "}\\pard");
+ if (!isEmpty) {
+ JabberStringAppend(&rtf, &msgSize, "\\par");
+ }
+ isEmpty = false;
+ if (event->iType == MUCC_EVENT_MESSAGE) {
+ if (getOptions()&FLAG_SHOW_DATE || getOptions()&FLAG_SHOW_TIMESTAMP) {
+ bBold = fontTimestamp->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontTimestamp->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontTimestamp->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontTimestamp->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ dbtts.cbDest = 90;
+ dbtts.szDest = timestampStr;
+ timestampStr[0]='\0';
+ //time_t time = time
+ if (getOptions()&FLAG_SHOW_DATE && getOptions()&FLAG_SHOW_TIMESTAMP) {
+ if (getOptions()&FLAG_LONG_DATE) {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"D s" : (char *)"D t";
+ } else {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"d s" : (char *)"d t";
+ }
+ } else if (getOptions()&FLAG_SHOW_DATE) {
+ dbtts.szFormat = getOptions()&FLAG_LONG_DATE ? (char *)"D" : (char *)"d";
+ } else if (getOptions()&FLAG_SHOW_TIMESTAMP) {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"s" : (char *)"t";
+ } else {
+ dbtts.szFormat = (char *)"";
+ }
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRING, (WPARAM)event->time, (LPARAM) & dbtts);
+ JabberStringAppend(&rtf, &msgSize, "\\f0\\cf0\\fs%d\\b%d\\i%d%s %s ",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ timestampStr);
+ }
+ bBold = fontName->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontName->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontName->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontName->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ if (getOptions()&FLAG_SHOW_NICKNAMES) {
+ JabberStringAppend(&rtf, &msgSize, "\\f1\\cf1\\fs%d\\b%d\\i%d%s %s: ",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ escapedNick);
+ }
+ bBold = fontMessage->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontMessage->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontMessage->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontMessage->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ if (getOptions()&FLAG_FORMAT_STYLE) {
+ bBold = bItalic = bUnderline = 0;
+ if (event->dwFlags & MUCC_EF_FONT_BOLD) bBold = 1;
+ if (event->dwFlags & MUCC_EF_FONT_ITALIC) bItalic = 1;
+ if (event->dwFlags & MUCC_EF_FONT_UNDERLINE) bUnderline = 1;
+ }
+ if (getOptions()&FLAG_FORMAT_SIZE) {
+ if (event->iFontSize != 0) iFontSize = 2 * event->iFontSize;
+ }
+ if (getOptions()&FLAG_MSGINNEWLINE) {
+ JabberStringAppend(&rtf, &msgSize, "\\line");
+ }
+ JabberStringAppend(&rtf, &msgSize, "\\f2\\cf2\\fs%d\\b%d\\i%d%s %s",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ escapedStr);
+ } else {
+ if (event->iType == MUCC_EVENT_ERROR) {
+ bBold = fontName->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontName->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontName->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontName->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ JabberStringAppend(&rtf, &msgSize, "\\f1\\cf1\\fs%d\\b%d\\i%d%s %s: ",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ Translate("Error"));
+ } else {
+ if (getOptions()&FLAG_SHOW_DATE || getOptions()&FLAG_SHOW_TIMESTAMP) {
+ bBold = fontTimestamp->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontTimestamp->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontTimestamp->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontTimestamp->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ dbtts.cbDest = 90;
+ dbtts.szDest = timestampStr;
+ timestampStr[0]='\0';
+ //time_t time = time
+ if (getOptions()&FLAG_SHOW_DATE && getOptions()&FLAG_SHOW_TIMESTAMP) {
+ if (getOptions()&FLAG_LONG_DATE) {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"D s" : (char *)"D t";
+ } else {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"d s" : (char *)"d t";
+ }
+ } else if (getOptions()&FLAG_SHOW_DATE) {
+ dbtts.szFormat = getOptions()&FLAG_LONG_DATE ? (char *)"D" : (char *)"d";
+ } else if (getOptions()&FLAG_SHOW_TIMESTAMP) {
+ dbtts.szFormat = getOptions()&FLAG_SHOW_SECONDS ? (char *)"s" : (char *)"t";
+ } else {
+ dbtts.szFormat = (char *)"";
+ }
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRING, (WPARAM)event->time, (LPARAM) & dbtts);
+ JabberStringAppend(&rtf, &msgSize, "\\f0\\cf0\\fs%d\\b%d\\i%d%s %s ",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ timestampStr);
+ }
+ }
+ bBold = fontMessage->getStyle() & Font::BOLD ? 1 : 0;
+ bItalic = fontMessage->getStyle() & Font::ITALIC ? 1 : 0;
+ bUnderline = fontMessage->getStyle() & Font::UNDERLINE ? 1 : 0;
+ iFontSize = fontMessage->getSize();
+ iFontSize = 2 * abs((signed char)iFontSize) * 74 / logPixelSY;
+ JabberStringAppend(&rtf, &msgSize, "\\f2\\cf2\\fs%d\\b%d\\i%d%s %s",
+ iFontSize,
+ bBold,
+ bItalic,
+ bUnderline?"\\ul":"",
+ escapedStr);
+ }
+ JabberStringAppend(&rtf, &msgSize, "}");
+ hwndLog = GetDlgItem(getHWND(), IDC_LOG);
+ sel.cpMin = sel.cpMax = GetWindowTextLength(hwndLog);
+ SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) &sel);
+ stt.flags = ST_SELECTION;
+ stt.codepage = CP_ACP;
+ SendMessage(hwndLog, EM_SETTEXTEX, (WPARAM) &stt, (LPARAM) rtf);
+ free(rtf);
+ if (escapedStr != NULL) free(escapedStr);
+ if (escapedNick != NULL) free(escapedNick);
+ return 1;
+}
+
+void ChatWindow::setFont(int font, int size, int bBold, int bItalic, int bUnderline, COLORREF color) {
+ if (hEditFont != NULL) {
+ DeleteObject(hEditFont);
+ }
+ hEditFont = CreateFontA(MulDiv(-size, logPixelSY, 74), 0, 0, 0, bBold?FW_BOLD:FW_NORMAL,
+ bItalic, bUnderline, 0, 238, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ FIXED_PITCH | FF_ROMAN,
+ getFontName(font));
+ SendDlgItemMessage(hWnd, IDC_EDIT, WM_SETFONT, (WPARAM) hEditFont, TRUE);
+ this->font = font;
+ this->fontSize = size;
+ this->bBold = bBold;
+ this->bItalic = bItalic;
+ this->bUnderline = bUnderline;
+ this->fontColor = color;
+}
+
+int ChatWindow::getFontStyle() {
+ int style = 0;
+ if (bBold) style |= MUCC_EF_FONT_BOLD;
+ if (bItalic) style |= MUCC_EF_FONT_ITALIC;
+ if (bUnderline) style |= MUCC_EF_FONT_UNDERLINE;
+ return style;
+}
+
+int ChatWindow::getFont() {
+ return font;
+}
+
+int ChatWindow::getFontSize() {
+ return fontSize;
+}
+
+COLORREF ChatWindow::getFontColor() {
+ return fontColor;
+}
+
+void ChatWindow ::queryResultContacts(MUCCQUERYRESULT *queryResult) {
+ HelperDialog::inviteDlg(this, queryResult);
+}
+
+void ChatWindow ::queryResultUsers(MUCCQUERYRESULT *queryResult) {
+ if (adminWindow != NULL) {
+ adminWindow->queryResultUsers(queryResult);
+ }
+}
+
+ChatWindow * ChatWindow::getWindow(const char *module, const char *roomId) {
+ ChatWindow *ptr;
+ EnterCriticalSection(&mutex);
+ for (ptr=list; ptr != NULL; ptr=ptr->getNext()) {
+ if (strcmp(ptr->getRoomId(), roomId) == 0 && strcmp(ptr->getModule(), module) == 0) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&mutex);
+ return ptr;
+}
+
+
+static DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
+{
+ char *szFilename = (char *)dwCookie;
+ FILE *file;
+ file = fopen(szFilename, "ab");
+ if (file != NULL) {
+ *pcb = (LONG)fwrite(pbBuff, (size_t)cb, (size_t)1, file);
+ fclose(file);
+ return 0;
+ }
+ return 1;
+}
+
+static BOOL CALLBACK EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ChatWindow *chat;
+ chat = (ChatWindow *) GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
+ switch (msg) {
+// case WM_GETDLGCODE:
+// return DLGC_WANTALLKEYS; //DLGC_WANTARROWS|DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTALLKEYS;
+ case WM_CHAR:
+ if (wParam == '\r' || wParam == '\n') {
+ if (((GetKeyState(VK_CONTROL)&0x8000) == 0) == ((Options::getChatWindowOptions() & ChatWindow::FLAG_OPT_SENDONENTER) != 0)) {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return FALSE;
+ }
+ }
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProc(oldEditWndProc, hwnd, msg, wParam, lParam);
+}
+
+static BOOL CALLBACK SplitterWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ChatWindow *chat;
+ chat = (ChatWindow *) GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+ case WM_SETCURSOR:
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE);
+ return TRUE;
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ return 0;
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd) {
+ HWND hParent;
+ RECT rc;
+ POINT pt;
+ hParent = GetParent(hwnd);
+ GetClientRect(hwnd, &rc);
+ if (rc.right < rc.bottom) {
+ pt.x = LOWORD(GetMessagePos());
+ GetClientRect(hParent, &rc);
+ ScreenToClient(hParent, &pt);
+ if (pt.x < chat->vSplitterMinLeft)
+ pt.x = chat->vSplitterMinLeft;
+ if (rc.right-pt.x < chat->vSplitterMinRight)
+ pt.x = rc.right-chat->vSplitterMinRight;
+ if (chat->vSplitterPos != rc.right-pt.x) {
+ chat->vSplitterPos = rc.right-pt.x;
+ SendMessage(hParent, WM_SIZE, SIZE_RESTORED, (rc.bottom<<16)+rc.right);
+ }
+ } else {
+ pt.y = HIWORD(GetMessagePos());
+ GetClientRect(hParent, &rc);
+ ScreenToClient(hParent, &pt);
+ if (pt.y < chat->hSplitterMinTop)
+ pt.y = chat->hSplitterMinTop;
+ if (rc.bottom-pt.y < chat->hSplitterMinBottom)
+ pt.y = rc.bottom-chat->hSplitterMinBottom;
+ if (chat->hSplitterPos != rc.bottom-pt.y) {
+ chat->hSplitterPos = rc.bottom-pt.y;
+ SendMessage(hParent, WM_SIZE, SIZE_RESTORED, (rc.bottom<<16)+rc.right);
+ }
+ }
+ }
+ return 0;
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ return 0;
+ }
+ return CallWindowProc(oldSplitterWndProc, hwnd, msg, wParam, lParam);
+}
+
+
+
+
+static INT_PTR CALLBACK LogDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ ChatWindow *chatWindow;
+ chatWindow = (ChatWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (msg != WM_INITDIALOG && chatWindow == NULL) {
+ return FALSE;
+ }
+ switch (msg) {
+ case WM_INITDIALOG:
+ HDC hdc;
+ TranslateDialogDefault(hwndDlg);
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) muccIcon[MUCC_IDI_CHAT]);
+
+ chatWindow = (ChatWindow *) lParam;
+ chatWindow->setHWND(hwndDlg);
+ ChatWindow::refreshSettings(0);
+ oldSplitterWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_HSPLIT), GWLP_WNDPROC, (LONG_PTR) SplitterWndProc);
+ oldSplitterWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_VSPLIT), GWLP_WNDPROC, (LONG_PTR) SplitterWndProc);
+ oldEditWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT), GWLP_WNDPROC, (LONG_PTR) EditWndProc);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_LIST), SW_HIDE);
+ chatWindow->hSplitterMinTop = 90;
+ chatWindow->hSplitterMinBottom = 40;
+ chatWindow->hSplitterPos=50;
+ chatWindow->vSplitterMinLeft = 100;
+ chatWindow->vSplitterMinRight = 80;
+ chatWindow->vSplitterPos=110;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) chatWindow);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT), GWLP_USERDATA, (LONG_PTR) chatWindow);
+ chatWindow->refreshSettings();
+
+ SetWindowTextA(hwndDlg, chatWindow->getRoomName());
+ SendDlgItemMessage(hwndDlg, IDC_BOLD, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_BOLD]);
+ SendDlgItemMessage(hwndDlg, IDC_ITALIC, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_ITALIC]);
+ SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_UNDERLINE]);
+ SendDlgItemMessage(hwndDlg, IDC_SMILEYBTN, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_SMILEY]);
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETUNDOLIMIT, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0);
+
+ // LoadImage(hInst, smadd_iconinfo.SmileyIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0));
+ SendDlgItemMessage(hwndDlg, IDC_OPTIONS, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_OPTIONS]);
+ SendDlgItemMessage(hwndDlg, IDC_INVITE, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_INVITE]);
+
+ SendDlgItemMessage(hwndDlg, IDC_TOPIC_BUTTON, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_INVITE, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_ITALIC, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_ITALIC, BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_OPTIONS, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_SMILEYBTN, BUTTONSETASFLATBTN, TRUE, 0);
+
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_TREELIST),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_TREELIST),GWL_STYLE)|TVS_NOHSCROLL);
+ SendDlgItemMessage(hwndDlg,IDC_TREELIST, CCM_SETVERSION,(WPARAM)5,0);
+ //TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TREELIST), hImageList, TVSIL_STATE);
+ TreeView_SetItemHeight(GetDlgItem(hwndDlg, IDC_TREELIST), 16);
+ TreeView_SetIndent(GetDlgItem(hwndDlg, IDC_TREELIST), 16);
+ for (i=0;i<chatWindow->getFontSizeNum();i++) {
+ char str[10];
+ sprintf(str, "%d", chatWindow->getFontSize(i));
+ int n = SendDlgItemMessageA(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM) str);
+ SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_SETITEMDATA, n, chatWindow->getFontSize(i));
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_SETCURSEL, Options::getChatWindowFontSize(), 0);
+ for (i=0;i<chatWindow->getFontNameNum();i++) {
+ int n = SendDlgItemMessageA(hwndDlg, IDC_FONT, CB_ADDSTRING, 0, (LPARAM) chatWindow->getFontName(i));
+ SendDlgItemMessage(hwndDlg, IDC_FONT, CB_SETITEMDATA, n, i);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FONT, CB_SETCURSEL, Options::getChatWindowFont(), 0);
+ CheckDlgButton(hwndDlg, IDC_BOLD, Options::getChatWindowFontStyle()&Font::BOLD ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_ITALIC, Options::getChatWindowFontStyle()&Font::ITALIC ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_UNDERLINE, Options::getChatWindowFontStyle()&Font::UNDERLINE ? TRUE : FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_SETCOLOUR, 0, (LPARAM)Options::getChatWindowFontColor());
+ chatWindow->setFont(Options::getChatWindowFont(),
+ chatWindow->getFontSize(Options::getChatWindowFontSize()),
+ Options::getChatWindowFontStyle()&Font::BOLD ? 1 : 0,
+ Options::getChatWindowFontStyle()&Font::ITALIC ? 1 : 0,
+ Options::getChatWindowFontStyle()&Font::UNDERLINE ? 1 : 0,
+ Options::getChatWindowFontColor());
+ if (ServiceExists(MS_IEVIEW_WINDOW) && Options::getChatWindowOptions() & ChatWindow::FLAG_OPT_ENABLEIEVIEW) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_MUCC;
+ ieWindow.parent = hwndDlg;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 200;
+ ieWindow.cy = 300;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ chatWindow->setHWNDLog(ieWindow.hwnd);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_LOG), SW_HIDE);
+ }
+ SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 540, 370, SWP_NOMOVE | SWP_SHOWWINDOW);
+ SetFocus(GetDlgItem(hwndDlg, IDC_EDIT));
+ chatWindow->clearLog();
+ SetEvent(chatWindow->getEvent());
+ return TRUE;
+ break;
+ case DM_CHAT_EVENT:
+ MUCCEVENT *mucEvent;
+ mucEvent = (MUCCEVENT *) lParam;
+ switch (mucEvent->iType) {
+ case MUCC_EVENT_MESSAGE:
+ chatWindow->logEvent(mucEvent);
+ break;
+ case MUCC_EVENT_TOPIC:
+ chatWindow->changeTopic(mucEvent);
+ break;
+ case MUCC_EVENT_STATUS:
+ chatWindow->changePresence(mucEvent);
+ break;
+ case MUCC_EVENT_ERROR:
+ chatWindow->logEvent(mucEvent);
+ break;
+ //case MUCC_EVENT_LEAVE:
+ // DestroyWindow(hwndDlg);
+ // break;
+ case MUCC_EVENT_ROOM_INFO:
+ chatWindow->changeRoomInfo(mucEvent);
+ break;
+ }
+ return TRUE;
+ case DM_CHAT_QUERY:
+ MUCCQUERYRESULT *queryResult;
+ queryResult = (MUCCQUERYRESULT *)lParam;
+ switch (queryResult->iType) {
+ case MUCC_EVENT_QUERY_CONTACTS:
+ chatWindow->queryResultContacts(queryResult);
+ break;
+ case MUCC_EVENT_QUERY_USERS:
+ chatWindow->queryResultUsers(queryResult);
+ break;
+
+ }
+ return TRUE;
+ case WM_SETFOCUS:
+ SetFocus(GetDlgItem(hwndDlg, IDC_EDIT));
+ return TRUE;
+ case WM_GETMINMAXINFO:
+ MINMAXINFO *mmi;
+ mmi = (MINMAXINFO *) lParam;
+ mmi->ptMinTrackSize.x = 370;
+ mmi->ptMinTrackSize.y = 130;
+ return FALSE;
+ case WM_SIZE:
+ if (wParam != SIZE_MINIMIZED) {
+ int dlgWidth, dlgHeight;
+ RECT rc;
+ HDWP hdwp;
+ GetClientRect(hwndDlg, &rc);
+ dlgWidth = rc.right-rc.left;
+ dlgHeight = rc.bottom-rc.top;
+ if (dlgHeight-chatWindow->hSplitterPos < chatWindow->hSplitterMinTop) {
+ chatWindow->hSplitterPos = dlgHeight-chatWindow->hSplitterMinTop;
+ }
+ if (chatWindow->hSplitterPos < chatWindow->hSplitterMinBottom) {
+ chatWindow->hSplitterPos = chatWindow->hSplitterMinBottom;
+ }
+ if (dlgWidth-chatWindow->vSplitterPos < chatWindow->vSplitterMinLeft) {
+ chatWindow->vSplitterPos = dlgWidth-chatWindow->vSplitterMinLeft;
+ }
+ if (chatWindow->vSplitterPos < chatWindow->vSplitterMinRight) {
+ chatWindow->vSplitterPos = chatWindow->vSplitterMinRight;
+ }
+
+ hdwp = BeginDeferWindowPos(15);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_TOPIC), 0, 70, 7, dlgWidth-140, 18, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_LOG), 0, 0, 30, dlgWidth-(chatWindow->vSplitterPos)-2, dlgHeight-(chatWindow->hSplitterPos)-30-26-2, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_TREELIST), 0, dlgWidth-(chatWindow->vSplitterPos)+2, 30, (chatWindow->vSplitterPos)-2, dlgHeight-(chatWindow->hSplitterPos)-30-26-2, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_EDIT), 0, 0, dlgHeight-(chatWindow->hSplitterPos)+2, dlgWidth, (chatWindow->hSplitterPos)-5, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_INVITE), 0, dlgWidth-31, dlgHeight-(chatWindow->hSplitterPos)-26, 31, 24, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_BOLD), 0, 0, dlgHeight-(chatWindow->hSplitterPos)-26, 24, 24, SWP_NOZORDER );
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_ITALIC), 0, 24, dlgHeight-(chatWindow->hSplitterPos)-26, 24, 24, SWP_NOZORDER );
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_UNDERLINE), 0, 48, dlgHeight-(chatWindow->hSplitterPos)-26, 24, 24, SWP_NOZORDER );
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_COLOR), 0, 73, dlgHeight-(chatWindow->hSplitterPos)-25, 22, 22, SWP_NOZORDER );
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_FONT), 0, 98, dlgHeight-(chatWindow->hSplitterPos)-24, 110, 13, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_FONTSIZE), 0, 213, dlgHeight-(chatWindow->hSplitterPos)-24, 38, 13, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_SMILEYBTN), 0, 265, dlgHeight-(chatWindow->hSplitterPos)-26, 24, 24, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_OPTIONS), 0, dlgWidth-79, dlgHeight-(chatWindow->hSplitterPos)-26, 24, 24, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_VSPLIT), 0, dlgWidth-(chatWindow->vSplitterPos)-2, 30, 4, dlgHeight-(chatWindow->hSplitterPos)-30-26-2, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_HSPLIT), 0, 0, dlgHeight-(chatWindow->hSplitterPos)-2, dlgWidth-8, 4, SWP_NOZORDER);
+ EndDeferWindowPos(hdwp);
+ if (chatWindow->getHWNDLog() != NULL) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_SETPOS;
+ ieWindow.parent = hwndDlg;
+ ieWindow.hwnd = chatWindow->getHWNDLog();
+ ieWindow.x = 0;
+ ieWindow.y = 30;
+ ieWindow.cx = dlgWidth-(chatWindow->vSplitterPos)-2;
+ ieWindow.cy = dlgHeight-(chatWindow->hSplitterPos)-30-26-2;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+ }
+ break;
+ /*
+ case WM_SYSCOMMAND:
+ if (wParam == SC_CLOSE) {
+ SendMessage(hwndDlg, WM_CLOSE, 1, 0);
+// muce.iType = MUCC_EVENT_LEAVE;
+// muce.pszModule = chatWindow->getModule();
+// muce.pszID = chatWindow->getRoomId();
+// NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+// delete chatWindow;
+ return TRUE;
+ }
+ break;
+ */
+ case WM_CLOSE:
+ //if (wParam != 1) { // esc
+ //return FALSE;
+ //}
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case WM_DESTROY:
+ {
+ MUCCEVENT muce;
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_LEAVE;
+ muce.pszModule = chatWindow->getModule();
+ muce.pszID = chatWindow->getRoomId();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ if (chatWindow->getHWNDLog() != NULL) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_DESTROY;
+ ieWindow.hwnd = chatWindow->getHWNDLog();
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) NULL);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_HSPLIT), GWLP_WNDPROC, (LONG_PTR) oldSplitterWndProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_VSPLIT), GWLP_WNDPROC, (LONG_PTR) oldSplitterWndProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT), GWLP_WNDPROC, (LONG_PTR) oldEditWndProc);
+ delete chatWindow;
+ break;
+ }
+ case WM_TLEN_SMILEY:
+ if (ServiceExists(MS_SMILEYADD_REPLACESMILEYS)) {
+ SMADD_RICHEDIT3 smre = {0};
+ smre.cbSize = sizeof(SMADD_RICHEDIT3);
+ smre.hwndRichEditControl = GetDlgItem(hwndDlg, IDC_LOG);
+ smre.Protocolname = (char *)chatWindow->getModule();
+ smre.rangeToReplace = NULL;
+ smre.disableRedraw = FALSE;
+ smre.flags = 0; //SAFLRE_OUTGOING
+ smre.hContact = NULL;
+ CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM) &smre);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_OPTIONS:
+ {
+ MUCCEVENT muce;
+ HMENU hMenu;
+ RECT rc;
+ int iSelection;
+ hMenu=GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_CHATOPTIONS)),0);
+ TranslateMenu(hMenu);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_OPTIONS), &rc);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_SHOWNICKNAMES, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_SHOW_NICKNAMES ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_MSGINNEWLINE, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_MSGINNEWLINE ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_SHOWDATE, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_SHOW_DATE ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_SHOWTIMESTAMP, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_SHOW_TIMESTAMP ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_SHOWSECONDS, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_SHOW_SECONDS ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_USELONGDATE, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_LONG_DATE ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FORMATFONT, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FORMAT_FONT ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FORMATSIZE, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FORMAT_SIZE ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FORMATCOLOR, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FORMAT_COLOR ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FORMATSTYLE, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FORMAT_STYLE ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_LOGMESSAGES, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_LOG_MESSAGES ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_LOGJOINED, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_LOG_JOINED ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_LOGLEFT, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_LOG_LEFT ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_LOGTOPIC, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_LOG_TOPIC ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FLASHMESSAGES, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FLASH_MESSAGES ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FLASHJOINED, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FLASH_JOINED ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FLASHLEFT, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FLASH_LEFT ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_OPTIONMENU_FLASHTOPIC, MF_BYCOMMAND | chatWindow->getOptions()&ChatWindow::FLAG_FLASH_TOPIC ? MF_CHECKED : MF_UNCHECKED);
+ if (chatWindow->getMe() != NULL) {
+ if (chatWindow->getMe()->getFlags() & (MUCC_EF_USER_OWNER | MUCC_EF_USER_ADMIN)) {
+ EnableMenuItem(hMenu, ID_ADMINMENU_ADMIN, MF_BYCOMMAND | MF_ENABLED);
+ EnableMenuItem(hMenu, ID_ADMINMENU_BROWSE, MF_BYCOMMAND | MF_ENABLED);
+ }
+ if (chatWindow->getMe()->getFlags() & MUCC_EF_USER_OWNER) {
+ EnableMenuItem(hMenu, ID_ADMINMENU_DESTROY, MF_BYCOMMAND | MF_ENABLED);
+ }
+ }
+ iSelection = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_TOPALIGN | TPM_LEFTALIGN, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ switch (iSelection) {
+ case ID_OPTIONMENU_SHOWNICKNAMES:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_SHOW_NICKNAMES);
+ break;
+ case ID_OPTIONMENU_MSGINNEWLINE:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_MSGINNEWLINE);
+ break;
+ case ID_OPTIONMENU_SHOWDATE:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_SHOW_DATE);
+ break;
+ case ID_OPTIONMENU_SHOWTIMESTAMP:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_SHOW_TIMESTAMP);
+ break;
+ case ID_OPTIONMENU_SHOWSECONDS:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_SHOW_SECONDS);
+ break;
+ case ID_OPTIONMENU_USELONGDATE:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_LONG_DATE);
+ break;
+ case ID_OPTIONMENU_FORMATFONT:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FORMAT_FONT);
+ break;
+ case ID_OPTIONMENU_FORMATSIZE:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FORMAT_SIZE);
+ break;
+ case ID_OPTIONMENU_FORMATCOLOR:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FORMAT_COLOR);
+ break;
+ case ID_OPTIONMENU_FORMATSTYLE:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FORMAT_STYLE);
+ break;
+ case ID_OPTIONMENU_LOGMESSAGES:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_LOG_MESSAGES);
+ break;
+ case ID_OPTIONMENU_LOGJOINED:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_LOG_JOINED);
+ break;
+ case ID_OPTIONMENU_LOGLEFT:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_LOG_LEFT);
+ break;
+ case ID_OPTIONMENU_LOGTOPIC:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_LOG_TOPIC);
+ break;
+ case ID_OPTIONMENU_FLASHMESSAGES:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FLASH_MESSAGES);
+ break;
+ case ID_OPTIONMENU_FLASHJOINED:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FLASH_JOINED);
+ break;
+ case ID_OPTIONMENU_FLASHLEFT:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FLASH_LEFT);
+ break;
+ case ID_OPTIONMENU_FLASHTOPIC:
+ chatWindow->setOptions(chatWindow->getOptions()^ChatWindow::FLAG_FLASH_TOPIC);
+ break;
+ case ID_OPTIONMENU_SAVEDEFAULT:
+ Options::setChatWindowOptions(chatWindow->getOptions());
+ Options::setChatWindowFont((int)SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETCURSEL, 0, 0));
+ Options::setChatWindowFontSize((int)SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0));
+ Options::setChatWindowFontStyle(
+ (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? Font::BOLD : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_ITALIC) ? Font::ITALIC : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE) ? Font::UNDERLINE : 0)
+ );
+ Options::setChatWindowFontColor((COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_GETCOLOUR,0,0));
+ Options::saveSettings();
+ break;
+ case ID_ADMINMENU_DESTROY:
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_REMOVE_ROOM;
+ muce.pszModule = chatWindow->getModule();
+ muce.pszID = chatWindow->getRoomId();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ DestroyWindow(hwndDlg);
+ break;
+ case ID_ADMINMENU_ADMIN:
+ chatWindow->startAdminDialog(ChatWindow::ADMIN_MODE_KICK);
+ break;
+ case ID_ADMINMENU_BROWSE:
+ chatWindow->startAdminDialog(ChatWindow::ADMIN_MODE_ROLE);
+ break;
+ case ID_ADMINMENU_SAVELOG:
+ if (chatWindow->getHWNDLog() != NULL) {
+ IEVIEWEVENT iee;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.dwFlags = 0;
+ iee.hwnd = chatWindow->getHWNDLog();
+ iee.hContact = NULL;
+ iee.iType = IEE_SAVE_DOCUMENT;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+ } else {
+ char szFilename[MAX_PATH];
+ strcpy(szFilename, "");
+ OPENFILENAMEA ofn={0};
+ ofn.lStructSize=sizeof(OPENFILENAME);
+ ofn.hwndOwner=hwndDlg;
+ ofn.lpstrFile = szFilename;
+ ofn.lpstrFilter = "Rich Text File\0*.rtf\0\0";
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY;
+ ofn.lpstrDefExt = "rtf";
+ if (GetSaveFileNameA(&ofn)) {
+ //remove(szFilename);
+ EDITSTREAM stream = { 0 };
+ stream.dwCookie = (DWORD_PTR)szFilename;
+ stream.dwError = 0;
+ stream.pfnCallback = EditStreamCallback;
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_STREAMOUT, SF_RTF | SF_USECODEPAGE, (LPARAM) & stream);
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case IDC_SMILEYBTN:
+ SMADD_SHOWSEL3 smaddInfo;
+ RECT rc;
+ smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3);
+ smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_EDIT);
+ smaddInfo.targetMessage = EM_REPLACESEL;
+ smaddInfo.targetWParam = TRUE;
+ //smaddInfo.Protocolname = chatWindow->getModule();
+ Utils::copyString(&smaddInfo.Protocolname, chatWindow->getModule());
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEYBTN), &rc);
+ smaddInfo.Direction = 0;
+ smaddInfo.xPosition = rc.left;
+ smaddInfo.yPosition = rc.top + 24; ;
+ smaddInfo.hContact = NULL; //TODO add hcontact here
+ //smaddInfo.Protocolname =
+ CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM) &smaddInfo);
+ delete smaddInfo.Protocolname;
+ break;
+ case IDC_INVITE:
+ {
+ MUCCEVENT muce;
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_CONTACTS;
+ muce.pszModule = chatWindow->getModule();
+ muce.pszID = chatWindow->getRoomId();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ break;
+ case IDC_TOPIC_BUTTON:
+ HelperDialog::topicDlg(chatWindow);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case IDOK:
+ {
+ MUCCEVENT muce;
+ char text[2048];
+ GetDlgItemTextA(hwndDlg, IDC_EDIT, text, sizeof(text));
+ SetDlgItemTextA(hwndDlg, IDC_EDIT, "");
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_MESSAGE;
+ muce.pszModule = chatWindow->getModule();
+ muce.pszID = chatWindow->getRoomId();
+ muce.pszText = text;
+ muce.iFont = chatWindow->getFont();
+ muce.iFontSize = chatWindow->getFontSize();
+ muce.dwFlags = chatWindow->getFontStyle();
+ muce.color = chatWindow->getFontColor();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ break;
+ case IDC_BOLD:
+ case IDC_ITALIC:
+ case IDC_UNDERLINE:
+ if (HIWORD(wParam) == BN_CLICKED) {
+ chatWindow->setFont((int) SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETCURSEL, 0, 0), 0),
+ (int) SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0), 0),
+ IsDlgButtonChecked(hwndDlg, IDC_BOLD),
+ IsDlgButtonChecked(hwndDlg, IDC_ITALIC),
+ IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE),
+ (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_GETCOLOUR,0,0));
+ }
+ case IDC_FONT:
+ case IDC_FONTSIZE:
+ if (HIWORD(wParam) == CBN_SELCHANGE) {
+ chatWindow->setFont((int) SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETCURSEL, 0, 0), 0),
+ (int) SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0), 0),
+ IsDlgButtonChecked(hwndDlg, IDC_BOLD),
+ IsDlgButtonChecked(hwndDlg, IDC_ITALIC),
+ IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE),
+ (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_GETCOLOUR,0,0));
+ }
+ break;
+ case IDC_COLOR:
+ if (HIWORD(wParam) == CPN_COLOURCHANGED) {
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_EDIT), NULL, FALSE);
+ chatWindow->setFont((int) SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONT, CB_GETCURSEL, 0, 0), 0),
+ (int) SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0), 0),
+ IsDlgButtonChecked(hwndDlg, IDC_BOLD),
+ IsDlgButtonChecked(hwndDlg, IDC_ITALIC),
+ IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE),
+ (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_GETCOLOUR,0,0));
+ }
+ break;
+
+ }
+ break;
+ case WM_CTLCOLOREDIT:
+ if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_EDIT)) {
+ SetTextColor((HDC) wParam, (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLOR, CPM_GETCOLOUR,0,0));
+ SetBkColor((HDC) wParam, Options::getInputBgColor());
+ //SelectObject((HDC) wParam, Options::getInputBgBrush());
+ return (BOOL) Options::getInputBgBrush();
+ }
+
+ break;
+ case WM_NOTIFY:
+ LPNMHDR pNmhdr;
+ pNmhdr = (LPNMHDR)lParam;
+ if (pNmhdr->idFrom == IDC_TREELIST) {
+ switch (pNmhdr->code) {
+ case TVN_ITEMEXPANDING:
+ {
+ LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam;
+ if (pnmtv->action == TVE_COLLAPSE) {
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ break;
+ case NM_RCLICK:
+ {
+ TVHITTESTINFO hti;
+ hti.pt.x=(short)LOWORD(GetMessagePos());
+ hti.pt.y=(short)HIWORD(GetMessagePos());
+ ScreenToClient(pNmhdr->hwndFrom,&hti.pt);
+ if (TreeView_HitTest(pNmhdr->hwndFrom, &hti) && hti.flags&TVHT_ONITEM) {
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_PARAM|TVIF_HANDLE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(pNmhdr->hwndFrom, &tvi);
+ ChatUser *user = (ChatUser *) tvi.lParam;
+ if (user != NULL) {
+ TreeView_Select(pNmhdr->hwndFrom, tvi.hItem, TVGN_CARET);
+ if (!user->isMe()) {
+ HMENU hMenu;
+ int iSelection;
+ hMenu = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_CHATOPTIONS)),1);
+ TranslateMenu(hMenu);
+ if (chatWindow->getMe() != NULL) {
+ if (chatWindow->getMe()->getFlags() & MUCC_EF_USER_OWNER) {
+ EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
+ EnableMenuItem(hMenu, 3, MF_BYPOSITION | MF_ENABLED);
+ EnableMenuItem(hMenu, ID_USERMENU_ADMINISTRATION, MF_BYCOMMAND | MF_ENABLED);
+
+ } else if (chatWindow->getMe()->getFlags() & MUCC_EF_USER_ADMIN) {
+ if (!(user->getFlags() & (MUCC_EF_USER_OWNER | MUCC_EF_USER_OWNER))) {
+ EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
+ //EnableMenuItem(hMenu, 3, MF_BYPOSITION | MF_ENABLED);
+ EnableMenuItem(hMenu, ID_USERMENU_ADMINISTRATION, MF_BYCOMMAND | MF_ENABLED);
+ }
+ }
+ }
+ //CheckMenuItem(hMenu, ID_USERMENU_MESSAGE, MF_BYCOMMAND | MF_CHECKED : MF_UNCHECKED);
+ //EnableMenuItem(hMenu, ID_USERMENU_MESSAGE, MF_BYCOMMAND | MF_GRAYED);
+ iSelection = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_TOPALIGN | TPM_LEFTALIGN, (short)LOWORD(GetMessagePos()), (short)HIWORD(GetMessagePos()), 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ if (iSelection == ID_USERMENU_MESSAGE) {
+ chatWindow->startPriv();
+ } else if (iSelection >= ID_USERMENU_KICK_NO_BAN && iSelection <= ID_USERMENU_KICK_BAN_4_W) {
+ int banTime[] = {0, 1, 5, 15, 30, 60, 360, 1440, 4320, 10080, 20160, 40320};
+ chatWindow->kickAndBan(banTime[iSelection-ID_USERMENU_KICK_NO_BAN] *60);
+ } else if (iSelection == ID_USERMENU_RIGHTS_MEMBER) {
+ chatWindow->setRights(MUCC_EF_USER_MEMBER);
+ } else if (iSelection == ID_USERMENU_RIGHTS_ADMIN) {
+ chatWindow->setRights(MUCC_EF_USER_ADMIN);
+ } else if (iSelection == ID_USERMENU_RIGHTS_NO) {
+ chatWindow->setRights(0);
+ } else if (iSelection == ID_USERMENU_ADMINISTRATION) {
+ chatWindow->startAdminDialog(ChatWindow::ADMIN_MODE_KICK);
+ }
+ }
+ }
+ }
+
+ }
+ break;
+ case NM_CUSTOMDRAW:
+ LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
+ switch (pCustomDraw->nmcd.dwDrawStage) {
+ case CDDS_PREPAINT:
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NOTIFYITEMDRAW);
+ return TRUE;
+ case CDDS_ITEMPREPAINT:
+ {
+ TVITEM tvi;;
+ HICON hIcon;
+ TCHAR str[200];
+ RECT rc = pCustomDraw->nmcd.rc;
+ tvi.mask = TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_PARAM;
+ tvi.pszText = str;
+ tvi.cchTextMax = sizeof(str)/sizeof(TCHAR);
+ tvi.hItem = (HTREEITEM)pCustomDraw->nmcd.dwItemSpec;
+ TreeView_GetItem(pCustomDraw->nmcd.hdr.hwndFrom, &tvi);
+ ChatUser * user= (ChatUser *)pCustomDraw->nmcd.lItemlParam;
+ hIcon = NULL;
+ pCustomDraw->clrTextBk = Options::getListBgColor();
+ switch (pCustomDraw->iLevel) {
+ case 0:
+ pCustomDraw->clrText = ChatWindow::getListGroupTextColor();
+ SelectObject(pCustomDraw->nmcd.hdc, ChatWindow::getListGroupFont());
+ break;
+ case 1:
+ pCustomDraw->clrText = ChatWindow::getListTextColor();
+ if (pCustomDraw->nmcd.uItemState & CDIS_SELECTED) { // selected (CDIS_FOCUS |
+ pCustomDraw->clrTextBk = 0xDAC8C2;
+ } else {
+ pCustomDraw->clrTextBk = Options::getListBgColor();
+ }
+ if (user != NULL) {
+ if (user->getFlags()&MUCC_EF_USER_GLOBALOWNER) {
+ hIcon = muccIcon[MUCC_IDI_U_GLOBALOWNER];
+ } else if (user->getFlags()&MUCC_EF_USER_OWNER) {
+ hIcon = muccIcon[MUCC_IDI_U_OWNER];
+ } else if (user->getFlags()&MUCC_EF_USER_ADMIN) {
+ hIcon = muccIcon[MUCC_IDI_U_ADMIN];
+ } else if (user->getFlags()&MUCC_EF_USER_REGISTERED) {
+ hIcon = muccIcon[MUCC_IDI_U_REGISTERED];
+ }
+ }
+ SelectObject(pCustomDraw->nmcd.hdc, ChatWindow::getListFont());
+ break;
+ }
+ if (rc.bottom-rc.top != 0 && rc.right-rc.left != 0) {
+ HBRUSH hBr;
+ hBr = CreateSolidBrush(pCustomDraw->clrTextBk);
+ FillRect(pCustomDraw->nmcd.hdc, &rc, hBr);
+ DeleteObject(hBr);
+ if (hIcon != NULL) {
+ DrawIconEx(pCustomDraw->nmcd.hdc, rc.left, rc.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ }
+ SetBkMode(pCustomDraw->nmcd.hdc, TRANSPARENT);
+ SetTextColor(pCustomDraw->nmcd.hdc, pCustomDraw->clrText);
+ TextOut(pCustomDraw->nmcd.hdc,
+ rc.left+pCustomDraw->iLevel*GetSystemMetrics(SM_CXSMICON)+2,
+ rc.top, tvi.pszText, (int)_tcslen(tvi.pszText));
+ }
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT, CDRF_SKIPDEFAULT );
+ return TRUE;
+ }
+ }
+ break;
+ }
+ } else if (pNmhdr->idFrom == IDC_LOG) {
+ switch (((NMHDR *) lParam)->code) {
+ case EN_MSGFILTER:
+ switch (((MSGFILTER *) lParam)->msg) {
+ /*
+ case WM_LBUTTONDOWN:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) {
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE))
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ break;
+ }
+ */
+ case WM_RBUTTONUP:
+ {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+ CHARRANGE sel, all = { 0, -1 };
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 0);
+ TranslateMenu(hSubMenu);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin == sel.cpMax)
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case IDM_COPY:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ break;
+ case IDM_COPYALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel);
+ break;
+ case IDM_SELECTALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ break;
+ case IDM_CLEAR:
+ chatWindow->clearLog();
+ break;
+ }
+ DestroyMenu(hMenu);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ break;
+ case EN_LINK:
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_SETCURSOR:
+ SetCursor(hCurHyperlinkHand);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ {
+ TEXTRANGEA tr;
+ CHARRANGE sel;
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ break;
+ tr.chrg = ((ENLINK *) lParam)->chrg;
+ tr.lpstrText = (char *)malloc(tr.chrg.cpMax - tr.chrg.cpMin + 8);
+ SendDlgItemMessageA(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+ if (strchr(tr.lpstrText, '@') != NULL && strchr(tr.lpstrText, ':') == NULL && strchr(tr.lpstrText, '/') == NULL) {
+ MoveMemory(tr.lpstrText + 7, tr.lpstrText, tr.chrg.cpMax - tr.chrg.cpMin + 1);
+ CopyMemory(tr.lpstrText, "mailto:", 7);
+ }
+ if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 1);
+ TranslateMenu(hSubMenu);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case IDM_OPENNEW:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText);
+ break;
+ case IDM_OPENEXISTING:
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM) tr.lpstrText);
+ break;
+ case IDM_COPYLINK:
+ {
+ HGLOBAL hData;
+ if (!OpenClipboard(hwndDlg))
+ break;
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(tr.lpstrText) + 1);
+ lstrcpyA((char *)GlobalLock(hData), tr.lpstrText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_TEXT, hData);
+ CloseClipboard();
+ break;
+ }
+ }
+ free(tr.lpstrText);
+ DestroyMenu(hMenu);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ else {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_EDIT));
+ }
+ free(tr.lpstrText);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static char *JabberRtfEscape(char *str) {
+ char *escapedStr;
+ int size;
+ char *p, *q;
+
+ if (str == NULL)
+ return NULL;
+
+ for (p=str,size=0; *p != '\0'; p++) {
+ if (*p == '\\' || *p == '{' || *p == '}')
+ size += 2;
+ else if (*p == '\n' || *p == '\t')
+ size += 5;
+ else
+ size++;
+ }
+
+ if ((escapedStr=(char *)malloc(size+1)) == NULL)
+ return NULL;
+
+ for (p=str,q=escapedStr; *p != '\0'; p++) {
+ if (strchr("\\{}", *p) != NULL) {
+ *q++ = '\\';
+ *q++ = *p;
+ }
+ else if (*p == '\n') {
+ strcpy(q, "\\par ");
+ q += 5;
+ }
+ else if (*p == '\t') {
+ strcpy(q, "\\tab ");
+ q += 5;
+ }
+ else {
+ *q++ = *p;
+ }
+ }
+ *q = '\0';
+
+ return escapedStr;
+}
+
+static void JabberStringAppend(char **str, int *sizeAlloced, const char *fmt, ...) {
+ va_list vararg;
+ char *p;
+ int size, len;
+
+ if (str == NULL) return;
+
+ if (*str == NULL || *sizeAlloced <= 0) {
+ *sizeAlloced = size = 2048;
+ *str = (char *) malloc(size);
+ len = 0;
+ }
+ else {
+ len = (int)strlen(*str);
+ size = *sizeAlloced - (int)strlen(*str);
+ }
+
+ p = *str + len;
+ va_start(vararg, fmt);
+ while (_vsnprintf(p, size, fmt, vararg) == -1) {
+ size += 2048;
+ (*sizeAlloced) += 2048;
+ *str = (char *) realloc(*str, *sizeAlloced);
+ p = *str + len;
+ }
+ va_end(vararg);
+}
+
+
+//static DWORD CALLBACK Log_StreamCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
+//{
+// StreamData *stream = (StreamData *) dwCookie;
+/*
+ if (lstrdat->buffer == NULL)
+ {
+ lstrdat->iColCount = 4;
+ lstrdat->bufferOffset = 0;
+ lstrdat->buffer = Log_CreateBody(lstrdat);
+ lstrdat->bufferLen = lstrlen(lstrdat->buffer);
+ }
+ *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset);
+ CopyMemory(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb);
+ lstrdat->bufferOffset += *pcb;
+ if (lstrdat->bufferOffset == lstrdat->bufferLen)
+ {
+ free(lstrdat->buffer);
+ lstrdat->buffer = NULL;
+ }
+*/
+// return 0;
+//}
diff --git a/protocols/Tlen/tlen_czaty/src/ChatWindow.h b/protocols/Tlen/tlen_czaty/src/ChatWindow.h
new file mode 100644
index 0000000000..5aaf13d1a2
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ChatWindow.h
@@ -0,0 +1,196 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+
+class ChatWindow;
+
+#ifndef CHATWINDOW_INCLUDED
+#define CHATWINDOW_INCLUDED
+#include "mucc.h"
+#include "ChatEvent.h"
+#include "ChatUser.h"
+#include "AdminWindow.h"
+#include "ChatContainer.h"
+
+#define DM_CHAT_EVENT (WM_USER+1)
+#define DM_CHAT_QUERY (WM_USER+2)
+#define WM_TLEN_SMILEY (WM_USER+200)
+
+
+class StreamData {
+public:
+ ChatWindow *chat;
+ MUCCEVENT *event;
+};
+
+class ChatWindow{
+private:
+ static ChatWindow * list;
+ static CRITICAL_SECTION mutex;
+ static bool released;
+ static HFONT hListGroupFont, hListFont;
+ static COLORREF colorListBg, colorListText, colorListGroupText;
+ static COLORREF colorInputBg, colorLogBg;
+ ChatContainer * container;
+ HANDLE hEvent;
+ HWND hWnd;
+ HWND hWndLog;
+ HFONT hEditFont;
+ HTREEITEM hUserGroups[5];
+ char * module;
+ char * roomId;
+ char * roomName;
+ char * topic;
+ int options;
+ int roomFlags;
+ int font, fontSize;
+ int bBold, bItalic, bUnderline;
+ int wasFirstMessage;
+ bool isEmpty;
+ COLORREF fontColor;
+ int isStarted;
+ ChatWindow * prev;
+ ChatWindow * next;
+ int adminDialogMode;
+ AdminWindow * adminWindow;
+ ChatUser * users;
+ ChatUser * userMe;
+ void addUser(ChatUser *);
+ void removeUser(ChatUser *);
+ ChatUser * findUser(const char *);
+ int getUserGroup(ChatUser *);
+ ChatUser * getSelectedUser();
+ ChatEventList eventList;
+ void createRTFHeader();
+ int appendMessage(const MUCCEVENT *event);
+ int logMessage(const MUCCEVENT *event);
+public:
+ enum LOGFLAGS {
+ FLAG_SHOW_NICKNAMES = 0x00000001,
+ FLAG_MSGINNEWLINE = 0x00000002,
+ FLAG_OPT_SENDONENTER= 0x00000004,
+ FLAG_OPT_ENABLEIEVIEW=0x00000008,
+
+ FLAG_SHOW_DATE = 0x00000010,
+ FLAG_SHOW_TIMESTAMP = 0x00000020,
+ FLAG_SHOW_SECONDS = 0x00000040,
+ FLAG_LONG_DATE = 0x00000080,
+
+ FLAG_FORMAT_FONT = 0x00000100,
+ FLAG_FORMAT_SIZE = 0x00000200,
+ FLAG_FORMAT_COLOR = 0x00000400,
+ FLAG_FORMAT_STYLE = 0x00000800,
+ FLAG_FORMAT_ALL = 0x00000F00,
+
+ FLAG_LOG_MESSAGES = 0x00001000,
+ FLAG_LOG_JOINED = 0x00002000,
+ FLAG_LOG_LEFT = 0x00004000,
+ FLAG_LOG_TOPIC = 0x00008000,
+ FLAG_LOG_ALL = 0x0000F000,
+
+ FLAG_FLASH_MESSAGES = 0x00010000,
+ FLAG_FLASH_JOINED = 0x00020000,
+ FLAG_FLASH_LEFT = 0x00040000,
+ FLAG_FLASH_TOPIC = 0x00080000,
+ FLAG_FLASH_ALL = 0x000F0000,
+
+
+ };
+
+ enum ADMINMODES {
+ ADMIN_MODE_KICK = 1,
+ ADMIN_MODE_ROLE = 2,
+ ADMIN_MODE_BROWSER = 3
+ };
+ int hSplitterPos;
+ int vSplitterPos;
+ int hSplitterMinBottom;
+ int hSplitterMinTop;
+ int vSplitterMinLeft;
+ int vSplitterMinRight;
+ ChatWindow (MUCCWINDOW *);
+ ~ChatWindow ();
+ ChatWindow * getNext();
+ void setNext(ChatWindow *);
+ ChatWindow * getPrev();
+ ChatContainer* getContainer();
+ void setPrev(ChatWindow *);
+ void setHWND(HWND);
+ HWND getHWND();
+ void setHWNDLog(HWND);
+ HWND getHWNDLog();
+ HANDLE getEvent();
+ const char * getModule();
+ void setModule(const char *);
+ const char * getRoomId();
+ void setRoomId(const char *);
+ const char * getRoomName();
+ void setRoomName(const char *);
+ void setOptions(int);
+ int getOptions();
+ void setRoomFlags(int);
+ int getRoomFlags();
+ int getFontSizeNum();
+ int getFontSize(int);
+ int getFontNameNum();
+ const char * getFontName(int);
+ void setFont(int font, int size, int bBold, int bItalic, int bUnderline, COLORREF color);
+ int getFont();
+ int getFontSize();
+ int getFontStyle();
+ COLORREF getFontColor();
+ int start();
+ int startPriv();
+ void startAdminDialog(int mode);
+ int kickAndBan(int time);
+ int kickAndBan(const char *id, int time, const char *);
+ int unban(const char *id);
+ int setRights(int flags);
+ int setRights(const char *id, int flags);
+ void queryResultContacts(MUCCQUERYRESULT *queryResult);
+ void queryResultUsers(MUCCQUERYRESULT *queryResult);
+ void setTreeItem(int, HTREEITEM);
+ HTREEITEM getTreeItem(int);
+ ChatUser * findUserByNick(const char *);
+ ChatUser * getMe();
+ void refreshSettings();
+ void setAdminWindow(AdminWindow *);
+ AdminWindow * getAdminWindow();
+ void rebuildLog();
+ void clearLog();
+ int logEvent(const MUCCEVENT *event);
+ int changePresence(const MUCCEVENT *event);
+ int changeTopic(const MUCCEVENT *event);
+ int changeRoomInfo(const MUCCEVENT *event);
+ int leave();
+
+ static void refreshSettings(int force);
+ static HFONT getListGroupFont();
+ static HFONT getListFont();
+ static COLORREF getListTextColor();
+ static COLORREF getListGroupTextColor();
+ static int getDefaultOptions();
+
+ static void init();
+ static void release();
+ static ChatWindow * getWindow(const char *module, const char *roomId);
+
+};
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/FontList.cpp b/protocols/Tlen/tlen_czaty/src/FontList.cpp
new file mode 100644
index 0000000000..3bcf7554c5
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/FontList.cpp
@@ -0,0 +1,206 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "FontList.h"
+#include "Utils.h"
+
+#define FONTCOUNT 12
+static Font defFonts[] = {
+ Font("Timestamp","Verdana", DEFAULT_CHARSET, -9, Font::BOLD, 0x000000),
+// Font("Colon","Verdana", DEFAULT_CHARSET, -13, 0, 0x808080),
+ Font("Others names","Verdana", DEFAULT_CHARSET, -13, 0, 0x723732),
+ Font("Your name","Verdana", DEFAULT_CHARSET, -13, 0, 0x4453A4),
+ Font("Incoming message","Verdana", DEFAULT_CHARSET, -13, 0, 0x000000),
+ Font("Outgoing message","Verdana", DEFAULT_CHARSET, -13, 0, 0x505080),
+ Font("User has joined","Verdana", DEFAULT_CHARSET, -11, Font::ITALIC, 0x0F880F),
+ Font("User has left","Verdana", DEFAULT_CHARSET, -11, Font::ITALIC, 0x1313B9),
+ Font("The topic is ...","Verdana", DEFAULT_CHARSET, -13, Font::ITALIC, 0x991A53),
+ Font("Error","Verdana", DEFAULT_CHARSET, -13, Font::BOLD, 0x1010D0),
+ Font("Message typing area","Verdana", DEFAULT_CHARSET, -13, 0, 0x000000),
+ Font("User list","Tahoma", DEFAULT_CHARSET, -11, 0, 0x000000),
+ Font("User list group","Tahoma", DEFAULT_CHARSET, -11, Font::BOLD, 0x000000)
+
+};
+
+Font::Font() {
+ name = NULL;
+ face = NULL;
+ size = 0;
+ style = 0;
+ color = 0;
+ charSet = DEFAULT_CHARSET;
+}
+
+Font::Font(const char *n, const char *f, int cs, int s, int st, COLORREF c) {
+ name = NULL;
+ face = NULL;
+ size = 0;
+ style = 0;
+ color = 0;
+ setName(n);
+ setFace(f);
+ setCharSet(cs);
+ setSize(s);
+ setStyle(st);
+ setColor(c);
+}
+
+
+COLORREF Font::getColor() {
+ return color;
+}
+
+void Font::setColor(COLORREF c) {
+ color = c;
+}
+
+int Font::getSize() {
+ return size;
+}
+
+void Font::setSize(int s) {
+ size = s;
+}
+
+int Font::getStyle() {
+ return style;
+}
+
+void Font::setStyle(int s) {
+ style = s;
+}
+
+int Font::getCharSet() {
+ return charSet;
+}
+
+void Font::setCharSet(int s) {
+ charSet = s;
+}
+
+void Font::setName(const char *s) {
+ Utils::copyString(&name, s);
+}
+
+const char *Font::getName() {
+ return name;
+}
+
+void Font::setFace(const char *s) {
+ Utils::copyString(&face, s);
+}
+
+const char *Font::getFace() {
+ return face;
+}
+
+Font *FontList::fonts = NULL;
+Font *FontList::fontsSettings = NULL;
+
+Font *FontList::getFont(int index) {
+ if (index < FONTCOUNT) return &fonts[index];
+ else return NULL;
+}
+
+Font *FontList::getFontSettings(int index) {
+ if (index < FONTCOUNT) return &fontsSettings[index];
+ else return NULL;
+}
+
+void FontList::loadSettings() {
+ char fontParam[512];
+ for (int i=0;i<FONTCOUNT;i++) {
+ DBVARIANT dbv;
+ fontsSettings[i].setName(defFonts[i].getName());
+ fontsSettings[i].setFace(defFonts[i].getFace());
+ fontsSettings[i].setCharSet(defFonts[i].getCharSet());
+ fontsSettings[i].setSize(defFonts[i].getSize());
+ fontsSettings[i].setStyle(defFonts[i].getStyle());
+ fontsSettings[i].setColor(defFonts[i].getColor());
+ sprintf(fontParam, "Font%dFace", i);
+ if (!DBGetContactSetting(NULL, muccModuleName, fontParam, &dbv)) {
+ fontsSettings[i].setFace(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(fontParam, "Font%dSet", i);
+ if (!DBGetContactSetting(NULL, muccModuleName, fontParam, &dbv)) {
+ fontsSettings[i].setCharSet(dbv.bVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(fontParam, "Font%dSize", i);
+ if (!DBGetContactSetting(NULL, muccModuleName, fontParam, &dbv)) {
+ fontsSettings[i].setSize(dbv.lVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(fontParam, "Font%dCol", i);
+ if (!DBGetContactSetting(NULL, muccModuleName, fontParam, &dbv)) {
+ fontsSettings[i].setColor(dbv.lVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(fontParam, "Font%dStyle", i);
+ if (!DBGetContactSetting(NULL, muccModuleName, fontParam, &dbv)) {
+ fontsSettings[i].setStyle(dbv.bVal);
+ DBFreeVariant(&dbv);
+ }
+ fonts[i].setName(fontsSettings[i].getName());
+ fonts[i].setFace(fontsSettings[i].getFace());
+ fonts[i].setCharSet(fontsSettings[i].getCharSet());
+ fonts[i].setSize(fontsSettings[i].getSize());
+ fonts[i].setStyle(fontsSettings[i].getStyle());
+ fonts[i].setColor(fontsSettings[i].getColor());
+ }
+}
+
+void FontList::saveSettings() {
+ char fontParam[512];
+ for (int i=0;i<FONTCOUNT;i++) {
+ sprintf(fontParam, "Font%dFace", i);
+ DBWriteContactSettingString(NULL, muccModuleName, fontParam, fontsSettings[i].getFace());
+ sprintf(fontParam, "Font%dSet", i);
+ DBWriteContactSettingByte(NULL, muccModuleName, fontParam, fontsSettings[i].getCharSet());
+ sprintf(fontParam, "Font%dSize", i);
+ DBWriteContactSettingDword(NULL, muccModuleName, fontParam, fontsSettings[i].getSize());
+ sprintf(fontParam, "Font%dCol", i);
+ DBWriteContactSettingDword(NULL, muccModuleName, fontParam, fontsSettings[i].getColor());
+ sprintf(fontParam, "Font%dStyle", i);
+ DBWriteContactSettingByte(NULL, muccModuleName, fontParam, fontsSettings[i].getStyle());
+ fonts[i].setName(fontsSettings[i].getName());
+ fonts[i].setFace(fontsSettings[i].getFace());
+ fonts[i].setCharSet(fontsSettings[i].getCharSet());
+ fonts[i].setStyle(fontsSettings[i].getStyle());
+ fonts[i].setSize(fontsSettings[i].getSize());
+ fonts[i].setColor(fontsSettings[i].getColor());
+ }
+}
+
+void FontList::init() {
+ fonts = new Font[FONTCOUNT];
+ fontsSettings = new Font[FONTCOUNT];
+ loadSettings();
+}
+
+void FontList::release() {
+ delete[] fonts;
+ delete[] fontsSettings;
+}
+
+int FontList::getFontNum() {
+ return FONTCOUNT;
+}
diff --git a/protocols/Tlen/tlen_czaty/src/FontList.h b/protocols/Tlen/tlen_czaty/src/FontList.h
new file mode 100644
index 0000000000..0c876fcbfe
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/FontList.h
@@ -0,0 +1,90 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef FONTLIST_INCLUDED
+#define FONTLIST_INCLUDED
+#include "mucc.h"
+
+
+class Font {
+private:
+ COLORREF color;
+ char * face;
+ char * name;
+ int size;
+ int style;
+ int charSet;
+public:
+ enum STYLES {
+ BOLD = 1,
+ ITALIC = 2,
+ UNDERLINE = 4,
+ STROKE = 8,
+ UNDERWAVE = 16
+ };
+ Font();
+ Font(const char *name, const char *face, int charSet, int size, int style, COLORREF color);
+ void setColor(COLORREF c);
+ COLORREF getColor();
+ void setSize(int s);
+ int getSize();
+ void setStyle(int s);
+ int getStyle();
+ void setFace(const char *s);
+ const char *getFace();
+ void setName(const char *s);
+ const char *getName();
+ void setCharSet(int s);
+ int getCharSet();
+};
+
+class FontList {
+private:
+ static Font *fonts;
+ static Font *fontsSettings;
+public:
+ enum FONTIDEX {
+ FONT_TIMESTAMP = 0,
+// FONT_COLON = 1,
+ FONT_OTHERSNAMES = 1,
+ FONT_MYNAME = 2,
+ FONT_INMESSAGE = 3,
+ FONT_OUTMESSAGE = 4,
+ FONT_JOINED = 5,
+ FONT_LEFT = 6,
+ FONT_TOPIC = 7,
+// FONT_NOTIFICATION = 9,
+ FONT_ERROR = 8,
+ FONT_TYPING = 9,
+ FONT_USERLIST = 10,
+ FONT_USERLISTGROUP = 11
+ };
+ static Font *getFont(int index);
+ static Font *getFontSettings(int index);
+ static void release();
+ static void init();
+ static int getFontNum();
+ static void loadSettings();
+ static void saveSettings();
+};
+
+#endif
+
+
diff --git a/protocols/Tlen/tlen_czaty/src/HelperDialog.cpp b/protocols/Tlen/tlen_czaty/src/HelperDialog.cpp
new file mode 100644
index 0000000000..db9198e40b
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/HelperDialog.cpp
@@ -0,0 +1,589 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "HelperDialog.h"
+#include "Utils.h"
+
+static INT_PTR CALLBACK InviteDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK AcceptInvitationDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK JoinDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//static INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK TopicDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static void __cdecl InviteDlgThread(void *vDialog);
+static void __cdecl AcceptInvitationDlgThread(void *vDialog);
+static void __cdecl JoinDlgThread(void *vDialog);
+static void __cdecl ErrorDlgThread(void *vDialog);
+static void __cdecl TopicDlgThread(void *vDialog);
+
+HelperDialog * HelperDialog::list = NULL;
+CRITICAL_SECTION HelperDialog::mutex;
+
+HelperDialog::HelperContact::HelperContact(const char *id, const char *name) {
+ this->id = NULL;
+ this->name = NULL;
+ next = NULL;
+ Utils::copyString(&this->id, id);
+ Utils::copyString(&this->name, name);
+}
+HelperDialog::HelperContact::~HelperContact() {
+ if (id != NULL) delete id;
+ if (name != NULL) delete name;
+}
+
+void HelperDialog::HelperContact::setNext(HelperContact *next) {
+ this->next = next;
+}
+
+const char *HelperDialog::HelperContact::getId() {
+ return id;
+}
+
+const char *HelperDialog::HelperContact::getName() {
+ return name;
+}
+
+HelperDialog::HelperContact* HelperDialog::HelperContact::getNext() {
+ return next;
+}
+
+void HelperDialog::init() {
+ InitializeCriticalSection(&mutex);
+}
+
+void HelperDialog::release() {
+ while (list != NULL) {
+ delete list;
+ }
+ DeleteCriticalSection(&mutex);
+}
+
+HelperDialog::HelperDialog() {
+ module = nick = reason = roomId = roomName = NULL;
+ prev = next = NULL;
+ contactList = NULL;
+ hWnd = NULL;
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ EnterCriticalSection(&mutex);
+ setNext(list);
+ if (next != NULL) {
+ next->setPrev(this);
+ }
+ list = this;
+ LeaveCriticalSection(&mutex);
+}
+
+HelperDialog::HelperDialog(ChatWindow *chat) {
+ module = nick = reason = roomId = roomName = NULL;
+ prev = next = NULL;
+ contactList = NULL;
+ hWnd = NULL;
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ setModule(chat->getModule());
+ setRoomId(chat->getRoomId());
+ setRoomName(chat->getRoomName());
+ setRoomFlags(chat->getRoomFlags());
+ EnterCriticalSection(&mutex);
+ setNext(list);
+ if (next != NULL) {
+ next->setPrev(this);
+ }
+ list = this;
+ LeaveCriticalSection(&mutex);
+}
+
+HelperDialog::~HelperDialog()
+{
+ EnterCriticalSection(&mutex);
+ if (getPrev() != NULL) {
+ getPrev()->setNext(next);
+ } else {
+ list = getNext();
+ }
+ if (getNext() != NULL) {
+ getNext()->setPrev(prev);
+ }
+ LeaveCriticalSection(&mutex);
+ if (hEvent != NULL) CloseHandle(hEvent);
+ if (module != NULL) delete module;
+ if (roomId != NULL) delete roomId;
+ if (roomName != NULL) delete roomName;
+ if (nick != NULL) delete nick;
+ if (reason != NULL) delete reason;
+ for (HelperContact *ptr2, *ptr=contactList;ptr != NULL;ptr=ptr2) {
+ ptr2 = ptr->getNext();
+ delete ptr;
+ }
+}
+void HelperDialog::setHWND(HWND hWnd) {
+ this->hWnd = hWnd;
+}
+HWND HelperDialog::getHWND() {
+ return hWnd;
+}
+void HelperDialog::setPrev(HelperDialog *prev) {
+ this->prev = prev;
+}
+void HelperDialog::setNext(HelperDialog *next) {
+ this->next = next;
+}
+HelperDialog * HelperDialog::getPrev() {
+ return prev;
+}
+HelperDialog * HelperDialog::getNext() {
+ return next;
+}
+const char *HelperDialog::getModule()
+{
+ return module;
+}
+const char *HelperDialog::getRoomId()
+{
+ return roomId;
+}
+const char *HelperDialog::getRoomName()
+{
+ return roomName;
+}
+const char *HelperDialog::getNick()
+{
+ return nick;
+}
+const char *HelperDialog::getReason()
+{
+ return reason;
+}
+void HelperDialog::setModule(const char *module)
+{
+ Utils::copyString(&this->module, module);
+}
+void HelperDialog::setRoomId(const char *roomId)
+{
+ Utils::copyString(&this->roomId, roomId);
+}
+void HelperDialog::setRoomName(const char *roomName)
+{
+ Utils::copyString(&this->roomName, roomName);
+}
+void HelperDialog::setNick(const char *nick)
+{
+ Utils::copyString(&this->nick, nick);
+}
+void HelperDialog::setReason(const char *reason)
+{
+ Utils::copyString(&this->reason, reason);
+}
+void HelperDialog::setRoomFlags(DWORD flags)
+{
+ this->roomFlags = flags;
+}
+void HelperDialog::setContactList(MUCCQUERYRESULT *queryResult) {
+ HelperContact *ptr, *lastptr;
+ for (ptr=contactList; ptr != NULL; ptr=ptr->getNext()) {
+ delete ptr;
+ }
+ contactList = NULL;
+ lastptr = NULL;
+ for (int i=0;i<queryResult->iItemsNum;i++) {
+ ptr = new HelperContact(queryResult->pItems[i].pszID, queryResult->pItems[i].pszName);
+ if (lastptr != NULL) {
+ lastptr->setNext(ptr);
+ } else {
+ contactList = ptr;
+ }
+ lastptr = ptr;
+ }
+}
+
+HelperDialog::HelperContact * HelperDialog::getContactList() {
+ return contactList;
+}
+
+DWORD HelperDialog::getRoomFlags() {
+ return roomFlags;
+}
+
+void HelperDialog::inviteDlg(ChatWindow *chat, MUCCQUERYRESULT *queryResult) {
+ HelperDialog *dialog=new HelperDialog(chat);
+ dialog->setContactList(queryResult);
+ Utils::forkThread((void (__cdecl *)(void *))InviteDlgThread, 0, (void *) dialog);
+ //WaitForSingleObject(dialog->getEvent(), INFINITE);
+}
+
+void HelperDialog::acceptDlg(MUCCEVENT *event) {
+ HelperDialog *dialog=new HelperDialog();
+ dialog->setModule(event->pszModule);
+ dialog->setRoomId(event->pszID);
+ dialog->setRoomName(event->pszName);
+ dialog->setRoomFlags(event->dwFlags);
+ dialog->setNick(event->pszNick);
+ // dialog->setReason(event->pszText);
+ Utils::forkThread((void (__cdecl *)(void *))AcceptInvitationDlgThread, 0, (void *) dialog);
+// WaitForSingleObject(hEvent, INFINITE);
+}
+
+void HelperDialog::joinDlg(MUCCEVENT *event) {
+ HelperDialog *dialog=new HelperDialog();
+ dialog->setModule(event->pszModule);
+ dialog->setRoomId(event->pszID);
+ dialog->setRoomName(event->pszName);
+ dialog->setRoomFlags(event->dwFlags);
+ dialog->setNick(event->pszNick);
+ Utils::forkThread((void (__cdecl *)(void *))JoinDlgThread, 0, (void *) dialog);
+ //WaitForSingleObject(dialog->getEvent(), INFINITE);
+}
+
+void HelperDialog::errorDlg(MUCCEVENT *event) {
+ HelperDialog *dialog=new HelperDialog();
+ dialog->setReason(event->pszText);
+ Utils::forkThread((void (__cdecl *)(void *))ErrorDlgThread, 0, (void *) dialog);
+ //WaitForSingleObject(dialog->getEvent(), INFINITE);
+}
+
+void HelperDialog::topicDlg(ChatWindow *chat)
+{
+ HelperDialog *dialog=new HelperDialog();
+ dialog->setModule(chat->getModule());
+ dialog->setRoomId(chat->getRoomId());
+ Utils::forkThread((void (__cdecl *)(void *))TopicDlgThread, 0, (void *) dialog);
+}
+
+static void __cdecl InviteDlgThread(void *vDialog)
+{
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HELPER_INVITE), NULL, InviteDlgProc, (LPARAM) vDialog);
+}
+
+static void __cdecl AcceptInvitationDlgThread(void *vDialog)
+{
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HELPER_INVITE_ACCEPT), NULL, AcceptInvitationDlgProc, (LPARAM) vDialog);
+}
+
+static void __cdecl JoinDlgThread(void *vDialog)
+{
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HELPER_JOIN), NULL, JoinDlgProc, (LPARAM) vDialog);
+}
+
+static void __cdecl TopicDlgThread(void *vDialog)
+{
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HELPER_TOPIC), NULL, TopicDlgProc, (LPARAM) vDialog);
+}
+
+static INT_PTR CALLBACK InviteDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char str[256];
+ HelperDialog::HelperContact *contactList;
+ HelperDialog *dialog = (HelperDialog *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ dialog = (HelperDialog *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dialog);
+ dialog->setHWND(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_REASON, EM_SETREADONLY, (WPARAM)TRUE, 0);
+ for (contactList = dialog->getContactList();contactList != NULL;contactList=contactList->getNext()) {
+ SendDlgItemMessage(hwndDlg, IDC_USER, CB_ADDSTRING, 0, (LPARAM)contactList->getName());
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_INVITE:
+ MUCCEVENT muce;
+ GetDlgItemTextA(hwndDlg, IDC_USER, str, 255);
+ if (strlen(str)>0) {
+ for (contactList = dialog->getContactList();contactList != NULL;contactList=contactList->getNext()) {
+ if (!strcmp(str, contactList->getName())) {
+ dialog->setNick(contactList->getId());
+ break;
+ }
+ }
+ if (contactList == NULL) {
+ dialog->setNick(str);
+ }
+ }
+ muce.iType = MUCC_EVENT_INVITE;
+ muce.pszModule = dialog->getModule();
+ muce.pszID = dialog->getRoomId();
+ muce.pszNick = dialog->getNick();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ case IDCANCEL:
+ case IDCLOSE:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ delete dialog;
+ break;
+ }
+ return FALSE;
+}
+
+
+
+
+static INT_PTR CALLBACK AcceptInvitationDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char str[256];
+ HelperDialog *dialog;
+ dialog = (HelperDialog *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ dialog = (HelperDialog *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dialog);
+ dialog->setHWND(hwndDlg);
+ if (dialog->getNick() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_FROM, dialog->getNick());
+ }
+ if (dialog->getRoomName() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_ROOM, dialog->getRoomName());
+ }
+ if (dialog->getReason() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_REASON, dialog->getReason());
+ }
+
+// if (!DBGetContactSetting(NULL, jabberProtoName, "LoginName", &dbv)) {
+// SetDlgItemText(hwndDlg, IDC_NICK, dbv.pszVal);
+// DBFreeVariant(&dbv);
+// }
+
+ /*
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hInst, MAKEINTRESOURCE(IDI_GROUP)));
+*/
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_ACCEPT:
+ GetDlgItemTextA(hwndDlg, IDC_NICK, str, 255);
+ dialog->setNick(str);
+ MUCCEVENT muce;
+ muce.iType = MUCC_EVENT_JOIN;
+ muce.pszModule = dialog->getModule();
+ muce.pszID = dialog->getRoomId();
+ muce.pszName = dialog->getRoomName();
+ muce.dwFlags = dialog->getRoomFlags();
+ muce.pszNick = NULL;
+ if (strlen(dialog->getNick())>0) {
+ muce.pszNick = dialog->getNick();
+ } else {
+ muce.pszNick = NULL;
+ }
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ case IDCANCEL:
+ case IDCLOSE:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ delete dialog;
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static INT_PTR CALLBACK JoinDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char str[256];
+ HelperDialog *dialog;
+ dialog = (HelperDialog *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ dialog = (HelperDialog *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dialog);
+ dialog->setHWND(hwndDlg);
+ SetFocus(GetDlgItem(hwndDlg, IDOK));
+ if (dialog->getRoomFlags() & MUCC_EF_ROOM_NAME) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_ROOM));
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_ROOM, EM_SETREADONLY, (WPARAM)TRUE, 0);
+ }
+ if (dialog->getRoomFlags() & MUCC_EF_ROOM_NICKNAMES) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_NICK));
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_NICK, EM_SETREADONLY, (WPARAM)TRUE, 0);
+ }
+ if (dialog->getRoomName() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_ROOM, dialog->getRoomName());
+ }
+ if (dialog->getNick() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_NICK, dialog->getNick());
+ }
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ MUCCEVENT muce;
+ if (dialog->getRoomId() == NULL) {
+ GetDlgItemTextA(hwndDlg, IDC_ROOM, str, 255);
+ if (strlen(str)>0) {
+ //dialog->setRoomId(str);
+ dialog->setRoomName(str);
+ }
+ }
+ GetDlgItemTextA(hwndDlg, IDC_NICK, str, 255);
+ if (strlen(str)>0) {
+ dialog->setNick(str);
+ } else {
+ dialog->setNick(NULL);
+ }
+ muce.iType = MUCC_EVENT_JOIN;
+ muce.pszModule = dialog->getModule();
+ muce.pszID = dialog->getRoomId();
+ muce.pszName = dialog->getRoomName();
+ muce.pszNick = dialog->getNick();
+ muce.dwFlags = dialog->getRoomFlags();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ delete dialog;
+ break;
+ }
+ return FALSE;
+}
+
+static void __cdecl ErrorDlgThread(void *vDialog)
+{
+ HelperDialog *dialog=(HelperDialog *)vDialog;
+ MessageBoxA(NULL, dialog->getReason(), Translate("Error"), MB_OK | MB_ICONERROR);
+ /*
+ int result = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GROUPCHAT_JOIN), NULL, JoinDlgProc, (LPARAM) dialog);
+ if (result != 0) {
+ MUCCEVENT muce;
+ muce.iType = MUCC_EVENT_JOIN;
+ muce.pszModule = dialog->getModule();
+ muce.pszID = dialog->getRoomId();
+ muce.pszName = dialog->getRoomName();
+ muce.pszNick = dialog->getNick();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ */
+ delete dialog;
+}
+
+/*
+static INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char str[256];
+ HelperDialog *dialog;
+ dialog = (HelperDialog *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ dialog = (HelperDialog *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dialog);
+ dialog->setHWND(hwndDlg);
+ SetFocus(GetDlgItem(hwndDlg, IDOK));
+ if (dialog->getRoomName() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_ROOM, dialog->getRoomName());
+ }
+ if (dialog->getNick() != NULL) {
+ SetDlgItemTextA(hwndDlg, IDC_NICK, dialog->getNick());
+ }
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (dialog->getRoomId() == NULL) {
+ GetDlgItemTextA(hwndDlg, IDC_ROOM, str, 255);
+ if (strlen(str)>0) {
+ //dialog->setRoomId(str);
+ dialog->setRoomName(str);
+ }
+ }
+ GetDlgItemTextA(hwndDlg, IDC_NICK, str, 255);
+ if (strlen(str)>0) {
+ dialog->setNick(str);
+ } else {
+ dialog->setNick(NULL);
+ }
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ delete dialog;
+ break;
+ }
+ return FALSE;
+}
+*/
+
+static INT_PTR CALLBACK TopicDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char str[256];
+ HelperDialog *dialog;
+ dialog = (HelperDialog *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ dialog = (HelperDialog *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dialog);
+ dialog->setHWND(hwndDlg);
+ return FALSE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ MUCCEVENT muce;
+ GetDlgItemTextA(hwndDlg, IDC_TOPIC, str, 255);
+ dialog->setReason(str);
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_TOPIC;
+ muce.pszID = dialog->getRoomId();
+ muce.pszModule = dialog->getModule();
+ muce.pszText = dialog->getReason();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ break;
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+ case WM_DESTROY:
+ delete dialog;
+ break;
+ }
+ return FALSE;
+}
+
diff --git a/protocols/Tlen/tlen_czaty/src/HelperDialog.h b/protocols/Tlen/tlen_czaty/src/HelperDialog.h
new file mode 100644
index 0000000000..d1b3871a8c
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/HelperDialog.h
@@ -0,0 +1,95 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef DIALOGS_INCLUDED
+#define DIALOGS_INCLUDED
+
+#include "mucc.h"
+#include "m_mucc.h"
+#include "ChatWindow.h"
+
+
+class HelperDialog {
+public:
+ class HelperContact {
+ private:
+ char *id;
+ char *name;
+ HelperContact *next;
+ public:
+ HelperContact(const char *id, const char *name);
+ ~HelperContact();
+ void setNext(HelperContact *);
+ HelperContact* getNext();
+ const char * getId();
+ const char * getName();
+ };
+
+private:
+ static HelperDialog * list;
+ static CRITICAL_SECTION mutex;
+ char * module;
+ char * roomId;
+ char * roomName;
+ DWORD roomFlags;
+ HelperContact * contactList;
+ HelperDialog * prev;
+ HelperDialog * next;
+ char * nick;
+ char * reason;
+ HANDLE hEvent;
+ HWND hWnd;
+public:
+ HelperDialog();
+ HelperDialog(ChatWindow *);
+ ~HelperDialog();
+ void setModule(const char *);
+ void setRoomId(const char *);
+ void setRoomName(const char *);
+ void setRoomFlags(DWORD);
+ void setNick(const char *);
+ void setReason(const char *);
+ void setPrev(HelperDialog *);
+ HelperDialog* getPrev();
+ void setNext(HelperDialog *);
+ HelperDialog* getNext();
+ HWND getHWND();
+ void setHWND(HWND hWnd);
+ void setContactList(MUCCQUERYRESULT *queryResult);
+ HelperContact* getContactList();
+ const char * getModule();
+ const char * getRoomId();
+ const char * getRoomName();
+ DWORD getRoomFlags();
+ const char * getNick();
+ const char * getReason();
+ HANDLE getEvent();
+ static void init();
+ static void release();
+ static void inviteDlg(ChatWindow *chat, MUCCQUERYRESULT *queryResult);
+ static void acceptDlg(MUCCEVENT *event);
+ static void joinDlg(MUCCEVENT *event);
+ static void errorDlg(MUCCEVENT *event);
+ static void topicDlg(ChatWindow *chat);
+};
+
+
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/ManagerWindow.cpp b/protocols/Tlen/tlen_czaty/src/ManagerWindow.cpp
new file mode 100644
index 0000000000..584c9fec66
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ManagerWindow.cpp
@@ -0,0 +1,1067 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "ManagerWindow.h"
+#include "Utils.h"
+#include "HelperDialog.h"
+
+static INT_PTR CALLBACK ManagerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK ChatRoomsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK MyRoomsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ManagerWindow * ManagerWindow::list = NULL;
+bool ManagerWindow::released = false;
+CRITICAL_SECTION ManagerWindow::mutex;
+
+void ManagerWindow::init() {
+ released = false;
+ InitializeCriticalSection(&mutex);
+}
+
+void ManagerWindow::release() {
+ released = true;
+ for (ManagerWindow *ptr2, *ptr = list; ptr != NULL; ptr=ptr2) {
+ ptr2 = ptr->getNext();
+ delete ptr;
+// SendMessage(ptr->getHWND(), WM_CLOSE, 0, 0);
+ }
+ DeleteCriticalSection(&mutex);
+}
+
+ManagerWindow::ManagerWindow(const char *module)
+{
+ next = prev = NULL;
+ groups = NULL;
+ rooms = NULL;
+ myRooms = NULL;
+ currentGroup = NULL;
+ isStarted = 0;
+ currentTab = 0;
+ currentRoomsPage = 0;
+ lastRoomsPage = 0;
+ userNickList = userRoomList = 0;
+ this->module = NULL;
+ this->moduleName = NULL;
+ Utils::copyString(&this->module, module);
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ EnterCriticalSection(&mutex);
+ setNext(list);
+ if (next != NULL) {
+ next->setPrev(this);
+ }
+ list = this;
+ LeaveCriticalSection(&mutex);
+}
+
+ManagerWindow::~ManagerWindow()
+{
+ if (!released) {
+ EnterCriticalSection(&mutex);
+ if (getPrev() != NULL) {
+ getPrev()->setNext(next);
+ } else {
+ list = getNext();
+ }
+ if (getNext() != NULL) {
+ getNext()->setPrev(prev);
+ }
+ LeaveCriticalSection(&mutex);
+ }
+ if (hWnd != NULL) {
+ EndDialog(hWnd, 0);
+ }
+ if (hEvent != NULL) {
+ CloseHandle(hEvent);
+ }
+ while (groups != NULL) {
+ ChatGroup *group = groups;
+ groups = groups->getListNext();
+ delete group;
+ }
+ while (rooms != NULL) {
+ ChatRoom *room = rooms;
+ rooms = rooms->getNext();
+ delete room;
+ }
+ while (myRooms != NULL) {
+ ChatRoom *room = myRooms;
+ myRooms = myRooms->getNext();
+ delete room;
+ }
+ if (module != NULL) {
+ delete module;
+ }
+ if (moduleName != NULL) {
+ delete moduleName;
+ }
+}
+void ManagerWindow::setPrev(ManagerWindow *prev)
+{
+ this->prev = prev;
+}
+ManagerWindow * ManagerWindow::getPrev()
+{
+ return prev;
+}
+void ManagerWindow::setNext(ManagerWindow *next)
+{
+ this->next = next;
+}
+ManagerWindow * ManagerWindow::getNext()
+{
+ return next;
+}
+void ManagerWindow::setHWND(HWND h)
+{
+ hWnd=h;
+}
+HWND ManagerWindow::getHWND()
+{
+ return hWnd;
+}
+void ManagerWindow::setChatRoomsTabHWND(HWND h)
+{
+ hChatRoomsTabWnd=h;
+}
+HWND ManagerWindow::getChatRoomsTabHWND()
+{
+ return hChatRoomsTabWnd;
+}
+void ManagerWindow::setMyRoomsTabHWND(HWND h)
+{
+ hMyRoomsTabWnd=h;
+}
+HWND ManagerWindow::getMyRoomsTabHWND()
+{
+ return hMyRoomsTabWnd;
+}
+void ManagerWindow::setMyNicksTabHWND(HWND h)
+{
+ hMyNicksTabWnd=h;
+}
+HWND ManagerWindow::getMyNicksTabHWND()
+{
+ return hMyNicksTabWnd;
+}
+const char *ManagerWindow::getModule()
+{
+ return module;
+}
+const char *ManagerWindow::getModuleName()
+{
+ return moduleName;
+}
+void ManagerWindow::setModuleName(const char *moduleName)
+{
+ Utils::copyString(&this->moduleName, moduleName);
+}
+ChatGroup *ManagerWindow::getCurrentGroup()
+{
+ return currentGroup;
+}
+void ManagerWindow::setCurrentGroup(ChatGroup *group)
+{
+ currentGroup = group;
+}
+HANDLE ManagerWindow::getEvent()
+{
+ return hEvent;
+}
+int ManagerWindow::getCurrentTab()
+{
+ return currentTab;
+}
+void ManagerWindow::setCurrentRoomsPage(int currentRoomsPage)
+{
+ this->currentRoomsPage = currentRoomsPage;
+}
+int ManagerWindow::getCurrentRoomsPage()
+{
+ return currentRoomsPage;
+}
+void ManagerWindow::setCurrentTab(int currentTab)
+{
+ this->currentTab = currentTab;
+}
+void ManagerWindow::setLastRoomsPage(int lastRoomsPage)
+{
+ this->lastRoomsPage = lastRoomsPage;
+}
+int ManagerWindow::isLastRoomsPage()
+{
+ return lastRoomsPage;
+}
+int ManagerWindow::isUserNickListReceived()
+{
+ return userNickList;
+}
+int ManagerWindow::isUserRoomListReceived()
+{
+ return userRoomList;
+}
+static void __cdecl StartThread(void *vManager)
+{
+ OleInitialize(NULL);
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CHATMANAGER), NULL, ManagerDlgProc, (LPARAM) vManager);
+ OleUninitialize();
+}
+int ManagerWindow::start()
+{
+ if (isStarted) {
+ ShowWindow(hWnd, SW_SHOW);
+ return 0;
+ }
+ isStarted = 1;
+ Utils::forkThread((void (__cdecl *)(void *))StartThread, 0, (void *) this);
+ WaitForSingleObject(hEvent, INFINITE);
+ return 0;
+}
+void ManagerWindow::queryResultGroups(MUCCQUERYRESULT *queryResult)
+{
+ TVINSERTSTRUCT tvis;
+ ChatGroup * par = NULL;
+ ChatGroup * group;
+ if (queryResult->pszParent != NULL) {
+ par = findGroup(queryResult->pszParent);
+ if (par != NULL) {
+ if (par->getChild() != NULL) return;
+ }
+ }
+ for (int i=0; i<queryResult->iItemsNum; i++) {
+ group = new ChatGroup();
+ group->setId(queryResult->pItems[i].pszID);
+ group->setName(queryResult->pItems[i].pszName);
+ if (par != NULL) {
+ par->addChild(group);
+ //group->setParent(par);
+ tvis.hParent = par->getTreeItem();
+ } else {
+ tvis.hParent = NULL;
+ }
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM;
+ LPTSTR lps1 = Utils::mucc_mir_a2t(queryResult->pItems[i].pszName);
+ tvis.item.pszText = lps1;
+ tvis.item.cChildren = queryResult->pItems[i].iCount;
+ tvis.item.lParam = (LPARAM) group;
+ group->setTreeItem(TreeView_InsertItem(GetDlgItem(hWnd, IDC_GROUP), &tvis));
+ group->setListNext(groups);
+ groups = group;
+ if (par != NULL) {
+ TreeView_Expand(GetDlgItem(hWnd, IDC_GROUP), par->getTreeItem(), TVE_EXPAND);
+ }
+ Utils::mucc_mir_free(lps1);
+ }
+}
+
+void ManagerWindow::queryResultRooms(MUCCQUERYRESULT *queryResult)
+{
+ ChatRoom *room;
+ while (rooms != NULL) {
+ room = rooms;
+ rooms = rooms->getNext();
+ delete room;
+ }
+ TCHAR str[100];
+ if (getCurrentGroup() == NULL || strcmp(getCurrentGroup()->getId(), queryResult->pszParent) || queryResult->iPage != getCurrentRoomsPage()) return;
+ setLastRoomsPage(queryResult->iLastPage);
+ if (queryResult->iLastPage) {
+ EnableWindow(GetDlgItem(getChatRoomsTabHWND(), IDC_NEXT), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(getChatRoomsTabHWND(), IDC_NEXT), TRUE);
+ }
+ if (queryResult->iPage>0) {
+ EnableWindow(GetDlgItem(getChatRoomsTabHWND(), IDC_PREV), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(getChatRoomsTabHWND(), IDC_PREV), FALSE);
+ }
+ for (int i=0; i<queryResult->iItemsNum; i++) {
+ LVITEM lvItem;
+ room = new ChatRoom();
+ room->setId(queryResult->pItems[i].pszID);
+ room->setName(queryResult->pItems[i].pszName);
+ room->setFlags(queryResult->pItems[i].dwFlags);
+ room->setNext(rooms);
+ rooms=room;
+ lvItem.mask = LVIF_TEXT | LVIF_PARAM;
+ lvItem.iSubItem = 0;
+ lvItem.iItem = ListView_GetItemCount(GetDlgItem(getChatRoomsTabHWND(), IDC_ROOM));
+ LPTSTR lps1 = Utils::mucc_mir_a2t(queryResult->pItems[i].pszName);
+ lvItem.pszText = lps1;
+ lvItem.lParam = (LPARAM) room;
+ ListView_InsertItem(GetDlgItem(getChatRoomsTabHWND(), IDC_ROOM), &lvItem);
+ lvItem.iSubItem = 1;
+ ListView_InsertItem(GetDlgItem(getChatRoomsTabHWND(), IDC_ROOM), &lvItem);
+ _stprintf(str, _TEXT("%d"), queryResult->pItems[i].iCount);
+ ListView_SetItemText(GetDlgItem(getChatRoomsTabHWND(), IDC_ROOM), lvItem.iItem, 1, str);
+ Utils::mucc_mir_free(lps1);
+ }
+}
+
+void ManagerWindow::queryResultUserRooms(MUCCQUERYRESULT *queryResult)
+{
+ ChatRoom *room;
+ ListView_DeleteAllItems(GetDlgItem(getMyRoomsTabHWND(), IDC_LIST));
+ while (myRooms != NULL) {
+ room = myRooms;
+ myRooms = myRooms->getNext();
+ delete room;
+ }
+ for (int i=0; i<queryResult->iItemsNum; i++) {
+ LVITEM lvItem;
+ room = new ChatRoom();
+ room->setId(queryResult->pItems[i].pszID);
+ room->setName(queryResult->pItems[i].pszName);
+ room->setNext(myRooms);
+ myRooms=room;
+ lvItem.mask = LVIF_TEXT | LVIF_PARAM;
+ lvItem.iSubItem = 0;
+ lvItem.iItem = ListView_GetItemCount(GetDlgItem(getMyRoomsTabHWND(), IDC_LIST));
+ LPTSTR lps1 = Utils::mucc_mir_a2t(queryResult->pItems[i].pszName);
+ lvItem.pszText = lps1;
+ lvItem.lParam = (LPARAM) room;
+ ListView_InsertItem(GetDlgItem(getMyRoomsTabHWND(), IDC_LIST), &lvItem);
+ Utils::mucc_mir_free(lps1);
+ }
+ userRoomList = 1;
+}
+
+void ManagerWindow::queryResultUserNick(MUCCQUERYRESULT *queryResult)
+{
+ ListView_DeleteAllItems(GetDlgItem(getMyNicksTabHWND(), IDC_LIST));
+ for (int i=0; i<queryResult->iItemsNum; i++) {
+ LVITEM lvItem;
+ lvItem.mask = LVIF_TEXT;
+ lvItem.iSubItem = 0;
+ lvItem.iItem = ListView_GetItemCount(GetDlgItem(getMyNicksTabHWND(), IDC_LIST));
+ LPTSTR lps1 = Utils::mucc_mir_a2t(queryResult->pItems[i].pszName);
+ lvItem.pszText = lps1;
+ ListView_InsertItem(GetDlgItem(getMyNicksTabHWND(), IDC_LIST), &lvItem);
+ Utils::mucc_mir_free(lps1);
+ }
+ userNickList = 1;
+}
+
+ChatGroup *ManagerWindow::findGroup(const char *id)
+{
+ ChatGroup *group;
+ for (group = groups;group != NULL; group=group->getListNext()) {
+ if (!strcmp(group->getId(), id)) break;
+ }
+ return group;
+}
+
+
+static INT_PTR CALLBACK ChatRoomsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND lv;
+ LVCOLUMN lvCol;
+ ManagerWindow *manager;
+ manager = (ManagerWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ manager = (ManagerWindow *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) manager);
+ TranslateDialogDefault(hwndDlg);
+ manager->setChatRoomsTabHWND(hwndDlg);
+ SendDlgItemMessage(hwndDlg, IDC_PREV, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_NEXT, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_SEARCH, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_PREV, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_PREV]);
+ SendDlgItemMessage(hwndDlg, IDC_NEXT, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_NEXT]);
+ SendDlgItemMessage(hwndDlg, IDC_SEARCH, BM_SETIMAGE, IMAGE_ICON, (LPARAM) muccIcon[MUCC_IDI_SEARCH]);
+
+ lv = GetDlgItem(hwndDlg, IDC_ROOM);
+ ListView_SetExtendedListViewStyle(lv, LVS_EX_FULLROWSELECT);
+ lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+ lvCol.pszText = TranslateT("Name");
+ lvCol.cx = 270;
+ lvCol.iSubItem = 0;
+ ListView_InsertColumn(lv, 0, &lvCol);
+ lvCol.pszText = TranslateT("Persons");
+ lvCol.cx = 50;
+ lvCol.iSubItem = 1;
+ ListView_InsertColumn(lv, 1, &lvCol);
+ lvCol.pszText = _TEXT("");//Translate("");
+ lvCol.cx = 46;
+ lvCol.iSubItem = 2;
+ ListView_InsertColumn(lv, 2, &lvCol);
+ return TRUE;
+ case WM_NOTIFY:
+ switch (wParam) {
+ case IDC_ROOM:
+ switch (((LPNMHDR)lParam)->code) {
+ case LVN_COLUMNCLICK:
+ {
+ LPNMLISTVIEW pnmlv = (LPNMLISTVIEW) lParam;
+ if (pnmlv->iSubItem >= 0 && pnmlv->iSubItem <= 1) {
+ // if (pnmlv->iSubItem == sortColumn)
+ // sortAscending = !sortAscending;
+ // else {
+ // sortAscending = TRUE;
+ // sortColumn = pnmlv->iSubItem;
+ // }
+ // ListView_SortItems(GetDlgItem(hwndDlg, IDC_ROOM), GroupchatCompare, sortColumn);
+ }
+ }
+ break;
+ case NM_DBLCLK:
+ {
+ LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
+ LVITEM item;
+ item.iItem = lpnmitem->iItem;
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM;
+ if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_ROOM), &item)) {
+ MUCCEVENT event;
+ ChatRoom *room = (ChatRoom *)item.lParam;
+ Utils::log("entering room %s ", room->getId());
+ event.cbSize = sizeof(MUCCEVENT);
+ event.iType = MUCC_EVENT_JOIN;
+ event.pszModule = manager->getModule();
+ event.pszID = room->getId();
+ event.pszName = room->getName();
+ event.dwFlags = room->getFlags();
+ event.pszNick = NULL;
+ HelperDialog::joinDlg(&event);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_NEXT:
+ if (!manager->isLastRoomsPage()) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREV), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NEXT), FALSE);
+ manager->setCurrentRoomsPage(manager->getCurrentRoomsPage()+1);
+ SendMessage(GetParent(hwndDlg), WM_MUCC_REFRESH_ROOMS, 0, 0);
+ }
+ break;
+ case IDC_PREV:
+ if (manager->getCurrentRoomsPage()>0) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREV), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NEXT), FALSE);
+ manager->setCurrentRoomsPage(manager->getCurrentRoomsPage()-1);
+ }
+ SendMessage(GetParent(hwndDlg), WM_MUCC_REFRESH_ROOMS, 0, 0);
+ break;
+ case IDC_SEARCH:
+ {
+ MUCCEVENT event;
+ event.cbSize = sizeof(MUCCEVENT);
+ event.iType = MUCC_EVENT_JOIN;
+ event.dwFlags = MUCC_EF_ROOM_NAME;
+ event.pszModule = manager->getModule();
+ event.pszID = NULL;
+ event.pszName = NULL;
+ event.pszNick = NULL;
+ HelperDialog::joinDlg(&event);
+ break;
+ }
+ }
+ break;
+ case WM_MEASUREITEM:
+ if (wParam == IDC_ROOM) {
+ MEASUREITEMSTRUCT *lpMis = (MEASUREITEMSTRUCT *) lParam;
+ lpMis->itemHeight = GetSystemMetrics(SM_CYSMICON);
+ return TRUE;
+ }
+ break;
+ case WM_DRAWITEM:
+ if (wParam == IDC_ROOM) {
+ RECT rc;
+ int w, x, col;
+ DRAWITEMSTRUCT *lpDis = (DRAWITEMSTRUCT *) lParam;
+ ChatRoom *room = NULL;
+// if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_ROOM), &item)) {
+ room = (ChatRoom *)lpDis->itemData;// (ChatRoom *)item.lParam;
+// }
+ TCHAR text[256];
+ switch (lpDis->itemAction) {
+ default:
+ case ODA_SELECT:
+ case ODA_DRAWENTIRE:
+ if (lpDis->itemState & ODS_SELECTED) {
+ HBRUSH hBrush = CreateSolidBrush(RGB(0xC2, 0xC8, 0xDA));//0xDAC8C2);
+ FillRect(lpDis->hDC, &(lpDis->rcItem), hBrush);//(HBRUSH) (COLOR_HIGHLIGHT+1));
+ DeleteObject(hBrush);
+ SetTextColor(lpDis->hDC, 0);
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ else {
+// HBRUSH hBrush = CreateSolidBrush(RGB(0xC2, 0xC8, 0xDA));//0xDAC8C2);
+ FillRect(lpDis->hDC, &(lpDis->rcItem), (HBRUSH) (COLOR_WINDOW+1));
+// DeleteObject(hBrush);
+ SetTextColor(lpDis->hDC, RGB(0, 0, 0));//GetSysColor(COLOR_WINDOWTEXT));
+// SetBkColor(lpDis->hDC, GetSysColor(COLOR_WINDOW+1));
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ x = lpDis->rcItem.left;
+ for (col=0;col<3;col++) {
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_ROOM), lpDis->itemID, col, text, sizeof(text)/sizeof(TCHAR));
+ w = ListView_GetColumnWidth(GetDlgItem(hwndDlg, IDC_ROOM), col);
+ rc.left = x;
+ rc.top = lpDis->rcItem.top;
+ rc.bottom = lpDis->rcItem.bottom;
+ rc.right = x+w;
+ if (col == 0) {
+ rc.left+=2;
+ rc.right-=2;
+ DrawText(lpDis->hDC, text, (int)_tcslen(text), &rc, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ }
+ else if (col < 2) {
+ DrawText(lpDis->hDC, text, (int)_tcslen(text), &rc, DT_CENTER|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ } else {
+ if (room->getFlags()&MUCC_EF_ROOM_MODERATED) {
+ DrawIconEx(lpDis->hDC, x, rc.top, muccIcon[MUCC_IDI_R_MODERATED], GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ }
+ if (room->getFlags()&MUCC_EF_ROOM_MEMBERS_ONLY) {
+ DrawIconEx(lpDis->hDC, x+12+0*GetSystemMetrics(SM_CXSMICON), rc.top, muccIcon[MUCC_IDI_R_MEMBERS], GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ }
+ if (!(room->getFlags()&MUCC_EF_ROOM_NICKNAMES)) {
+ DrawIconEx(lpDis->hDC, x+24+0*GetSystemMetrics(SM_CXSMICON), rc.top, muccIcon[MUCC_IDI_R_ANONYMOUS], GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ }
+ }
+ x += w;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK MyRoomsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc;
+ HWND lv;
+ LVCOLUMN lvCol;
+ ManagerWindow *manager;
+ manager = (ManagerWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ manager = (ManagerWindow *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) manager);
+ TranslateDialogDefault(hwndDlg);
+ manager->setMyRoomsTabHWND(hwndDlg);
+ lv = GetDlgItem(hwndDlg, IDC_LIST);
+ ListView_SetExtendedListViewStyle(lv, LVS_EX_FULLROWSELECT);
+ GetClientRect(lv, &rc);
+ lvCol.mask = LVCF_WIDTH;
+ lvCol.cx = rc.right - rc.left;
+ ListView_InsertColumn(lv, 0, &lvCol);
+ return TRUE;
+ case WM_NOTIFY:
+ switch (wParam) {
+ case IDC_LIST:
+ switch (((LPNMHDR)lParam)->code) {
+ case NM_DBLCLK:
+ {
+ LVITEM item;
+ item.iItem = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST));
+ if (item.iItem >= 0) {
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM;
+ if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_LIST), &item)) {
+ ChatRoom *room = (ChatRoom *)item.lParam;
+ Utils::log("entering room %s (%s)", room->getId(), room->getId());
+ MUCCEVENT muce;
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_JOIN;
+ muce.pszModule = manager->getModule();
+ muce.pszID = room->getId();
+ muce.pszName = room->getName();
+ muce.dwFlags = MUCC_EF_ROOM_NICKNAMES;
+ muce.pszNick = NULL;
+ HelperDialog::joinDlg(&muce);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_REFRESH:
+ SendMessage(GetParent(hwndDlg), WM_MUCC_REFRESH_USER_ROOMS, 0, 0);
+ break;
+ case IDC_REGISTER:
+ {
+ MUCCEVENT muce;
+ if (manager->getCurrentGroup() != NULL) {
+ TCHAR name[256];
+ GetDlgItemText(hwndDlg, IDC_NAME, name, 255);
+ if (_tcslen(name) != 0) {
+ int flags = 0;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_PUBLIC)) {
+ flags |= MUCC_EF_ROOM_PUBLIC;
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_PERMANENT)) {
+ flags |= MUCC_EF_ROOM_PERMANENT;
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEMBERS)) {
+ flags |= MUCC_EF_ROOM_MEMBERS_ONLY;
+ }
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_NICKNAMES)) {
+ flags |= MUCC_EF_ROOM_NICKNAMES;
+ }
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_REGISTER_ROOM;
+ muce.pszModule = manager->getModule();
+ muce.pszID = manager->getCurrentGroup()->getId();
+ char* lps1 = Utils::mucc_mir_t2a(name);
+ muce.pszName = lps1;
+ muce.pszNick = NULL;
+ muce.dwFlags = flags;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ Utils::mucc_mir_free(lps1);
+ }
+ } else {
+ muce.pszText = "Please select a group first.";
+ HelperDialog::errorDlg(&muce);
+ }
+ }
+ break;
+ }
+ break;
+ case WM_MEASUREITEM:
+ if (wParam == IDC_LIST) {
+ MEASUREITEMSTRUCT *lpMis = (MEASUREITEMSTRUCT *) lParam;
+ lpMis->itemHeight = 16;//GetSystemMetrics(SM_CYSMICON);
+ return TRUE;
+ }
+ break;
+ case WM_DRAWITEM:
+ if (wParam == IDC_LIST) {
+ TCHAR text[256];
+ DRAWITEMSTRUCT *lpDis = (DRAWITEMSTRUCT *) lParam;
+ switch (lpDis->itemAction) {
+ default:
+ case ODA_SELECT:
+ case ODA_DRAWENTIRE:
+ if (lpDis->itemState & ODS_SELECTED) {
+ HBRUSH hBrush = CreateSolidBrush(RGB(0xC2, 0xC8, 0xDA));//0xDAC8C2);
+ FillRect(lpDis->hDC, &(lpDis->rcItem), hBrush);//(HBRUSH) (COLOR_HIGHLIGHT+1));
+ DeleteObject(hBrush);
+ SetTextColor(lpDis->hDC, 0);
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ else {
+ FillRect(lpDis->hDC, &(lpDis->rcItem), (HBRUSH) (COLOR_WINDOW+1));
+ SetTextColor(lpDis->hDC, RGB(0, 0, 0));//GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), lpDis->itemID, 0, text, sizeof(text)/sizeof(TCHAR));
+ DrawText(lpDis->hDC, text, (int)_tcslen(text), &(lpDis->rcItem), DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ break;
+ }
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK MyNicksDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc;
+ HWND lv;
+ LVCOLUMN lvCol;
+ ManagerWindow *manager;
+ manager = (ManagerWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ manager = (ManagerWindow *)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) manager);
+ TranslateDialogDefault(hwndDlg);
+ manager->setMyNicksTabHWND(hwndDlg);
+ lv = GetDlgItem(hwndDlg, IDC_LIST);
+ ListView_SetExtendedListViewStyle(lv, LVS_EX_FULLROWSELECT);
+ GetClientRect(lv, &rc);
+ lvCol.mask = LVCF_WIDTH;
+ lvCol.cx = rc.right - rc.left;
+ ListView_InsertColumn(lv, 0, &lvCol);
+ return TRUE;
+ case WM_NOTIFY:
+ switch (wParam) {
+ case IDC_LIST:
+ break;
+
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_REFRESH:
+ SendMessage(GetParent(hwndDlg), WM_MUCC_REFRESH_USER_NICKS, 0, 0);
+ break;
+ case IDC_REGISTER:
+ {
+ char nick[256];
+ GetDlgItemTextA(hwndDlg, IDC_NICK, nick, 255);
+ if (strlen(nick) != 0) {
+ MUCCEVENT muce;
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_REGISTER_NICK;
+ muce.pszModule = manager->getModule();
+ muce.pszNick = nick;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ }
+ break;
+ case IDC_REMOVE:
+ {
+ LVITEM item;
+ item.iItem = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LIST));
+ if (item.iItem >= 0) {
+ TCHAR text[256];
+ item.iSubItem = 0;
+ item.mask = LVIF_TEXT;
+ item.pszText = text;
+ item.cchTextMax = sizeof(text);
+ if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_LIST), &item)) {
+ MUCCEVENT muce;
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_REMOVE_NICK;
+ muce.pszModule = manager->getModule();
+ char* lps2 = Utils::mucc_mir_t2a(text);
+ muce.pszNick = lps2;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ Utils::mucc_mir_free(lps2);
+ }
+ }
+ }
+ }
+ break;
+ case WM_MEASUREITEM:
+ if (wParam == IDC_LIST) {
+ MEASUREITEMSTRUCT *lpMis = (MEASUREITEMSTRUCT *) lParam;
+ lpMis->itemHeight = 16;//GetSystemMetrics(SM_CYSMICON);
+ return TRUE;
+ }
+ break;
+ case WM_DRAWITEM:
+ if (wParam == IDC_LIST) {
+ TCHAR text[256];
+ DRAWITEMSTRUCT *lpDis = (DRAWITEMSTRUCT *) lParam;
+ switch (lpDis->itemAction) {
+ default:
+ case ODA_SELECT:
+ case ODA_DRAWENTIRE:
+ if (lpDis->itemState & ODS_SELECTED) {
+ HBRUSH hBrush = CreateSolidBrush(RGB(0xC2, 0xC8, 0xDA));//0xDAC8C2);
+ FillRect(lpDis->hDC, &(lpDis->rcItem), hBrush);//(HBRUSH) (COLOR_HIGHLIGHT+1));
+ DeleteObject(hBrush);
+ SetTextColor(lpDis->hDC, 0);
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ else {
+ FillRect(lpDis->hDC, &(lpDis->rcItem), (HBRUSH) (COLOR_WINDOW+1));
+ SetTextColor(lpDis->hDC, RGB(0, 0, 0));//GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ }
+ ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LIST), lpDis->itemID, 0, text, sizeof(text)/sizeof(TCHAR));
+ DrawText(lpDis->hDC, text, (int)_tcslen(text), &(lpDis->rcItem), DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK ManagerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd, tc;
+ TCITEM tci;
+ char text[128];
+// HIMAGELIST hImageList;
+ ManagerWindow *manager;
+ MUCCEVENT muce;
+ int dlgWidth, dlgHeight, tabPos;
+ RECT rc2;
+
+ manager = (ManagerWindow *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (manager == NULL && msg != WM_INITDIALOG) return FALSE;
+ switch (msg) {
+ case WM_INITDIALOG:
+ // lParam is the initial conference server (if any)
+ manager = (ManagerWindow *)lParam;
+ manager->setHWND(hwndDlg);
+ sprintf(text, "%s Chats", manager->getModuleName());
+ SetWindowTextA(hwndDlg, text);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) manager);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) muccIcon[MUCC_IDI_CHAT]);
+
+ TranslateDialogDefault(hwndDlg);
+// sortColumn = -1;
+ manager->setCurrentTab(0);
+ tc = GetDlgItem(hwndDlg, IDC_TABS);
+ tci.mask = TCIF_TEXT;
+ // Public rooms tab
+ tci.pszText = TranslateT("Chat rooms");
+ TabCtrl_InsertItem(tc, 0, &tci);
+ // Create room tab
+ tci.pszText = TranslateT("My rooms");
+ TabCtrl_InsertItem(tc, 1, &tci);
+ tci.pszText = TranslateT("My nicknames");
+ TabCtrl_InsertItem(tc, 2, &tci);
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_TAB_CHATROOMS), hwndDlg, ChatRoomsDlgProc, (LPARAM) manager);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ ShowWindow(hwnd, SW_SHOW);
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_TAB_MYROOMS), hwndDlg, MyRoomsDlgProc, (LPARAM) manager);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_TAB_MYNICKNAMES), hwndDlg, MyNicksDlgProc, (LPARAM) manager);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_PREV), FALSE);
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_NEXT), FALSE);
+
+ GetWindowRect(manager->getMyRoomsTabHWND(), &rc2);
+ rc2.right-=rc2.left;
+ rc2.bottom-=rc2.top;
+ SetWindowPos(hwndDlg, NULL, 0, 0, rc2.right+300, 118+rc2.bottom, SWP_NOMOVE | SWP_NOZORDER);
+ TreeView_SetItemHeight(GetDlgItem(hwndDlg, IDC_GROUP), 16);
+// hImageList=ImageList_Create(100, 100, ILC_COLOR32, 0, 10);
+// ListView_SetImageList(GetDlgItem(hwndDlg, IDC_ROOM), hImageList, LVSIL_SMALL);
+ SetEvent(manager->getEvent());
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_GROUPS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = NULL;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ return TRUE;
+ case WM_SIZING:
+ RECT *rc, rc2;
+ rc = (RECT *)lParam;
+ GetWindowRect(manager->getMyRoomsTabHWND(), &rc2);
+ rc2.right-=rc2.left;
+ rc2.bottom-=rc2.top;
+ if (rc->right-rc->left<(rc2.right+80)) {
+ if (wParam == WMSZ_RIGHT || wParam == WMSZ_BOTTOMRIGHT || wParam == WMSZ_TOPRIGHT) {
+ rc->right=rc->left+rc2.right+80;
+ } else {
+ rc->left=rc->right-rc2.right-80;
+ }
+ }
+ if (rc->bottom-rc->top<118+rc2.bottom || rc->bottom-rc->top>118+rc2.bottom) {
+ if (wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT) {
+ rc->bottom=rc->top+118+rc2.bottom;
+ } else {
+ rc->top=rc->bottom-118-rc2.bottom;
+ }
+ }
+ return TRUE;
+ case WM_SIZE:
+ if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED) {
+ HDWP hdwp;
+ dlgWidth = LOWORD(lParam);
+ dlgHeight = HIWORD(lParam);
+ GetWindowRect(manager->getMyRoomsTabHWND(), &rc2);
+ rc2.right-=rc2.left;
+ rc2.bottom-=rc2.top;
+ tabPos = dlgWidth - rc2.right - 15;
+ hdwp = BeginDeferWindowPos(6);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_TABS), 0, tabPos, 10, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, manager->getChatRoomsTabHWND(), 0, tabPos+3, 45, 371, 292, SWP_NOZORDER | SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, manager->getMyRoomsTabHWND() , 0, tabPos+3, 45, 371, 292, SWP_NOZORDER | SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, manager->getMyNicksTabHWND() , 0, tabPos+3, 45, 371, 292, SWP_NOZORDER | SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_GROUP), 0, 0, 0, tabPos-16, dlgHeight-40, SWP_NOZORDER | SWP_NOMOVE);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDCLOSE), 0, dlgWidth-88, dlgHeight-34, 0, 0 , SWP_NOZORDER | SWP_NOSIZE);
+ EndDeferWindowPos(hdwp);
+ }
+ break;
+ case WM_NOTIFY:
+ switch (wParam) {
+ case IDC_GROUP:
+ switch (((LPNMHDR)lParam)->code) {
+ case TVN_ITEMEXPANDING:
+ {
+ LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam;
+ if (pnmtv->action == TVE_EXPAND) {
+ TVITEM item = (TVITEM) pnmtv->itemNew;
+ ChatGroup *group = (ChatGroup *) item.lParam;// manager->findGroup(item.hItem);
+ if (group != NULL) {
+ if (group->getChild() == NULL) {
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_GROUPS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = group->getId();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ }
+ }
+ }
+ break;
+ case TVN_SELCHANGED:
+ {
+ LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam;
+ TVITEM item = (TVITEM) pnmtv->itemNew;
+ ChatGroup *group = (ChatGroup *) item.lParam;// manager->findGroup(item.hItem);
+ if (group != NULL) {
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_PREV), FALSE);
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_NEXT), FALSE);
+ ListView_DeleteAllItems(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_ROOM));
+ manager->setCurrentGroup(group);
+ manager->setCurrentRoomsPage(0);
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_ROOMS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = (char *)group->getId();
+ muce.dwData = 0;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ }
+ break;
+ case NM_CUSTOMDRAW:
+ {
+ if (((LPNMHDR)lParam)->idFrom == IDC_GROUP) {
+ LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
+ switch (pCustomDraw->nmcd.dwDrawStage) {
+ case CDDS_PREPAINT:
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT,CDRF_NOTIFYITEMDRAW);
+ return TRUE;
+ case CDDS_ITEMPREPAINT:
+ {
+ if (pCustomDraw->nmcd.uItemState & CDIS_FOCUS) { // selected (CDIS_FOCUS | CDIS_SELECTED
+ pCustomDraw->clrText = 0;
+ pCustomDraw->clrTextBk = 0xDAC8C2;
+ }
+ else {
+ pCustomDraw->clrText = 0;
+ }
+ // HBRUSH hBr;
+ // hBr = CreateSolidBrush(pCustomDraw->clrTextBk);//g_LogOptions.crUserListBGColor ) ;
+ // FillRect(pCustomDraw->nmcd.hdc, &rc, hBr);
+ // DeleteObject(hBr);
+ SetWindowLongPtr(hwndDlg,DWLP_MSGRESULT, CDRF_NEWFONT);
+ return TRUE;
+ }
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case IDC_TABS:
+ switch (((LPNMHDR) lParam)->code) {
+ case TCN_SELCHANGE:
+ switch (manager->getCurrentTab()) {
+ case 0:
+ ShowWindow(manager->getChatRoomsTabHWND(), SW_HIDE);
+ break;
+ case 1:
+ ShowWindow(manager->getMyRoomsTabHWND(), SW_HIDE);
+ break;
+ case 2:
+ ShowWindow(manager->getMyNicksTabHWND(), SW_HIDE);
+ break;
+ }
+ manager->setCurrentTab(TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TABS)));
+ switch (manager->getCurrentTab()) {
+ case 0:
+ ShowWindow(manager->getChatRoomsTabHWND(), SW_SHOW);
+ break;
+ case 1:
+ ShowWindow(manager->getMyRoomsTabHWND(), SW_SHOW);
+ if (!manager->isUserRoomListReceived()) {
+ SendMessage(hwndDlg, WM_MUCC_REFRESH_USER_ROOMS, 0, 0);
+ }
+ break;
+ case 2:
+ ShowWindow(manager->getMyNicksTabHWND(), SW_SHOW);
+ if (!manager->isUserNickListReceived()) {
+ SendMessage(hwndDlg, WM_MUCC_REFRESH_USER_NICKS, 0, 0);
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_MUCC_REFRESH_USER_ROOMS:
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_USER_ROOMS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = NULL;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ break;
+ case WM_MUCC_REFRESH_USER_NICKS:
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_USER_NICKS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = NULL;
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ break;
+ case WM_MUCC_REFRESH_ROOMS:
+ {
+ ChatGroup *group = manager->getCurrentGroup();
+ if (manager->getCurrentGroup() != NULL) {
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_PREV), FALSE);
+ EnableWindow(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_NEXT), FALSE);
+ ListView_DeleteAllItems(GetDlgItem(manager->getChatRoomsTabHWND(), IDC_ROOM));
+ /*
+ * TODO: delete rooms here !!!
+ */
+ muce.cbSize = sizeof(MUCCEVENT);
+ muce.iType = MUCC_EVENT_QUERY_ROOMS;
+ muce.pszModule = manager->getModule();
+ muce.pszID = (char *)group->getId();
+ muce.dwData = manager->getCurrentRoomsPage();
+ NotifyEventHooks(hHookEvent, 0,(WPARAM)&muce);
+ }
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCLOSE:
+ ShowWindow(hwndDlg, SW_HIDE);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ ShowWindow(hwndDlg, SW_HIDE);
+ break;
+
+ }
+ return FALSE;
+}
+
+ManagerWindow* ManagerWindow::getWindow(const char *module) {
+ ManagerWindow *ptr;
+ EnterCriticalSection(&mutex);
+ for (ptr=list;ptr != NULL;ptr=ptr->getNext()) {
+ if (strcmp(ptr->getModule(), module) == 0) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&mutex);
+ if (ptr == NULL) {
+ ptr = new ManagerWindow(module);
+ }
+ return ptr;
+}
+
diff --git a/protocols/Tlen/tlen_czaty/src/ManagerWindow.h b/protocols/Tlen/tlen_czaty/src/ManagerWindow.h
new file mode 100644
index 0000000000..afa4243cae
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/ManagerWindow.h
@@ -0,0 +1,93 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef MANAGERWINDOW_INCLUDED
+#define MANAGERWINDOW_INCLUDED
+#include "mucc.h"
+#include "ChatGroup.h"
+#include "ChatRoom.h"
+
+class ManagerWindow{
+
+private:
+ static CRITICAL_SECTION mutex;
+ static bool released;
+ static ManagerWindow * list;
+ HWND hWnd;
+ HWND hChatRoomsTabWnd;
+ HWND hMyRoomsTabWnd;
+ HWND hMyNicksTabWnd;
+ HANDLE hEvent;
+ ManagerWindow * prev;
+ ManagerWindow * next;
+ ChatGroup * groups;
+ ChatRoom * rooms;
+ ChatRoom * myRooms;
+ char * module;
+ char * moduleName;
+ ChatGroup * currentGroup;
+ int isStarted;
+ int userNickList, userRoomList;
+ int currentTab;
+ int currentRoomsPage;
+ int lastRoomsPage;
+public:
+ ManagerWindow (const char *module);
+ ~ManagerWindow ();
+ int start();
+ ChatGroup * findGroup(const char *id);
+ void queryResultGroups(MUCCQUERYRESULT *queryResult);
+ void queryResultRooms(MUCCQUERYRESULT *queryResult);
+ void queryResultUserRooms(MUCCQUERYRESULT *queryResult);
+ void queryResultUserNick(MUCCQUERYRESULT *queryResult);
+ ManagerWindow * getNext();
+ void setNext(ManagerWindow *);
+ ManagerWindow * getPrev();
+ void setPrev(ManagerWindow *);
+ void setHWND(HWND);
+ HWND getHWND();
+ HANDLE getEvent();
+ void setChatRoomsTabHWND(HWND);
+ HWND getChatRoomsTabHWND();
+ void setMyNicksTabHWND(HWND);
+ HWND getMyNicksTabHWND();
+ void setMyRoomsTabHWND(HWND);
+ HWND getMyRoomsTabHWND();
+ void setModuleName(const char *moduleName);
+ void setCurrentTab(int);
+ int getCurrentTab();
+ const char * getModule();
+ const char * getModuleName();
+ void setCurrentGroup(ChatGroup *);
+ ChatGroup * getCurrentGroup();
+ void setCurrentRoomsPage(int);
+ int getCurrentRoomsPage();
+ void setLastRoomsPage(int);
+ int isLastRoomsPage();
+ int isUserRoomListReceived();
+ int isUserNickListReceived();
+
+ static ManagerWindow* getWindow(const char *module);
+ static void release();
+ static void init();
+
+};
+#endif
+
diff --git a/protocols/Tlen/tlen_czaty/src/Options.cpp b/protocols/Tlen/tlen_czaty/src/Options.cpp
new file mode 100644
index 0000000000..0ab39dd9b0
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/Options.cpp
@@ -0,0 +1,789 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "mucc.h"
+#include "Options.h"
+#include "ChatWindow.h"
+#include "Utils.h"
+#include "resource.h"
+#include <commctrl.h>
+#include "m_ieview.h"
+
+static INT_PTR CALLBACK MUCCOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//static INT_PTR CALLBACK MUCCLogOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+//static INT_PTR CALLBACK MUCCPopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+COLORREF Options::colorListBg, Options::colorInputBg, Options::colorLogBg, Options::chatWindowFontColor;
+HBRUSH Options::brushListBg=NULL, Options::brushInputBg=NULL, Options::brushLogBg=NULL;
+int Options::logLimit, Options::chatWindowOptions, Options::chatContainerOptions;
+int Options::chatWindowFont, Options::chatWindowFontSize, Options::chatWindowFontStyle;
+
+void Options::setListBgColor(COLORREF c) {
+ colorListBg = c;
+ if (brushListBg != NULL) {
+ DeleteObject(brushListBg);
+ }
+ brushListBg = CreateSolidBrush(colorListBg);
+}
+
+void Options::setInputBgColor(COLORREF c) {
+ colorInputBg = c;
+ if (brushInputBg != NULL) {
+ DeleteObject(brushInputBg);
+ }
+ brushInputBg = CreateSolidBrush(colorInputBg);
+}
+
+void Options::setLogBgColor(COLORREF c) {
+ colorLogBg = c;
+ if (brushLogBg != NULL) {
+ DeleteObject(brushLogBg);
+ }
+ brushLogBg = CreateSolidBrush(colorLogBg);
+}
+
+COLORREF Options::getListBgColor() {
+ return colorListBg;
+}
+
+COLORREF Options::getInputBgColor() {
+ return colorInputBg;
+}
+
+COLORREF Options::getLogBgColor() {
+ return colorLogBg;
+}
+
+HBRUSH Options::getListBgBrush() {
+ return brushListBg;
+}
+
+HBRUSH Options::getInputBgBrush() {
+ return brushInputBg;
+}
+
+HBRUSH Options::getLogBgBrush() {
+ return brushLogBg;
+}
+
+void Options::setLogLimit(int l) {
+ logLimit = l;
+}
+
+int Options::getLogLimit() {
+ return logLimit;
+}
+
+void Options::setChatWindowFont(int o) {
+ chatWindowFont = o;
+}
+
+int Options::getChatWindowFont() {
+ return chatWindowFont;
+}
+
+void Options::setChatWindowFontSize(int o) {
+ chatWindowFontSize = o;
+}
+
+int Options::getChatWindowFontSize() {
+ return chatWindowFontSize;
+}
+
+void Options::setChatWindowFontStyle(int o) {
+ chatWindowFontStyle = o;
+}
+
+int Options::getChatWindowFontStyle() {
+ return chatWindowFontStyle;
+}
+
+void Options::setChatWindowFontColor(COLORREF o) {
+ chatWindowFontColor = o;
+}
+
+COLORREF Options::getChatWindowFontColor() {
+ return chatWindowFontColor;
+}
+
+void Options::setChatWindowOptions(int o) {
+ chatWindowOptions = o;
+}
+
+int Options::getChatWindowOptions() {
+ return chatWindowOptions;
+}
+
+void Options::setChatContainerOptions(int o) {
+ chatContainerOptions = o;
+}
+
+int Options::getChatContainerOptions() {
+ return chatContainerOptions;
+}
+
+void Options::setExpandFlags(int o) {
+ DBWriteContactSettingDword(NULL, muccModuleName, "ExpandFlags", o);
+}
+
+int Options::getExpandFlags() {
+ return DBGetContactSettingDword(NULL, muccModuleName, "ExpandFlags", 0xFFFFFFFF);
+}
+
+void Options::loadSettings() {
+ FontList::loadSettings();
+ setLogBgColor((COLORREF)DBGetContactSettingDword(NULL, muccModuleName, "BackgroundLog", 0xFFFFFF));
+ setListBgColor((COLORREF)DBGetContactSettingDword(NULL, muccModuleName, "BackgroundList", 0xFFFFFF));
+ setInputBgColor((COLORREF)DBGetContactSettingDword(NULL, muccModuleName, "BackgroundTyping", 0xFFFFFF));
+ setLogLimit(DBGetContactSettingDword(NULL, muccModuleName, "LogSizeLimit", 100));
+ setChatContainerOptions(DBGetContactSettingDword(NULL, muccModuleName, "ChatContainerOptions", ChatContainer::getDefaultOptions()));
+ setChatWindowOptions(DBGetContactSettingDword(NULL, muccModuleName, "ChatWindowOptions", ChatWindow::getDefaultOptions()));
+ setChatWindowFont(DBGetContactSettingDword(NULL, muccModuleName, "ChatWindowFont", 0));
+ setChatWindowFontSize(DBGetContactSettingDword(NULL, muccModuleName, "ChatWindowFontSize", 5));
+ setChatWindowFontStyle(DBGetContactSettingDword(NULL, muccModuleName, "ChatWindowFontStyle", 0));
+ setChatWindowFontColor(DBGetContactSettingDword(NULL, muccModuleName, "ChatWindowFontColor", 0));
+}
+
+void Options::saveSettings() {
+ FontList::saveSettings();
+ DBWriteContactSettingDword(NULL, muccModuleName, "BackgroundLog", colorLogBg);
+ DBWriteContactSettingDword(NULL, muccModuleName, "BackgroundList", colorListBg);
+ DBWriteContactSettingDword(NULL, muccModuleName, "BackgroundTyping", colorInputBg);
+ DBWriteContactSettingDword(NULL, muccModuleName, "LogSizeLimit", logLimit);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatContainerOptions", chatContainerOptions);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatWindowOptions", chatWindowOptions);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatWindowFont", chatWindowFont);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatWindowFontSize", chatWindowFontSize);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatWindowFontStyle", chatWindowFontStyle);
+ DBWriteContactSettingDword(NULL, muccModuleName, "ChatWindowFontColor", chatWindowFontColor);
+}
+
+void Options::init()
+{
+ FontList::init();
+ loadSettings();
+}
+
+int MUCCOptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 0;
+ odp.hInstance = hInst;
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+// odp.pszTitle = muccModuleName;
+ odp.pszTitle = LPGEN("Tlen czaty");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = MUCCOptDlgProc;
+ odp.nIDBottomSimpleControl = 0;
+ Options_AddPage(wParam, &odp);
+
+ /*
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS_LOG);
+ _snprintf(str, sizeof(str), "%s %s", muccModuleName, Translate("Log"));
+ str[sizeof(str)-1] = '\0';
+ odp.pszTitle = str;
+ odp.pfnDlgProc = MUCCLLogOptDlgProc;
+ odp.flags = ODPF_BOLDGROUPS|ODPF_EXPERTONLY;
+ odp.nIDBottomSimpleControl = 0;
+ Options_AddPage(wParam, &odp);
+ if (ServiceExists(MS_POPUP_ADDPOPUP)) {
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszGroup = LPGEN("PopUps");
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS_POPUPS);
+ odp.pszTitle = jabberModuleName;
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = TlenPopupsDlgProc;
+ odp.nIDBottomSimpleControl = 0;
+ Options_AddPage(wParam, &odp);
+ }
+
+*/
+ return 0;
+}
+
+
+static int getOptions(HWND hTreeControl, HTREEITEM hItem, int flags) {
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.hItem = hItem;
+ TreeView_GetItem(hTreeControl, &tvi);
+ if ((tvi.state>>12) == 2) {
+ flags |= tvi.lParam;
+ } else {
+ flags &= ~tvi.lParam;
+ }
+ tvi.hItem = TreeView_GetChild(hTreeControl, hItem);
+ if (tvi.hItem != NULL) {
+ flags = getOptions(hTreeControl, tvi.hItem, flags);
+ }
+ tvi.hItem=TreeView_GetNextSibling(hTreeControl, hItem);
+ if (tvi.hItem != NULL) {
+ flags = getOptions(hTreeControl, tvi.hItem, flags);
+ }
+ return flags;
+
+}
+
+static int getExpandFlags(HWND hTreeControl) {
+ TVITEM tvi = {0};
+ int flags =0, mask = 1;
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.stateMask = TVIS_EXPANDED;
+ tvi.hItem = TreeView_GetRoot(hTreeControl);
+ while (tvi.hItem != NULL) {
+ TreeView_GetItem(hTreeControl, &tvi);
+ if (tvi.state & TVIS_EXPANDED) {
+ flags |= mask;
+ }
+ mask <<= 1;
+ tvi.hItem=TreeView_GetNextSibling(hTreeControl, tvi.hItem);
+ }
+ return flags;
+}
+
+
+static int addOption(HWND hTreeControl, HTREEITEM hParent, const char *text, int flag) {
+ TVINSERTSTRUCT tvis;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.hParent = hParent;
+ tvis.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
+ char* textA = Translate(text);
+ LPTSTR textT = Utils::mucc_mir_a2t(textA);
+ tvis.item.pszText = textT;
+ tvis.item.lParam = flag;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = Options::getChatWindowOptions() & flag ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1);
+ TreeView_InsertItem(hTreeControl, &tvis);
+ Utils::mucc_mir_free(textT);
+ return (Options::getChatWindowOptions() & flag) != 0;
+
+}
+
+static INT_PTR CALLBACK MUCCOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ char *pszText;
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TVINSERTSTRUCT tvis;
+ TVITEM tvi;
+ HWND hTreeControl;
+ HTREEITEM hItem;
+ int bCheckParent, expandFlags;
+
+ TranslateDialogDefault(hwndDlg);
+ Options::loadSettings();
+ for (i=0;i<Options::getFontNum();i++) {
+ SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_ADDSTRING, 0, i + 1);
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETSEL, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETCOLOUR, 0, Options::getFontSettings(0)->getColor());
+ SendDlgItemMessage(hwndDlg, IDC_COLORBKG, CPM_SETCOLOUR, 0, Options::getLogBgColor());
+ SendDlgItemMessage(hwndDlg, IDC_COLORLIST, CPM_SETCOLOUR, 0, Options::getListBgColor());
+ SendDlgItemMessage(hwndDlg, IDC_COLORINPUT, CPM_SETCOLOUR, 0, Options::getInputBgColor());
+ SendDlgItemMessage(hwndDlg, IDC_LOGLIMITSPIN, UDM_SETRANGE, 0, MAKELONG(1000,20));
+ SendDlgItemMessage(hwndDlg, IDC_LOGLIMITSPIN, UDM_SETPOS, 0, MAKELONG(Options::getLogLimit(), 0));
+
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_TREELIST),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_TREELIST),GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES);
+
+
+ hTreeControl = GetDlgItem(hwndDlg, IDC_TREELIST);
+ expandFlags = Options::getExpandFlags();
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM;
+ tvis.hParent = NULL;
+ tvis.item.lParam = 0;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+
+ tvis.item.pszText = TranslateT("Default Log Appearence");
+ hItem = TreeView_InsertItem(hTreeControl, &tvis);
+ bCheckParent = 1;
+ bCheckParent &= addOption(hTreeControl, hItem, "Show nicknames", ChatWindow::FLAG_SHOW_NICKNAMES);
+ bCheckParent &= addOption(hTreeControl, hItem, "Show message on a new line", ChatWindow::FLAG_MSGINNEWLINE);
+ tvi.state = (bCheckParent ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1));
+ tvi.hItem = hItem;
+ TreeView_SetItem(hTreeControl, &tvi);
+ if (expandFlags & 1) {
+ TreeView_Expand(hTreeControl, hItem, TVE_EXPAND);
+ }
+
+ tvis.item.pszText = TranslateT("Default Timestamp Settings");
+ hItem = TreeView_InsertItem(hTreeControl, &tvis);
+ bCheckParent = 1;
+ bCheckParent &= addOption(hTreeControl, hItem, "Show date", ChatWindow::FLAG_SHOW_DATE);
+ bCheckParent &= addOption(hTreeControl, hItem, "Show timestamp", ChatWindow::FLAG_SHOW_TIMESTAMP);
+ bCheckParent &= addOption(hTreeControl, hItem, "Show seconds", ChatWindow::FLAG_SHOW_SECONDS);
+ bCheckParent &= addOption(hTreeControl, hItem, "Use long date format", ChatWindow::FLAG_LONG_DATE);
+ tvi.state = (bCheckParent ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1));
+ tvi.hItem = hItem;
+ TreeView_SetItem(hTreeControl, &tvi);
+ if (expandFlags & 2) {
+ TreeView_Expand(hTreeControl, hItem, TVE_EXPAND);
+ }
+
+ tvis.item.pszText = TranslateT("Default Text Formatting Filter");
+ hItem = TreeView_InsertItem(hTreeControl, &tvis);
+ bCheckParent = 1;
+ bCheckParent &= addOption(hTreeControl, hItem, "Font name", ChatWindow::FLAG_FORMAT_FONT);
+ bCheckParent &= addOption(hTreeControl, hItem, "Font size", ChatWindow::FLAG_FORMAT_SIZE);
+ bCheckParent &= addOption(hTreeControl, hItem, "Font style", ChatWindow::FLAG_FORMAT_STYLE);
+ bCheckParent &= addOption(hTreeControl, hItem, "Font color", ChatWindow::FLAG_FORMAT_COLOR);
+ tvi.state = (bCheckParent ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1));
+ tvi.hItem = hItem;
+ TreeView_SetItem(hTreeControl, &tvi);
+ if (expandFlags & 4) {
+ TreeView_Expand(hTreeControl, hItem, TVE_EXPAND);
+ }
+
+ tvis.item.pszText = TranslateT("Default Event Filter");
+ hItem = TreeView_InsertItem(hTreeControl, &tvis);
+ bCheckParent = 1;
+ bCheckParent &= addOption(hTreeControl, hItem, "Messages", ChatWindow::FLAG_LOG_MESSAGES);
+ bCheckParent &= addOption(hTreeControl, hItem, "User has joined", ChatWindow::FLAG_LOG_JOINED);
+ bCheckParent &= addOption(hTreeControl, hItem, "User has left", ChatWindow::FLAG_LOG_LEFT);
+ bCheckParent &= addOption(hTreeControl, hItem, "Topic changes", ChatWindow::FLAG_LOG_TOPIC);
+ tvi.state = (bCheckParent ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1));
+ tvi.hItem = hItem;
+ TreeView_SetItem(hTreeControl, &tvi);
+ if (expandFlags & 8) {
+ TreeView_Expand(hTreeControl, hItem, TVE_EXPAND);
+ }
+
+ tvis.item.pszText = TranslateT("Default Window Flashing");
+ hItem = TreeView_InsertItem(hTreeControl, &tvis);
+ bCheckParent = 1;
+ bCheckParent &= addOption(hTreeControl, hItem, "Messages", ChatWindow::FLAG_FLASH_MESSAGES);
+ bCheckParent &= addOption(hTreeControl, hItem, "User has joined", ChatWindow::FLAG_FLASH_JOINED);
+ bCheckParent &= addOption(hTreeControl, hItem, "User has left", ChatWindow::FLAG_FLASH_LEFT);
+ bCheckParent &= addOption(hTreeControl, hItem, "Topic changes", ChatWindow::FLAG_FLASH_TOPIC);
+ tvi.state = (bCheckParent ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1));
+ tvi.hItem = hItem;
+ TreeView_SetItem(hTreeControl, &tvi);
+ if (expandFlags & 16) {
+ TreeView_Expand(hTreeControl, hItem, TVE_EXPAND);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_SENDONENTER, Options::getChatWindowOptions() & ChatWindow::FLAG_OPT_SENDONENTER);
+ CheckDlgButton(hwndDlg, IDC_ENABLEIEVIEW, Options::getChatWindowOptions() & ChatWindow::FLAG_OPT_ENABLEIEVIEW);
+ if (!ServiceExists(MS_IEVIEW_WINDOW)) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEIEVIEW), FALSE);
+ }
+ CheckDlgButton(hwndDlg, IDC_USETABS, Options::getChatContainerOptions() & ChatContainer::FLAG_USE_TABS);
+
+ }
+ case WM_MEASUREITEM:
+ if (wParam == IDC_FONTLIST) {
+ MEASUREITEMSTRUCT *lpMis = (MEASUREITEMSTRUCT *) lParam;
+ HFONT hFont, hoFont;
+ HDC hDC;
+ SIZE fontSize;
+ int iItem = lpMis->itemData - 1;
+ Font *font = Options::getFontSettings(iItem);
+ if (font != NULL) {
+
+ LPTSTR lps1 = Utils::mucc_mir_a2t(font->getFace());
+ hFont = CreateFont(font->getSize(), 0, 0, 0,
+ font->getStyle() & Font::BOLD ? FW_BOLD : FW_NORMAL,
+ font->getStyle() & Font::ITALIC ? 1 : 0, 0, 0,
+ font->getCharSet(),
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, lps1);
+ Utils::mucc_mir_free(lps1);
+
+ hDC = GetDC(GetDlgItem(hwndDlg, lpMis->CtlID));
+ hoFont = (HFONT) SelectObject(hDC, hFont);
+ pszText = Translate(Options::getFontSettings(iItem)->getName());
+ LPTSTR pszTextT1 = Utils::mucc_mir_a2t(pszText);
+ GetTextExtentPoint32(hDC, pszTextT1, lstrlen(pszTextT1), &fontSize);
+ Utils::mucc_mir_free(pszTextT1);
+ SelectObject(hDC, hoFont);
+ ReleaseDC(GetDlgItem(hwndDlg, lpMis->CtlID), hDC);
+ DeleteObject(hFont);
+ lpMis->itemWidth = fontSize.cx;
+ lpMis->itemHeight = fontSize.cy;
+ return TRUE;
+ }
+ break;
+ }
+ case WM_DRAWITEM:
+ if (wParam == IDC_FONTLIST) {
+ DRAWITEMSTRUCT *lpDis = (DRAWITEMSTRUCT *) lParam;
+ HFONT hFont;
+ HBRUSH hBrush;
+ int iItem = lpDis->itemData - 1;
+ Font *font = Options::getFontSettings(iItem);
+ if (font != NULL) {
+ COLORREF color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORBKG, CPM_GETCOLOUR, 0, 0);
+ if (iItem == Options::FONT_USERLIST || iItem == Options::FONT_USERLISTGROUP) {
+ color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORLIST, CPM_GETCOLOUR, 0, 0);
+ } else if (iItem == Options::FONT_TYPING) {
+ color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORINPUT, CPM_GETCOLOUR, 0, 0);
+ }
+ hBrush = CreateSolidBrush(color);
+
+ LPTSTR lps2 = Utils::mucc_mir_a2t(font->getFace());
+ hFont = CreateFont(font->getSize(), 0, 0, 0,
+ font->getStyle() & Font::BOLD ? FW_BOLD : FW_NORMAL,
+ font->getStyle() & Font::ITALIC ? 1 : 0,
+ font->getStyle() & Font::UNDERLINE ? 1 : 0, 0,
+ font->getCharSet(),
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
+ lps2);
+ Utils::mucc_mir_free(lps2);
+
+ hFont = (HFONT) SelectObject(lpDis->hDC, hFont);
+ SetBkMode(lpDis->hDC, TRANSPARENT);
+ FillRect(lpDis->hDC, &lpDis->rcItem, hBrush);
+ if (lpDis->itemState & ODS_SELECTED) {
+ FrameRect(lpDis->hDC, &lpDis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+ SetTextColor(lpDis->hDC, font->getColor());
+ pszText = Translate(font->getName());
+ LPTSTR pszTextT2 = Utils::mucc_mir_a2t(pszText);
+ TextOut(lpDis->hDC, lpDis->rcItem.left, lpDis->rcItem.top, pszTextT2, lstrlen(pszTextT2));
+ Utils::mucc_mir_free(pszTextT2);
+ hFont = (HFONT) SelectObject(lpDis->hDC, hFont);
+ DeleteObject(hBrush);
+ DeleteObject(hFont);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_COLORTXT:
+ {
+ int totalCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCOUNT, 0, 0);
+ int *selItems= new int[totalCount];
+ int selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, totalCount, (LPARAM) selItems);
+ COLORREF color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_GETCOLOUR, 0, 0);
+ for (int i=0; i<selCount; i++) {
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[i], 0) - 1;
+ Font *font = Options::getFontSettings(iItem);
+ if (font != NULL) {
+ font->setColor(color);
+ }
+ }
+ delete selItems;
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, FALSE);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+ case IDC_LOGLIMIT:
+ if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {
+ i = GetDlgItemInt(hwndDlg, IDC_LOGLIMIT, NULL, FALSE);
+ // if (i>1000) {
+ // i = 1000;
+ // SetDlgItemInt(hwndDlg, IDC_LOGLIMIT, i, FALSE);
+ // }
+ if (i != Options::getLogLimit()) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case IDC_COLORBKG:
+ case IDC_COLORLIST:
+ case IDC_COLORINPUT:
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, FALSE);
+ case IDC_SENDONENTER:
+ case IDC_USETABS:
+ case IDC_ENABLEIEVIEW:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case IDC_FONTLIST:
+ if (HIWORD(wParam) == LBN_SELCHANGE) {
+ if (SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELCOUNT, 0, 0) > 1) {
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETCOLOUR, 0, GetSysColor(COLOR_3DFACE));
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT));
+ }
+ else {
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), 0) - 1;
+ Font *font = Options::getFontSettings(iItem);
+ if (font != NULL) {
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETCOLOUR, 0, font->getColor());
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETDEFAULTCOLOUR, 0, font->getColor());
+ }
+ }
+ }
+ if (HIWORD(wParam) != LBN_DBLCLK) {
+ return TRUE;
+ }
+ case IDC_CHOOSEFONT:
+ {
+ CHOOSEFONT cf;
+ LOGFONT lf;
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), 0) - 1;
+ ZeroMemory(&cf, sizeof(cf));
+ ZeroMemory(&lf, sizeof(lf));
+ Font *font = Options::getFontSettings(iItem);
+ if (font != NULL) {
+ lf.lfHeight = font->getSize();
+ lf.lfWeight = font->getStyle() & Font::BOLD ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = font->getStyle() & Font::ITALIC ? 1 : 0;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ LPTSTR lps3 = Utils::mucc_mir_a2t(font->getFace());
+ lstrcpy(lf.lfFaceName, lps3);
+ Utils::mucc_mir_free(lps3);
+ cf.lStructSize = sizeof(cf);
+ cf.hwndOwner = hwndDlg;
+ cf.lpLogFont = &lf;
+ cf.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
+ if (ChooseFont(&cf)) {
+ int totalCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCOUNT, 0, 0);
+ int *selItems= new int[totalCount];
+ int selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, totalCount, (LPARAM) selItems);
+ for (int i=0; i<selCount; i++) {
+ int iItem = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[i], 0) - 1;
+ Font *font2 = Options::getFontSettings(iItem);
+ if (font2 != NULL) {
+ font2->setStyle((lf.lfWeight >= FW_BOLD ? Font::BOLD : 0) | (lf.lfItalic ? Font::ITALIC : 0));
+ font2->setCharSet(lf.lfCharSet);
+ font2->setSize(lf.lfHeight);
+ char* lps4 = Utils::mucc_mir_t2a(lf.lfFaceName);
+ font2->setFace(lps4);
+ Utils::mucc_mir_free(lps4);
+ MEASUREITEMSTRUCT mis;
+ ZeroMemory(&mis, sizeof(mis));
+ mis.CtlID = IDC_FONTLIST;
+ mis.itemData = iItem + 1;
+ SendMessage(hwndDlg, WM_MEASUREITEM, (WPARAM)IDC_FONTLIST, (LPARAM) & mis);
+ SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETITEMHEIGHT, selItems[i], mis.itemHeight);
+ }
+ }
+ delete selItems;
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, TRUE);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ Options::setExpandFlags(getExpandFlags(GetDlgItem(hwndDlg, IDC_TREELIST)));
+ break;
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ COLORREF color;
+ color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORLIST, CPM_GETCOLOUR, 0, 0);
+ Options::setListBgColor(color);
+ color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORINPUT, CPM_GETCOLOUR, 0, 0);
+ Options::setInputBgColor(color);
+ color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_COLORBKG, CPM_GETCOLOUR, 0, 0);
+ Options::setLogBgColor(color);
+ Options::setLogLimit(SendDlgItemMessage(hwndDlg, IDC_LOGLIMITSPIN, UDM_GETPOS, 0, 0));
+ Options::setChatWindowOptions(getOptions(GetDlgItem(hwndDlg, IDC_TREELIST), TreeView_GetRoot(GetDlgItem(hwndDlg, IDC_TREELIST)), 0));
+ Options::setChatWindowOptions(Options::getChatWindowOptions() | (IsDlgButtonChecked(hwndDlg, IDC_SENDONENTER) ? ChatWindow::FLAG_OPT_SENDONENTER : 0));
+ Options::setChatWindowOptions(Options::getChatWindowOptions() | (IsDlgButtonChecked(hwndDlg, IDC_ENABLEIEVIEW) ? ChatWindow::FLAG_OPT_ENABLEIEVIEW : 0));
+ Options::setChatContainerOptions(IsDlgButtonChecked(hwndDlg, IDC_USETABS) ? ChatContainer::FLAG_USE_TABS : 0);
+ Options::saveSettings();
+ ChatWindow::refreshSettings(1);
+ break;
+ case NM_CLICK:
+ /* Handle checking/unchecking options here - update children and parent appropriately */
+ if (((LPNMHDR)lParam)->idFrom == IDC_TREELIST) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom, &hti.pt);
+ if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti)) {
+ if (hti.flags&TVHT_ONITEMSTATEICON) {
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+ tvi.state ^= INDEXTOSTATEIMAGEMASK(3);
+ tvi.hItem = TreeView_GetChild(((LPNMHDR)lParam)->hwndFrom, hti.hItem);
+ if (tvi.hItem != NULL) {
+ while (tvi.hItem != NULL) {
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+ tvi.hItem=TreeView_GetNextSibling(((LPNMHDR)lParam)->hwndFrom, tvi.hItem);
+ }
+ } else {
+ HTREEITEM hParent = TreeView_GetParent(((LPNMHDR)lParam)->hwndFrom, hti.hItem);
+ if (hParent != NULL) {
+ if ((tvi.state>>12) == 2) {
+ tvi.hItem = TreeView_GetNextSibling(((LPNMHDR)lParam)->hwndFrom, hti.hItem);
+ while (tvi.hItem != NULL) {
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+ if ((tvi.state>>12) != 2) {
+ break;
+ }
+ tvi.hItem = TreeView_GetNextSibling(((LPNMHDR)lParam)->hwndFrom, tvi.hItem);
+ }
+ if ((tvi.state>>12) == 2) {
+ tvi.hItem = TreeView_GetPrevSibling(((LPNMHDR)lParam)->hwndFrom, hti.hItem);
+ while (tvi.hItem != NULL) {
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+ if ((tvi.state>>12) != 2) {
+ break;
+ }
+ tvi.hItem = TreeView_GetPrevSibling(((LPNMHDR)lParam)->hwndFrom, tvi.hItem);
+ }
+ }
+ }
+ tvi.hItem = hParent;
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/*
+#define POPUP_DEFAULT_COLORBKG 0xDCBDA5
+#define POPUP_DEFAULT_COLORTXT 0x000000
+static void MailPopupPreview(DWORD colorBack, DWORD colorText, char *title, char *emailInfo, int delay)
+{
+ POPUPDATAEX ppd;
+ char * lpzContactName;
+ char * lpzText;
+
+ lpzContactName = title;
+ lpzText = emailInfo;
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = NULL;
+ ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIL));
+ lstrcpy(ppd.lpzContactName, lpzContactName);
+ lstrcpy(ppd.lpzText, lpzText);
+ ppd.colorBack = colorBack;
+ ppd.colorText = colorText;
+ ppd.PluginWindowProc = NULL;
+ ppd.PluginData=NULL;
+ if ( ServiceExists( MS_POPUP_ADDPOPUPEX )) {
+ ppd.iSeconds = delay;
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+
+ }
+ else if ( ServiceExists( MS_POPUP_ADDPOPUP )) {
+ CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0);
+ }
+}
+*/
+//static INT_PTR CALLBACK MUCCPopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+//{
+ /*
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ BYTE delayMode;
+ CheckDlgButton(hwndDlg, IDC_ENABLEPOPUP, DBGetContactSettingByte(NULL, jabberProtoName, "MailPopupEnabled", TRUE));
+ SendDlgItemMessage(hwndDlg, IDC_COLORBKG, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, jabberProtoName, "MailPopupBack", POPUP_DEFAULT_COLORBKG));
+ SendDlgItemMessage(hwndDlg, IDC_COLORTXT, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, jabberProtoName, "MailPopupText", POPUP_DEFAULT_COLORTXT));
+ SetDlgItemInt(hwndDlg, IDC_DELAY, DBGetContactSettingDword(NULL, jabberProtoName, "MailPopupDelay", 4), FALSE);
+ delayMode = DBGetContactSettingByte(NULL, jabberProtoName, "MailPopupDelayMode", 0);
+ if (delayMode == 1) {
+ CheckDlgButton(hwndDlg, IDC_DELAY_CUSTOM, TRUE);
+ } else if (delayMode == 2) {
+ CheckDlgButton(hwndDlg, IDC_DELAY_PERMANENT, TRUE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_DELAY_POPUP, TRUE);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_COLORTXT:
+ case IDC_COLORBKG:
+ case IDC_ENABLEPOPUP:
+ case IDC_DELAY:
+ case IDC_DELAY_POPUP:
+ case IDC_DELAY_CUSTOM:
+ case IDC_DELAY_PERMANENT:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case IDC_PREVIEW:
+ {
+ int delay;
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_POPUP)) {
+ delay=0;
+ } else if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_PERMANENT)) {
+ delay=-1;
+ } else {
+ delay=GetDlgItemInt(hwndDlg, IDC_DELAY, NULL, FALSE);
+ }
+ MailPopupPreview((DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORBKG,CPM_GETCOLOUR,0,0),
+ (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORTXT,CPM_GETCOLOUR,0,0),
+ "New mail",
+ "From: test@test.test\nSubject: test",
+ delay);
+ }
+
+ }
+ break;
+
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ BYTE delayMode;
+ DBWriteContactSettingByte(NULL, jabberProtoName, "MailPopupEnabled", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ENABLEPOPUP));
+ DBWriteContactSettingDword(NULL, jabberProtoName, "MailPopupBack", (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORBKG,CPM_GETCOLOUR,0,0));
+ DBWriteContactSettingDword(NULL, jabberProtoName, "MailPopupText", (DWORD) SendDlgItemMessage(hwndDlg,IDC_COLORTXT,CPM_GETCOLOUR,0,0));
+ DBWriteContactSettingDword(NULL, jabberProtoName, "MailPopupDelay", (DWORD) GetDlgItemInt(hwndDlg,IDC_DELAY, NULL, FALSE));
+ delayMode=0;
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_CUSTOM)) {
+ delayMode=1;
+ } else if (IsDlgButtonChecked(hwndDlg, IDC_DELAY_PERMANENT)) {
+ delayMode=2;
+
+ }
+ DBWriteContactSettingByte(NULL, jabberProtoName, "MailPopupDelayMode", delayMode);
+ return TRUE;
+ }
+ }
+ break;
+
+ }*/
+// return FALSE;
+//}
+
diff --git a/protocols/Tlen/tlen_czaty/src/Options.h b/protocols/Tlen/tlen_czaty/src/Options.h
new file mode 100644
index 0000000000..e8eb79dab5
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/Options.h
@@ -0,0 +1,75 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef OPTIONS_INCLUDED
+#define OPTIONS_INCLUDED
+#include "FontList.h"
+#include "mucc.h"
+
+extern int MUCCOptInit(WPARAM wParam, LPARAM lParam);
+
+class Options:public FontList {
+private:
+ static COLORREF colorInputBg;
+ static COLORREF colorLogBg;
+ static COLORREF colorListBg;
+ static HBRUSH brushInputBg;
+ static HBRUSH brushLogBg;
+ static HBRUSH brushListBg;
+ static int logLimit;
+ static int chatContainerOptions;
+ static int chatWindowOptions;
+ static COLORREF chatWindowFontColor;
+ static int chatWindowFont;
+ static int chatWindowFontSize;
+ static int chatWindowFontStyle;
+public:
+ static void setListBgColor(COLORREF c);
+ static void setLogBgColor(COLORREF c);
+ static void setInputBgColor(COLORREF c);
+ static COLORREF getListBgColor();
+ static COLORREF getLogBgColor();
+ static COLORREF getInputBgColor();
+ static HBRUSH getListBgBrush();
+ static HBRUSH getInputBgBrush();
+ static HBRUSH getLogBgBrush();
+ static void setLogLimit(int l);
+ static int getLogLimit();
+ static void setChatContainerOptions(int o);
+ static int getChatContainerOptions();
+ static void setChatWindowOptions(int o);
+ static int getChatWindowOptions();
+ static void setChatWindowFontColor(COLORREF o);
+ static COLORREF getChatWindowFontColor();
+ static void setChatWindowFont(int o);
+ static int getChatWindowFont();
+ static void setChatWindowFontSize(int o);
+ static int getChatWindowFontSize();
+ static void setChatWindowFontStyle(int o);
+ static int getChatWindowFontStyle();
+ static void setExpandFlags(int l);
+ static int getExpandFlags();
+ static void init();
+ static void loadSettings();
+ static void saveSettings();
+
+};
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/Utils.cpp b/protocols/Tlen/tlen_czaty/src/Utils.cpp
new file mode 100644
index 0000000000..37c99a8e07
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/Utils.cpp
@@ -0,0 +1,138 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "Utils.h"
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void (__cdecl *threadcode)(void*);
+ void *arg;
+};
+
+static void __cdecl forkthread_r(struct FORK_ARG *fa)
+{
+ void (*callercode)(void*) = fa->threadcode;
+ void *arg = fa->arg;
+ Thread_Push(0);
+ SetEvent(fa->hEvent);
+ callercode(arg);
+ Thread_Pop();
+ return;
+}
+
+unsigned long Utils::forkThread(void (__cdecl *threadcode)(void*), unsigned long stacksize, void *arg) {
+
+ unsigned long rc;
+ struct FORK_ARG fa;
+
+ fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+ rc = _beginthread((void (__cdecl *)(void*))forkthread_r, stacksize, &fa);
+ if ((unsigned long) -1L != rc) {
+ WaitForSingleObject(fa.hEvent, INFINITE);
+ }
+ CloseHandle(fa.hEvent);
+ return rc;
+}
+
+void Utils::copyString(char **a, const char *b) {
+ char *oldA;
+ char *newA;
+ oldA = *a;
+ if (b != NULL) {
+ newA = new char[strlen(b)+1];
+ strcpy(newA, b);
+ } else {
+ newA = NULL;
+ }
+ *a = newA;
+ if (oldA != NULL) {
+ delete oldA;
+ }
+
+}
+
+
+
+//MM_INTERFACE Utils::mmi;
+
+void Utils::mucc_mir_free(void* ptr)
+{
+ mir_free(ptr);
+}
+
+char* Utils::mucc_mir_t2a(LPCTSTR src)
+{
+ return mir_t2a(src);
+}
+
+LPTSTR Utils::mucc_mir_a2t(const char* src)
+{
+ return mir_a2t(src);
+}
+
+
+
+void Utils::log(const char *fmt, ...)
+{
+#ifdef ENABLE_LOGGING
+ char *str;
+ va_list vararg;
+ int strsize;
+ char *text;
+ char *p, *q;
+ int extra;
+
+ va_start(vararg, fmt);
+ str = (char *) malloc(strsize=2048);
+ while (_vsnprintf(str, strsize, fmt, vararg) == -1)
+ str = (char *) realloc(str, strsize+=2048);
+ va_end(vararg);
+
+ extra = 0;
+ for (p=str; *p != '\0'; p++)
+ if (*p == '\n' || *p == '\r')
+ extra++;
+ text = (char *) malloc(strlen(muccModuleName)+2+strlen(str)+2+extra);
+ wsprintf(text, "[%s]", muccModuleName);
+ for (p=str,q=text+strlen(text); *p != '\0'; p++,q++) {
+ if (*p == '\r') {
+ *q = '\\';
+ *(q+1) = 'r';
+ q++;
+ }
+ else if (*p == '\n') {
+ *q = '\\';
+ *(q+1) = 'n';
+ q++;
+ }
+ else
+ *q = *p;
+ }
+ *q = '\n';
+ *(q+1) = '\0';
+// CallService(MS_NETLIB_LOG, (WPARAM) NULL, (LPARAM) text);
+ //OutputDebugString(text);
+ free(text);
+ free(str);
+#endif
+}
+
diff --git a/protocols/Tlen/tlen_czaty/src/Utils.h b/protocols/Tlen/tlen_czaty/src/Utils.h
new file mode 100644
index 0000000000..a9f0777145
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/Utils.h
@@ -0,0 +1,38 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef UTILS_INCLUDED
+#define UTILS_INCLUDED
+#include "mucc.h"
+
+class Utils {
+public:
+ static unsigned long forkThread(void (__cdecl *threadcode)(void*),unsigned long stacksize,void *arg);
+ static void copyString(char **, const char *b);
+ static void log(const char *fmt, ...);
+
+// static MM_INTERFACE mmi;
+ static void mucc_mir_free(void*);
+ static char* mucc_mir_t2a(LPCTSTR);
+ static LPTSTR mucc_mir_a2t(const char* );
+
+};
+
+#endif
diff --git a/protocols/Tlen/tlen_czaty/src/mucc.cpp b/protocols/Tlen/tlen_czaty/src/mucc.cpp
new file mode 100644
index 0000000000..cca6980691
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/mucc.cpp
@@ -0,0 +1,166 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "../../src/commons.h"
+#include "mucc.h"
+#include "mucc_services.h"
+#include "HelperDialog.h"
+#include "Options.h"
+#include "Utils.h"
+
+char *muccModuleName;
+HINSTANCE hInst;
+HANDLE hHookEvent = NULL;
+HIMAGELIST hImageList = NULL;
+HICON muccIcon[MUCC_ICON_TOTAL];
+int hLangpack;
+static int ModulesLoaded(WPARAM wParam, LPARAM lParam);
+static int PreShutdown(WPARAM wParam, LPARAM lParam);
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ "Tlen Czaty",
+ PLUGIN_MAKE_VERSION(MUCC_MAJOR_VERSION,MUCC_MINOR_VERSION,MUCC_RELEASE_NUM,MUCC_BUILD_NUM),
+ "Group chats GUI plugin for Miranda NG (formerly known as mucc.dll) (version: " MUCC_VERSION_STRING ")",
+ "Piotr Piastucki",
+ "the_leech@users.berlios.de",
+ "(c) 2004-2012 Piotr Piastucki",
+ "http://miranda-ng.org/",
+ UNICODE_AWARE,
+ {0xadd9390c, 0x1dd4, 0x4c0d, { 0x9b, 0xa9, 0xcc, 0x76, 0x5d, 0x3d, 0xe5, 0x97 }}
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved)
+{
+ hInst = hModule;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+#ifndef MIID_TLEN_MUCC
+#define MIID_TLEN_MUCC { 0xba658997, 0x0bce, 0x4f96, { 0xba, 0x48, 0x54, 0x55, 0x34, 0x16, 0x73, 0xea } }
+#endif
+
+extern "C" __declspec(dllexport) const MUUID interfaces[] = {
+ MIID_TLEN_MUCC,
+ MIID_LAST
+ };
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+static void LoadIcons() {
+ int i;
+ static int iconList[] = {
+ IDI_CHAT,
+ IDI_GLOBALOWNER,
+ IDI_OWNER,
+ IDI_ADMIN,
+ IDI_REGISTERED,
+ IDI_R_MODERATED,
+ IDI_R_MEMBERS,
+ IDI_R_ANONYMOUS,
+ IDI_PREV,
+ IDI_NEXT,
+ IDI_SEARCH,
+ IDI_BOLD,
+ IDI_ITALIC,
+ IDI_UNDERLINE,
+ IDI_OPTIONS,
+ IDI_INVITE,
+ IDI_ADMINISTRATION,
+ IDI_SMILEY,
+ IDI_MESSAGE
+
+ };
+ for (i=0; i<MUCC_ICON_TOTAL; i++) {
+ muccIcon[i] = (HICON) LoadImage(hInst, MAKEINTRESOURCE(iconList[i]), IMAGE_ICON, 0, 0, 0);
+ }
+ if (hImageList != NULL) {
+ ImageList_Destroy(hImageList);
+ }
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,0,3);
+// ImageList_AddIcon(hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_BLANK)));
+// ImageList_AddIcon(hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_BLANK)));
+ ImageList_AddIcon(hImageList, muccIcon[MUCC_IDI_MESSAGE]);
+
+}
+
+extern "C" int __declspec(dllexport) Load(void/*PLUGINLINK *link*/)
+{
+// char text[_MAX_PATH];
+// char *p, *q;
+// GetModuleFileNameA(hInst, text, sizeof(text));
+// p = strrchr(text, '\\');
+// p++;
+// q = strrchr(p, '.');
+// *q = '\0';
+// muccModuleName = _strdup(p);
+// _strupr(muccModuleName);
+
+ muccModuleName = "MUCC";
+
+ //pluginLink = link;
+ HookEvent(ME_OPT_INITIALISE, MUCCOptInit);
+ HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown);
+
+ CreateServiceFunction(MS_MUCC_QUERY_RESULT, MUCCQueryResult);
+ CreateServiceFunction(MS_MUCC_NEW_WINDOW, MUCCNewWindow);
+ CreateServiceFunction(MS_MUCC_EVENT, MUCCEvent);
+ hHookEvent = CreateHookableEvent(ME_MUCC_EVENT);
+
+ mir_getLP(&pluginInfoEx);
+
+ LoadIcons();
+ return 0;
+}
+
+static int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ Options::init();
+ HelperDialog::init();
+ ManagerWindow::init();
+ ChatWindow::init();
+ ChatContainer::init();
+ return 0;
+}
+
+static int PreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ ChatContainer::release();
+ ChatWindow::release();
+ ManagerWindow::release();
+ HelperDialog::release();
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
diff --git a/protocols/Tlen/tlen_czaty/src/mucc.h b/protocols/Tlen/tlen_czaty/src/mucc.h
new file mode 100644
index 0000000000..efb048d7ce
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/mucc.h
@@ -0,0 +1,106 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef MUCC_INCLUDED
+#define MUCC_INCLUDED
+
+//#define ENABLE_LOGGING
+
+#define _WIN32_WINNT 0x0501
+#define _WIN32_IE 0x0500
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <limits.h>
+
+#ifdef __MINGW32__
+#define EM_SETTEXTEX (WM_USER + 97)
+#define ST_DEFAULT 0
+#define ST_KEEPUNDO 1
+#define ST_SELECTION 2
+#define ST_NEWCHARS 4
+#else
+#include <win2k.h>
+#endif
+
+#define MIRANDA_VER 0x0A00
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_userinfo.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_utils.h>
+#include <m_message.h>
+#include <m_skin.h>
+#include <m_popup.h>
+#include <m_button.h>
+
+#include "resource.h"
+
+enum {
+ MUCC_IDI_CHAT = 0,
+ MUCC_IDI_U_GLOBALOWNER,
+ MUCC_IDI_U_OWNER,
+ MUCC_IDI_U_ADMIN,
+ MUCC_IDI_U_REGISTERED,
+ MUCC_IDI_R_MODERATED,
+ MUCC_IDI_R_MEMBERS,
+ MUCC_IDI_R_ANONYMOUS,
+ MUCC_IDI_PREV,
+ MUCC_IDI_NEXT,
+ MUCC_IDI_SEARCH,
+ MUCC_IDI_BOLD,
+ MUCC_IDI_ITALIC,
+ MUCC_IDI_UNDERLINE,
+ MUCC_IDI_OPTIONS,
+ MUCC_IDI_INVITE,
+ MUCC_IDI_ADMINISTRATION,
+ MUCC_IDI_SMILEY,
+ MUCC_IDI_MESSAGE,
+ MUCC_ICON_TOTAL
+
+};
+
+//extern PLUGINLINK * pluginLink;
+extern char *muccModuleName;
+extern HINSTANCE hInst;
+extern HANDLE hHookEvent;
+extern HIMAGELIST hImageList;
+extern HICON muccIcon[MUCC_ICON_TOTAL];
+
+#include "m_mucc.h"
+
+#define WM_MUCC_REFRESH_ROOMS (WM_USER+101)
+#define WM_MUCC_REFRESH_USER_ROOMS (WM_USER+102)
+#define WM_MUCC_REFRESH_USER_NICKS (WM_USER+103)
+
+#endif
+
diff --git a/protocols/Tlen/tlen_czaty/src/mucc_services.cpp b/protocols/Tlen/tlen_czaty/src/mucc_services.cpp
new file mode 100644
index 0000000000..fd890dc763
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/mucc_services.cpp
@@ -0,0 +1,140 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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 "mucc_services.h"
+#include "Utils.h"
+#include "HelperDialog.h"
+
+int MUCCQueryChatGroups(MUCCQUERYRESULT *queryResult)
+{
+ ManagerWindow *managerWnd=ManagerWindow::getWindow(queryResult->pszModule);
+ if (managerWnd != NULL) {
+ managerWnd->queryResultGroups(queryResult);
+ }
+ return 1;
+}
+
+int MUCCQueryChatRooms(MUCCQUERYRESULT *queryResult)
+{
+ ManagerWindow *managerWnd=ManagerWindow::getWindow(queryResult->pszModule);
+ if (managerWnd != NULL) {
+ managerWnd->queryResultRooms(queryResult);
+ }
+ return 1;
+}
+
+int MUCCQueryUserRooms(MUCCQUERYRESULT *queryResult)
+{
+ ManagerWindow *managerWnd=ManagerWindow::getWindow(queryResult->pszModule);
+ if (managerWnd != NULL) {
+ managerWnd->queryResultUserRooms(queryResult);
+ }
+ return 1;
+}
+
+int MUCCQueryUserNicks(MUCCQUERYRESULT *queryResult)
+{
+ ManagerWindow *managerWnd=ManagerWindow::getWindow(queryResult->pszModule);
+ if (managerWnd != NULL) {
+ managerWnd->queryResultUserNick(queryResult);
+ }
+ return 1;
+}
+
+INT_PTR MUCCQueryResult(WPARAM wParam, LPARAM lParam)
+{
+ MUCCQUERYRESULT *queryResult=(MUCCQUERYRESULT *)lParam;
+ ChatWindow * chatWindow = NULL;
+ switch (queryResult->iType) {
+ case MUCC_EVENT_QUERY_GROUPS:
+ MUCCQueryChatGroups(queryResult);
+ break;
+ case MUCC_EVENT_QUERY_ROOMS:
+ MUCCQueryChatRooms(queryResult);
+ break;
+ case MUCC_EVENT_QUERY_USER_ROOMS:
+ MUCCQueryUserRooms(queryResult);
+ break;
+ case MUCC_EVENT_QUERY_USER_NICKS:
+ MUCCQueryUserNicks(queryResult);
+ break;
+ case MUCC_EVENT_QUERY_CONTACTS:
+ case MUCC_EVENT_QUERY_USERS:
+ chatWindow=ChatWindow::getWindow(queryResult->pszModule, queryResult->pszParent);
+ if (chatWindow != NULL) {
+ SendMessage(chatWindow->getHWND(), DM_CHAT_QUERY, (WPARAM) 0, (LPARAM) queryResult);
+ }
+ break;
+ }
+ return 0;
+}
+
+INT_PTR MUCCNewWindow(WPARAM wParam, LPARAM lParam)
+{
+ MUCCWINDOW *mucWindow = (MUCCWINDOW *) lParam;
+ if (mucWindow->iType == MUCC_WINDOW_CHATROOM) {
+ ChatWindow *chat = ChatWindow::getWindow(mucWindow->pszModule, mucWindow->pszID);
+ if (chat == NULL) {
+ chat = new ChatWindow(mucWindow);
+ }
+ } else if (mucWindow->iType == MUCC_WINDOW_CHATLIST) {
+ ManagerWindow *manager = ManagerWindow::getWindow(mucWindow->pszModule);
+ if (manager == NULL) {
+
+ }
+ //Utils::log("setting name: %s", mucWindow->pszModuleName);
+ manager->setModuleName(mucWindow->pszModuleName);
+ manager->start();
+ }
+ return 0;
+}
+
+INT_PTR MUCCEvent(WPARAM wParam, LPARAM lParam)
+{
+ MUCCEVENT* mucEvent = (MUCCEVENT *) lParam;
+ ChatWindow * chatWindow = NULL;
+ switch (mucEvent->iType) {
+ case MUCC_EVENT_STATUS:
+ case MUCC_EVENT_MESSAGE:
+ case MUCC_EVENT_ROOM_INFO:
+ case MUCC_EVENT_LEAVE:
+ case MUCC_EVENT_TOPIC:
+ chatWindow = ChatWindow::getWindow(mucEvent->pszModule, mucEvent->pszID);
+ if (chatWindow != NULL) {
+ SendMessage(chatWindow->getHWND(), DM_CHAT_EVENT, (WPARAM) 0, (LPARAM) mucEvent);
+ }
+ break;
+ case MUCC_EVENT_ERROR:
+ chatWindow = ChatWindow::getWindow(mucEvent->pszModule, mucEvent->pszID);
+ if (chatWindow != NULL) {
+ SendMessage(chatWindow->getHWND(), DM_CHAT_EVENT, (WPARAM) 0, (LPARAM) mucEvent);
+ } else {
+ HelperDialog::errorDlg(mucEvent);
+ }
+ break;
+ case MUCC_EVENT_INVITATION:
+ HelperDialog::acceptDlg(mucEvent);
+ break;
+ case MUCC_EVENT_JOIN:
+ HelperDialog::joinDlg(mucEvent);
+ break;
+ }
+ return 0;
+}
diff --git a/protocols/Tlen/tlen_czaty/src/mucc_services.h b/protocols/Tlen/tlen_czaty/src/mucc_services.h
new file mode 100644
index 0000000000..6829203aea
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/mucc_services.h
@@ -0,0 +1,35 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#ifndef MUCCSERVICES_INCLUDED
+#define MUCCSERVICES_INCLUDED
+
+#include "mucc.h"
+#include "ManagerWindow.h"
+#include "ChatWindow.h"
+
+extern int MUCCServicesInit(WPARAM wParam, LPARAM lParam);
+
+extern INT_PTR MUCCQueryResult(WPARAM wParam, LPARAM lParam) ;
+extern INT_PTR MUCCNewWindow(WPARAM wParam, LPARAM lParam) ;
+extern INT_PTR MUCCEvent(WPARAM wParam, LPARAM lParam) ;
+
+#endif
+
diff --git a/protocols/Tlen/tlen_czaty/src/resource.h b/protocols/Tlen/tlen_czaty/src/resource.h
new file mode 100644
index 0000000000..04ef97014f
--- /dev/null
+++ b/protocols/Tlen/tlen_czaty/src/resource.h
@@ -0,0 +1,218 @@
+/*
+
+MUCC Group Chat GUI Plugin for Miranda NG
+Copyright (C) 2004 Piotr Piastucki
+
+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.
+
+*/
+#define IDI_CHAT 100
+#define IDI_ITALIC 101
+#define IDI_BOLD 102
+#define IDI_UNDERLINE 103
+#define IDI_OPTIONS 104
+#define IDI_OWNER 105
+#define IDI_ADMIN 106
+#define IDI_REGISTERED 107
+#define IDI_R_MODERATED 108
+#define IDI_R_MEMBERS 109
+#define IDI_R_ANONYMOUS 110
+#define IDI_SEARCH 111
+#define IDI_PREV 112
+#define IDI_NEXT 113
+#define IDI_BLANK 114
+#define IDI_INVITE 115
+#define IDI_ADMINISTRATION 116
+#define IDI_GLOBALOWNER 117
+#define IDI_SMILEY 118
+#define IDI_MESSAGE 119
+
+#define IDD_CHATMANAGER 150
+#define IDD_GROUPCHAT_LOG 151
+#define IDD_HELPER_JOIN 152
+#define IDD_HELPER_INPUT 153
+#define IDD_HELPER_INVITE 154
+#define IDD_HELPER_INVITE_ACCEPT 155
+#define IDD_HELPER_TOPIC 156
+#define IDD_OPTIONS 157
+#define IDD_OPT_POPUPS 158
+#define IDD_TAB_CHATROOMS 159
+#define IDD_TAB_MYROOMS 160
+#define IDD_TAB_MYNICKNAMES 161
+#define IDD_USER_ADMIN 162
+#define IDD_USER_KICK 163
+#define IDD_USER_ROLE 164
+#define IDD_USER_BROWSER 165
+#define IDD_GROUPCHAT_CONTAINER 166
+
+#define IDR_CHATOPTIONS 200
+#define IDR_CONTEXT 201
+
+#define IDC_FONTLIST 1000
+#define IDC_COLORINPUT 1001
+#define IDC_COLORBKG 1002
+#define IDC_COLORLIST 1003
+#define IDC_COLORTXT 1004
+#define IDC_CHOOSEFONT 1005
+#define IDC_FONTSGB 1006
+#define IDC_OPTIONSGB 1007
+#define IDC_LOGLIMITSPIN 1008
+#define IDC_LOGLIMIT 1009
+#define IDC_SENDONENTER 1010
+#define IDC_USETABS 1011
+#define IDC_ENABLEIEVIEW 1012
+#define IDC_REGISTER 1020
+#define IDC_NAME 1021
+#define IDC_FRAME 1037
+#define IDC_SIMPLE 1041
+#define IDC_PASSWORD 1050
+#define IDC_JID 1051
+#define IDC_COUNTRY 1060
+#define IDC_NICKNAME 1062
+#define IDC_MSG 1084
+#define IDC_TITLE 1089
+#define IDC_DESC 1090
+#define IDC_DELETE 1092
+#define IDC_LOAD 1093
+#define IDC_JOIN 1123
+#define IDC_ROOM 1124
+#define IDC_ROOM_LABEL 1125
+#define IDC_BROWSE 1126
+#define IDC_VSCROLL 1128
+#define IDC_NICK 1129
+#define IDC_NICK_LABEL 1130
+#define IDC_EDIT 1131
+#define IDC_TREELIST 1132
+#define IDC_LIST 1133
+#define IDC_HSPLIT 1134
+#define IDC_LOG 1136
+#define IDC_VSPLIT 1137
+#define IDC_SET 1140
+#define IDC_TABS 1141
+#define IDC_TOPIC 1141
+#define IDC_TOPIC_BUTTON 1142
+#define IDC_FONT 1143
+#define IDC_ENTER 1144
+#define IDC_CTRLENTER 1145
+#define IDC_FLASH 1148
+#define IDC_TIME 1156
+#define IDC_DATE 1157
+#define IDC_REASON 1171
+#define IDC_USER 1172
+#define IDC_INVITE 1173
+#define IDC_ACCEPT 1174
+#define IDC_FROM 1175
+#define IDC_DELAY 1180
+#define IDC_PREVIEW 1183
+#define IDC_ENABLEPOPUP 1184
+#define IDC_DELAY_PERMANENT 1185
+#define IDC_DELAY_CUSTOM 1186
+#define IDC_DELAY_POPUP 1187
+#define IDC_GROUP 1203
+#define IDC_BOLD 1204
+#define IDC_SMILEY 1205
+#define IDC_UNDERLINE 1205
+#define IDC_ITALIC 1206
+#define IDC_COLOR 1207
+#define IDC_OPTIONS 1208
+#define IDC_SMILEYBTN 1209
+#define IDC_CHECK_PERMANENT 1210
+#define IDC_CHECK_PUBLIC 1211
+#define IDC_CHECK_NICKNAMES 1212
+#define IDC_CHECK_MEMBERS 1213
+#define IDC_NEXT 1214
+#define IDC_PREV 1215
+#define IDC_FONTSIZE 1215
+#define IDC_SEARCH 1216
+#define IDC_REFRESH 1216
+#define IDC_REMOVE 1217
+#define IDC_KICK_OPTIONS 1218
+#define IDC_ROLE_OPTIONS 1219
+#define IDC_KICK 1220
+#define IDC_SET_ROLE 1221
+#define IDC_UPDATE 1313
+#define IDC_STATUS 1414
+#define IDC_PLAN 1415
+#define IDC_SHOW 1416
+
+#define IDC_PERSONALGROUP 1434
+#define IDC_EXTRAGROUP 1436
+
+#define ID_OPTIONMENU_SHOWNICKNAMES 40001
+#define ID_OPTIONMENU_MSGINNEWLINE 40002
+#define ID_OPTIONMENU_SHOWTIMESTAMP 40011
+#define ID_OPTIONMENU_SHOWDATE 40012
+#define ID_OPTIONMENU_SHOWSECONDS 40013
+#define ID_OPTIONMENU_USELONGDATE 40014
+#define ID_OPTIONMENU_FORMATFONT 40021
+#define ID_OPTIONMENU_FORMATSIZE 40022
+#define ID_OPTIONMENU_FORMATCOLOR 40023
+#define ID_OPTIONMENU_FORMATSTYLE 40024
+#define ID_OPTIONMENU_LOGMESSAGES 40031
+#define ID_OPTIONMENU_LOGJOINED 40032
+#define ID_OPTIONMENU_LOGLEFT 40033
+#define ID_OPTIONMENU_LOGTOPIC 40034
+#define ID_OPTIONMENU_FLASHMESSAGES 40035
+#define ID_OPTIONMENU_FLASHJOINED 40036
+#define ID_OPTIONMENU_FLASHLEFT 40037
+#define ID_OPTIONMENU_FLASHTOPIC 40038
+#define ID_OPTIONMENU_SAVEDEFAULT 40040
+#define ID_USERMENU_MESSAGE 40050
+#define ID_USERMENU_KICK_POPUP 40051
+#define ID_USERMENU_KICK_NO_BAN 40052
+#define ID_USERMENU_KICK_BAN_1_MIN 40053
+#define ID_USERMENU_KICK_BAN_5_MIN 40054
+#define ID_USERMENU_KICK_BAN_15_MIN 40055
+#define ID_USERMENU_KICK_BAN_30_MIN 40056
+#define ID_USERMENU_KICK_BAN_1_H 40057
+#define ID_USERMENU_KICK_BAN_6_H 40058
+#define ID_USERMENU_KICK_BAN_1_D 40059
+#define ID_USERMENU_KICK_BAN_3_D 40060
+#define ID_USERMENU_KICK_BAN_1_W 40061
+#define ID_USERMENU_KICK_BAN_2_W 40062
+#define ID_USERMENU_KICK_BAN_4_W 40063
+#define ID_USERMENU_RIGHTS_NO 40065
+#define ID_USERMENU_RIGHTS_MEMBER 40066
+#define ID_USERMENU_RIGHTS_ADMIN 40067
+#define ID_USERMENU_ADMINISTRATION 40070
+#define ID_USERMENU_UNBAN 40071
+#define ID_ADMINMENU_DESTROY 40080
+#define ID_ADMINMENU_ADMIN 40081
+#define ID_ADMINMENU_BROWSE 40082
+#define ID_ADMINMENU_SAVELOG 40083
+
+#define IDM_CUT 40000
+#define IDM_COPY 40001
+#define IDM_PASTE 40002
+#define IDM_UNDO 40003
+#define IDM_DELETE 40004
+#define IDM_REDO 40005
+#define IDM_COPYALL 40011
+#define IDM_SELECTALL 40012
+#define IDM_CLEAR 40013
+#define IDM_OPENNEW 40014
+#define IDM_OPENEXISTING 40015
+#define IDM_COPYLINK 40016
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 205
+#define _APS_NEXT_COMMAND_VALUE 40090
+#define _APS_NEXT_CONTROL_VALUE 1217
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif