diff options
Diffstat (limited to 'protocols/Sametime')
153 files changed, 41096 insertions, 0 deletions
diff --git a/protocols/Sametime/docs/dll_x32/intl.dll b/protocols/Sametime/docs/dll_x32/intl.dll Binary files differnew file mode 100644 index 0000000000..d2612081ca --- /dev/null +++ b/protocols/Sametime/docs/dll_x32/intl.dll diff --git a/protocols/Sametime/docs/dll_x32/libglib-2.0-0.dll b/protocols/Sametime/docs/dll_x32/libglib-2.0-0.dll Binary files differnew file mode 100644 index 0000000000..143e1daadc --- /dev/null +++ b/protocols/Sametime/docs/dll_x32/libglib-2.0-0.dll diff --git a/protocols/Sametime/docs/dll_x64/libglib-2.0-0.dll b/protocols/Sametime/docs/dll_x64/libglib-2.0-0.dll Binary files differnew file mode 100644 index 0000000000..cde4d25439 --- /dev/null +++ b/protocols/Sametime/docs/dll_x64/libglib-2.0-0.dll diff --git a/protocols/Sametime/docs/dll_x64/libintl-8.dll b/protocols/Sametime/docs/dll_x64/libintl-8.dll Binary files differnew file mode 100644 index 0000000000..de0ef3043f --- /dev/null +++ b/protocols/Sametime/docs/dll_x64/libintl-8.dll diff --git a/protocols/Sametime/docs/license.txt b/protocols/Sametime/docs/license.txt new file mode 100644 index 0000000000..818433ecc0 --- /dev/null +++ b/protocols/Sametime/docs/license.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/protocols/Sametime/docs/readme.txt b/protocols/Sametime/docs/readme.txt new file mode 100644 index 0000000000..337d12e892 --- /dev/null +++ b/protocols/Sametime/docs/readme.txt @@ -0,0 +1,66 @@ +
+sametime.dll
+
+Miranda NG Sametime protocol
+
+
+
+
+
+The Meanwhile Library
+Fork of meanwhile 1.0.2 from
+http://meanwhile.sourceforge.net/
+
+
+
+
+
+INSTALATION
+
+This plugin needs glib windows dll libraries copied into main Miranda directory (directory with Miranda32.exe or Miranda64.exe) to work.
+
+For 32 bit version (\docs\dll_x32\):
+libglib-2.0-0.dll from http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.26/glib_2.26.1-1_win32.zip
+intl.dll from http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zip
+
+For 64 bit version (\docs\dll_x64\):
+libglib-2.0-0.dll from http://ftp.gnome.org/pub/gnome/binaries/win64/glib/2.26/glib_2.26.1-1_win64.zip
+libintl-8.dll from http://ftp.gnome.org/pub/gnome/binaries/win64/dependencies/gettext-runtime_0.18.1.1-2_win64.zip
+
+
+
+
+
+
+KNOWN ISSUES
+
+1)
+Receiving files from same oryginal clients (Lotus Sametime 8.0.2) doesn't work.
+At Miranda IM too.
+Miranda NG <-> Miranda NG file transfers are ok.
+
+2)
+Receiving conferences announcements is unimplemented
+
+3)
+Crash on Miranda exit. (environment depends)
+Exception: User Defined Breakpoint at address 74923C38.
+764E1DA7 (KERNELBASE 764D0000): (filename not available) (0): FreeLibrary
+0042A156 (Miranda32 00400000): e:\sources\miranda_ng_compilation\src\modules\plugins\newplugins.cpp (308): Plugin_Uninit
+0042AC81 (Miranda32 00400000): e:\sources\miranda_ng_compilation\src\modules\plugins\newplugins.cpp (716): UnloadNewPlugins
+00401A78 (Miranda32 00400000): e:\sources\miranda_ng_compilation\src\core\modules.cpp (169): UnloadDefaultModules
+00401104 (Miranda32 00400000): e:\sources\miranda_ng_compilation\src\core\miranda.cpp (130): SystemShutdownProc
+
+
+
+
+
+
+TESTING SERVER ENVIRONMENT
+
+https://apps.ce.collabserv.com/manage/account/public/trial/showCreateTrialAccount?country=PL&ibm-continue=Continue
+see: http://www.wissel.net/blog/d6plinks/SHWL-84KE8U
+
+
+
+
diff --git a/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj b/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj new file mode 100644 index 0000000000..6cb5cbf6ad --- /dev/null +++ b/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj @@ -0,0 +1,131 @@ +<?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">
+ <ProjectGuid>{217C99B1-0D5E-4A85-A84F-836FCA167B25}</ProjectGuid>
+ <ProjectName>Proto_Sametime</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <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 Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <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)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Icons\</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)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Icons\</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)'=='Debug|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Proto_Sametime.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj.filters b/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj.filters new file mode 100644 index 0000000000..2fa8a4aabd --- /dev/null +++ b/protocols/Sametime/proto_sametime/Proto_Sametime_10.vcxproj.filters @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Proto_Sametime.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj b/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj new file mode 100644 index 0000000000..e113fe994a --- /dev/null +++ b/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.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">
+ <ProjectGuid>{217C99B1-0D5E-4A85-A84F-836FCA167B25}</ProjectGuid>
+ <ProjectName>Proto_Sametime</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <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 Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <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)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Icons\</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)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Icons\</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)'=='Debug|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Proto_Sametime.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj.filters b/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj.filters new file mode 100644 index 0000000000..2fa8a4aabd --- /dev/null +++ b/protocols/Sametime/proto_sametime/Proto_Sametime_12.vcxproj.filters @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Proto_Sametime.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/proto_sametime/res/Away.ico b/protocols/Sametime/proto_sametime/res/Away.ico Binary files differnew file mode 100644 index 0000000000..6204baa145 --- /dev/null +++ b/protocols/Sametime/proto_sametime/res/Away.ico diff --git a/protocols/Sametime/proto_sametime/res/DND.ico b/protocols/Sametime/proto_sametime/res/DND.ico Binary files differnew file mode 100644 index 0000000000..f198b121f5 --- /dev/null +++ b/protocols/Sametime/proto_sametime/res/DND.ico diff --git a/protocols/Sametime/proto_sametime/res/Offline.ico b/protocols/Sametime/proto_sametime/res/Offline.ico Binary files differnew file mode 100644 index 0000000000..323f880ce5 --- /dev/null +++ b/protocols/Sametime/proto_sametime/res/Offline.ico diff --git a/protocols/Sametime/proto_sametime/res/Online.ico b/protocols/Sametime/proto_sametime/res/Online.ico Binary files differnew file mode 100644 index 0000000000..839e79c9f7 --- /dev/null +++ b/protocols/Sametime/proto_sametime/res/Online.ico diff --git a/protocols/Sametime/proto_sametime/res/Proto_Sametime.rc b/protocols/Sametime/proto_sametime/res/Proto_Sametime.rc new file mode 100644 index 0000000000..2553b55145 --- /dev/null +++ b/protocols/Sametime/proto_sametime/res/Proto_Sametime.rc @@ -0,0 +1,72 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "..\src\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian (Russia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\\src\\resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON "Offline.ico"
+IDI_ICON2 ICON "Online.ico"
+IDI_ICON3 ICON "Away.ico"
+IDI_ICON4 ICON "DND.ico"
+#endif // Russian (Russia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/Sametime/proto_sametime/src/resource.h b/protocols/Sametime/proto_sametime/src/resource.h new file mode 100644 index 0000000000..3decee6cf7 --- /dev/null +++ b/protocols/Sametime/proto_sametime/src/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Proto_Sametime.rc
+//
+#define IDI_ICON1 105
+#define IDI_ICON2 104
+#define IDI_ICON3 128
+#define IDI_ICON4 158
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 108
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/Sametime/res/announce.ico b/protocols/Sametime/res/announce.ico Binary files differnew file mode 100644 index 0000000000..ac9673a7dc --- /dev/null +++ b/protocols/Sametime/res/announce.ico diff --git a/protocols/Sametime/res/error.ico b/protocols/Sametime/res/error.ico Binary files differnew file mode 100644 index 0000000000..5f8956218e --- /dev/null +++ b/protocols/Sametime/res/error.ico diff --git a/protocols/Sametime/res/invite.ico b/protocols/Sametime/res/invite.ico Binary files differnew file mode 100644 index 0000000000..944ebf818c --- /dev/null +++ b/protocols/Sametime/res/invite.ico diff --git a/protocols/Sametime/res/notify.ico b/protocols/Sametime/res/notify.ico Binary files differnew file mode 100644 index 0000000000..b4934e4e1f --- /dev/null +++ b/protocols/Sametime/res/notify.ico diff --git a/protocols/Sametime/res/online.ico b/protocols/Sametime/res/online.ico Binary files differnew file mode 100644 index 0000000000..8362c83159 --- /dev/null +++ b/protocols/Sametime/res/online.ico diff --git a/protocols/Sametime/res/part.ico b/protocols/Sametime/res/part.ico Binary files differnew file mode 100644 index 0000000000..1b698a76b3 --- /dev/null +++ b/protocols/Sametime/res/part.ico diff --git a/protocols/Sametime/res/resource.rc b/protocols/Sametime/res/resource.rc new file mode 100644 index 0000000000..1f7384711d --- /dev/null +++ b/protocols/Sametime/res/resource.rc @@ -0,0 +1,177 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "..\src\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTNET DIALOGEX 0, 0, 314, 203
+STYLE DS_SETFONT | WS_CHILD
+FONT 8, "MS Sans Serif", 0, 0, 0x0
+BEGIN
+ RTEXT "Server name:",IDC_STATIC,14,61,49,8
+ EDITTEXT IDC_ED_SNAME,70,57,92,14,ES_AUTOHSCROLL
+ RTEXT "Port:",IDC_STATIC,14,81,49,8
+ EDITTEXT IDC_ED_PORT,70,77,36,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Get contacts from server",IDC_CHK_GETSERVERCONTACTS,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,180,15,115,15
+ PUSHBUTTON "Upload Contacts",IDC_BTN_UPLOADCONTACTS,180,29,115,15
+ PUSHBUTTON "Import from file...",IDC_BTN_IMPORTCONTACTS,180,48,115,15
+ COMBOBOX IDC_CMB_CLIENT,10,109,114,107,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_ED_CLIENTID,126,109,37,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "Id:",IDC_STATIC,14,17,49,8
+ EDITTEXT IDC_ED_NAME,70,13,92,14,ES_AUTOHSCROLL
+ RTEXT "Password:",IDC_STATIC,14,39,49,8
+ EDITTEXT IDC_ED_PWORD,70,35,92,14,ES_PASSWORD | ES_AUTOHSCROLL
+ GROUPBOX "Error Display",IDC_STATIC,7,143,161,53
+ CONTROL "Use message boxes",IDC_RAD_ERRMB,"Button",BS_AUTORADIOBUTTON | WS_GROUP,20,156,122,10
+ CONTROL "Use popups",IDC_RAD_ERRPOP,"Button",BS_AUTORADIOBUTTON,20,169,122,10
+ CONTROL "Use system tray baloons",IDC_RAD_ERRBAL,"Button",BS_AUTORADIOBUTTON,21,182,122,10
+ GROUPBOX "Connection",IDC_STATIC,7,7,161,91
+ GROUPBOX "Contacts",IDC_STATIC,172,7,135,91
+ GROUPBOX "Client ID",IDC_STATIC,7,98,161,44
+ CONTROL "Auto-add new contacts",IDC_CHK_ADDCONTACTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,180,67,115,11
+ GROUPBOX "Encryption",IDC_STATIC,172,98,135,44
+ CONTROL "40 or 128 bit",IDC_RAD_ENC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,190,113,88,10
+ CONTROL "None",IDC_RAD_NOENC,"Button",BS_AUTORADIOBUTTON,190,126,88,10
+ CTEXT "Static",IDC_ST_CLIENTVER,185,165,102,12,SS_SUNKEN
+ CTEXT "Static",IDC_ST_SERVERVER,185,180,102,12,SS_SUNKEN
+ CONTROL "Treat 'idle' as 'away'",IDC_CHK_IDLEAWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,180,81,115,11
+ CTEXT "Meanwhile lib ver: 1.0.2",IDC_ST_LIBVER,185,150,102,12
+ GROUPBOX "",IDC_STATIC,172,143,135,53
+ CONTROL "Use old client version",IDC_CHK_OLDDEFAULTVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,127,115,11
+END
+
+IDD_SESSIONANNOUNCE DIALOG 0, 0, 286, 263
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Send Announcement"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,95,242,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,150,242,50,14
+ EDITTEXT IDC_ED_ANMSG,10,20,264,60,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN
+ LTEXT "Message Text:",IDC_STATIC,9,9,142,8
+ CONTROL "List1",IDC_LST_ANTO,"SysListView32",LVS_REPORT | WS_BORDER | WS_TABSTOP,10,92,197,132
+ PUSHBUTTON "Select All",IDC_BUT_SELALL,214,122,58,36
+ PUSHBUTTON "Invert\n Selection",IDC_BUT_SELINV,214,167,58,36,BS_MULTILINE
+END
+
+IDD_USERSEARCH DIALOG 0, 0, 155, 86
+STYLE DS_SETFONT | WS_POPUP
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,34,32,103,14,ES_AUTOHSCROLL
+ LTEXT "ID:",IDC_STATIC,18,35,10,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPTNET, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 307
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 196
+ END
+
+ IDD_SESSIONANNOUNCE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 279
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 256
+ END
+
+ IDD_USERSEARCH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 148
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 79
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON_PROTO ICON "online.ico"
+IDI_ICON_LEAVE ICON "part.ico"
+IDI_ICON_INVITE ICON "invite.ico"
+IDI_ICON_ANNOUNCE ICON "announce.ico"
+IDI_ICON_NOTIFY ICON "notify.ico"
+IDI_ICON_ERROR ICON "error.ico"
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/Sametime/sametime_10.vcxproj b/protocols/Sametime/sametime_10.vcxproj new file mode 100644 index 0000000000..a9e17c8773 --- /dev/null +++ b/protocols/Sametime/sametime_10.vcxproj @@ -0,0 +1,306 @@ +<?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>Sametime</ProjectName>
+ <ProjectGuid>{BE22A21F-73B7-453F-86A0-B867F0056490}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </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)'=='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)'=='Release|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)'=='Debug|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)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib32/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib64/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib32/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib64/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\conference.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\files.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\channel.c" />
+ <ClCompile Include="src\meanwhile\src\cipher.c" />
+ <ClCompile Include="src\meanwhile\src\common.c" />
+ <ClCompile Include="src\meanwhile\src\error.c" />
+ <ClCompile Include="src\meanwhile\src\message.c" />
+ <ClCompile Include="src\meanwhile\src\mpi\mpi.c" />
+ <ClCompile Include="src\meanwhile\src\mw_debug.c" />
+ <ClCompile Include="src\meanwhile\src\mw_util.c" />
+ <ClCompile Include="src\meanwhile\src\service.c" />
+ <ClCompile Include="src\meanwhile\src\session.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_aware.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_conf.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_dir.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_ft.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_im.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_place.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_resolve.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_store.c" />
+ <ClCompile Include="src\meanwhile\src\st_list.c" />
+ <ClCompile Include="src\messaging.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\places.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime_proto.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime_session.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\session_announce_win.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\StdAfx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\userlist.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-config.h" />
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-types.h" />
+ <ClInclude Include="src\meanwhile\src\mpi\mpi.h" />
+ <ClInclude Include="src\meanwhile\src\mw_channel.h" />
+ <ClInclude Include="src\meanwhile\src\mw_cipher.h" />
+ <ClInclude Include="src\meanwhile\src\mw_common.h" />
+ <ClInclude Include="src\meanwhile\src\mw_debug.h" />
+ <ClInclude Include="src\meanwhile\src\mw_error.h" />
+ <ClInclude Include="src\meanwhile\src\mw_message.h" />
+ <ClInclude Include="src\meanwhile\src\mw_service.h" />
+ <ClInclude Include="src\meanwhile\src\mw_session.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_aware.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_conf.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_dir.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_ft.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_im.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_place.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_resolve.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_store.h" />
+ <ClInclude Include="src\meanwhile\src\mw_st_list.h" />
+ <ClInclude Include="src\meanwhile\src\mw_util.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\sametime.h" />
+ <ClInclude Include="src\sametime_proto.h" />
+ <ClInclude Include="src\StdAfx.h" />
+ <ClInclude Include="src\version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\announce.ico" />
+ <None Include="res\invite.ico" />
+ <None Include="res\online.ico" />
+ <None Include="res\part.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/sametime_10.vcxproj.filters b/protocols/Sametime/sametime_10.vcxproj.filters new file mode 100644 index 0000000000..e97b6b31da --- /dev/null +++ b/protocols/Sametime/sametime_10.vcxproj.filters @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{b2fb3090-cd03-4404-a154-94e31360b079}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{97a29dbd-67df-4a06-a2d0-a82721b109c2}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{34e64f6c-b825-450f-bf46-f974acd71f72}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Meanwhile">
+ <UniqueIdentifier>{addc907a-8009-4c31-b03d-37759cb8c021}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Meanwhile\mpi">
+ <UniqueIdentifier>{c23f9d40-96f3-4bce-a8eb-670346163e26}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\conference.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\files.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\messaging.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\places.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\session_announce_win.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\userlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\StdAfx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime_proto.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\st_list.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\channel.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\cipher.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\common.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\error.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\message.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mw_debug.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mw_util.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\service.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\session.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_aware.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_conf.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_dir.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_ft.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_im.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_place.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_resolve.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_store.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mpi\mpi.c">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime_session.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\sametime.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\StdAfx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\sametime_proto.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_channel.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_cipher.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_common.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_debug.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_error.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_message.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_service.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_session.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_aware.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_conf.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_dir.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_ft.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_im.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_place.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_resolve.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_store.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_st_list.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_util.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-types.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-config.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\announce.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\invite.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\online.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\part.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/sametime_12.vcxproj b/protocols/Sametime/sametime_12.vcxproj new file mode 100644 index 0000000000..f56100fd70 --- /dev/null +++ b/protocols/Sametime/sametime_12.vcxproj @@ -0,0 +1,311 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.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>Sametime</ProjectName>
+ <ProjectGuid>{BE22A21F-73B7-453F-86A0-B867F0056490}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </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)'=='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)'=='Release|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)'=='Debug|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)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib32/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib64/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib32/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/sametime.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\include;src\meanwhile\src;src\glib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>./src/glib/lib64/glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\conference.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\files.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\channel.c" />
+ <ClCompile Include="src\meanwhile\src\cipher.c" />
+ <ClCompile Include="src\meanwhile\src\common.c" />
+ <ClCompile Include="src\meanwhile\src\error.c" />
+ <ClCompile Include="src\meanwhile\src\message.c" />
+ <ClCompile Include="src\meanwhile\src\mpi\mpi.c" />
+ <ClCompile Include="src\meanwhile\src\mw_debug.c" />
+ <ClCompile Include="src\meanwhile\src\mw_util.c" />
+ <ClCompile Include="src\meanwhile\src\service.c" />
+ <ClCompile Include="src\meanwhile\src\session.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_aware.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_conf.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_dir.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_ft.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_im.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_place.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_resolve.c" />
+ <ClCompile Include="src\meanwhile\src\srvc_store.c" />
+ <ClCompile Include="src\meanwhile\src\st_list.c" />
+ <ClCompile Include="src\messaging.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\places.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime_proto.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sametime_session.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\session_announce_win.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\StdAfx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\userlist.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-config.h" />
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-types.h" />
+ <ClInclude Include="src\meanwhile\src\mpi\mpi.h" />
+ <ClInclude Include="src\meanwhile\src\mw_channel.h" />
+ <ClInclude Include="src\meanwhile\src\mw_cipher.h" />
+ <ClInclude Include="src\meanwhile\src\mw_common.h" />
+ <ClInclude Include="src\meanwhile\src\mw_debug.h" />
+ <ClInclude Include="src\meanwhile\src\mw_error.h" />
+ <ClInclude Include="src\meanwhile\src\mw_message.h" />
+ <ClInclude Include="src\meanwhile\src\mw_service.h" />
+ <ClInclude Include="src\meanwhile\src\mw_session.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_aware.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_conf.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_dir.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_ft.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_im.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_place.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_resolve.h" />
+ <ClInclude Include="src\meanwhile\src\mw_srvc_store.h" />
+ <ClInclude Include="src\meanwhile\src\mw_st_list.h" />
+ <ClInclude Include="src\meanwhile\src\mw_util.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\sametime.h" />
+ <ClInclude Include="src\sametime_proto.h" />
+ <ClInclude Include="src\StdAfx.h" />
+ <ClInclude Include="src\version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\announce.ico" />
+ <None Include="res\invite.ico" />
+ <None Include="res\online.ico" />
+ <None Include="res\part.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/sametime_12.vcxproj.filters b/protocols/Sametime/sametime_12.vcxproj.filters new file mode 100644 index 0000000000..e97b6b31da --- /dev/null +++ b/protocols/Sametime/sametime_12.vcxproj.filters @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{b2fb3090-cd03-4404-a154-94e31360b079}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{97a29dbd-67df-4a06-a2d0-a82721b109c2}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{34e64f6c-b825-450f-bf46-f974acd71f72}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Meanwhile">
+ <UniqueIdentifier>{addc907a-8009-4c31-b03d-37759cb8c021}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Meanwhile\mpi">
+ <UniqueIdentifier>{c23f9d40-96f3-4bce-a8eb-670346163e26}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\conference.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\files.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\messaging.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\places.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\session_announce_win.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\userlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\StdAfx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime_proto.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\st_list.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\channel.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\cipher.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\common.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\error.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\message.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mw_debug.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mw_util.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\service.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\session.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_aware.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_conf.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_dir.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_ft.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_im.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_place.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_resolve.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\srvc_store.c">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClCompile>
+ <ClCompile Include="src\meanwhile\src\mpi\mpi.c">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClCompile>
+ <ClCompile Include="src\sametime_session.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\sametime.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\StdAfx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\sametime_proto.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_channel.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_cipher.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_common.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_debug.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_error.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_message.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_service.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_session.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_aware.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_conf.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_dir.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_ft.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_im.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_place.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_resolve.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_srvc_store.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_st_list.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mw_util.h">
+ <Filter>Source Files\Meanwhile</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-types.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ <ClInclude Include="src\meanwhile\src\mpi\mpi-config.h">
+ <Filter>Source Files\Meanwhile\mpi</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\announce.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\invite.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\online.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\part.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/protocols/Sametime/src/StdAfx.cpp b/protocols/Sametime/src/StdAfx.cpp new file mode 100644 index 0000000000..287357e7a4 --- /dev/null +++ b/protocols/Sametime/src/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes
+// sametime.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "StdAfx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/protocols/Sametime/src/StdAfx.h b/protocols/Sametime/src/StdAfx.h new file mode 100644 index 0000000000..a5e7c9b64f --- /dev/null +++ b/protocols/Sametime/src/StdAfx.h @@ -0,0 +1,97 @@ +// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#pragma warning( disable : 4503 4786 )
+
+
+// Windows
+#define _WIN32_WINNT 0x501 // for QueueUserAPC
+#include <windows.h>
+#include <commctrl.h>
+#include <process.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+
+// STL
+#include <queue> // for conference.cpp, messaging.cpp
+#include <string> // for conference.cpp, userlist.cpp
+#include <map> // for messaging.cpp
+#include <fstream> // for userlist.cpp
+#include <iostream> // for userlist.cpp
+
+
+// Glib
+//
+// Subset of libs and includes from Glib v 2.26 from:
+// http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.26/glib-dev_2.26.1-1_win32.zip
+// http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.26/glib-dev_2.26.1-1_win64.zip
+//
+//
+// dll files needed in main Miranda directory:
+//
+// x32
+// libglib-2.0-0.dll from http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.26/glib_2.26.1-1_win32.zip
+// intl.dll from http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zip
+//
+// x64
+// libglib-2.0-0.dll from http://ftp.gnome.org/pub/gnome/binaries/win64/glib/2.26/glib_2.26.1-1_win64.zip
+// libintl-8.dll from http://ftp.gnome.org/pub/gnome/binaries/win64/dependencies/gettext-runtime_0.18.1.1-2_win64.zip
+//
+#include <glib.h> //for meanwhile and session.cpp
+
+
+// Menwhile
+// Sources of Meanwhile v 1.0.2 from
+// http://meanwhile.sourceforge.net/
+extern "C" {
+#include <mw_session.h>
+#include <mw_cipher.h>
+#include <mw_st_list.h>
+//#include <mw_util.h>
+#include <mw_service.h>
+#include <mw_channel.h>
+#include <mw_srvc_im.h>
+#include <mw_srvc_aware.h>
+#include <mw_srvc_resolve.h>
+#include <mw_srvc_store.h>
+#include <mw_srvc_place.h>
+#include <mw_srvc_ft.h>
+#include <mw_srvc_conf.h>
+#include <mw_error.h>
+#include <mw_message.h>
+};
+
+
+// Miranda
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_protoint.h>
+#include <m_options.h>
+#include <m_skin.h>
+#include <m_clist.h>
+#include <m_message.h>
+#include <statusmodes.h>
+#include <m_langpack.h>
+#include <m_netlib.h>
+#include <m_database.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_ignore.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_utils.h>
+#include <m_idle.h>
+#include <m_addcontact.h>
+#include <m_popup.h>
+#include <m_chat.h>
+#include <m_genmenu.h>
+#include <m_icolib.h>
+
diff --git a/protocols/Sametime/src/conference.cpp b/protocols/Sametime/src/conference.cpp new file mode 100644 index 0000000000..e72c089e73 --- /dev/null +++ b/protocols/Sametime/src/conference.cpp @@ -0,0 +1,566 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+
+void CloseMyConference(CSametimeProto* proto) {
+ mwConference_destroy(proto->my_conference, 0, Translate("I'm outa here."));
+ proto->my_conference = 0;
+}
+
+
+CSametimeProto* getProtoFromMwConference(mwConference* conf)
+{
+ mwServiceConference* servConference = mwConference_getServiceConference(conf);
+ mwService* service = mwServiceConference_getService(servConference);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+
+/** triggered when we receive a conference invitation. Call
+ mwConference_accept to accept the invitation and join the
+ conference, or mwConference_close to reject the invitation.
+
+ @param conf the newly created conference
+ @param inviter the indentity of the user who sent the invitation
+ @param invite the invitation text
+*/
+void mwServiceConf_on_invited(mwConference* conf, mwLoginInfo* inviter, const char* invite) {
+
+ GList *members, *mem;
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_on_invited() start"));
+
+ members = mem = mwConference_getMembers(conf);
+ for (;mem;mem=mem->next) {
+ if (proto->my_login_info && strcmp(proto->my_login_info->login_id, ((mwLoginInfo*)mem->data)->login_id) == 0) {
+ proto->debugLog(_T("mwServiceConf_on_invited() already present"));
+ char* utfs = mir_utf8encodeT(TranslateT("Invitation rejected - already present."));
+ mwConference_reject(conf, 0, utfs);
+ mir_free(utfs);
+ return;
+ }
+ }
+ g_list_free(members);
+
+ wchar_t ws_username[128];
+ MultiByteToWideChar(CP_UTF8, 0, (const char*)inviter->user_name, -1, ws_username, 128);
+
+ wchar_t ws_invite[512];
+ MultiByteToWideChar(CP_UTF8, 0, (const char*)invite, -1, ws_invite, 128);
+
+ if (MessageBoxW(0, ws_invite, ws_username, MB_OKCANCEL) == IDOK) {
+ proto->debugLog(_T("mwServiceConf_on_invited() mwConference_accept"));
+ mwConference_accept(conf);
+ } else {
+ proto->debugLog(_T("mwServiceConf_on_invited() mwConference_reject"));
+ char* temp = mir_utf8encodeT(TranslateT("Your invitation has been rejected."));
+ mwConference_reject(conf, 0, temp);
+ mir_free(temp);
+ }
+
+}
+
+void CSametimeProto::ClearInviteQueue() {
+
+ debugLog(_T("CSametimeProto::ClearInviteQueue() start"));
+ if (!my_conference) return;
+
+ mwIdBlock idb;
+ idb.community = 0;
+
+ while(invite_queue.size()) {
+ idb.user = (char *)invite_queue.front().c_str();
+
+ MCONTACT hContact = FindContactByUserId(idb.user);
+ if (!hContact) {
+ mwSametimeList* user_list = mwSametimeList_new();
+ char* utfs = mir_utf8encodeT(TranslateT("None"));
+ mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, utfs);
+ mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &idb);
+
+ hContact = AddContact(stuser, (options.add_contacts ? false : true));
+ mwSametimeList_free(user_list);
+ mir_free(utfs);
+
+ }
+
+ bool found = false;
+ GList *members, *mem;
+ members = mem = mwConference_getMembers(my_conference);
+ for (;mem;mem=mem->next) {
+ if (my_login_info && strcmp(idb.user, ((mwLoginInfo *)mem->data)->user_id) == 0) {
+ found = true;
+ break;
+ }
+ }
+ g_list_free(members);
+
+ if (!found) {
+ char* temp = mir_utf8encodeT(TranslateT("Please join this meeting."));
+ mwConference_invite(my_conference, &idb, temp);
+ mir_free(temp);
+ }
+
+ invite_queue.pop();
+ }
+}
+
+/** triggered when we enter the conference. Provides the initial
+ conference membership list as a GList of mwLoginInfo structures
+
+ @param conf the conference just joined
+ @param members mwLoginInfo list of existing conference members
+*/
+void mwServiceConf_conf_opened(mwConference* conf, GList* members)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_conf_opened() start"));
+
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));
+ TCHAR* tszConfTitle = mir_utf8decodeT(mwConference_getTitle(conf));
+
+ // create new chat session
+ GCSESSION gcs = { sizeof(gcs) };
+ gcs.dwFlags = 0;
+ gcs.iType = GCW_CHATROOM;
+ gcs.pszModule = proto->m_szModuleName;
+ gcs.ptszID = tszConfId;
+ gcs.ptszName = tszConfTitle;
+ gcs.dwItemData = 0;
+
+ CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcs);
+ mir_free(tszConfTitle);
+
+ //add a group
+ GCDEST gcd = { proto->m_szModuleName, 0 };
+ gcd.iType = GC_EVENT_ADDGROUP;
+ gcd.ptszID = tszConfId;
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.ptszStatus = TranslateT("Normal");
+
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
+
+ // add users
+ gcd.iType = GC_EVENT_JOIN;
+
+ GList *user = members;
+ for (;user; user=user->next) {
+ proto->debugLog(_T("mwServiceConf_conf_opened() add user"));
+
+ TCHAR* tszUserName = mir_utf8decodeT(((mwLoginInfo*)user->data)->user_name);
+ TCHAR* tszUserId = mir_utf8decodeT(((mwLoginInfo*)user->data)->login_id);
+ gce.ptszNick = tszUserName;
+ gce.ptszUID = tszUserId;
+ gce.bIsMe = (strcmp(((mwLoginInfo*)user->data)->login_id, proto->my_login_info->login_id) == 0);
+
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM) &gce);
+
+ mir_free(tszUserName);
+ mir_free(tszUserId);
+ }
+
+ // finalize setup (show window)
+ gcd.iType = GC_EVENT_CONTROL;
+ CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
+
+ gcd.iType = GC_EVENT_CONTROL;
+ CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
+
+ if (conf == proto->my_conference) {
+ proto->ClearInviteQueue();
+ }
+
+ mir_free(tszConfId);
+}
+
+/** triggered when a conference is closed. This is typically when
+ we've left it */
+void mwServiceConf_conf_closed(mwConference* conf, guint32 reason)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_conf_closed() start"));
+
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));
+
+ GCDEST gcd = { proto->m_szModuleName };
+ gcd.ptszID = tszConfId;
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+
+ CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
+ CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
+ mir_free(tszConfId);
+}
+
+/** triggered when someone joins the conference */
+void mwServiceConf_on_peer_joined(mwConference* conf, mwLoginInfo* user)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_on_peer_joined() start"));
+
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));
+
+ MCONTACT hContact = proto->FindContactByUserId(((mwLoginInfo*)user)->user_id);
+ if (!hContact) {
+ mwIdBlock idb;
+ idb.user = ((mwLoginInfo *)user)->user_id;
+ idb.community = 0;
+
+ mwSametimeList* user_list = mwSametimeList_new();
+ char* utfs = mir_utf8encodeT(TranslateT("None"));
+ mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, utfs);
+ mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &idb);
+
+ hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true));
+
+ mwSametimeList_free(user_list);
+ mir_free(utfs);
+ }
+
+ // add user
+ GCDEST gcd = { proto->m_szModuleName };
+ gcd.ptszID = tszConfId;
+ gcd.iType = GC_EVENT_JOIN;
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ TCHAR* tszUserName = mir_utf8decodeT(((mwLoginInfo*)user)->user_name);
+ TCHAR* tszUserId = mir_utf8decodeT(((mwLoginInfo*)user)->login_id);
+ gce.ptszNick = tszUserName;
+ gce.ptszUID = tszUserId;
+ gce.ptszStatus = _T("Normal");
+ gce.time = (DWORD)time(0);
+
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM) &gce);
+
+ mir_free(tszUserName);
+ mir_free(tszUserId);
+ mir_free(tszConfId);
+}
+
+/** triggered when someone leaves the conference */
+void mwServiceConf_on_peer_parted(mwConference* conf, mwLoginInfo* user)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_on_peer_parted() start"));
+
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));
+
+ // remove user
+ GCDEST gcd = { proto->m_szModuleName };
+ gcd.ptszID = tszConfId;
+ gcd.iType = GC_EVENT_PART;
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ TCHAR* tszUserName = mir_utf8decodeT(((mwLoginInfo*)user)->user_name);
+ TCHAR* tszUserId = mir_utf8decodeT(((mwLoginInfo*)user)->login_id);
+ gce.ptszNick = tszUserName;
+ gce.ptszUID = tszUserId;
+ gce.ptszStatus = _T("Normal");
+ gce.time = (DWORD)time(0);
+
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce);
+
+ mir_free(tszUserName);
+ mir_free(tszUserId);
+ mir_free(tszConfId);
+}
+
+/** triggered when someone says something */
+void mwServiceConf_on_text(mwConference* conf, mwLoginInfo* user, const char* what)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_on_text() start"));
+
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName(conf));
+
+ GCDEST gcd = { proto->m_szModuleName };
+ gcd.ptszID = tszConfId;
+ gcd.iType = GC_EVENT_MESSAGE;
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+
+ TCHAR* textT = mir_utf8decodeT(what);
+ TCHAR* tszUserName = mir_utf8decodeT(((mwLoginInfo*)user)->user_name);
+ TCHAR* tszUserId = mir_utf8decodeT(((mwLoginInfo*)user)->login_id);
+ gce.ptszText = textT;
+ gce.ptszNick = tszUserName;
+ gce.ptszUID = tszUserId;
+ gce.time = (DWORD)time(0);
+
+ CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce);
+
+ mir_free(textT);
+ mir_free(tszUserName);
+ mir_free(tszUserId);
+ mir_free(tszConfId);
+}
+
+/** typing notification */
+void mwServiceConf_on_typing(mwConference* conf, mwLoginInfo* who, gboolean typing)
+{
+ CSametimeProto* proto = getProtoFromMwConference(conf);
+ proto->debugLog(_T("mwServiceConf_on_typing() start"));
+ ///TODO unimplemented
+}
+
+/** optional. called from mwService_free */
+void mwServiceConf_clear(mwServiceConference* srvc)
+{
+}
+
+mwConferenceHandler mwConference_handler = {
+ mwServiceConf_on_invited,
+ mwServiceConf_conf_opened,
+ mwServiceConf_conf_closed,
+ mwServiceConf_on_peer_joined,
+ mwServiceConf_on_peer_parted,
+ mwServiceConf_on_text,
+ mwServiceConf_on_typing,
+ mwServiceConf_clear
+};
+
+void CSametimeProto::TerminateConference(char* name)
+{
+ debugLog(_T("CSametimeProto::TerminateConference() start"));
+
+ GList *conferences, *conf;
+ conferences = conf = mwServiceConference_getConferences(service_conference);
+ for (;conf;conf = conf->next) {
+ if (strcmp(name, mwConference_getName((mwConference*)conf->data)) == 0) {
+
+ TCHAR* idt = mir_utf8decodeT(name);
+ GCDEST gcd = {m_szModuleName, idt, GC_EVENT_CONTROL};
+
+ GCEVENT gce = { sizeof(gce), &gcd };
+ gce.dwFlags = GCEF_ADDTOLOG;
+ CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
+
+ mir_free(idt);
+ }
+ }
+ g_list_free(conferences);
+}
+
+
+int CSametimeProto::GcEventHook(WPARAM wParam, LPARAM lParam) {
+
+ GCHOOK* gch = (GCHOOK*)lParam;
+
+ if (strcmp(gch->pDest->pszModule, m_szModuleName) != 0) return 0;
+
+ GList *conferences, *conf;
+ conferences = conf = mwServiceConference_getConferences(service_conference);
+ for (;conf;conf = conf->next) {
+ TCHAR* tszConfId = mir_utf8decodeT(mwConference_getName((mwConference*)conf->data));
+ if (_tcscmp(gch->pDest->ptszID, tszConfId) == 0) {
+
+ switch(gch->pDest->iType) {
+ case GC_USER_MESSAGE:
+ {
+ debugLog(_T("CSametimeProto::GcEventHook() GC_USER_MESSAGE"));
+ char* utf_msg;
+ utf_msg = mir_utf8encodeT(gch->ptszText);
+ mwConference_sendText((mwConference*)conf->data, utf_msg);
+ mir_free(utf_msg);
+ }
+ break;
+ case GC_SESSION_TERMINATE:
+ {
+ if (my_conference == conf->data){
+ debugLog(_T("CSametimeProto::GcEventHook() GC_SESSION_TERMINATE CloseMyConference"));
+ CloseMyConference(this);
+ } else {
+ debugLog(_T("CSametimeProto::GcEventHook() GC_SESSION_TERMINATE mwConference_destroy"));
+ char* utfs = mir_utf8encodeT(TranslateT("I'm outa here."));
+ mwConference_destroy((mwConference*)conf->data, 0, utfs);
+ mir_free(utfs);
+ }
+ }
+ break;
+ }
+
+ break;
+ }
+ mir_free(tszConfId);
+ }
+
+ g_list_free(conferences);
+
+ return 0;
+}
+
+int CSametimeProto::ChatDeleted(MCONTACT hContact) {
+
+ if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 0)
+ return 0;
+
+ debugLog(_T("CSametimeProto::ChatDeleted() hContact=[%x]"), hContact);
+ DBVARIANT dbv;
+ if (!db_get_s(hContact, m_szModuleName, "ChatRoomID", &dbv)) {
+ TerminateConference(dbv.pszVal);
+ db_free(&dbv);
+ }
+
+ return 0;
+}
+
+
+INT_PTR CSametimeProto::onMenuLeaveChat(WPARAM wParam, LPARAM lParam)
+{
+ MCONTACT hContact = (MCONTACT)wParam;
+ debugLog(_T("CSametimeProto::onMenuLeaveChat() hContact=[%x]"), hContact);
+ ChatDeleted(hContact);
+ return 0;
+}
+
+
+INT_PTR CSametimeProto::onMenuCreateChat(WPARAM wParam, LPARAM lParam)
+{
+ MCONTACT hContact = (MCONTACT)wParam;
+ debugLog(_T("CSametimeProto::onMenuCreateChat() hContact=[%x]"), hContact);
+ mwAwareIdBlock id_block;
+ mwIdBlock idb;
+ if (my_login_info && GetAwareIdFromContact(hContact, &id_block)) {
+ TCHAR title[512];
+ TCHAR* ts = mir_utf8decodeT(my_login_info->user_name);
+ mir_sntprintf(title, SIZEOF(title), TranslateT("%s's Conference"), ts);
+ mir_free(ts);
+
+ idb.user = id_block.user;
+ idb.community = id_block.community;
+
+ invite_queue.push(idb.user);
+
+ if (!my_conference) {
+ debugLog(_T("CSametimeProto::onMenuCreateChat() mwConference_open"));
+ char* utfs;
+ my_conference = mwConference_new(service_conference, utfs = mir_utf8encodeT(title));
+ mwConference_open(my_conference);
+ mir_free(utfs);
+ } else {
+ debugLog(_T("CSametimeProto::onMenuCreateChat() ClearInviteQueue"));
+ ClearInviteQueue();
+ }
+
+ free(id_block.user);
+ }
+
+ return 0;
+}
+
+int CSametimeProto::PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ MCONTACT hContact = (MCONTACT)wParam;
+ debugLog(_T("CSametimeProto::PrebuildContactMenu() hContact=[%x]"), hContact);
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 1 ? 0 : CMIF_HIDDEN);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hLeaveChatMenuItem, (LPARAM)&mi);
+
+ // if user is already in our meeting,
+ bool not_present = true;
+ DBVARIANT dbv;
+ if (my_conference && !db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
+ char* user_id = dbv.pszVal;
+
+ GList *members, *mem;
+ members = mem = mwConference_getMembers(my_conference);
+ for (;mem;mem=mem->next) {
+ if (my_login_info && strcmp(user_id, ((mwLoginInfo *)mem->data)->user_id) == 0) {
+ not_present = false;
+ break;
+ }
+ }
+ g_list_free(members);
+
+ db_free(&dbv);
+ }
+ mi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 0 && not_present ? 0 : CMIF_HIDDEN);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hCreateChatMenuItem, (LPARAM)&mi);
+
+ return 0;
+}
+
+void CSametimeProto::InitConference()
+{
+ debugLog(_T("CSametimeProto::InitConference()"));
+
+ my_login_info = mwSession_getLoginInfo(session);
+
+ service_conference = mwServiceConference_new(session, &mwConference_handler);
+ mwSession_addService(session, (struct mwService*)service_conference);
+
+ HookProtoEvent(ME_GC_EVENT, &CSametimeProto::GcEventHook);
+}
+
+void CSametimeProto::DeinitConference()
+{
+ GList *conferences, *conf;
+ debugLog(_T("CSametimeProto::DeinitConference()"));
+
+ if (service_conference){
+ conferences = conf = mwServiceConference_getConferences(service_conference);
+ for (;conf;conf = conf->next) {
+ if (my_conference == conf->data) CloseMyConference(this);
+ else {
+ char* utfs = mir_utf8encodeT(TranslateT("I'm outa here."));
+ mwConference_destroy((mwConference*)conf->data, 0, utfs);
+ mir_free(utfs);
+ }
+ }
+ g_list_free(conferences);
+ }
+
+ my_login_info = 0;
+
+ mwSession_removeService(session, mwService_CONFERENCE);
+ if (service_conference){
+ mwService_free((mwService*)service_conference);
+ service_conference = 0;
+ }
+}
+
+void CSametimeProto::InitConferenceMenu()
+{
+ debugLog(_T("CSametimeProto::InitConferenceMenu()"));
+
+ CreateProtoService(MS_SAMETIME_MENULEAVECHAT, &CSametimeProto::onMenuLeaveChat);
+ CreateProtoService(MS_SAMETIME_MENUCREATECHAT, &CSametimeProto::onMenuCreateChat);
+
+ char service[128];
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIF_TCHAR | CMIF_NOTOFFLINE;
+ mi.pszContactOwner = m_szModuleName;
+
+ mi.ptszName = LPGENT("Leave Conference");
+ mir_snprintf(service, sizeof(service), "%s%s", m_szModuleName, MS_SAMETIME_MENULEAVECHAT);
+ mi.pszService = service;
+ mi.icolibItem = GetIconHandle(IDI_ICON_LEAVE);
+ hLeaveChatMenuItem = Menu_AddContactMenuItem(&mi);
+
+ mi.ptszName = LPGENT("Start Conference");
+ mir_snprintf(service, sizeof(service), "%s%s", m_szModuleName, MS_SAMETIME_MENUCREATECHAT);
+ mi.pszService = service;
+ mi.icolibItem = GetIconHandle(IDI_ICON_INVITE);
+ hCreateChatMenuItem = Menu_AddContactMenuItem(&mi);
+
+ HookProtoEvent(ME_CLIST_PREBUILDCONTACTMENU, &CSametimeProto::PrebuildContactMenu);
+}
+
+void CSametimeProto::DeinitConferenceMenu()
+{
+ debugLog(_T("CSametimeProto::DeinitConferenceMenu()"));
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hLeaveChatMenuItem, (LPARAM)0);
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hCreateChatMenuItem, (LPARAM)0);
+}
+
diff --git a/protocols/Sametime/src/files.cpp b/protocols/Sametime/src/files.cpp new file mode 100644 index 0000000000..a08fa49968 --- /dev/null +++ b/protocols/Sametime/src/files.cpp @@ -0,0 +1,457 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+CSametimeProto* getProtoFromMwFileTransfer(mwFileTransfer* ft)
+{
+ mwServiceFileTransfer* serviceFT = mwFileTransfer_getService(ft);
+ mwService* service = mwServiceFileTransfer_getService(serviceFT);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+
+/** an incoming file transfer has been offered */
+void mwFileTransfer_offered(mwFileTransfer* ft) {
+
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ proto->debugLog(_T("mwFileTransfer_offered() start"));
+
+ const mwIdBlock* idb = mwFileTransfer_getUser(ft);
+ MCONTACT hContact = proto->FindContactByUserId(idb->user);
+ proto->debugLog(_T("Sametime mwFileTransfer_offered hContact=[%x]"), hContact);
+
+ if (!hContact) {
+ mwSametimeList* user_list = mwSametimeList_new();
+ mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
+ mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, (mwIdBlock*)idb);
+ hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true));
+ }
+
+ proto->ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)ft, 0);
+
+ TCHAR* filenameT = mir_utf8decodeT(mwFileTransfer_getFileName(ft));
+ const char* message = mwFileTransfer_getMessage(ft);
+ TCHAR descriptionT[512];
+ if (message) {
+ TCHAR* messageT = mir_utf8decodeT(message);
+ mir_sntprintf(descriptionT, SIZEOF(descriptionT), _T("%s - %s"), filenameT, messageT);
+ mir_free(messageT);
+ } else {
+ mir_sntprintf(descriptionT, SIZEOF(descriptionT), _T("%s"), filenameT);
+ }
+
+ PROTORECVFILET pre = {0};
+ pre.flags = PREF_TCHAR;
+ pre.fileCount = 1;
+ pre.timestamp = time(NULL);
+ pre.tszDescription = descriptionT;
+ pre.ptszFiles = &filenameT;
+ pre.lParam = (LPARAM)ft;
+
+ ProtoChainRecvFile(hContact, &pre);
+
+ mir_free(filenameT);
+
+}
+
+//returns 0 if finished with current file
+int SendFileChunk(CSametimeProto* proto, mwFileTransfer* ft, FileTransferClientData* ftcd) {
+ DWORD bytes_read;
+ mwOpaque o;
+
+ if (!ftcd || !ftcd->buffer)
+ return 0;
+
+ if (!ReadFile(ftcd->hFile, ftcd->buffer, FILE_BUFF_SIZE, &bytes_read, 0)) {
+ proto->debugLog(_T("Sametime closing file transfer (SendFileChunk)"));
+ mwFileTransfer_close(ft, mwFileTransfer_SUCCESS);
+ return 0;
+ }
+ o.data = (unsigned char*)ftcd->buffer;
+ o.len = bytes_read;
+
+ mwFileTransfer_send(ft, &o);
+
+ return bytes_read;
+}
+
+void __cdecl SendThread(LPVOID param) {
+
+ mwFileTransfer* ft = (mwFileTransfer*)param;
+ if (!ft) return;
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+
+ proto->debugLog(_T("SendThread() start"));
+
+ PROTOFILETRANSFERSTATUS pfts = {0};
+
+ pfts.cbSize = sizeof(pfts);
+ pfts.flags = PFTS_UTF;
+ pfts.hContact = ftcd->hContact;
+ if (ftcd->sending == 1){
+ pfts.flags |= PFTS_SENDING;
+ }
+ pfts.pszFiles = NULL;
+ pfts.totalFiles = ftcd->first->ft_count;
+ pfts.totalBytes = ftcd->first->totalSize;
+
+ while(SendFileChunk(proto, ft, ftcd) && !Miranda_Terminated()) {
+
+ pfts.currentFileNumber = ftcd->ft_number;
+ pfts.totalProgress = ftcd->sizeToHere + mwFileTransfer_getSent(ft);
+ pfts.szWorkingDir = ftcd->save_path;
+ pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft);
+ pfts.currentFileSize = mwFileTransfer_getFileSize(ft);
+ pfts.currentFileProgress = mwFileTransfer_getSent(ft);
+ pfts.currentFileTime = 0; //?
+
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts);
+
+ SleepEx(500,TRUE);
+ }
+
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0);
+
+ mwFileTransfer_removeClientData(ft);
+ if (ftcd->save_path) free(ftcd->save_path);
+ if (ftcd->buffer) delete[] ftcd->buffer;
+ delete ftcd;
+
+ proto->debugLog(_T("SendThread() end"));
+ return;
+}
+
+/** a file transfer has been fully initiated */
+void mwFileTransfer_opened(mwFileTransfer* ft) {
+
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+
+ proto->debugLog(_T("Sametime mwFileTransfer_opened start"));
+
+ if (ftcd->sending) {
+ // create a thread to send chunks - since it seems not all clients send acks for each of our chunks!
+ mir_forkthread(SendThread, (void*)ft);
+ }
+}
+
+/** a file transfer has been closed. Check the status of the file
+ transfer to determine if the transfer was complete or if it had
+ been interrupted */
+void mwFileTransfer_closed(mwFileTransfer* ft, guint32 code) {
+
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+ proto->debugLog(_T("mwFileTransfer_closed() start"));
+
+ if (ftcd) {
+ if (ftcd->hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(ftcd->hFile);
+
+ if (code != mwFileTransfer_SUCCESS || !mwFileTransfer_isDone(ft)) {
+ if (!ftcd->sending) {
+ char fn[MAX_PATH];
+ if (ftcd->save_path) strcpy(fn, ftcd->save_path);
+ else fn[0] = 0;
+ strcat(fn, mwFileTransfer_getFileName(ft));
+
+ DeleteFileA(fn);
+ }
+
+ if (code == mwFileTransfer_REJECTED) {
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ftcd->hFt, 0);
+ } else {
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ftcd->hFt, 0);
+ }
+
+ if (ftcd->sending) {
+ FileTransferClientData* ftcd_next = ftcd->next, *ftcd_temp;
+ while(ftcd_next) {
+ mwFileTransfer_free((mwFileTransfer*)ftcd_next->ft);
+ ftcd_temp = ftcd_next->next;
+
+ if (ftcd_next->hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(ftcd->hFile);
+
+ if (ftcd_next->save_path) free(ftcd_next->save_path);
+ if (ftcd_next->buffer) delete[] ftcd_next->buffer;
+ delete ftcd_next;
+ ftcd_next = ftcd_temp;
+ }
+ } else {
+ mwFileTransfer_removeClientData(ft);
+ if (ftcd->save_path) free(ftcd->save_path);
+ if (ftcd->buffer) delete[] ftcd->buffer;
+ delete ftcd;
+
+ mwFileTransfer_free(ft);
+ }
+
+ } else {
+ if (ftcd->sending) {
+ // check if we have more files to send...
+ if (ftcd->next) {
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ftcd->hFt, 0);
+ mwFileTransfer_offer(ftcd->next->ft);
+ }
+ } else {
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0);
+
+ mwFileTransfer_removeClientData(ft);
+ if (ftcd->save_path) free(ftcd->save_path);
+ if (ftcd->buffer) delete[] ftcd->buffer;
+ delete ftcd;
+
+ mwFileTransfer_free(ft);
+ }
+ }
+
+ }
+
+}
+
+/** receive a chunk of a file from an inbound file transfer. */
+void mwFileTransfer_recv(mwFileTransfer* ft, struct mwOpaque* data) {
+
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+ proto->debugLog(_T("mwFileTransfer_recv() start"));
+
+ DWORD bytes_written;
+ if (!WriteFile(ftcd->hFile, data->data, data->len, &bytes_written, 0)) {
+ proto->debugLog(_T("mwFileTransfer_recv() !WriteFile"));
+ mwFileTransfer_cancel(ft);
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ftcd->hFt, 0);
+ proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_FAILED"));
+ } else {
+ //if (mwFileTransfer_isOpen(ft))
+ mwFileTransfer_ack(ft); // acknowledge chunk
+
+ PROTOFILETRANSFERSTATUS pfts = {0};
+ pfts.cbSize = sizeof(pfts);
+ pfts.flags = PFTS_UTF;
+ pfts.hContact = ftcd->hContact;
+ if (ftcd->sending == 1){
+ pfts.flags |= PFTS_SENDING;
+ }
+ pfts.pszFiles = NULL;
+ pfts.totalFiles = 1;
+ pfts.currentFileNumber = 0;
+ pfts.totalBytes = mwFileTransfer_getFileSize(ft);
+ pfts.totalProgress = mwFileTransfer_getSent(ft);
+ pfts.szWorkingDir = ftcd->save_path;
+ pfts.szCurrentFile = (char*)mwFileTransfer_getFileName(ft);
+ pfts.currentFileSize = mwFileTransfer_getFileSize(ft);
+ pfts.currentFileProgress = mwFileTransfer_getSent(ft);
+ pfts.currentFileTime = 0; //?
+
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftcd->hFt, (LPARAM)&pfts);
+ proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_DATA"));
+
+ if (mwFileTransfer_isDone(ft)){
+ proto->ProtoBroadcastAck(ftcd->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftcd->hFt, 0);
+ proto->debugLog(_T("mwFileTransfer_recv() ACKRESULT_SUCCESS"));
+ }
+ }
+
+}
+
+/** received an ack for a sent chunk on an outbound file transfer.
+ this indicates that a previous call to mwFileTransfer_send has
+ reached the target and that the target has responded. */
+void mwFileTransfer_handle_ack(mwFileTransfer* ft) {
+ // see SendThread above - not all clients send us acks
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ //FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+ proto->debugLog(_T("mwFileTransfer_handle_ack()"));
+}
+
+/** optional. called from mwService_free */
+void mwFileTransfer_clear(mwServiceFileTransfer* srvc) {
+
+}
+
+mwFileTransferHandler mwFileTransfer_handler = {
+ mwFileTransfer_offered,
+ mwFileTransfer_opened,
+ mwFileTransfer_closed,
+ mwFileTransfer_recv,
+ mwFileTransfer_handle_ack,
+ mwFileTransfer_clear
+};
+
+HANDLE CSametimeProto::SendFilesToUser(MCONTACT hContact, PROTOCHAR** files, const PROTOCHAR* ptszDesc)
+{
+ debugLog(_T("CSametimeProto::SendFilesToUser() start"));
+
+ mwAwareIdBlock id_block;
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ mwIdBlock idb;
+ idb.user = id_block.user;
+ idb.community = id_block.community;
+
+ HANDLE hFile;
+ DWORD filesize;
+ FileTransferClientData *ftcd, *prev_ftcd = 0, *first_ftcd = 0;
+ mwFileTransfer *ft, *first_ft = 0;
+
+ TCHAR* fn;
+
+ for (int i = 0; files[i]; i++) {
+ hFile = CreateFile(files[i], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (hFile != INVALID_HANDLE_VALUE) {
+ filesize = GetFileSize(hFile, 0);
+
+ fn = _tcsrchr(files[i], '\\');
+ if (fn) fn++;
+
+ char* pszDesc_utf8 = mir_utf8encodeT(ptszDesc);
+ char* pszFile_utf8;
+ if (fn) {
+ pszFile_utf8 = mir_utf8encodeT(fn);
+ } else {
+ pszFile_utf8 = mir_utf8encodeT(files[i]);
+ }
+ ft = mwFileTransfer_new(service_files, &idb, pszDesc_utf8, pszFile_utf8, filesize);
+ mir_free(pszFile_utf8);
+ mir_free(pszDesc_utf8);
+
+ ftcd = new FileTransferClientData;
+ memset((void*)ftcd, 0, sizeof(FileTransferClientData));
+
+ ftcd->ft = ft;
+ ftcd->hContact = hContact;
+
+ ftcd->next = 0;
+ if (prev_ftcd) {
+ prev_ftcd->next = ftcd; // link into list
+
+ // each node contains a pointer to the first - it will contain infor linke the count etc
+ ftcd->first = prev_ftcd->first;
+ } else {
+ ftcd->first = ftcd;
+ }
+
+ if (!first_ft) first_ft = ft;
+
+ ftcd->sending = true;
+ ftcd->hFile = hFile;
+ ftcd->hFt = (HANDLE)first_ft;
+
+ ftcd->save_path = 0;
+ ftcd->buffer = new char[FILE_BUFF_SIZE];
+
+ ftcd->ft_number = ftcd->first->ft_count;
+ ftcd->first->ft_count++;
+ ftcd->sizeToHere = ftcd->first->totalSize;
+ ftcd->first->totalSize += filesize;
+
+ mwFileTransfer_setClientData(ft, (gpointer)ftcd, 0);
+
+ prev_ftcd = ftcd;
+ }
+ }
+
+ free(id_block.user);
+
+ if (first_ft) {
+ mwFileTransfer_offer(first_ft);
+ return (HANDLE)first_ft;
+ }
+
+ }
+
+ return 0;
+}
+
+HANDLE CSametimeProto::AcceptFileTransfer(MCONTACT hContact, HANDLE hFt, char* save_path)
+{
+
+ mwFileTransfer* ft = (mwFileTransfer*)(hFt);
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ debugLog(_T("CSametimeProto::AcceptFileTransfer() start"));
+
+ FileTransferClientData* ftcd = new FileTransferClientData;
+ memset((void*)ftcd, 0, sizeof(FileTransferClientData));
+ ftcd->ft = ft;
+ ftcd->sending = false;
+ ftcd->hFt = (HANDLE)ft;
+
+ if (save_path) // save path
+ ftcd->save_path = _strdup(save_path);
+ else
+ ftcd->save_path = 0;
+
+ mwFileTransfer_setClientData(ft, (gpointer)ftcd, 0);
+
+ char fp[MAX_PATH];
+ char* fn = strrchr((char*)mwFileTransfer_getFileName(ft), '\\');
+ if (fn) fn++;
+
+ if (ftcd->save_path)
+ strcpy(fp, ftcd->save_path);
+ else
+ fp[0] = 0;
+
+ if (fn) strcat(fp, fn);
+ else strcat(fp, mwFileTransfer_getFileName(ft));
+
+ ftcd->hFile = CreateFileA(fp, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
+ if (ftcd->hFile == INVALID_HANDLE_VALUE) {
+ debugLog(_T("CSametimeProto::AcceptFileTransfer() INVALID_HANDLE_VALUE"));
+ mwFileTransfer_close(ft, mwFileTransfer_ERROR);
+ return 0;
+ }
+
+ ftcd->hContact = hContact;
+
+ mwFileTransfer_setClientData(ft, (gpointer)ftcd, 0);
+
+ mwFileTransfer_accept(ft);
+ return hFt;
+}
+
+
+void CSametimeProto::RejectFileTransfer(HANDLE hFt)
+{
+ mwFileTransfer* ft = (mwFileTransfer*)hFt;
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ debugLog(_T("CSametimeProto::RejectFileTransfer() start"));
+
+ mwFileTransfer_reject(ft);
+}
+
+
+void CSametimeProto::CancelFileTransfer(HANDLE hFt)
+{
+ mwFileTransfer* ft = (mwFileTransfer*)hFt;
+ CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
+ debugLog(_T("CSametimeProto::CancelFileTransfer() start"));
+
+ FileTransferClientData* ftcd = (FileTransferClientData*)mwFileTransfer_getClientData(ft);
+
+ if (ftcd) {
+ while(mwFileTransfer_isDone(ftcd->ft) && ftcd)
+ ftcd = ftcd->next;
+
+ if (ftcd) mwFileTransfer_cancel(ftcd->ft);
+ } else
+ mwFileTransfer_cancel(ft);
+}
+
+void CSametimeProto::InitFiles()
+{
+ debugLog(_T("CSametimeProto::InitFiles()"));
+ mwSession_addService(session, (mwService*)(service_files = mwServiceFileTransfer_new(session, &mwFileTransfer_handler)));
+}
+
+void CSametimeProto::DeinitFiles()
+{
+ debugLog(_T("CSametimeProto::DeinitFiles()"));
+ mwSession_removeService(session, mwService_FILE_TRANSFER);
+ mwService_free((mwService*)service_files);
+ service_files = 0;
+}
+
diff --git a/protocols/Sametime/src/glib/include/glib.h b/protocols/Sametime/src/glib/include/glib.h new file mode 100644 index 0000000000..06d0190b24 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib.h @@ -0,0 +1,99 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __G_LIB_H__ +#define __G_LIB_H__ + +#define __GLIB_H_INSIDE__ + +#include <glib/galloca.h> +#include <glib/garray.h> +#include <glib/gasyncqueue.h> +#include <glib/gatomic.h> +#include <glib/gbacktrace.h> +#include <glib/gbase64.h> +#include <glib/gbitlock.h> +#include <glib/gbookmarkfile.h> +#include <glib/gcache.h> +#include <glib/gchecksum.h> +#include <glib/gcompletion.h> +#include <glib/gconvert.h> +#include <glib/gdataset.h> +#include <glib/gdate.h> +#include <glib/gdatetime.h> +#include <glib/gdir.h> +#include <glib/gerror.h> +#include <glib/gfileutils.h> +#include <glib/ghash.h> +#include <glib/ghook.h> +#include <glib/ghostutils.h> +#include <glib/giochannel.h> +#include <glib/gkeyfile.h> +#include <glib/glist.h> +#include <glib/gmacros.h> +#include <glib/gmain.h> +#include <glib/gmappedfile.h> +#include <glib/gmarkup.h> +#include <glib/gmem.h> +#include <glib/gmessages.h> +#include <glib/gnode.h> +#include <glib/goption.h> +#include <glib/gpattern.h> +#include <glib/gpoll.h> +#include <glib/gprimes.h> +#include <glib/gqsort.h> +#include <glib/gquark.h> +#include <glib/gqueue.h> +#include <glib/grand.h> +#include <glib/grel.h> +#include <glib/gregex.h> +#include <glib/gscanner.h> +#include <glib/gsequence.h> +#include <glib/gshell.h> +#include <glib/gslice.h> +#include <glib/gslist.h> +#include <glib/gspawn.h> +#include <glib/gstrfuncs.h> +#include <glib/gstring.h> +#include <glib/gtestutils.h> +#include <glib/gthread.h> +#include <glib/gthreadpool.h> +#include <glib/gtimer.h> +#include <glib/gtimezone.h> +#include <glib/gtree.h> +#include <glib/gtypes.h> +#include <glib/gunicode.h> +#include <glib/gurifuncs.h> +#include <glib/gutils.h> +#include <glib/gvarianttype.h> +#include <glib/gvariant.h> +#ifdef G_PLATFORM_WIN32 +#include <glib/gwin32.h> +#endif + +#undef __GLIB_H_INSIDE__ + +#endif /* __G_LIB_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/galloca.h b/protocols/Sametime/src/glib/include/glib/galloca.h new file mode 100644 index 0000000000..8876836a6f --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/galloca.h @@ -0,0 +1,110 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_ALLOCA_H__ +#define __G_ALLOCA_H__ + +#include <glib/gtypes.h> + +#ifdef __GNUC__ +/* GCC does the right thing */ +# undef alloca +# define alloca(size) __builtin_alloca (size) +#elif defined (GLIB_HAVE_ALLOCA_H) +/* a native and working alloca.h is there */ +# include <alloca.h> +#else /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */ +# if defined(_MSC_VER) || defined(__DMC__) +# include <malloc.h> +# define alloca _alloca +# else /* !_MSC_VER && !__DMC__ */ +# ifdef _AIX +# pragma alloca +# else /* !_AIX */ +# ifndef alloca /* predefined by HP cc +Olibcalls */ +G_BEGIN_DECLS +char *alloca (); +G_END_DECLS +# endif /* !alloca */ +# endif /* !_AIX */ +# endif /* !_MSC_VER && !__DMC__ */ +#endif /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */ + +/** + * g_alloca: + * @size: number of bytes to allocate. + * + * Allocates @size bytes on the stack; these bytes will be freed when the current + * stack frame is cleaned up. This macro essentially just wraps the alloca() + * function present on most UNIX variants. + * Thus it provides the same advantages and pitfalls as alloca(): + * <variablelist> + * <varlistentry><term></term><listitem><para> + * + alloca() is very fast, as on most systems it's implemented by just adjusting + * the stack pointer register. + * </para></listitem></varlistentry> + * <varlistentry><term></term><listitem><para> + * + It doesn't cause any memory fragmentation, within its scope, separate alloca() + * blocks just build up and are released together at function end. + * </para></listitem></varlistentry> + * <varlistentry><term></term><listitem><para> + * - Allocation sizes have to fit into the current stack frame. For instance in a + * threaded environment on Linux, the per-thread stack size is limited to 2 Megabytes, + * so be sparse with alloca() uses. + * </para></listitem></varlistentry> + * <varlistentry><term></term><listitem><para> + * - Allocation failure due to insufficient stack space is not indicated with a %NULL + * return like e.g. with malloc(). Instead, most systems probably handle it the same + * way as out of stack space situations from infinite function recursion, i.e. + * with a segmentation fault. + * </para></listitem></varlistentry> + * <varlistentry><term></term><listitem><para> + * - Special care has to be taken when mixing alloca() with GNU C variable sized arrays. + * Stack space allocated with alloca() in the same scope as a variable sized array + * will be freed together with the variable sized array upon exit of that scope, and + * not upon exit of the enclosing function scope. + * </para></listitem></varlistentry> + * </variablelist> + * + * Returns: space for @size bytes, allocated on the stack + */ +#define g_alloca(size) alloca (size) +/** + * g_newa: + * @struct_type: Type of memory chunks to be allocated + * @n_structs: Number of chunks to be allocated + * + * Wraps g_alloca() in a more typesafe manner. + * + * Returns: Pointer to stack space for @n_structs chunks of type @struct_type + */ +#define g_newa(struct_type, n_structs) ((struct_type*) g_alloca (sizeof (struct_type) * (gsize) (n_structs))) + +#endif /* __G_ALLOCA_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/garray.h b/protocols/Sametime/src/glib/include/glib/garray.h new file mode 100644 index 0000000000..6bc51f797e --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/garray.h @@ -0,0 +1,179 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_ARRAY_H__ +#define __G_ARRAY_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef struct _GArray GArray; +typedef struct _GByteArray GByteArray; +typedef struct _GPtrArray GPtrArray; + +struct _GArray +{ + gchar *data; + guint len; +}; + +struct _GByteArray +{ + guint8 *data; + guint len; +}; + +struct _GPtrArray +{ + gpointer *pdata; + guint len; +}; + +/* Resizable arrays. remove fills any cleared spot and shortens the + * array, while preserving the order. remove_fast will distort the + * order by moving the last element to the position of the removed. + */ + +#define g_array_append_val(a,v) g_array_append_vals (a, &(v), 1) +#define g_array_prepend_val(a,v) g_array_prepend_vals (a, &(v), 1) +#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &(v), 1) +#define g_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)]) + +GArray* g_array_new (gboolean zero_terminated, + gboolean clear_, + guint element_size); +GArray* g_array_sized_new (gboolean zero_terminated, + gboolean clear_, + guint element_size, + guint reserved_size); +gchar* g_array_free (GArray *array, + gboolean free_segment); +GArray *g_array_ref (GArray *array); +void g_array_unref (GArray *array); +guint g_array_get_element_size (GArray *array); +GArray* g_array_append_vals (GArray *array, + gconstpointer data, + guint len); +GArray* g_array_prepend_vals (GArray *array, + gconstpointer data, + guint len); +GArray* g_array_insert_vals (GArray *array, + guint index_, + gconstpointer data, + guint len); +GArray* g_array_set_size (GArray *array, + guint length); +GArray* g_array_remove_index (GArray *array, + guint index_); +GArray* g_array_remove_index_fast (GArray *array, + guint index_); +GArray* g_array_remove_range (GArray *array, + guint index_, + guint length); +void g_array_sort (GArray *array, + GCompareFunc compare_func); +void g_array_sort_with_data (GArray *array, + GCompareDataFunc compare_func, + gpointer user_data); + +/* Resizable pointer array. This interface is much less complicated + * than the above. Add appends a pointer. Remove fills any cleared + * spot and shortens the array. remove_fast will again distort order. + */ +#define g_ptr_array_index(array,index_) ((array)->pdata)[index_] +GPtrArray* g_ptr_array_new (void); +GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func); +GPtrArray* g_ptr_array_sized_new (guint reserved_size); +gpointer* g_ptr_array_free (GPtrArray *array, + gboolean free_seg); +GPtrArray* g_ptr_array_ref (GPtrArray *array); +void g_ptr_array_unref (GPtrArray *array); +void g_ptr_array_set_free_func (GPtrArray *array, + GDestroyNotify element_free_func); +void g_ptr_array_set_size (GPtrArray *array, + gint length); +gpointer g_ptr_array_remove_index (GPtrArray *array, + guint index_); +gpointer g_ptr_array_remove_index_fast (GPtrArray *array, + guint index_); +gboolean g_ptr_array_remove (GPtrArray *array, + gpointer data); +gboolean g_ptr_array_remove_fast (GPtrArray *array, + gpointer data); +void g_ptr_array_remove_range (GPtrArray *array, + guint index_, + guint length); +void g_ptr_array_add (GPtrArray *array, + gpointer data); +void g_ptr_array_sort (GPtrArray *array, + GCompareFunc compare_func); +void g_ptr_array_sort_with_data (GPtrArray *array, + GCompareDataFunc compare_func, + gpointer user_data); +void g_ptr_array_foreach (GPtrArray *array, + GFunc func, + gpointer user_data); + + +/* Byte arrays, an array of guint8. Implemented as a GArray, + * but type-safe. + */ + +GByteArray* g_byte_array_new (void); +GByteArray* g_byte_array_sized_new (guint reserved_size); +guint8* g_byte_array_free (GByteArray *array, + gboolean free_segment); +GByteArray *g_byte_array_ref (GByteArray *array); +void g_byte_array_unref (GByteArray *array); +GByteArray* g_byte_array_append (GByteArray *array, + const guint8 *data, + guint len); +GByteArray* g_byte_array_prepend (GByteArray *array, + const guint8 *data, + guint len); +GByteArray* g_byte_array_set_size (GByteArray *array, + guint length); +GByteArray* g_byte_array_remove_index (GByteArray *array, + guint index_); +GByteArray* g_byte_array_remove_index_fast (GByteArray *array, + guint index_); +GByteArray* g_byte_array_remove_range (GByteArray *array, + guint index_, + guint length); +void g_byte_array_sort (GByteArray *array, + GCompareFunc compare_func); +void g_byte_array_sort_with_data (GByteArray *array, + GCompareDataFunc compare_func, + gpointer user_data); + +G_END_DECLS + +#endif /* __G_ARRAY_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gasyncqueue.h b/protocols/Sametime/src/glib/include/glib/gasyncqueue.h new file mode 100644 index 0000000000..9da43e36da --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gasyncqueue.h @@ -0,0 +1,120 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_ASYNCQUEUE_H__ +#define __G_ASYNCQUEUE_H__ + +#include <glib/gthread.h> + +G_BEGIN_DECLS + +typedef struct _GAsyncQueue GAsyncQueue; + +/* Asyncronous Queues, can be used to communicate between threads */ + +/* Get a new GAsyncQueue with the ref_count 1 */ +GAsyncQueue* g_async_queue_new (void); + +GAsyncQueue* g_async_queue_new_full (GDestroyNotify item_free_func); + +/* Lock and unlock a GAsyncQueue. All functions lock the queue for + * themselves, but in certain cirumstances you want to hold the lock longer, + * thus you lock the queue, call the *_unlocked functions and unlock it again. + */ +void g_async_queue_lock (GAsyncQueue *queue); +void g_async_queue_unlock (GAsyncQueue *queue); + +/* Ref and unref the GAsyncQueue. */ +GAsyncQueue* g_async_queue_ref (GAsyncQueue *queue); +void g_async_queue_unref (GAsyncQueue *queue); + +#ifndef G_DISABLE_DEPRECATED +/* You don't have to hold the lock for calling *_ref and *_unref anymore. */ +void g_async_queue_ref_unlocked (GAsyncQueue *queue); +void g_async_queue_unref_and_unlock (GAsyncQueue *queue); +#endif /* !G_DISABLE_DEPRECATED */ + +/* Push data into the async queue. Must not be NULL. */ +void g_async_queue_push (GAsyncQueue *queue, + gpointer data); +void g_async_queue_push_unlocked (GAsyncQueue *queue, + gpointer data); + +void g_async_queue_push_sorted (GAsyncQueue *queue, + gpointer data, + GCompareDataFunc func, + gpointer user_data); +void g_async_queue_push_sorted_unlocked (GAsyncQueue *queue, + gpointer data, + GCompareDataFunc func, + gpointer user_data); + +/* Pop data from the async queue. When no data is there, the thread is blocked + * until data arrives. + */ +gpointer g_async_queue_pop (GAsyncQueue *queue); +gpointer g_async_queue_pop_unlocked (GAsyncQueue *queue); + +/* Try to pop data. NULL is returned in case of empty queue. */ +gpointer g_async_queue_try_pop (GAsyncQueue *queue); +gpointer g_async_queue_try_pop_unlocked (GAsyncQueue *queue); + + + +/* Wait for data until at maximum until end_time is reached. NULL is returned + * in case of empty queue. + */ +gpointer g_async_queue_timed_pop (GAsyncQueue *queue, + GTimeVal *end_time); +gpointer g_async_queue_timed_pop_unlocked (GAsyncQueue *queue, + GTimeVal *end_time); + +/* Return the length of the queue. Negative values mean that threads + * are waiting, positve values mean that there are entries in the + * queue. Actually this function returns the length of the queue minus + * the number of waiting threads, g_async_queue_length == 0 could also + * mean 'n' entries in the queue and 'n' thread waiting. Such can + * happen due to locking of the queue or due to scheduling. + */ +gint g_async_queue_length (GAsyncQueue *queue); +gint g_async_queue_length_unlocked (GAsyncQueue *queue); +void g_async_queue_sort (GAsyncQueue *queue, + GCompareDataFunc func, + gpointer user_data); +void g_async_queue_sort_unlocked (GAsyncQueue *queue, + GCompareDataFunc func, + gpointer user_data); + +/* Private API */ +GMutex* _g_async_queue_get_mutex (GAsyncQueue *queue); + +G_END_DECLS + +#endif /* __G_ASYNCQUEUE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gatomic.h b/protocols/Sametime/src/glib/include/glib/gatomic.h new file mode 100644 index 0000000000..ddd39b8a3a --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gatomic.h @@ -0,0 +1,105 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * g_atomic_*: atomic operations. + * Copyright (C) 2003 Sebastian Wilhelmi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_ATOMIC_H__ +#define __G_ATOMIC_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +gint g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, + gint val); +void g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic, + gint val); +gboolean g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, + gint oldval, + gint newval); +gboolean g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, + gpointer oldval, + gpointer newval); + +gint g_atomic_int_get (volatile gint G_GNUC_MAY_ALIAS *atomic); +void g_atomic_int_set (volatile gint G_GNUC_MAY_ALIAS *atomic, + gint newval); +gpointer g_atomic_pointer_get (volatile gpointer G_GNUC_MAY_ALIAS *atomic); +void g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALIAS *atomic, + gpointer newval); + +#ifndef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED +# define g_atomic_int_get(atomic) ((gint)*(atomic)) +# define g_atomic_int_set(atomic, newval) ((void) (*(atomic) = (newval))) +# define g_atomic_pointer_get(atomic) ((gpointer)*(atomic)) +# define g_atomic_pointer_set(atomic, newval) ((void) (*(atomic) = (newval))) +#else +# define g_atomic_int_get(atomic) \ + ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]), \ + (g_atomic_int_get) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic))) +# define g_atomic_int_set(atomic, newval) \ + ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gint) ? 1 : -1]), \ + (g_atomic_int_set) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval))) +# define g_atomic_pointer_get(atomic) \ + ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \ + (g_atomic_pointer_get) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic))) +# define g_atomic_pointer_set(atomic, newval) \ + ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \ + (g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval))) +#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ + +/** + * g_atomic_int_inc: + * @atomic: a pointer to an integer. + * + * Atomically increments the integer pointed to by @atomic by 1. + * + * Since: 2.4 + */ +#define g_atomic_int_inc(atomic) (g_atomic_int_add ((atomic), 1)) + +/** + * g_atomic_int_dec_and_test: + * @atomic: a pointer to an integer + * + * Atomically decrements the integer pointed to by @atomic by 1. + * + * Returns: %TRUE if the integer pointed to by @atomic is 0 + * after decrementing it + * + * Since: 2.4 + */ +#define g_atomic_int_dec_and_test(atomic) \ + (g_atomic_int_exchange_and_add ((atomic), -1) == 1) + +G_END_DECLS + +#endif /* __G_ATOMIC_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gbacktrace.h b/protocols/Sametime/src/glib/include/glib/gbacktrace.h new file mode 100644 index 0000000000..43a0c46a21 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gbacktrace.h @@ -0,0 +1,68 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_BACKTRACE_H__ +#define __G_BACKTRACE_H__ + +#include <glib/gtypes.h> +#include <signal.h> + +G_BEGIN_DECLS + +/* Fatal error handlers. + * g_on_error_query() will prompt the user to either + * [E]xit, [H]alt, [P]roceed or show [S]tack trace. + * g_on_error_stack_trace() invokes gdb, which attaches to the current + * process and shows a stack trace. + * These function may cause different actions on non-unix platforms. + * The prg_name arg is required by gdb to find the executable, if it is + * passed as NULL, g_on_error_query() will try g_get_prgname(). + */ +void g_on_error_query (const gchar *prg_name); +void g_on_error_stack_trace (const gchar *prg_name); + +/* Hacker macro to place breakpoints for selected machines. + * Actual use is strongly discouraged of course ;) + */ +#if (defined (__i386__) || defined (__x86_64__)) && defined (__GNUC__) && __GNUC__ >= 2 +# define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("int $03"); }G_STMT_END +#elif (defined (_MSC_VER) || defined (__DMC__)) && defined (_M_IX86) +# define G_BREAKPOINT() G_STMT_START{ __asm int 3h }G_STMT_END +#elif defined (_MSC_VER) +# define G_BREAKPOINT() G_STMT_START{ __debugbreak(); }G_STMT_END +#elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2 +# define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("bpt"); }G_STMT_END +#else /* !__i386__ && !__alpha__ */ +# define G_BREAKPOINT() G_STMT_START{ raise (SIGTRAP); }G_STMT_END +#endif /* __i386__ */ + +G_END_DECLS + +#endif /* __G_BACKTRACE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gbase64.h b/protocols/Sametime/src/glib/include/glib/gbase64.h new file mode 100644 index 0000000000..930389a674 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gbase64.h @@ -0,0 +1,57 @@ +/* gbase64.h - Base64 coding functions + * + * Copyright (C) 2005 Alexander Larsson <alexl@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_BASE64_H__ +#define __G_BASE64_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +gsize g_base64_encode_step (const guchar *in, + gsize len, + gboolean break_lines, + gchar *out, + gint *state, + gint *save); +gsize g_base64_encode_close (gboolean break_lines, + gchar *out, + gint *state, + gint *save); +gchar* g_base64_encode (const guchar *data, + gsize len) G_GNUC_MALLOC; +gsize g_base64_decode_step (const gchar *in, + gsize len, + guchar *out, + gint *state, + guint *save); +guchar *g_base64_decode (const gchar *text, + gsize *out_len) G_GNUC_MALLOC; +guchar *g_base64_decode_inplace (gchar *text, + gsize *out_len); + + +G_END_DECLS + +#endif /* __G_BASE64_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gbitlock.h b/protocols/Sametime/src/glib/include/glib/gbitlock.h new file mode 100644 index 0000000000..5f6a67fd84 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gbitlock.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2008 Ryan Lortie + * Copyright © 2010 Codethink Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#ifndef __G_BITLOCK_H__ +#define __G_BITLOCK_H__ + +#include <glib/gtypes.h> + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +G_BEGIN_DECLS + +void g_bit_lock (volatile gint *address, + gint lock_bit); +gboolean g_bit_trylock (volatile gint *address, + gint lock_bit); +void g_bit_unlock (volatile gint *address, + gint lock_bit); + +G_END_DECLS + +#endif /* __G_BITLOCK_H_ */ diff --git a/protocols/Sametime/src/glib/include/glib/gbookmarkfile.h b/protocols/Sametime/src/glib/include/glib/gbookmarkfile.h new file mode 100644 index 0000000000..f663ebf27f --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gbookmarkfile.h @@ -0,0 +1,215 @@ +/* gbookmarkfile.h: parsing and building desktop bookmarks + * + * Copyright (C) 2005-2006 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_BOOKMARK_FILE_H__ +#define __G_BOOKMARK_FILE_H__ + +#include <glib/gerror.h> +#include <time.h> + +G_BEGIN_DECLS + +/** + * G_BOOKMARK_FILE_ERROR: + * + * Error domain for bookmark file parsing. + * Errors in this domain will be from the #GBookmarkFileError + * enumeration. See #GError for information on error domains. + */ +#define G_BOOKMARK_FILE_ERROR (g_bookmark_file_error_quark ()) + + +/** + * GBookmarkFileError: + * @G_BOOKMARK_FILE_ERROR_INVALID_URI: URI was ill-formed + * @G_BOOKMARK_FILE_ERROR_INVALID_VALUE: a requested field was not found + * @G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED: a requested application did + * not register a bookmark + * @G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND: a requested URI was not found + * @G_BOOKMARK_FILE_ERROR_READ: document was ill formed + * @G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING: the text being parsed was + * in an unknown encoding + * @G_BOOKMARK_FILE_ERROR_WRITE: an error occurred while writing + * @G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND: requested file was not found + * + * Error codes returned by bookmark file parsing. + */ +typedef enum +{ + G_BOOKMARK_FILE_ERROR_INVALID_URI, + G_BOOKMARK_FILE_ERROR_INVALID_VALUE, + G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED, + G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, + G_BOOKMARK_FILE_ERROR_READ, + G_BOOKMARK_FILE_ERROR_UNKNOWN_ENCODING, + G_BOOKMARK_FILE_ERROR_WRITE, + G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND +} GBookmarkFileError; + +GQuark g_bookmark_file_error_quark (void); + +/** + * GBookmarkFile: + * + * The <structname>GBookmarkFile</structname> struct contains only + * private data and should not be directly accessed. + */ +typedef struct _GBookmarkFile GBookmarkFile; + +GBookmarkFile *g_bookmark_file_new (void); +void g_bookmark_file_free (GBookmarkFile *bookmark); + +gboolean g_bookmark_file_load_from_file (GBookmarkFile *bookmark, + const gchar *filename, + GError **error); +gboolean g_bookmark_file_load_from_data (GBookmarkFile *bookmark, + const gchar *data, + gsize length, + GError **error); +gboolean g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark, + const gchar *file, + gchar **full_path, + GError **error); +gchar * g_bookmark_file_to_data (GBookmarkFile *bookmark, + gsize *length, + GError **error) G_GNUC_MALLOC; +gboolean g_bookmark_file_to_file (GBookmarkFile *bookmark, + const gchar *filename, + GError **error); + +void g_bookmark_file_set_title (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *title); +gchar * g_bookmark_file_get_title (GBookmarkFile *bookmark, + const gchar *uri, + GError **error) G_GNUC_MALLOC; +void g_bookmark_file_set_description (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *description); +gchar * g_bookmark_file_get_description (GBookmarkFile *bookmark, + const gchar *uri, + GError **error) G_GNUC_MALLOC; +void g_bookmark_file_set_mime_type (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *mime_type); +gchar * g_bookmark_file_get_mime_type (GBookmarkFile *bookmark, + const gchar *uri, + GError **error) G_GNUC_MALLOC; +void g_bookmark_file_set_groups (GBookmarkFile *bookmark, + const gchar *uri, + const gchar **groups, + gsize length); +void g_bookmark_file_add_group (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *group); +gboolean g_bookmark_file_has_group (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *group, + GError **error); +gchar ** g_bookmark_file_get_groups (GBookmarkFile *bookmark, + const gchar *uri, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_bookmark_file_add_application (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *name, + const gchar *exec); +gboolean g_bookmark_file_has_application (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *name, + GError **error); +gchar ** g_bookmark_file_get_applications (GBookmarkFile *bookmark, + const gchar *uri, + gsize *length, + GError **error) G_GNUC_MALLOC; +gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *name, + const gchar *exec, + gint count, + time_t stamp, + GError **error); +gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *name, + gchar **exec, + guint *count, + time_t *stamp, + GError **error); +void g_bookmark_file_set_is_private (GBookmarkFile *bookmark, + const gchar *uri, + gboolean is_private); +gboolean g_bookmark_file_get_is_private (GBookmarkFile *bookmark, + const gchar *uri, + GError **error); +void g_bookmark_file_set_icon (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *href, + const gchar *mime_type); +gboolean g_bookmark_file_get_icon (GBookmarkFile *bookmark, + const gchar *uri, + gchar **href, + gchar **mime_type, + GError **error); +void g_bookmark_file_set_added (GBookmarkFile *bookmark, + const gchar *uri, + time_t added); +time_t g_bookmark_file_get_added (GBookmarkFile *bookmark, + const gchar *uri, + GError **error); +void g_bookmark_file_set_modified (GBookmarkFile *bookmark, + const gchar *uri, + time_t modified); +time_t g_bookmark_file_get_modified (GBookmarkFile *bookmark, + const gchar *uri, + GError **error); +void g_bookmark_file_set_visited (GBookmarkFile *bookmark, + const gchar *uri, + time_t visited); +time_t g_bookmark_file_get_visited (GBookmarkFile *bookmark, + const gchar *uri, + GError **error); +gboolean g_bookmark_file_has_item (GBookmarkFile *bookmark, + const gchar *uri); +gint g_bookmark_file_get_size (GBookmarkFile *bookmark); +gchar ** g_bookmark_file_get_uris (GBookmarkFile *bookmark, + gsize *length) G_GNUC_MALLOC; +gboolean g_bookmark_file_remove_group (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *group, + GError **error); +gboolean g_bookmark_file_remove_application (GBookmarkFile *bookmark, + const gchar *uri, + const gchar *name, + GError **error); +gboolean g_bookmark_file_remove_item (GBookmarkFile *bookmark, + const gchar *uri, + GError **error); +gboolean g_bookmark_file_move_item (GBookmarkFile *bookmark, + const gchar *old_uri, + const gchar *new_uri, + GError **error); + +G_END_DECLS + +#endif /* __G_BOOKMARK_FILE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gcache.h b/protocols/Sametime/src/glib/include/glib/gcache.h new file mode 100644 index 0000000000..7d60d5888c --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gcache.h @@ -0,0 +1,69 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_CACHE_H__ +#define __G_CACHE_H__ + +#include <glib/glist.h> + +G_BEGIN_DECLS + +typedef struct _GCache GCache; + +typedef gpointer (*GCacheNewFunc) (gpointer key); +typedef gpointer (*GCacheDupFunc) (gpointer value); +typedef void (*GCacheDestroyFunc) (gpointer value); + +/* Caches + */ +GCache* g_cache_new (GCacheNewFunc value_new_func, + GCacheDestroyFunc value_destroy_func, + GCacheDupFunc key_dup_func, + GCacheDestroyFunc key_destroy_func, + GHashFunc hash_key_func, + GHashFunc hash_value_func, + GEqualFunc key_equal_func); +void g_cache_destroy (GCache *cache); +gpointer g_cache_insert (GCache *cache, + gpointer key); +void g_cache_remove (GCache *cache, + gconstpointer value); +void g_cache_key_foreach (GCache *cache, + GHFunc func, + gpointer user_data); +#ifndef G_DISABLE_DEPRECATED +void g_cache_value_foreach (GCache *cache, + GHFunc func, + gpointer user_data); +#endif + +G_END_DECLS + +#endif /* __G_CACHE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gchecksum.h b/protocols/Sametime/src/glib/include/glib/gchecksum.h new file mode 100644 index 0000000000..57aea103f7 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gchecksum.h @@ -0,0 +1,86 @@ +/* gchecksum.h - data hashing functions + * + * Copyright (C) 2007 Emmanuele Bassi <ebassi@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_CHECKSUM_H__ +#define __G_CHECKSUM_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/** + * GChecksumType: + * @G_CHECKSUM_MD5: Use the MD5 hashing algorithm + * @G_CHECKSUM_SHA1: Use the SHA-1 hashing algorithm + * @G_CHECKSUM_SHA256: Use the SHA-256 hashing algorithm + * + * The hashing algorithm to be used by #GChecksum when performing the + * digest of some data. + * + * Note that the #GChecksumType enumeration may be extended at a later + * date to include new hashing algorithm types. + * + * Since: 2.16 + */ +typedef enum { + G_CHECKSUM_MD5, + G_CHECKSUM_SHA1, + G_CHECKSUM_SHA256 +} GChecksumType; + +/** + * GChecksum: + * + * An opaque structure representing a checksumming operation. + * To create a new GChecksum, use g_checksum_new(). To free + * a GChecksum, use g_checksum_free(). + * + * Since: 2.16 + */ +typedef struct _GChecksum GChecksum; + +gssize g_checksum_type_get_length (GChecksumType checksum_type); + +GChecksum * g_checksum_new (GChecksumType checksum_type); +void g_checksum_reset (GChecksum *checksum); +GChecksum * g_checksum_copy (const GChecksum *checksum); +void g_checksum_free (GChecksum *checksum); +void g_checksum_update (GChecksum *checksum, + const guchar *data, + gssize length); +G_CONST_RETURN gchar *g_checksum_get_string (GChecksum *checksum); +void g_checksum_get_digest (GChecksum *checksum, + guint8 *buffer, + gsize *digest_len); + +gchar *g_compute_checksum_for_data (GChecksumType checksum_type, + const guchar *data, + gsize length); +gchar *g_compute_checksum_for_string (GChecksumType checksum_type, + const gchar *str, + gssize length); + +G_END_DECLS + +#endif /* __G_CHECKSUM_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gcompletion.h b/protocols/Sametime/src/glib/include/glib/gcompletion.h new file mode 100644 index 0000000000..04c024fc5a --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gcompletion.h @@ -0,0 +1,81 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_COMPLETION_H__ +#define __G_COMPLETION_H__ + +#include <glib/glist.h> + +G_BEGIN_DECLS + +typedef struct _GCompletion GCompletion; + +typedef gchar* (*GCompletionFunc) (gpointer); + +/* GCompletion + */ + +typedef gint (*GCompletionStrncmpFunc) (const gchar *s1, + const gchar *s2, + gsize n); + +struct _GCompletion +{ + GList* items; + GCompletionFunc func; + + gchar* prefix; + GList* cache; + GCompletionStrncmpFunc strncmp_func; +}; + +#ifndef G_DISABLE_DEPRECATED + +GCompletion* g_completion_new (GCompletionFunc func); +void g_completion_add_items (GCompletion* cmp, + GList* items); +void g_completion_remove_items (GCompletion* cmp, + GList* items); +void g_completion_clear_items (GCompletion* cmp); +GList* g_completion_complete (GCompletion* cmp, + const gchar* prefix, + gchar** new_prefix); +GList* g_completion_complete_utf8 (GCompletion *cmp, + const gchar* prefix, + gchar** new_prefix); +void g_completion_set_compare (GCompletion *cmp, + GCompletionStrncmpFunc strncmp_func); +void g_completion_free (GCompletion* cmp); + +#endif + +G_END_DECLS + +#endif /* __G_COMPLETION_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gconvert.h b/protocols/Sametime/src/glib/include/glib/gconvert.h new file mode 100644 index 0000000000..e4c20d77d5 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gconvert.h @@ -0,0 +1,162 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_CONVERT_H__ +#define __G_CONVERT_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +/** + * GConvertError: + * @G_CONVERT_ERROR_NO_CONVERSION: Conversion between the requested character + * sets is not supported. + * @G_CONVERT_ERROR_ILLEGAL_SEQUENCE: Invalid byte sequence in conversion input. + * @G_CONVERT_ERROR_FAILED: Conversion failed for some reason. + * @G_CONVERT_ERROR_PARTIAL_INPUT: Partial character sequence at end of input. + * @G_CONVERT_ERROR_BAD_URI: URI is invalid. + * @G_CONVERT_ERROR_NOT_ABSOLUTE_PATH: Pathname is not an absolute path. + * + * Error codes returned by character set conversion routines. + */ +typedef enum +{ + G_CONVERT_ERROR_NO_CONVERSION, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + G_CONVERT_ERROR_FAILED, + G_CONVERT_ERROR_PARTIAL_INPUT, + G_CONVERT_ERROR_BAD_URI, + G_CONVERT_ERROR_NOT_ABSOLUTE_PATH +} GConvertError; + +/** + * G_CONVERT_ERROR: + * + * Error domain for character set conversions. Errors in this domain will + * be from the #GConvertError enumeration. See #GError for information on + * error domains. + */ +#define G_CONVERT_ERROR g_convert_error_quark() +GQuark g_convert_error_quark (void); + +/** + * GIconv: + * + * The <structname>GIConv</structname> struct wraps an + * iconv() conversion descriptor. It contains private data + * and should only be accessed using the following functions. + */ +typedef struct _GIConv *GIConv; + +GIConv g_iconv_open (const gchar *to_codeset, + const gchar *from_codeset); +gsize g_iconv (GIConv converter, + gchar **inbuf, + gsize *inbytes_left, + gchar **outbuf, + gsize *outbytes_left); +gint g_iconv_close (GIConv converter); + + +gchar* g_convert (const gchar *str, + gssize len, + const gchar *to_codeset, + const gchar *from_codeset, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; +gchar* g_convert_with_iconv (const gchar *str, + gssize len, + GIConv converter, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; +gchar* g_convert_with_fallback (const gchar *str, + gssize len, + const gchar *to_codeset, + const gchar *from_codeset, + const gchar *fallback, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; + + +/* Convert between libc's idea of strings and UTF-8. + */ +gchar* g_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; +gchar* g_locale_from_utf8 (const gchar *utf8string, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; + +/* Convert between the operating system (or C runtime) + * representation of file names and UTF-8. + */ +#ifdef G_OS_WIN32 +#define g_filename_to_utf8 g_filename_to_utf8_utf8 +#define g_filename_from_utf8 g_filename_from_utf8_utf8 +#define g_filename_from_uri g_filename_from_uri_utf8 +#define g_filename_to_uri g_filename_to_uri_utf8 +#endif + +gchar* g_filename_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; +gchar* g_filename_from_utf8 (const gchar *utf8string, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; + +gchar *g_filename_from_uri (const gchar *uri, + gchar **hostname, + GError **error) G_GNUC_MALLOC; + +gchar *g_filename_to_uri (const gchar *filename, + const gchar *hostname, + GError **error) G_GNUC_MALLOC; +gchar *g_filename_display_name (const gchar *filename) G_GNUC_MALLOC; +gboolean g_get_filename_charsets (G_CONST_RETURN gchar ***charsets); + +gchar *g_filename_display_basename (const gchar *filename) G_GNUC_MALLOC; + +gchar **g_uri_list_extract_uris (const gchar *uri_list) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __G_CONVERT_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gdataset.h b/protocols/Sametime/src/glib/include/glib/gdataset.h new file mode 100644 index 0000000000..2733ffb033 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gdataset.h @@ -0,0 +1,122 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_DATASET_H__ +#define __G_DATASET_H__ + +#include <glib/gquark.h> + +G_BEGIN_DECLS + +typedef struct _GData GData; + +typedef void (*GDataForeachFunc) (GQuark key_id, + gpointer data, + gpointer user_data); + +/* Keyed Data List + */ +void g_datalist_init (GData **datalist); +void g_datalist_clear (GData **datalist); +gpointer g_datalist_id_get_data (GData **datalist, + GQuark key_id); +void g_datalist_id_set_data_full (GData **datalist, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func); +gpointer g_datalist_id_remove_no_notify (GData **datalist, + GQuark key_id); +void g_datalist_foreach (GData **datalist, + GDataForeachFunc func, + gpointer user_data); + +/** + * G_DATALIST_FLAGS_MASK: + * + * A bitmask that restricts the possible flags passed to + * g_datalist_set_flags(). Passing a flags value where + * flags & ~G_DATALIST_FLAGS_MASK != 0 is an error. + */ +#define G_DATALIST_FLAGS_MASK 0x3 + +void g_datalist_set_flags (GData **datalist, + guint flags); +void g_datalist_unset_flags (GData **datalist, + guint flags); +guint g_datalist_get_flags (GData **datalist); + +#define g_datalist_id_set_data(dl, q, d) \ + g_datalist_id_set_data_full ((dl), (q), (d), NULL) +#define g_datalist_id_remove_data(dl, q) \ + g_datalist_id_set_data ((dl), (q), NULL) +#define g_datalist_get_data(dl, k) \ + (g_datalist_id_get_data ((dl), g_quark_try_string (k))) +#define g_datalist_set_data_full(dl, k, d, f) \ + g_datalist_id_set_data_full ((dl), g_quark_from_string (k), (d), (f)) +#define g_datalist_remove_no_notify(dl, k) \ + g_datalist_id_remove_no_notify ((dl), g_quark_try_string (k)) +#define g_datalist_set_data(dl, k, d) \ + g_datalist_set_data_full ((dl), (k), (d), NULL) +#define g_datalist_remove_data(dl, k) \ + g_datalist_id_set_data ((dl), g_quark_try_string (k), NULL) + + +/* Location Associated Keyed Data + */ +void g_dataset_destroy (gconstpointer dataset_location); +gpointer g_dataset_id_get_data (gconstpointer dataset_location, + GQuark key_id); +void g_dataset_id_set_data_full (gconstpointer dataset_location, + GQuark key_id, + gpointer data, + GDestroyNotify destroy_func); +gpointer g_dataset_id_remove_no_notify (gconstpointer dataset_location, + GQuark key_id); +void g_dataset_foreach (gconstpointer dataset_location, + GDataForeachFunc func, + gpointer user_data); +#define g_dataset_id_set_data(l, k, d) \ + g_dataset_id_set_data_full ((l), (k), (d), NULL) +#define g_dataset_id_remove_data(l, k) \ + g_dataset_id_set_data ((l), (k), NULL) +#define g_dataset_get_data(l, k) \ + (g_dataset_id_get_data ((l), g_quark_try_string (k))) +#define g_dataset_set_data_full(l, k, d, f) \ + g_dataset_id_set_data_full ((l), g_quark_from_string (k), (d), (f)) +#define g_dataset_remove_no_notify(l, k) \ + g_dataset_id_remove_no_notify ((l), g_quark_try_string (k)) +#define g_dataset_set_data(l, k, d) \ + g_dataset_set_data_full ((l), (k), (d), NULL) +#define g_dataset_remove_data(l, k) \ + g_dataset_id_set_data ((l), g_quark_try_string (k), NULL) + +G_END_DECLS + +#endif /* __G_DATASET_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gdate.h b/protocols/Sametime/src/glib/include/glib/gdate.h new file mode 100644 index 0000000000..cb1f566155 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gdate.h @@ -0,0 +1,263 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_DATE_H__ +#define __G_DATE_H__ + +#include <time.h> + +#include <glib/gtypes.h> +#include <glib/gquark.h> + +G_BEGIN_DECLS + +/* GDate + * + * Date calculations (not time for now, to be resolved). These are a + * mutant combination of Steffen Beyer's DateCalc routines + * (http://www.perl.com/CPAN/authors/id/STBEY/) and Jon Trowbridge's + * date routines (written for in-house software). Written by Havoc + * Pennington <hp@pobox.com> + */ + +typedef gint32 GTime; +typedef guint16 GDateYear; +typedef guint8 GDateDay; /* day of the month */ +typedef struct _GDate GDate; + +/* enum used to specify order of appearance in parsed date strings */ +typedef enum +{ + G_DATE_DAY = 0, + G_DATE_MONTH = 1, + G_DATE_YEAR = 2 +} GDateDMY; + +/* actual week and month values */ +typedef enum +{ + G_DATE_BAD_WEEKDAY = 0, + G_DATE_MONDAY = 1, + G_DATE_TUESDAY = 2, + G_DATE_WEDNESDAY = 3, + G_DATE_THURSDAY = 4, + G_DATE_FRIDAY = 5, + G_DATE_SATURDAY = 6, + G_DATE_SUNDAY = 7 +} GDateWeekday; +typedef enum +{ + G_DATE_BAD_MONTH = 0, + G_DATE_JANUARY = 1, + G_DATE_FEBRUARY = 2, + G_DATE_MARCH = 3, + G_DATE_APRIL = 4, + G_DATE_MAY = 5, + G_DATE_JUNE = 6, + G_DATE_JULY = 7, + G_DATE_AUGUST = 8, + G_DATE_SEPTEMBER = 9, + G_DATE_OCTOBER = 10, + G_DATE_NOVEMBER = 11, + G_DATE_DECEMBER = 12 +} GDateMonth; + +#define G_DATE_BAD_JULIAN 0U +#define G_DATE_BAD_DAY 0U +#define G_DATE_BAD_YEAR 0U + +/* Note: directly manipulating structs is generally a bad idea, but + * in this case it's an *incredibly* bad idea, because all or part + * of this struct can be invalid at any given time. Use the functions, + * or you will get hosed, I promise. + */ +struct _GDate +{ + guint julian_days : 32; /* julian days representation - we use a + * bitfield hoping that 64 bit platforms + * will pack this whole struct in one big + * int + */ + + guint julian : 1; /* julian is valid */ + guint dmy : 1; /* dmy is valid */ + + /* DMY representation */ + guint day : 6; + guint month : 4; + guint year : 16; +}; + +/* g_date_new() returns an invalid date, you then have to _set() stuff + * to get a usable object. You can also allocate a GDate statically, + * then call g_date_clear() to initialize. + */ +GDate* g_date_new (void); +GDate* g_date_new_dmy (GDateDay day, + GDateMonth month, + GDateYear year); +GDate* g_date_new_julian (guint32 julian_day); +void g_date_free (GDate *date); + +/* check g_date_valid() after doing an operation that might fail, like + * _parse. Almost all g_date operations are undefined on invalid + * dates (the exceptions are the mutators, since you need those to + * return to validity). + */ +gboolean g_date_valid (const GDate *date); +gboolean g_date_valid_day (GDateDay day) G_GNUC_CONST; +gboolean g_date_valid_month (GDateMonth month) G_GNUC_CONST; +gboolean g_date_valid_year (GDateYear year) G_GNUC_CONST; +gboolean g_date_valid_weekday (GDateWeekday weekday) G_GNUC_CONST; +gboolean g_date_valid_julian (guint32 julian_date) G_GNUC_CONST; +gboolean g_date_valid_dmy (GDateDay day, + GDateMonth month, + GDateYear year) G_GNUC_CONST; + +GDateWeekday g_date_get_weekday (const GDate *date); +GDateMonth g_date_get_month (const GDate *date); +GDateYear g_date_get_year (const GDate *date); +GDateDay g_date_get_day (const GDate *date); +guint32 g_date_get_julian (const GDate *date); +guint g_date_get_day_of_year (const GDate *date); +/* First monday/sunday is the start of week 1; if we haven't reached + * that day, return 0. These are not ISO weeks of the year; that + * routine needs to be added. + * these functions return the number of weeks, starting on the + * corrsponding day + */ +guint g_date_get_monday_week_of_year (const GDate *date); +guint g_date_get_sunday_week_of_year (const GDate *date); +guint g_date_get_iso8601_week_of_year (const GDate *date); + +/* If you create a static date struct you need to clear it to get it + * in a sane state before use. You can clear a whole array at + * once with the ndates argument. + */ +void g_date_clear (GDate *date, + guint n_dates); + +/* The parse routine is meant for dates typed in by a user, so it + * permits many formats but tries to catch common typos. If your data + * needs to be strictly validated, it is not an appropriate function. + */ +void g_date_set_parse (GDate *date, + const gchar *str); +void g_date_set_time_t (GDate *date, + time_t timet); +void g_date_set_time_val (GDate *date, + GTimeVal *timeval); +#ifndef G_DISABLE_DEPRECATED +void g_date_set_time (GDate *date, + GTime time_); +#endif +void g_date_set_month (GDate *date, + GDateMonth month); +void g_date_set_day (GDate *date, + GDateDay day); +void g_date_set_year (GDate *date, + GDateYear year); +void g_date_set_dmy (GDate *date, + GDateDay day, + GDateMonth month, + GDateYear y); +void g_date_set_julian (GDate *date, + guint32 julian_date); +gboolean g_date_is_first_of_month (const GDate *date); +gboolean g_date_is_last_of_month (const GDate *date); + +/* To go forward by some number of weeks just go forward weeks*7 days */ +void g_date_add_days (GDate *date, + guint n_days); +void g_date_subtract_days (GDate *date, + guint n_days); + +/* If you add/sub months while day > 28, the day might change */ +void g_date_add_months (GDate *date, + guint n_months); +void g_date_subtract_months (GDate *date, + guint n_months); + +/* If it's feb 29, changing years can move you to the 28th */ +void g_date_add_years (GDate *date, + guint n_years); +void g_date_subtract_years (GDate *date, + guint n_years); +gboolean g_date_is_leap_year (GDateYear year) G_GNUC_CONST; +guint8 g_date_get_days_in_month (GDateMonth month, + GDateYear year) G_GNUC_CONST; +guint8 g_date_get_monday_weeks_in_year (GDateYear year) G_GNUC_CONST; +guint8 g_date_get_sunday_weeks_in_year (GDateYear year) G_GNUC_CONST; + +/* Returns the number of days between the two dates. If date2 comes + before date1, a negative value is return. */ +gint g_date_days_between (const GDate *date1, + const GDate *date2); + +/* qsort-friendly (with a cast...) */ +gint g_date_compare (const GDate *lhs, + const GDate *rhs); +void g_date_to_struct_tm (const GDate *date, + struct tm *tm); + +void g_date_clamp (GDate *date, + const GDate *min_date, + const GDate *max_date); + +/* Swap date1 and date2's values if date1 > date2. */ +void g_date_order (GDate *date1, GDate *date2); + +/* Just like strftime() except you can only use date-related formats. + * Using a time format is undefined. + */ +gsize g_date_strftime (gchar *s, + gsize slen, + const gchar *format, + const GDate *date); + +#ifndef G_DISABLE_DEPRECATED + +#define g_date_weekday g_date_get_weekday +#define g_date_month g_date_get_month +#define g_date_year g_date_get_year +#define g_date_day g_date_get_day +#define g_date_julian g_date_get_julian +#define g_date_day_of_year g_date_get_day_of_year +#define g_date_monday_week_of_year g_date_get_monday_week_of_year +#define g_date_sunday_week_of_year g_date_get_sunday_week_of_year +#define g_date_days_in_month g_date_get_days_in_month +#define g_date_monday_weeks_in_year g_date_get_monday_weeks_in_year +#define g_date_sunday_weeks_in_year g_date_get_sunday_weeks_in_year + +#endif /* G_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __G_DATE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gdatetime.h b/protocols/Sametime/src/glib/include/glib/gdatetime.h new file mode 100644 index 0000000000..b76df89c7e --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gdatetime.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2009-2010 Christian Hergert <chris@dronelabs.com> + * Copyright © 2010 Codethink Limited + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * licence, or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA. + * + * Authors: Christian Hergert <chris@dronelabs.com> + * Thiago Santos <thiago.sousa.santos@collabora.co.uk> + * Emmanuele Bassi <ebassi@linux.intel.com> + * Ryan Lortie <desrt@desrt.ca> + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_DATE_TIME_H__ +#define __G_DATE_TIME_H__ + +#include <glib/gtimezone.h> + +G_BEGIN_DECLS + +/** + * G_TIME_SPAN_DAY: + * + * Evaluates to a time span of one day. + * + * Since: 2.26 + */ +#define G_TIME_SPAN_DAY (G_GINT64_CONSTANT (86400000000)) + +/** + * G_TIME_SPAN_HOUR: + * + * Evaluates to a time span of one hour. + * + * Since: 2.26 + */ +#define G_TIME_SPAN_HOUR (G_GINT64_CONSTANT (3600000000)) + +/** + * G_TIME_SPAN_MINUTE: + * + * Evaluates to a time span of one minute. + * + * Since: 2.26 + */ +#define G_TIME_SPAN_MINUTE (G_GINT64_CONSTANT (60000000)) + +/** + * G_TIME_SPAN_SECOND: + * + * Evaluates to a time span of one second. + * + * Since: 2.26 + */ +#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT (1000000)) + +/** + * G_TIME_SPAN_MILLISECOND: + * + * Evaluates to a time span of one millisecond. + * + * Since: 2.26 + */ +#define G_TIME_SPAN_MILLISECOND (G_GINT64_CONSTANT (1000)) + +/** + * GTimeSpan: + * + * A value representing an interval of time, in microseconds. + * + * Since: 2.26 + */ +typedef gint64 GTimeSpan; + +/** + * GDateTime: + * + * <structname>GDateTime</structname> is an opaque structure whose members + * cannot be accessed directly. + * + * Since: 2.26 + */ +typedef struct _GDateTime GDateTime; + +void g_date_time_unref (GDateTime *datetime); +GDateTime * g_date_time_ref (GDateTime *datetime); + +GDateTime * g_date_time_new_now (GTimeZone *tz); +GDateTime * g_date_time_new_now_local (void); +GDateTime * g_date_time_new_now_utc (void); + +GDateTime * g_date_time_new_from_unix_local (gint64 t); +GDateTime * g_date_time_new_from_unix_utc (gint64 t); + +GDateTime * g_date_time_new_from_timeval_local (const GTimeVal *tv); +GDateTime * g_date_time_new_from_timeval_utc (const GTimeVal *tv); + +GDateTime * g_date_time_new (GTimeZone *tz, + gint year, + gint month, + gint day, + gint hour, + gint minute, + gdouble seconds); +GDateTime * g_date_time_new_local (gint year, + gint month, + gint day, + gint hour, + gint minute, + gdouble seconds); +GDateTime * g_date_time_new_utc (gint year, + gint month, + gint day, + gint hour, + gint minute, + gdouble seconds); + +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add (GDateTime *datetime, + GTimeSpan timespan); + +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_years (GDateTime *datetime, + gint years); +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_months (GDateTime *datetime, + gint months); +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_weeks (GDateTime *datetime, + gint weeks); +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_days (GDateTime *datetime, + gint days); + +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_hours (GDateTime *datetime, + gint hours); +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_minutes (GDateTime *datetime, + gint minutes); +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_seconds (GDateTime *datetime, + gdouble seconds); + +G_GNUC_WARN_UNUSED_RESULT +GDateTime * g_date_time_add_full (GDateTime *datetime, + gint years, + gint months, + gint days, + gint hours, + gint minutes, + gdouble seconds); + +gint g_date_time_compare (gconstpointer dt1, + gconstpointer dt2); +GTimeSpan g_date_time_difference (GDateTime *end, + GDateTime *begin); +guint g_date_time_hash (gconstpointer datetime); +gboolean g_date_time_equal (gconstpointer dt1, + gconstpointer dt2); + +void g_date_time_get_ymd (GDateTime *datetime, + gint *year, + gint *month, + gint *day); + +gint g_date_time_get_year (GDateTime *datetime); +gint g_date_time_get_month (GDateTime *datetime); +gint g_date_time_get_day_of_month (GDateTime *datetime); + +gint g_date_time_get_week_numbering_year (GDateTime *datetime); +gint g_date_time_get_week_of_year (GDateTime *datetime); +gint g_date_time_get_day_of_week (GDateTime *datetime); + +gint g_date_time_get_day_of_year (GDateTime *datetime); + +gint g_date_time_get_hour (GDateTime *datetime); +gint g_date_time_get_minute (GDateTime *datetime); +gint g_date_time_get_second (GDateTime *datetime); +gint g_date_time_get_microsecond (GDateTime *datetime); +gdouble g_date_time_get_seconds (GDateTime *datetime); + +gint64 g_date_time_to_unix (GDateTime *datetime); +gboolean g_date_time_to_timeval (GDateTime *datetime, + GTimeVal *tv); + +GTimeSpan g_date_time_get_utc_offset (GDateTime *datetime); +const gchar * g_date_time_get_timezone_abbreviation (GDateTime *datetime); +gboolean g_date_time_is_daylight_savings (GDateTime *datetime); + +GDateTime * g_date_time_to_timezone (GDateTime *datetime, + GTimeZone *tz); +GDateTime * g_date_time_to_local (GDateTime *datetime); +GDateTime * g_date_time_to_utc (GDateTime *datetime); + +gchar * g_date_time_format (GDateTime *datetime, + const gchar *format) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __G_DATE_TIME_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gdir.h b/protocols/Sametime/src/glib/include/glib/gdir.h new file mode 100644 index 0000000000..85e989695a --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gdir.h @@ -0,0 +1,52 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gdir.c: Simplified wrapper around the DIRENT functions. + * + * Copyright 2001 Hans Breuer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_DIR_H__ +#define __G_DIR_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +typedef struct _GDir GDir; + +#ifdef G_OS_WIN32 +/* For DLL ABI stability, keep old names for old (non-UTF-8) functionality. */ +#define g_dir_open g_dir_open_utf8 +#define g_dir_read_name g_dir_read_name_utf8 +#endif + +GDir * g_dir_open (const gchar *path, + guint flags, + GError **error); +G_CONST_RETURN gchar *g_dir_read_name (GDir *dir); +void g_dir_rewind (GDir *dir); +void g_dir_close (GDir *dir); + +G_END_DECLS + +#endif /* __G_DIR_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gerror.h b/protocols/Sametime/src/glib/include/glib/gerror.h new file mode 100644 index 0000000000..b303487782 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gerror.h @@ -0,0 +1,98 @@ +/* gerror.h - Error reporting system + * + * Copyright 2000 Red Hat, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_ERROR_H__ +#define __G_ERROR_H__ + +#include <stdarg.h> + +#include <glib/gquark.h> + +G_BEGIN_DECLS + +typedef struct _GError GError; + +struct _GError +{ + GQuark domain; + gint code; + gchar *message; +}; + +GError* g_error_new (GQuark domain, + gint code, + const gchar *format, + ...) G_GNUC_PRINTF (3, 4); + +GError* g_error_new_literal (GQuark domain, + gint code, + const gchar *message); +GError* g_error_new_valist (GQuark domain, + gint code, + const gchar *format, + va_list args); + +void g_error_free (GError *error); +GError* g_error_copy (const GError *error); + +gboolean g_error_matches (const GError *error, + GQuark domain, + gint code); + +/* if (err) *err = g_error_new(domain, code, format, ...), also has + * some sanity checks. + */ +void g_set_error (GError **err, + GQuark domain, + gint code, + const gchar *format, + ...) G_GNUC_PRINTF (4, 5); + +void g_set_error_literal (GError **err, + GQuark domain, + gint code, + const gchar *message); + +/* if (dest) *dest = src; also has some sanity checks. + */ +void g_propagate_error (GError **dest, + GError *src); + +/* if (err && *err) { g_error_free(*err); *err = NULL; } */ +void g_clear_error (GError **err); + +/* if (err) prefix the formatted string to the ->message */ +void g_prefix_error (GError **err, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); + +/* g_propagate_error then g_error_prefix on dest */ +void g_propagate_prefixed_error (GError **dest, + GError *src, + const gchar *format, + ...) G_GNUC_PRINTF (3, 4); + +G_END_DECLS + +#endif /* __G_ERROR_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gfileutils.h b/protocols/Sametime/src/glib/include/glib/gfileutils.h new file mode 100644 index 0000000000..d8f9d3bea1 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gfileutils.h @@ -0,0 +1,128 @@ +/* gfileutils.h - File utility functions + * + * Copyright 2000 Red Hat, Inc. + * + * GLib is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * GLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GLib; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_FILEUTILS_H__ +#define __G_FILEUTILS_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +#define G_FILE_ERROR g_file_error_quark () + +typedef enum +{ + G_FILE_ERROR_EXIST, + G_FILE_ERROR_ISDIR, + G_FILE_ERROR_ACCES, + G_FILE_ERROR_NAMETOOLONG, + G_FILE_ERROR_NOENT, + G_FILE_ERROR_NOTDIR, + G_FILE_ERROR_NXIO, + G_FILE_ERROR_NODEV, + G_FILE_ERROR_ROFS, + G_FILE_ERROR_TXTBSY, + G_FILE_ERROR_FAULT, + G_FILE_ERROR_LOOP, + G_FILE_ERROR_NOSPC, + G_FILE_ERROR_NOMEM, + G_FILE_ERROR_MFILE, + G_FILE_ERROR_NFILE, + G_FILE_ERROR_BADF, + G_FILE_ERROR_INVAL, + G_FILE_ERROR_PIPE, + G_FILE_ERROR_AGAIN, + G_FILE_ERROR_INTR, + G_FILE_ERROR_IO, + G_FILE_ERROR_PERM, + G_FILE_ERROR_NOSYS, + G_FILE_ERROR_FAILED +} GFileError; + +/* For backward-compat reasons, these are synced to an old + * anonymous enum in libgnome. But don't use that enum + * in new code. + */ +typedef enum +{ + G_FILE_TEST_IS_REGULAR = 1 << 0, + G_FILE_TEST_IS_SYMLINK = 1 << 1, + G_FILE_TEST_IS_DIR = 1 << 2, + G_FILE_TEST_IS_EXECUTABLE = 1 << 3, + G_FILE_TEST_EXISTS = 1 << 4 +} GFileTest; + +GQuark g_file_error_quark (void); +/* So other code can generate a GFileError */ +GFileError g_file_error_from_errno (gint err_no); + +#ifdef G_OS_WIN32 +#define g_file_test g_file_test_utf8 +#define g_file_get_contents g_file_get_contents_utf8 +#define g_mkstemp g_mkstemp_utf8 +#define g_file_open_tmp g_file_open_tmp_utf8 +#endif + +gboolean g_file_test (const gchar *filename, + GFileTest test); +gboolean g_file_get_contents (const gchar *filename, + gchar **contents, + gsize *length, + GError **error); +gboolean g_file_set_contents (const gchar *filename, + const gchar *contents, + gssize length, + GError **error); +gchar *g_file_read_link (const gchar *filename, + GError **error); + +/* Wrapper / workalike for mkstemp() */ +gint g_mkstemp (gchar *tmpl); +gint g_mkstemp_full (gchar *tmpl, + int flags, + int mode); + +/* Wrapper for g_mkstemp */ +gint g_file_open_tmp (const gchar *tmpl, + gchar **name_used, + GError **error); + +char *g_format_size_for_display (goffset size); + +gchar *g_build_path (const gchar *separator, + const gchar *first_element, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +gchar *g_build_pathv (const gchar *separator, + gchar **args) G_GNUC_MALLOC; + +gchar *g_build_filename (const gchar *first_element, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +gchar *g_build_filenamev (gchar **args) G_GNUC_MALLOC; + +int g_mkdir_with_parents (const gchar *pathname, + int mode); + +G_END_DECLS + +#endif /* __G_FILEUTILS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/ghash.h b/protocols/Sametime/src/glib/include/glib/ghash.h new file mode 100644 index 0000000000..9128721bcf --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/ghash.h @@ -0,0 +1,166 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_HASH_H__ +#define __G_HASH_H__ + +#include <glib/gtypes.h> +#include <glib/glist.h> + +G_BEGIN_DECLS + +typedef struct _GHashTable GHashTable; + +typedef gboolean (*GHRFunc) (gpointer key, + gpointer value, + gpointer user_data); + +typedef struct _GHashTableIter GHashTableIter; + +struct _GHashTableIter +{ + /*< private >*/ + gpointer dummy1; + gpointer dummy2; + gpointer dummy3; + int dummy4; + gboolean dummy5; + gpointer dummy6; +}; + +/* Hash tables + */ +GHashTable* g_hash_table_new (GHashFunc hash_func, + GEqualFunc key_equal_func); +GHashTable* g_hash_table_new_full (GHashFunc hash_func, + GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func); +void g_hash_table_destroy (GHashTable *hash_table); +void g_hash_table_insert (GHashTable *hash_table, + gpointer key, + gpointer value); +void g_hash_table_replace (GHashTable *hash_table, + gpointer key, + gpointer value); +gboolean g_hash_table_remove (GHashTable *hash_table, + gconstpointer key); +void g_hash_table_remove_all (GHashTable *hash_table); +gboolean g_hash_table_steal (GHashTable *hash_table, + gconstpointer key); +void g_hash_table_steal_all (GHashTable *hash_table); +gpointer g_hash_table_lookup (GHashTable *hash_table, + gconstpointer key); +gboolean g_hash_table_lookup_extended (GHashTable *hash_table, + gconstpointer lookup_key, + gpointer *orig_key, + gpointer *value); +void g_hash_table_foreach (GHashTable *hash_table, + GHFunc func, + gpointer user_data); +gpointer g_hash_table_find (GHashTable *hash_table, + GHRFunc predicate, + gpointer user_data); +guint g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); +guint g_hash_table_foreach_steal (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); +guint g_hash_table_size (GHashTable *hash_table); +GList * g_hash_table_get_keys (GHashTable *hash_table); +GList * g_hash_table_get_values (GHashTable *hash_table); + +void g_hash_table_iter_init (GHashTableIter *iter, + GHashTable *hash_table); +gboolean g_hash_table_iter_next (GHashTableIter *iter, + gpointer *key, + gpointer *value); +GHashTable* g_hash_table_iter_get_hash_table (GHashTableIter *iter); +void g_hash_table_iter_remove (GHashTableIter *iter); +void g_hash_table_iter_steal (GHashTableIter *iter); + +/* keeping hash tables alive */ +GHashTable* g_hash_table_ref (GHashTable *hash_table); +void g_hash_table_unref (GHashTable *hash_table); + +#ifndef G_DISABLE_DEPRECATED + +/** + * g_hash_table_freeze: + * @hash_table: a #GHashTable + * + * This function is deprecated and will be removed in the next major + * release of GLib. It does nothing. + **/ +#define g_hash_table_freeze(hash_table) ((void)0) + +/** + * g_hash_table_thaw: + * @hash_table: a #GHashTable + * + * This function is deprecated and will be removed in the next major + * release of GLib. It does nothing. + **/ +#define g_hash_table_thaw(hash_table) ((void)0) + +#endif /* G_DISABLE_DEPRECATED */ + +/* Hash Functions + */ +gboolean g_str_equal (gconstpointer v1, + gconstpointer v2); +guint g_str_hash (gconstpointer v); + +gboolean g_int_equal (gconstpointer v1, + gconstpointer v2); +guint g_int_hash (gconstpointer v); + +gboolean g_int64_equal (gconstpointer v1, + gconstpointer v2); +guint g_int64_hash (gconstpointer v); + +gboolean g_double_equal (gconstpointer v1, + gconstpointer v2); +guint g_double_hash (gconstpointer v); + +/* This "hash" function will just return the key's address as an + * unsigned integer. Useful for hashing on plain addresses or + * simple integer values. + * Passing NULL into g_hash_table_new() as GHashFunc has the + * same effect as passing g_direct_hash(). + */ +guint g_direct_hash (gconstpointer v) G_GNUC_CONST; +gboolean g_direct_equal (gconstpointer v1, + gconstpointer v2) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __G_HASH_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/ghook.h b/protocols/Sametime/src/glib/include/glib/ghook.h new file mode 100644 index 0000000000..5577fc3e21 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/ghook.h @@ -0,0 +1,181 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_HOOK_H__ +#define __G_HOOK_H__ + +#include <glib/gmem.h> + +G_BEGIN_DECLS + + +/* --- typedefs --- */ +typedef struct _GHook GHook; +typedef struct _GHookList GHookList; + +typedef gint (*GHookCompareFunc) (GHook *new_hook, + GHook *sibling); +typedef gboolean (*GHookFindFunc) (GHook *hook, + gpointer data); +typedef void (*GHookMarshaller) (GHook *hook, + gpointer marshal_data); +typedef gboolean (*GHookCheckMarshaller) (GHook *hook, + gpointer marshal_data); +typedef void (*GHookFunc) (gpointer data); +typedef gboolean (*GHookCheckFunc) (gpointer data); +typedef void (*GHookFinalizeFunc) (GHookList *hook_list, + GHook *hook); +typedef enum +{ + G_HOOK_FLAG_ACTIVE = 1 << 0, + G_HOOK_FLAG_IN_CALL = 1 << 1, + G_HOOK_FLAG_MASK = 0x0f +} GHookFlagMask; +#define G_HOOK_FLAG_USER_SHIFT (4) + + +/* --- structures --- */ +struct _GHookList +{ + gulong seq_id; + guint hook_size : 16; + guint is_setup : 1; + GHook *hooks; + gpointer dummy3; + GHookFinalizeFunc finalize_hook; + gpointer dummy[2]; +}; +struct _GHook +{ + gpointer data; + GHook *next; + GHook *prev; + guint ref_count; + gulong hook_id; + guint flags; + gpointer func; + GDestroyNotify destroy; +}; + + +/* --- macros --- */ +#define G_HOOK(hook) ((GHook*) (hook)) +#define G_HOOK_FLAGS(hook) (G_HOOK (hook)->flags) +#define G_HOOK_ACTIVE(hook) ((G_HOOK_FLAGS (hook) & \ + G_HOOK_FLAG_ACTIVE) != 0) +#define G_HOOK_IN_CALL(hook) ((G_HOOK_FLAGS (hook) & \ + G_HOOK_FLAG_IN_CALL) != 0) +#define G_HOOK_IS_VALID(hook) (G_HOOK (hook)->hook_id != 0 && \ + (G_HOOK_FLAGS (hook) & \ + G_HOOK_FLAG_ACTIVE)) +#define G_HOOK_IS_UNLINKED(hook) (G_HOOK (hook)->next == NULL && \ + G_HOOK (hook)->prev == NULL && \ + G_HOOK (hook)->hook_id == 0 && \ + G_HOOK (hook)->ref_count == 0) + + +/* --- prototypes --- */ +/* callback maintenance functions */ +void g_hook_list_init (GHookList *hook_list, + guint hook_size); +void g_hook_list_clear (GHookList *hook_list); +GHook* g_hook_alloc (GHookList *hook_list); +void g_hook_free (GHookList *hook_list, + GHook *hook); +GHook * g_hook_ref (GHookList *hook_list, + GHook *hook); +void g_hook_unref (GHookList *hook_list, + GHook *hook); +gboolean g_hook_destroy (GHookList *hook_list, + gulong hook_id); +void g_hook_destroy_link (GHookList *hook_list, + GHook *hook); +void g_hook_prepend (GHookList *hook_list, + GHook *hook); +void g_hook_insert_before (GHookList *hook_list, + GHook *sibling, + GHook *hook); +void g_hook_insert_sorted (GHookList *hook_list, + GHook *hook, + GHookCompareFunc func); +GHook* g_hook_get (GHookList *hook_list, + gulong hook_id); +GHook* g_hook_find (GHookList *hook_list, + gboolean need_valids, + GHookFindFunc func, + gpointer data); +GHook* g_hook_find_data (GHookList *hook_list, + gboolean need_valids, + gpointer data); +GHook* g_hook_find_func (GHookList *hook_list, + gboolean need_valids, + gpointer func); +GHook* g_hook_find_func_data (GHookList *hook_list, + gboolean need_valids, + gpointer func, + gpointer data); +/* return the first valid hook, and increment its reference count */ +GHook* g_hook_first_valid (GHookList *hook_list, + gboolean may_be_in_call); +/* return the next valid hook with incremented reference count, and + * decrement the reference count of the original hook + */ +GHook* g_hook_next_valid (GHookList *hook_list, + GHook *hook, + gboolean may_be_in_call); +/* GHookCompareFunc implementation to insert hooks sorted by their id */ +gint g_hook_compare_ids (GHook *new_hook, + GHook *sibling); +/* convenience macros */ +#define g_hook_append( hook_list, hook ) \ + g_hook_insert_before ((hook_list), NULL, (hook)) +/* invoke all valid hooks with the (*GHookFunc) signature. + */ +void g_hook_list_invoke (GHookList *hook_list, + gboolean may_recurse); +/* invoke all valid hooks with the (*GHookCheckFunc) signature, + * and destroy the hook if FALSE is returned. + */ +void g_hook_list_invoke_check (GHookList *hook_list, + gboolean may_recurse); +/* invoke a marshaller on all valid hooks. + */ +void g_hook_list_marshal (GHookList *hook_list, + gboolean may_recurse, + GHookMarshaller marshaller, + gpointer marshal_data); +void g_hook_list_marshal_check (GHookList *hook_list, + gboolean may_recurse, + GHookCheckMarshaller marshaller, + gpointer marshal_data); + +G_END_DECLS + +#endif /* __G_HOOK_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/ghostutils.h b/protocols/Sametime/src/glib/include/glib/ghostutils.h new file mode 100644 index 0000000000..0349da364b --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/ghostutils.h @@ -0,0 +1,40 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_HOST_UTILS_H__ +#define __G_HOST_UTILS_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +gboolean g_hostname_is_non_ascii (const gchar *hostname); +gboolean g_hostname_is_ascii_encoded (const gchar *hostname); +gboolean g_hostname_is_ip_address (const gchar *hostname); + +gchar *g_hostname_to_ascii (const gchar *hostname); +gchar *g_hostname_to_unicode (const gchar *hostname); + +G_END_DECLS + +#endif /* __G_HOST_UTILS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/giochannel.h b/protocols/Sametime/src/glib/include/glib/giochannel.h new file mode 100644 index 0000000000..2a40aa29ae --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/giochannel.h @@ -0,0 +1,366 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_IOCHANNEL_H__ +#define __G_IOCHANNEL_H__ + +#include <glib/gconvert.h> +#include <glib/gmain.h> +#include <glib/gstring.h> + +G_BEGIN_DECLS + +/* GIOChannel + */ + +typedef struct _GIOChannel GIOChannel; +typedef struct _GIOFuncs GIOFuncs; + +typedef enum +{ + G_IO_ERROR_NONE, + G_IO_ERROR_AGAIN, + G_IO_ERROR_INVAL, + G_IO_ERROR_UNKNOWN +} GIOError; + +#define G_IO_CHANNEL_ERROR g_io_channel_error_quark() + +typedef enum +{ + /* Derived from errno */ + G_IO_CHANNEL_ERROR_FBIG, + G_IO_CHANNEL_ERROR_INVAL, + G_IO_CHANNEL_ERROR_IO, + G_IO_CHANNEL_ERROR_ISDIR, + G_IO_CHANNEL_ERROR_NOSPC, + G_IO_CHANNEL_ERROR_NXIO, + G_IO_CHANNEL_ERROR_OVERFLOW, + G_IO_CHANNEL_ERROR_PIPE, + /* Other */ + G_IO_CHANNEL_ERROR_FAILED +} GIOChannelError; + +typedef enum +{ + G_IO_STATUS_ERROR, + G_IO_STATUS_NORMAL, + G_IO_STATUS_EOF, + G_IO_STATUS_AGAIN +} GIOStatus; + +typedef enum +{ + G_SEEK_CUR, + G_SEEK_SET, + G_SEEK_END +} GSeekType; + +typedef enum +{ + G_IO_IN GLIB_SYSDEF_POLLIN, + G_IO_OUT GLIB_SYSDEF_POLLOUT, + G_IO_PRI GLIB_SYSDEF_POLLPRI, + G_IO_ERR GLIB_SYSDEF_POLLERR, + G_IO_HUP GLIB_SYSDEF_POLLHUP, + G_IO_NVAL GLIB_SYSDEF_POLLNVAL +} GIOCondition; + +typedef enum +{ + G_IO_FLAG_APPEND = 1 << 0, + G_IO_FLAG_NONBLOCK = 1 << 1, + G_IO_FLAG_IS_READABLE = 1 << 2, /* Read only flag */ + G_IO_FLAG_IS_WRITEABLE = 1 << 3, /* Read only flag */ + G_IO_FLAG_IS_SEEKABLE = 1 << 4, /* Read only flag */ + G_IO_FLAG_MASK = (1 << 5) - 1, + G_IO_FLAG_GET_MASK = G_IO_FLAG_MASK, + G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK +} GIOFlags; + +struct _GIOChannel +{ + /*< private >*/ + gint ref_count; + GIOFuncs *funcs; + + gchar *encoding; + GIConv read_cd; + GIConv write_cd; + gchar *line_term; /* String which indicates the end of a line of text */ + guint line_term_len; /* So we can have null in the line term */ + + gsize buf_size; + GString *read_buf; /* Raw data from the channel */ + GString *encoded_read_buf; /* Channel data converted to UTF-8 */ + GString *write_buf; /* Data ready to be written to the file */ + gchar partial_write_buf[6]; /* UTF-8 partial characters, null terminated */ + + /* Group the flags together, immediately after partial_write_buf, to save memory */ + + guint use_buffer : 1; /* The encoding uses the buffers */ + guint do_encode : 1; /* The encoding uses the GIConv coverters */ + guint close_on_unref : 1; /* Close the channel on final unref */ + guint is_readable : 1; /* Cached GIOFlag */ + guint is_writeable : 1; /* ditto */ + guint is_seekable : 1; /* ditto */ + + gpointer reserved1; + gpointer reserved2; +}; + +typedef gboolean (*GIOFunc) (GIOChannel *source, + GIOCondition condition, + gpointer data); +struct _GIOFuncs +{ + GIOStatus (*io_read) (GIOChannel *channel, + gchar *buf, + gsize count, + gsize *bytes_read, + GError **err); + GIOStatus (*io_write) (GIOChannel *channel, + const gchar *buf, + gsize count, + gsize *bytes_written, + GError **err); + GIOStatus (*io_seek) (GIOChannel *channel, + gint64 offset, + GSeekType type, + GError **err); + GIOStatus (*io_close) (GIOChannel *channel, + GError **err); + GSource* (*io_create_watch) (GIOChannel *channel, + GIOCondition condition); + void (*io_free) (GIOChannel *channel); + GIOStatus (*io_set_flags) (GIOChannel *channel, + GIOFlags flags, + GError **err); + GIOFlags (*io_get_flags) (GIOChannel *channel); +}; + +void g_io_channel_init (GIOChannel *channel); +GIOChannel *g_io_channel_ref (GIOChannel *channel); +void g_io_channel_unref (GIOChannel *channel); + +#ifndef G_DISABLE_DEPRECATED +GIOError g_io_channel_read (GIOChannel *channel, + gchar *buf, + gsize count, + gsize *bytes_read); +GIOError g_io_channel_write (GIOChannel *channel, + const gchar *buf, + gsize count, + gsize *bytes_written); +GIOError g_io_channel_seek (GIOChannel *channel, + gint64 offset, + GSeekType type); +void g_io_channel_close (GIOChannel *channel); +#endif /* G_DISABLE_DEPRECATED */ + +GIOStatus g_io_channel_shutdown (GIOChannel *channel, + gboolean flush, + GError **err); +guint g_io_add_watch_full (GIOChannel *channel, + gint priority, + GIOCondition condition, + GIOFunc func, + gpointer user_data, + GDestroyNotify notify); +GSource * g_io_create_watch (GIOChannel *channel, + GIOCondition condition); +guint g_io_add_watch (GIOChannel *channel, + GIOCondition condition, + GIOFunc func, + gpointer user_data); + +/* character encoding conversion involved functions. + */ + +void g_io_channel_set_buffer_size (GIOChannel *channel, + gsize size); +gsize g_io_channel_get_buffer_size (GIOChannel *channel); +GIOCondition g_io_channel_get_buffer_condition (GIOChannel *channel); +GIOStatus g_io_channel_set_flags (GIOChannel *channel, + GIOFlags flags, + GError **error); +GIOFlags g_io_channel_get_flags (GIOChannel *channel); +void g_io_channel_set_line_term (GIOChannel *channel, + const gchar *line_term, + gint length); +G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel, + gint *length); +void g_io_channel_set_buffered (GIOChannel *channel, + gboolean buffered); +gboolean g_io_channel_get_buffered (GIOChannel *channel); +GIOStatus g_io_channel_set_encoding (GIOChannel *channel, + const gchar *encoding, + GError **error); +G_CONST_RETURN gchar* g_io_channel_get_encoding (GIOChannel *channel); +void g_io_channel_set_close_on_unref (GIOChannel *channel, + gboolean do_close); +gboolean g_io_channel_get_close_on_unref (GIOChannel *channel); + + +GIOStatus g_io_channel_flush (GIOChannel *channel, + GError **error); +GIOStatus g_io_channel_read_line (GIOChannel *channel, + gchar **str_return, + gsize *length, + gsize *terminator_pos, + GError **error); +GIOStatus g_io_channel_read_line_string (GIOChannel *channel, + GString *buffer, + gsize *terminator_pos, + GError **error); +GIOStatus g_io_channel_read_to_end (GIOChannel *channel, + gchar **str_return, + gsize *length, + GError **error); +GIOStatus g_io_channel_read_chars (GIOChannel *channel, + gchar *buf, + gsize count, + gsize *bytes_read, + GError **error); +GIOStatus g_io_channel_read_unichar (GIOChannel *channel, + gunichar *thechar, + GError **error); +GIOStatus g_io_channel_write_chars (GIOChannel *channel, + const gchar *buf, + gssize count, + gsize *bytes_written, + GError **error); +GIOStatus g_io_channel_write_unichar (GIOChannel *channel, + gunichar thechar, + GError **error); +GIOStatus g_io_channel_seek_position (GIOChannel *channel, + gint64 offset, + GSeekType type, + GError **error); +#ifdef G_OS_WIN32 +#define g_io_channel_new_file g_io_channel_new_file_utf8 +#endif + +GIOChannel* g_io_channel_new_file (const gchar *filename, + const gchar *mode, + GError **error); + +/* Error handling */ + +GQuark g_io_channel_error_quark (void); +GIOChannelError g_io_channel_error_from_errno (gint en); + +/* On Unix, IO channels created with this function for any file + * descriptor or socket. + * + * On Win32, this can be used either for files opened with the MSVCRT + * (the Microsoft run-time C library) _open() or _pipe, including file + * descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr), + * or for Winsock SOCKETs. If the parameter is a legal file + * descriptor, it is assumed to be such, otherwise it should be a + * SOCKET. This relies on SOCKETs and file descriptors not + * overlapping. If you want to be certain, call either + * g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket() + * instead as appropriate. + * + * The term file descriptor as used in the context of Win32 refers to + * the emulated Unix-like file descriptors MSVCRT provides. The native + * corresponding concept is file HANDLE. There isn't as of yet a way to + * get GIOChannels for Win32 file HANDLEs. + */ +GIOChannel* g_io_channel_unix_new (int fd); +gint g_io_channel_unix_get_fd (GIOChannel *channel); + + +/* Hook for GClosure / GSource integration. Don't touch */ +GLIB_VAR GSourceFuncs g_io_watch_funcs; + +#ifdef G_OS_WIN32 + +/* You can use this "pseudo file descriptor" in a GPollFD to add + * polling for Windows messages. GTK applications should not do that. + */ + +#define G_WIN32_MSG_HANDLE 19981206 + +/* Use this to get a GPollFD from a GIOChannel, so that you can call + * g_io_channel_win32_poll(). After calling this you should only use + * g_io_channel_read() to read from the GIOChannel, i.e. never read() + * from the underlying file descriptor. For SOCKETs, it is possible to call + * recv(). + */ +void g_io_channel_win32_make_pollfd (GIOChannel *channel, + GIOCondition condition, + GPollFD *fd); + +/* This can be used to wait a until at least one of the channels is readable. + * On Unix you would do a select() on the file descriptors of the channels. + */ +gint g_io_channel_win32_poll (GPollFD *fds, + gint n_fds, + gint timeout_); + +/* Create an IO channel for Windows messages for window handle hwnd. */ +#if GLIB_SIZEOF_VOID_P == 8 +/* We use gsize here so that it is still an integer type and not a + * pointer, like the guint in the traditional prototype. We can't use + * intptr_t as that is not portable enough. + */ +GIOChannel *g_io_channel_win32_new_messages (gsize hwnd); +#else +GIOChannel *g_io_channel_win32_new_messages (guint hwnd); +#endif + +/* Create an IO channel for C runtime (emulated Unix-like) file + * descriptors. After calling g_io_add_watch() on a IO channel + * returned by this function, you shouldn't call read() on the file + * descriptor. This is because adding polling for a file descriptor is + * implemented on Win32 by starting a thread that sits blocked in a + * read() from the file descriptor most of the time. All reads from + * the file descriptor should be done by this internal GLib + * thread. Your code should call only g_io_channel_read_chars(). + */ +GIOChannel* g_io_channel_win32_new_fd (gint fd); + +/* Get the C runtime file descriptor of a channel. */ +gint g_io_channel_win32_get_fd (GIOChannel *channel); + +/* Create an IO channel for a winsock socket. The parameter should be + * a SOCKET. Contrary to IO channels for file descriptors (on *Win32), + * you can use normal recv() or recvfrom() on sockets even if GLib + * is polling them. + */ +GIOChannel *g_io_channel_win32_new_socket (gint socket); + +#endif + +G_END_DECLS + +#endif /* __G_IOCHANNEL_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gkeyfile.h b/protocols/Sametime/src/glib/include/glib/gkeyfile.h new file mode 100644 index 0000000000..e16dc61272 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gkeyfile.h @@ -0,0 +1,266 @@ +/* gkeyfile.h - desktop entry file parser + * + * Copyright 2004 Red Hat, Inc. + * + * Ray Strode <halfline@hawaii.rr.com> + * + * GLib is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * GLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GLib; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_KEY_FILE_H__ +#define __G_KEY_FILE_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +typedef enum +{ + G_KEY_FILE_ERROR_UNKNOWN_ENCODING, + G_KEY_FILE_ERROR_PARSE, + G_KEY_FILE_ERROR_NOT_FOUND, + G_KEY_FILE_ERROR_KEY_NOT_FOUND, + G_KEY_FILE_ERROR_GROUP_NOT_FOUND, + G_KEY_FILE_ERROR_INVALID_VALUE +} GKeyFileError; + +#define G_KEY_FILE_ERROR g_key_file_error_quark() + +GQuark g_key_file_error_quark (void); + +typedef struct _GKeyFile GKeyFile; + +typedef enum +{ + G_KEY_FILE_NONE = 0, + G_KEY_FILE_KEEP_COMMENTS = 1 << 0, + G_KEY_FILE_KEEP_TRANSLATIONS = 1 << 1 +} GKeyFileFlags; + +GKeyFile *g_key_file_new (void); +void g_key_file_free (GKeyFile *key_file); +void g_key_file_set_list_separator (GKeyFile *key_file, + gchar separator); +gboolean g_key_file_load_from_file (GKeyFile *key_file, + const gchar *file, + GKeyFileFlags flags, + GError **error); +gboolean g_key_file_load_from_data (GKeyFile *key_file, + const gchar *data, + gsize length, + GKeyFileFlags flags, + GError **error); +gboolean g_key_file_load_from_dirs (GKeyFile *key_file, + const gchar *file, + const gchar **search_dirs, + gchar **full_path, + GKeyFileFlags flags, + GError **error); +gboolean g_key_file_load_from_data_dirs (GKeyFile *key_file, + const gchar *file, + gchar **full_path, + GKeyFileFlags flags, + GError **error); +gchar *g_key_file_to_data (GKeyFile *key_file, + gsize *length, + GError **error) G_GNUC_MALLOC; +gchar *g_key_file_get_start_group (GKeyFile *key_file) G_GNUC_MALLOC; +gchar **g_key_file_get_groups (GKeyFile *key_file, + gsize *length) G_GNUC_MALLOC; +gchar **g_key_file_get_keys (GKeyFile *key_file, + const gchar *group_name, + gsize *length, + GError **error) G_GNUC_MALLOC; +gboolean g_key_file_has_group (GKeyFile *key_file, + const gchar *group_name); +gboolean g_key_file_has_key (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +gchar *g_key_file_get_value (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_value (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *value); +gchar *g_key_file_get_string (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_string (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *string); +gchar *g_key_file_get_locale_string (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *locale, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_locale_string (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *locale, + const gchar *string); +gboolean g_key_file_get_boolean (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +void g_key_file_set_boolean (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gboolean value); +gint g_key_file_get_integer (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +void g_key_file_set_integer (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gint value); +gint64 g_key_file_get_int64 (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +void g_key_file_set_int64 (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gint64 value); +guint64 g_key_file_get_uint64 (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +void g_key_file_set_uint64 (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + guint64 value); +gdouble g_key_file_get_double (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +void g_key_file_set_double (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gdouble value); +gchar **g_key_file_get_string_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_string_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar * const list[], + gsize length); +gchar **g_key_file_get_locale_string_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *locale, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_locale_string_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *locale, + const gchar * const list[], + gsize length); +gboolean *g_key_file_get_boolean_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_boolean_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gboolean list[], + gsize length); +gint *g_key_file_get_integer_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_double_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gdouble list[], + gsize length); +gdouble *g_key_file_get_double_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gsize *length, + GError **error) G_GNUC_MALLOC; +void g_key_file_set_integer_list (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + gint list[], + gsize length); +gboolean g_key_file_set_comment (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + const gchar *comment, + GError **error); +gchar *g_key_file_get_comment (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) G_GNUC_MALLOC; + +gboolean g_key_file_remove_comment (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +gboolean g_key_file_remove_key (GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error); +gboolean g_key_file_remove_group (GKeyFile *key_file, + const gchar *group_name, + GError **error); + +/* Defines for handling freedesktop.org Desktop files */ +#define G_KEY_FILE_DESKTOP_GROUP "Desktop Entry" + +#define G_KEY_FILE_DESKTOP_KEY_TYPE "Type" +#define G_KEY_FILE_DESKTOP_KEY_VERSION "Version" +#define G_KEY_FILE_DESKTOP_KEY_NAME "Name" +#define G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME "GenericName" +#define G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY "NoDisplay" +#define G_KEY_FILE_DESKTOP_KEY_COMMENT "Comment" +#define G_KEY_FILE_DESKTOP_KEY_ICON "Icon" +#define G_KEY_FILE_DESKTOP_KEY_HIDDEN "Hidden" +#define G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN "OnlyShowIn" +#define G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN "NotShowIn" +#define G_KEY_FILE_DESKTOP_KEY_TRY_EXEC "TryExec" +#define G_KEY_FILE_DESKTOP_KEY_EXEC "Exec" +#define G_KEY_FILE_DESKTOP_KEY_PATH "Path" +#define G_KEY_FILE_DESKTOP_KEY_TERMINAL "Terminal" +#define G_KEY_FILE_DESKTOP_KEY_MIME_TYPE "MimeType" +#define G_KEY_FILE_DESKTOP_KEY_CATEGORIES "Categories" +#define G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY "StartupNotify" +#define G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS "StartupWMClass" +#define G_KEY_FILE_DESKTOP_KEY_URL "URL" + +#define G_KEY_FILE_DESKTOP_TYPE_APPLICATION "Application" +#define G_KEY_FILE_DESKTOP_TYPE_LINK "Link" +#define G_KEY_FILE_DESKTOP_TYPE_DIRECTORY "Directory" + +G_END_DECLS + +#endif /* __G_KEY_FILE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/glist.h b/protocols/Sametime/src/glib/include/glib/glist.h new file mode 100644 index 0000000000..e74ed96f15 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/glist.h @@ -0,0 +1,120 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_LIST_H__ +#define __G_LIST_H__ + +#include <glib/gmem.h> + +G_BEGIN_DECLS + +typedef struct _GList GList; + +struct _GList +{ + gpointer data; + GList *next; + GList *prev; +}; + +/* Doubly linked lists + */ +GList* g_list_alloc (void) G_GNUC_WARN_UNUSED_RESULT; +void g_list_free (GList *list); +void g_list_free_1 (GList *list); +#define g_list_free1 g_list_free_1 +GList* g_list_append (GList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_prepend (GList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert (GList *list, + gpointer data, + gint position) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_sorted (GList *list, + gpointer data, + GCompareFunc func) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_sorted_with_data (GList *list, + gpointer data, + GCompareDataFunc func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_before (GList *list, + GList *sibling, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_concat (GList *list1, + GList *list2) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove (GList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove_all (GList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove_link (GList *list, + GList *llink) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_delete_link (GList *list, + GList *link_) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_reverse (GList *list) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_copy (GList *list) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_nth (GList *list, + guint n); +GList* g_list_nth_prev (GList *list, + guint n); +GList* g_list_find (GList *list, + gconstpointer data); +GList* g_list_find_custom (GList *list, + gconstpointer data, + GCompareFunc func); +gint g_list_position (GList *list, + GList *llink); +gint g_list_index (GList *list, + gconstpointer data); +GList* g_list_last (GList *list); +GList* g_list_first (GList *list); +guint g_list_length (GList *list); +void g_list_foreach (GList *list, + GFunc func, + gpointer user_data); +GList* g_list_sort (GList *list, + GCompareFunc compare_func) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_sort_with_data (GList *list, + GCompareDataFunc compare_func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +gpointer g_list_nth_data (GList *list, + guint n); + + +#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL) +#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL) + +#ifndef G_DISABLE_DEPRECATED +void g_list_push_allocator (gpointer allocator); +void g_list_pop_allocator (void); +#endif + +G_END_DECLS + +#endif /* __G_LIST_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmacros.h b/protocols/Sametime/src/glib/include/glib/gmacros.h new file mode 100644 index 0000000000..9f9c25dcb1 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmacros.h @@ -0,0 +1,284 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* This file must not include any other glib header file and must thus + * not refer to variables from glibconfig.h + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MACROS_H__ +#define __G_MACROS_H__ + +/* We include stddef.h to get the system's definition of NULL + */ +#include <stddef.h> + +/* Here we provide G_GNUC_EXTENSION as an alias for __extension__, + * where this is valid. This allows for warningless compilation of + * "long long" types even in the presence of '-ansi -pedantic'. + */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) +# define G_GNUC_EXTENSION __extension__ +#else +# define G_GNUC_EXTENSION +#endif + +/* Provide macros to feature the GCC function attribute. + */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define G_GNUC_PURE \ + __attribute__((__pure__)) +#define G_GNUC_MALLOC \ + __attribute__((__malloc__)) +#else +#define G_GNUC_PURE +#define G_GNUC_MALLOC +#endif + +#if __GNUC__ >= 4 +#define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +#else +#define G_GNUC_NULL_TERMINATED +#endif + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) +#define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y))) +#else +#define G_GNUC_ALLOC_SIZE(x) +#define G_GNUC_ALLOC_SIZE2(x,y) +#endif + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#define G_GNUC_SCANF( format_idx, arg_idx ) \ + __attribute__((__format__ (__scanf__, format_idx, arg_idx))) +#define G_GNUC_FORMAT( arg_idx ) \ + __attribute__((__format_arg__ (arg_idx))) +#define G_GNUC_NORETURN \ + __attribute__((__noreturn__)) +#define G_GNUC_CONST \ + __attribute__((__const__)) +#define G_GNUC_UNUSED \ + __attribute__((__unused__)) +#define G_GNUC_NO_INSTRUMENT \ + __attribute__((__no_instrument_function__)) +#else /* !__GNUC__ */ +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#define G_GNUC_SCANF( format_idx, arg_idx ) +#define G_GNUC_FORMAT( arg_idx ) +#define G_GNUC_NORETURN +#define G_GNUC_CONST +#define G_GNUC_UNUSED +#define G_GNUC_NO_INSTRUMENT +#endif /* !__GNUC__ */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define G_GNUC_DEPRECATED \ + __attribute__((__deprecated__)) +#else +#define G_GNUC_DEPRECATED +#endif /* __GNUC__ */ + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define G_GNUC_DEPRECATED_FOR(f) \ + __attribute__((deprecated("Use " #f " instead"))) +#else +#define G_GNUC_DEPRECATED_FOR(f) G_GNUC_DEPRECATED +#endif /* __GNUC__ */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# define G_GNUC_MAY_ALIAS __attribute__((may_alias)) +#else +# define G_GNUC_MAY_ALIAS +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define G_GNUC_WARN_UNUSED_RESULT \ + __attribute__((warn_unused_result)) +#else +#define G_GNUC_WARN_UNUSED_RESULT +#endif /* __GNUC__ */ + +#ifndef G_DISABLE_DEPRECATED +/* Wrap the gcc __PRETTY_FUNCTION__ and __FUNCTION__ variables with + * macros, so we can refer to them as strings unconditionally. + * usage not-recommended since gcc-3.0 + */ +#if defined (__GNUC__) && (__GNUC__ < 3) +#define G_GNUC_FUNCTION __FUNCTION__ +#define G_GNUC_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else /* !__GNUC__ */ +#define G_GNUC_FUNCTION "" +#define G_GNUC_PRETTY_FUNCTION "" +#endif /* !__GNUC__ */ +#endif /* !G_DISABLE_DEPRECATED */ + +#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string) +#define G_STRINGIFY_ARG(contents) #contents + +#define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2 +#define G_PASTE(identifier1,identifier2) G_PASTE_ARGS (identifier1, identifier2) +#define G_STATIC_ASSERT(expr) typedef struct { char Compile_Time_Assertion[(expr) ? 1 : -1]; } G_PASTE (_GStaticAssert_, __LINE__) + +/* Provide a string identifying the current code position */ +#if defined(__GNUC__) && (__GNUC__ < 3) && !defined(__cplusplus) +# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()" +#else +# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) +#endif + +/* Provide a string identifying the current function, non-concatenatable */ +#if defined (__GNUC__) +# define G_STRFUNC ((const char*) (__PRETTY_FUNCTION__)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 19901L +# define G_STRFUNC ((const char*) (__func__)) +#else +# define G_STRFUNC ((const char*) ("???")) +#endif + +/* Guard C code in headers, while including them from C++ */ +#ifdef __cplusplus +# define G_BEGIN_DECLS extern "C" { +# define G_END_DECLS } +#else +# define G_BEGIN_DECLS +# define G_END_DECLS +#endif + +/* Provide definitions for some commonly used macros. + * Some of them are only provided if they haven't already + * been defined. It is assumed that if they are already + * defined then the current definition is correct. + */ +#ifndef NULL +# ifdef __cplusplus +# define NULL (0L) +# else /* !__cplusplus */ +# define NULL ((void*) 0) +# endif /* !__cplusplus */ +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#undef ABS +#define ABS(a) (((a) < 0) ? -(a) : (a)) + +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +/* Count the number of elements in an array. The array must be defined + * as such; using this with a dynamically allocated array will give + * incorrect results. + */ +#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) + +/* Macros by analogy to GINT_TO_POINTER, GPOINTER_TO_INT + */ +#define GPOINTER_TO_SIZE(p) ((gsize) (p)) +#define GSIZE_TO_POINTER(s) ((gpointer) (gsize) (s)) + +/* Provide convenience macros for handling structure + * fields through their offsets. + */ + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define G_STRUCT_OFFSET(struct_type, member) \ + ((glong) offsetof (struct_type, member)) +#else +# define G_STRUCT_OFFSET(struct_type, member) \ + ((glong) ((guint8*) &((struct_type*) 0)->member)) +#endif + +#define G_STRUCT_MEMBER_P(struct_p, struct_offset) \ + ((gpointer) ((guint8*) (struct_p) + (glong) (struct_offset))) +#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset) \ + (*(member_type*) G_STRUCT_MEMBER_P ((struct_p), (struct_offset))) + +/* Provide simple macro statement wrappers: + * G_STMT_START { statements; } G_STMT_END; + * This can be used as a single statement, like: + * if (x) G_STMT_START { ... } G_STMT_END; else ... + * This intentionally does not use compiler extensions like GCC's '({...})' to + * avoid portability issue or side effects when compiled with different compilers. + */ +#if !(defined (G_STMT_START) && defined (G_STMT_END)) +# define G_STMT_START do +# define G_STMT_END while (0) +#endif + +/* Allow the app programmer to select whether or not return values + * (usually char*) are const or not. Don't try using this feature for + * functions with C++ linkage. + */ +#ifdef G_DISABLE_CONST_RETURNS +#define G_CONST_RETURN +#else +#define G_CONST_RETURN const +#endif + +/* + * The G_LIKELY and G_UNLIKELY macros let the programmer give hints to + * the compiler about the expected result of an expression. Some compilers + * can use this information for optimizations. + * + * The _G_BOOLEAN_EXPR macro is intended to trigger a gcc warning when + * putting assignments in g_return_if_fail (). + */ +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#define _G_BOOLEAN_EXPR(expr) \ + __extension__ ({ \ + int _g_boolean_var_; \ + if (expr) \ + _g_boolean_var_ = 1; \ + else \ + _g_boolean_var_ = 0; \ + _g_boolean_var_; \ +}) +#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1)) +#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0)) +#else +#define G_LIKELY(expr) (expr) +#define G_UNLIKELY(expr) (expr) +#endif + +#endif /* __G_MACROS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmain.h b/protocols/Sametime/src/glib/include/glib/gmain.h new file mode 100644 index 0000000000..24c6171fe6 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmain.h @@ -0,0 +1,531 @@ +/* gmain.h - the GLib Main loop + * Copyright (C) 1998-2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MAIN_H__ +#define __G_MAIN_H__ + +#include <glib/gpoll.h> +#include <glib/gslist.h> +#include <glib/gthread.h> + +G_BEGIN_DECLS + +/** + * GMainContext: + * + * The <structname>GMainContext</structname> struct is an opaque data + * type representing a set of sources to be handled in a main loop. + */ +typedef struct _GMainContext GMainContext; + +/** + * GMainLoop: + * + * The <structname>GMainLoop</structname> struct is an opaque data type + * representing the main event loop of a GLib or GTK+ application. + */ +typedef struct _GMainLoop GMainLoop; + +/** + * GSource: + * + * The <structname>GSource</structname> struct is an opaque data type + * representing an event source. + */ +typedef struct _GSource GSource; + +/** + * GSourceCallbackFuncs: + * @ref: Called when a reference is added to the callback object + * @unref: Called when a reference to the callback object is dropped + * @get: Called to extract the callback function and data from the + * callback object. + + * The <structname>GSourceCallbackFuncs</structname> struct contains + * functions for managing callback objects. + */ +typedef struct _GSourceCallbackFuncs GSourceCallbackFuncs; + +/** + * GSourceFuncs: + * @prepare: Called before all the file descriptors are polled. If the + * source can determine that it is ready here (without waiting for the + * results of the poll() call) it should return %TRUE. It can also return + * a @timeout_ value which should be the maximum timeout (in milliseconds) + * which should be passed to the poll() call. The actual timeout used will + * be -1 if all sources returned -1, or it will be the minimum of all the + * @timeout_ values returned which were >= 0. + * @check: Called after all the file descriptors are polled. The source + * should return %TRUE if it is ready to be dispatched. Note that some + * time may have passed since the previous prepare function was called, + * so the source should be checked again here. + * @dispatch: Called to dispatch the event source, after it has returned + * %TRUE in either its @prepare or its @check function. The @dispatch + * function is passed in a callback function and data. The callback + * function may be %NULL if the source was never connected to a callback + * using g_source_set_callback(). The @dispatch function should call the + * callback function with @user_data and whatever additional parameters + * are needed for this type of event source. + * @finalize: Called when the source is finalized. + * @closure_callback: + * @closure_marshal: + * + * The <structname>GSourceFuncs</structname> struct contains a table of + * functions used to handle event sources in a generic manner. + * + * For idle sources, the prepare and check functions always return %TRUE + * to indicate that the source is always ready to be processed. The prepare + * function also returns a timeout value of 0 to ensure that the poll() call + * doesn't block (since that would be time wasted which could have been spent + * running the idle function). + * + * For timeout sources, the prepare and check functions both return %TRUE + * if the timeout interval has expired. The prepare function also returns + * a timeout value to ensure that the poll() call doesn't block too long + * and miss the next timeout. + * + * For file descriptor sources, the prepare function typically returns %FALSE, + * since it must wait until poll() has been called before it knows whether + * any events need to be processed. It sets the returned timeout to -1 to + * indicate that it doesn't mind how long the poll() call blocks. In the + * check function, it tests the results of the poll() call to see if the + * required condition has been met, and returns %TRUE if so. + */ +typedef struct _GSourceFuncs GSourceFuncs; + +/** + * GPid: + * + * A type which is used to hold a process identification. + * + * On UNIX, processes are identified by a process id (an integer), + * while Windows uses process handles (which are pointers). + */ + +typedef gboolean (*GSourceFunc) (gpointer data); + +/** + * GChildWatchFunc: + * @pid: the process id of the child process + * @status: Status information about the child process, + * see waitpid(2) for more information about this field + * @data: user data passed to g_child_watch_add() + * + * The type of functions to be called when a child exists. + */ +typedef void (*GChildWatchFunc) (GPid pid, + gint status, + gpointer data); +struct _GSource +{ + /*< private >*/ + gpointer callback_data; + GSourceCallbackFuncs *callback_funcs; + + GSourceFuncs *source_funcs; + guint ref_count; + + GMainContext *context; + + gint priority; + guint flags; + guint source_id; + + GSList *poll_fds; + + GSource *prev; + GSource *next; + + char *name; + gpointer reserved2; +}; + +struct _GSourceCallbackFuncs +{ + void (*ref) (gpointer cb_data); + void (*unref) (gpointer cb_data); + void (*get) (gpointer cb_data, + GSource *source, + GSourceFunc *func, + gpointer *data); +}; + +typedef void (*GSourceDummyMarshal) (void); + +struct _GSourceFuncs +{ + gboolean (*prepare) (GSource *source, + gint *timeout_); + gboolean (*check) (GSource *source); + gboolean (*dispatch) (GSource *source, + GSourceFunc callback, + gpointer user_data); + void (*finalize) (GSource *source); /* Can be NULL */ + + /* For use by g_source_set_closure */ + GSourceFunc closure_callback; + GSourceDummyMarshal closure_marshal; /* Really is of type GClosureMarshal */ +}; + +/* Standard priorities */ + +/** + * G_PRIORITY_HIGH: + * + * Use this for high priority event sources. + * + * It is not used within GLib or GTK+. + */ +#define G_PRIORITY_HIGH -100 + +/** + * G_PRIORITY_DEFAULT: + * + * Use this for default priority event sources. + * + * In GLib this priority is used when adding timeout functions + * with g_timeout_add(). In GDK this priority is used for events + * from the X server. + */ +#define G_PRIORITY_DEFAULT 0 + +/** + * G_PRIORITY_HIGH_IDLE: + * + * Use this for high priority idle functions. + * + * GTK+ uses #G_PRIORITY_HIGH_IDLE + 10 for resizing operations, + * and #G_PRIORITY_HIGH_IDLE + 20 for redrawing operations. (This is + * done to ensure that any pending resizes are processed before any + * pending redraws, so that widgets are not redrawn twice unnecessarily.) + */ +#define G_PRIORITY_HIGH_IDLE 100 + +/** + * G_PRIORITY_DEFAULT_IDLE: + * + * Use this for default priority idle functions. + * + * In GLib this priority is used when adding idle functions with + * g_idle_add(). + */ +#define G_PRIORITY_DEFAULT_IDLE 200 + +/** + * G_PRIORITY_LOW: + * + * Use this for very low priority background tasks. + * + * It is not used within GLib or GTK+. + */ +#define G_PRIORITY_LOW 300 + +/* GMainContext: */ + +GMainContext *g_main_context_new (void); +GMainContext *g_main_context_ref (GMainContext *context); +void g_main_context_unref (GMainContext *context); +GMainContext *g_main_context_default (void); + +gboolean g_main_context_iteration (GMainContext *context, + gboolean may_block); +gboolean g_main_context_pending (GMainContext *context); + +/* For implementation of legacy interfaces + */ +GSource *g_main_context_find_source_by_id (GMainContext *context, + guint source_id); +GSource *g_main_context_find_source_by_user_data (GMainContext *context, + gpointer user_data); +GSource *g_main_context_find_source_by_funcs_user_data (GMainContext *context, + GSourceFuncs *funcs, + gpointer user_data); + +/* Low level functions for implementing custom main loops. + */ +void g_main_context_wakeup (GMainContext *context); +gboolean g_main_context_acquire (GMainContext *context); +void g_main_context_release (GMainContext *context); +gboolean g_main_context_is_owner (GMainContext *context); +gboolean g_main_context_wait (GMainContext *context, + GCond *cond, + GMutex *mutex); + +gboolean g_main_context_prepare (GMainContext *context, + gint *priority); +gint g_main_context_query (GMainContext *context, + gint max_priority, + gint *timeout_, + GPollFD *fds, + gint n_fds); +gint g_main_context_check (GMainContext *context, + gint max_priority, + GPollFD *fds, + gint n_fds); +void g_main_context_dispatch (GMainContext *context); + +void g_main_context_set_poll_func (GMainContext *context, + GPollFunc func); +GPollFunc g_main_context_get_poll_func (GMainContext *context); + +/* Low level functions for use by source implementations + */ +void g_main_context_add_poll (GMainContext *context, + GPollFD *fd, + gint priority); +void g_main_context_remove_poll (GMainContext *context, + GPollFD *fd); + +gint g_main_depth (void); +GSource *g_main_current_source (void); + +/* GMainContexts for other threads + */ +void g_main_context_push_thread_default (GMainContext *context); +void g_main_context_pop_thread_default (GMainContext *context); +GMainContext *g_main_context_get_thread_default (void); + +/* GMainLoop: */ + +GMainLoop *g_main_loop_new (GMainContext *context, + gboolean is_running); +void g_main_loop_run (GMainLoop *loop); +void g_main_loop_quit (GMainLoop *loop); +GMainLoop *g_main_loop_ref (GMainLoop *loop); +void g_main_loop_unref (GMainLoop *loop); +gboolean g_main_loop_is_running (GMainLoop *loop); +GMainContext *g_main_loop_get_context (GMainLoop *loop); + +/* GSource: */ + +GSource *g_source_new (GSourceFuncs *source_funcs, + guint struct_size); +GSource *g_source_ref (GSource *source); +void g_source_unref (GSource *source); + +guint g_source_attach (GSource *source, + GMainContext *context); +void g_source_destroy (GSource *source); + +void g_source_set_priority (GSource *source, + gint priority); +gint g_source_get_priority (GSource *source); +void g_source_set_can_recurse (GSource *source, + gboolean can_recurse); +gboolean g_source_get_can_recurse (GSource *source); +guint g_source_get_id (GSource *source); + +GMainContext *g_source_get_context (GSource *source); + +void g_source_set_callback (GSource *source, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); + +void g_source_set_funcs (GSource *source, + GSourceFuncs *funcs); +gboolean g_source_is_destroyed (GSource *source); + +void g_source_set_name (GSource *source, + const char *name); +G_CONST_RETURN char* g_source_get_name (GSource *source); +void g_source_set_name_by_id (guint tag, + const char *name); + + +/* Used to implement g_source_connect_closure and internally*/ +void g_source_set_callback_indirect (GSource *source, + gpointer callback_data, + GSourceCallbackFuncs *callback_funcs); + +void g_source_add_poll (GSource *source, + GPollFD *fd); +void g_source_remove_poll (GSource *source, + GPollFD *fd); + +void g_source_get_current_time (GSource *source, + GTimeVal *timeval); + + /* void g_source_connect_closure (GSource *source, + GClosure *closure); + */ + +/* Specific source types + */ +GSource *g_idle_source_new (void); +GSource *g_child_watch_source_new (GPid pid); +GSource *g_timeout_source_new (guint interval); +GSource *g_timeout_source_new_seconds (guint interval); + +/* Miscellaneous functions + */ +void g_get_current_time (GTimeVal *result); + +/* ============== Compat main loop stuff ================== */ + +#ifndef G_DISABLE_DEPRECATED + +/** + * g_main_new: + * @is_running: set to %TRUE to indicate that the loop is running. This + * is not very important since calling g_main_run() will set this + * to %TRUE anyway. + * + * Creates a new #GMainLoop for th default main context. + * + * Returns: a new #GMainLoop + * + * Deprecated: 2.2: Use g_main_loop_new() instead + */ +#define g_main_new(is_running) g_main_loop_new (NULL, is_running) + +/** + * g_main_run: + * @loop: a #GMainLoop + * + * Runs a main loop until it stops running. + * + * Deprecated: 2.2: Use g_main_loop_run() instead + */ +#define g_main_run(loop) g_main_loop_run(loop) + +/** + * g_main_quit: + * @loop: a #GMainLoop + * + * Stops the #GMainLoop. + * If g_main_run() was called to run the #GMainLoop, it will now return. + * + * Deprecated: 2.2: Use g_main_loop_quit() instead + */ +#define g_main_quit(loop) g_main_loop_quit(loop) + +/** + * g_main_destroy: + * @loop: a #GMainLoop + * + * Frees the memory allocated for the #GMainLoop. + * + * Deprecated: 2.2: Use g_main_loop_unref() instead + */ +#define g_main_destroy(loop) g_main_loop_unref(loop) + +/** + * g_main_is_running: + * @loop: a #GMainLoop + * + * Checks if the main loop is running. + * + * Returns: %TRUE if the main loop is running + * + * Deprecated: 2.2: Use g_main_loop_is_running() instead + */ +#define g_main_is_running(loop) g_main_loop_is_running(loop) + +/** + * g_main_iteration: + * @may_block: set to %TRUE if it should block (i.e. wait) until an event + * source becomes ready. It will return after an event source has been + * processed. If set to %FALSE it will return immediately if no event + * source is ready to be processed. + * + * Runs a single iteration for the default #GMainContext. + * + * Returns: %TRUE if more events are pending. + * + * Deprecated: 2.2: Use g_main_context_iteration() instead. + */ +#define g_main_iteration(may_block) g_main_context_iteration (NULL, may_block) + +/** + * g_main_pending: + * + * Checks if any events are pending for the default #GMainContext + * (i.e. ready to be processed). + * + * Returns: %TRUE if any events are pending. + * + * Deprected: 2.2: Use g_main_context_pending() instead. + */ +#define g_main_pending() g_main_context_pending (NULL) + +/** + * g_main_set_poll_func: + * @func: the function to call to poll all file descriptors + * + * Sets the function to use for the handle polling of file descriptors + * for the default main context. + * + * Deprecated: 2.2: Use g_main_context_set_poll_func() again + */ +#define g_main_set_poll_func(func) g_main_context_set_poll_func (NULL, func) + +#endif /* G_DISABLE_DEPRECATED */ + +/* Source manipulation by ID */ +gboolean g_source_remove (guint tag); +gboolean g_source_remove_by_user_data (gpointer user_data); +gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs, + gpointer user_data); + +/* Idles, child watchers and timeouts */ +guint g_timeout_add_full (gint priority, + guint interval, + GSourceFunc function, + gpointer data, + GDestroyNotify notify); +guint g_timeout_add (guint interval, + GSourceFunc function, + gpointer data); +guint g_timeout_add_seconds_full (gint priority, + guint interval, + GSourceFunc function, + gpointer data, + GDestroyNotify notify); +guint g_timeout_add_seconds (guint interval, + GSourceFunc function, + gpointer data); +guint g_child_watch_add_full (gint priority, + GPid pid, + GChildWatchFunc function, + gpointer data, + GDestroyNotify notify); +guint g_child_watch_add (GPid pid, + GChildWatchFunc function, + gpointer data); +guint g_idle_add (GSourceFunc function, + gpointer data); +guint g_idle_add_full (gint priority, + GSourceFunc function, + gpointer data, + GDestroyNotify notify); +gboolean g_idle_remove_by_data (gpointer data); + +/* Hook for GClosure / GSource integration. Don't touch */ +GLIB_VAR GSourceFuncs g_timeout_funcs; +GLIB_VAR GSourceFuncs g_child_watch_funcs; +GLIB_VAR GSourceFuncs g_idle_funcs; + +G_END_DECLS + +#endif /* __G_MAIN_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmappedfile.h b/protocols/Sametime/src/glib/include/glib/gmappedfile.h new file mode 100644 index 0000000000..dbb3f89e6a --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmappedfile.h @@ -0,0 +1,49 @@ +/* GLIB - Library of useful routines for C programming + * gmappedfile.h: Simplified wrapper around the mmap function + * + * Copyright 2005 Matthias Clasen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MAPPED_FILE_H__ +#define __G_MAPPED_FILE_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +typedef struct _GMappedFile GMappedFile; + +GMappedFile *g_mapped_file_new (const gchar *filename, + gboolean writable, + GError **error) G_GNUC_MALLOC; +gsize g_mapped_file_get_length (GMappedFile *file); +gchar *g_mapped_file_get_contents (GMappedFile *file); +GMappedFile *g_mapped_file_ref (GMappedFile *file); +void g_mapped_file_unref (GMappedFile *file); + +#ifndef G_DISABLE_DEPRECATED +void g_mapped_file_free (GMappedFile *file); +#endif + +G_END_DECLS + +#endif /* __G_MAPPED_FILE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmarkup.h b/protocols/Sametime/src/glib/include/glib/gmarkup.h new file mode 100644 index 0000000000..7bfc08641c --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmarkup.h @@ -0,0 +1,163 @@ +/* gmarkup.h - Simple XML-like string parser/writer + * + * Copyright 2000 Red Hat, Inc. + * + * GLib is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * GLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GLib; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MARKUP_H__ +#define __G_MARKUP_H__ + +#include <stdarg.h> + +#include <glib/gerror.h> +#include <glib/gslist.h> + +G_BEGIN_DECLS + +typedef enum +{ + G_MARKUP_ERROR_BAD_UTF8, + G_MARKUP_ERROR_EMPTY, + G_MARKUP_ERROR_PARSE, + /* The following are primarily intended for specific GMarkupParser + * implementations to set. + */ + G_MARKUP_ERROR_UNKNOWN_ELEMENT, + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, + G_MARKUP_ERROR_INVALID_CONTENT, + G_MARKUP_ERROR_MISSING_ATTRIBUTE +} GMarkupError; + +#define G_MARKUP_ERROR g_markup_error_quark () + +GQuark g_markup_error_quark (void); + +typedef enum +{ + G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG = 1 << 0, + G_MARKUP_TREAT_CDATA_AS_TEXT = 1 << 1, + G_MARKUP_PREFIX_ERROR_POSITION = 1 << 2 +} GMarkupParseFlags; + +typedef struct _GMarkupParseContext GMarkupParseContext; +typedef struct _GMarkupParser GMarkupParser; + +struct _GMarkupParser +{ + /* Called for open tags <foo bar="baz"> */ + void (*start_element) (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error); + + /* Called for close tags </foo> */ + void (*end_element) (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error); + + /* Called for character data */ + /* text is not nul-terminated */ + void (*text) (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error); + + /* Called for strings that should be re-saved verbatim in this same + * position, but are not otherwise interpretable. At the moment + * this includes comments and processing instructions. + */ + /* text is not nul-terminated. */ + void (*passthrough) (GMarkupParseContext *context, + const gchar *passthrough_text, + gsize text_len, + gpointer user_data, + GError **error); + + /* Called on error, including one set by other + * methods in the vtable. The GError should not be freed. + */ + void (*error) (GMarkupParseContext *context, + GError *error, + gpointer user_data); +}; + +GMarkupParseContext *g_markup_parse_context_new (const GMarkupParser *parser, + GMarkupParseFlags flags, + gpointer user_data, + GDestroyNotify user_data_dnotify); +void g_markup_parse_context_free (GMarkupParseContext *context); +gboolean g_markup_parse_context_parse (GMarkupParseContext *context, + const gchar *text, + gssize text_len, + GError **error); +void g_markup_parse_context_push (GMarkupParseContext *context, + const GMarkupParser *parser, + gpointer user_data); +gpointer g_markup_parse_context_pop (GMarkupParseContext *context); + +gboolean g_markup_parse_context_end_parse (GMarkupParseContext *context, + GError **error); +G_CONST_RETURN gchar *g_markup_parse_context_get_element (GMarkupParseContext *context); +G_CONST_RETURN GSList *g_markup_parse_context_get_element_stack (GMarkupParseContext *context); + +/* For user-constructed error messages, has no precise semantics */ +void g_markup_parse_context_get_position (GMarkupParseContext *context, + gint *line_number, + gint *char_number); +gpointer g_markup_parse_context_get_user_data (GMarkupParseContext *context); + +/* useful when saving */ +gchar* g_markup_escape_text (const gchar *text, + gssize length); + +gchar *g_markup_printf_escaped (const char *format, + ...) G_GNUC_PRINTF (1, 2); +gchar *g_markup_vprintf_escaped (const char *format, + va_list args); + +typedef enum +{ + G_MARKUP_COLLECT_INVALID, + G_MARKUP_COLLECT_STRING, + G_MARKUP_COLLECT_STRDUP, + G_MARKUP_COLLECT_BOOLEAN, + G_MARKUP_COLLECT_TRISTATE, + + G_MARKUP_COLLECT_OPTIONAL = (1 << 16) +} GMarkupCollectType; + + +/* useful from start_element */ +gboolean g_markup_collect_attributes (const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + GError **error, + GMarkupCollectType first_type, + const gchar *first_attr, + ...); + +G_END_DECLS + +#endif /* __G_MARKUP_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmem.h b/protocols/Sametime/src/glib/include/glib/gmem.h new file mode 100644 index 0000000000..01d953e6c5 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmem.h @@ -0,0 +1,309 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MEM_H__ +#define __G_MEM_H__ + +#include <glib/gslice.h> +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/** + * GMemVTable: + * @malloc: function to use for allocating memory. + * @realloc: function to use for reallocating memory. + * @free: function to use to free memory. + * @calloc: function to use for allocating zero-filled memory. + * @try_malloc: function to use for allocating memory without a default error handler. + * @try_realloc: function to use for reallocating memory without a default error handler. + * + * A set of functions used to perform memory allocation. The same #GMemVTable must + * be used for all allocations in the same program; a call to g_mem_set_vtable(), + * if it exists, should be prior to any use of GLib. + */ +typedef struct _GMemVTable GMemVTable; + + +#if GLIB_SIZEOF_VOID_P > GLIB_SIZEOF_LONG +/** + * G_MEM_ALIGN: + * + * Indicates the number of bytes to which memory will be aligned on the + * current platform. + */ +# define G_MEM_ALIGN GLIB_SIZEOF_VOID_P +#else /* GLIB_SIZEOF_VOID_P <= GLIB_SIZEOF_LONG */ +# define G_MEM_ALIGN GLIB_SIZEOF_LONG +#endif /* GLIB_SIZEOF_VOID_P <= GLIB_SIZEOF_LONG */ + + +/* Memory allocation functions + */ + +void g_free (gpointer mem); + +gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_realloc (gpointer mem, + gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT; +gpointer g_try_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_try_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_try_realloc (gpointer mem, + gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT; + +gpointer g_malloc_n (gsize n_blocks, + gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2); +gpointer g_malloc0_n (gsize n_blocks, + gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2); +gpointer g_realloc_n (gpointer mem, + gsize n_blocks, + gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT; +gpointer g_try_malloc_n (gsize n_blocks, + gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2); +gpointer g_try_malloc0_n (gsize n_blocks, + gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2); +gpointer g_try_realloc_n (gpointer mem, + gsize n_blocks, + gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT; + + +/* Optimise: avoid the call to the (slower) _n function if we can + * determine at compile-time that no overflow happens. + */ +#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) +# define _G_NEW(struct_type, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + gsize __n = (gsize) (n_structs); \ + gsize __s = sizeof (struct_type); \ + gpointer __p; \ + if (__s == 1) \ + __p = g_##func (__n); \ + else if (__builtin_constant_p (__n) && \ + (__s == 0 || __n <= G_MAXSIZE / __s)) \ + __p = g_##func (__n * __s); \ + else \ + __p = g_##func##_n (__n, __s); \ + __p; \ + })) +# define _G_RENEW(struct_type, mem, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + gsize __n = (gsize) (n_structs); \ + gsize __s = sizeof (struct_type); \ + gpointer __p = (gpointer) (mem); \ + if (__s == 1) \ + __p = g_##func (__p, __n); \ + else if (__builtin_constant_p (__n) && \ + (__s == 0 || __n <= G_MAXSIZE / __s)) \ + __p = g_##func (__p, __n * __s); \ + else \ + __p = g_##func##_n (__p, __n, __s); \ + __p; \ + })) + +#else + +/* Unoptimised version: always call the _n() function. */ + +#define _G_NEW(struct_type, n_structs, func) \ + ((struct_type *) g_##func##_n ((n_structs), sizeof (struct_type))) +#define _G_RENEW(struct_type, mem, n_structs, func) \ + ((struct_type *) g_##func##_n (mem, (n_structs), sizeof (struct_type))) + +#endif + +/** + * g_new: + * @struct_type: the type of the elements to allocate + * @n_structs: the number of elements to allocate + * + * Allocates @n_structs elements of type @struct_type. + * The returned pointer is cast to a pointer to the given type. + * If @n_structs is 0 it returns %NULL. + * Care is taken to avoid overflow when calculating the size of the allocated block. + * + * Since the returned pointer is already casted to the right type, + * it is normally unnecessary to cast it explicitly, and doing + * so might hide memory allocation errors. + * + * Returns: a pointer to the allocated memory, cast to a pointer to @struct_type + */ +#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc) +/** + * g_new0: + * @struct_type: the type of the elements to allocate. + * @n_structs: the number of elements to allocate. + * + * Allocates @n_structs elements of type @struct_type, initialized to 0's. + * The returned pointer is cast to a pointer to the given type. + * If @n_structs is 0 it returns %NULL. + * Care is taken to avoid overflow when calculating the size of the allocated block. + * + * Since the returned pointer is already casted to the right type, + * it is normally unnecessary to cast it explicitly, and doing + * so might hide memory allocation errors. + * + * Returns: a pointer to the allocated memory, cast to a pointer to @struct_type. + */ +#define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0) +/** + * g_renew: + * @struct_type: the type of the elements to allocate + * @mem: the currently allocated memory + * @n_structs: the number of elements to allocate + * + * Reallocates the memory pointed to by @mem, so that it now has space for + * @n_structs elements of type @struct_type. It returns the new address of + * the memory, which may have been moved. + * Care is taken to avoid overflow when calculating the size of the allocated block. + * + * Returns: a pointer to the new allocated memory, cast to a pointer to @struct_type + */ +#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, realloc) +/** + * g_try_new: + * @struct_type: the type of the elements to allocate + * @n_structs: the number of elements to allocate + * + * Attempts to allocate @n_structs elements of type @struct_type, and returns + * %NULL on failure. Contrast with g_new(), which aborts the program on failure. + * The returned pointer is cast to a pointer to the given type. + * The function returns %NULL when @n_structs is 0 of if an overflow occurs. + * + * Since: 2.8 + * Returns: a pointer to the allocated memory, cast to a pointer to @struct_type + */ +#define g_try_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc) +/** + * g_try_new0: + * @struct_type: the type of the elements to allocate + * @n_structs: the number of elements to allocate + * + * Attempts to allocate @n_structs elements of type @struct_type, initialized + * to 0's, and returns %NULL on failure. Contrast with g_new0(), which aborts + * the program on failure. + * The returned pointer is cast to a pointer to the given type. + * The function returns %NULL when @n_structs is 0 of if an overflow occurs. + * + * Since: 2.8 + * Returns: a pointer to the allocated memory, cast to a pointer to @struct_type + */ +#define g_try_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc0) +/** + * g_try_renew: + * @struct_type: the type of the elements to allocate + * @mem: the currently allocated memory + * @n_structs: the number of elements to allocate + * + * Attempts to reallocate the memory pointed to by @mem, so that it now has + * space for @n_structs elements of type @struct_type, and returns %NULL on + * failure. Contrast with g_renew(), which aborts the program on failure. + * It returns the new address of the memory, which may have been moved. + * The function returns %NULL if an overflow occurs. + * + * Since: 2.8 + * Returns: a pointer to the new allocated memory, cast to a pointer to @struct_type + */ +#define g_try_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, try_realloc) + + +/* Memory allocation virtualization for debugging purposes + * g_mem_set_vtable() has to be the very first GLib function called + * if being used + */ +struct _GMemVTable { + gpointer (*malloc) (gsize n_bytes); + gpointer (*realloc) (gpointer mem, + gsize n_bytes); + void (*free) (gpointer mem); + /* optional; set to NULL if not used ! */ + gpointer (*calloc) (gsize n_blocks, + gsize n_block_bytes); + gpointer (*try_malloc) (gsize n_bytes); + gpointer (*try_realloc) (gpointer mem, + gsize n_bytes); +}; +void g_mem_set_vtable (GMemVTable *vtable); +gboolean g_mem_is_system_malloc (void); + +GLIB_VAR gboolean g_mem_gc_friendly; + +/* Memory profiler and checker, has to be enabled via g_mem_set_vtable() + */ +GLIB_VAR GMemVTable *glib_mem_profiler_table; +void g_mem_profile (void); + + +/* deprecated memchunks and allocators */ +#if !defined (G_DISABLE_DEPRECATED) || defined (GTK_COMPILATION) || defined (GDK_COMPILATION) +typedef struct _GAllocator GAllocator; +typedef struct _GMemChunk GMemChunk; +#define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \ + g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \ + sizeof (type), \ + sizeof (type) * (pre_alloc), \ + (alloc_type)) \ +) +#define g_chunk_new(type, chunk) ( \ + (type *) g_mem_chunk_alloc (chunk) \ +) +#define g_chunk_new0(type, chunk) ( \ + (type *) g_mem_chunk_alloc0 (chunk) \ +) +#define g_chunk_free(mem, mem_chunk) G_STMT_START { \ + g_mem_chunk_free ((mem_chunk), (mem)); \ +} G_STMT_END +#define G_ALLOC_ONLY 1 +#define G_ALLOC_AND_FREE 2 +GMemChunk* g_mem_chunk_new (const gchar *name, + gint atom_size, + gsize area_size, + gint type); +void g_mem_chunk_destroy (GMemChunk *mem_chunk); +gpointer g_mem_chunk_alloc (GMemChunk *mem_chunk); +gpointer g_mem_chunk_alloc0 (GMemChunk *mem_chunk); +void g_mem_chunk_free (GMemChunk *mem_chunk, + gpointer mem); +void g_mem_chunk_clean (GMemChunk *mem_chunk); +void g_mem_chunk_reset (GMemChunk *mem_chunk); +void g_mem_chunk_print (GMemChunk *mem_chunk); +void g_mem_chunk_info (void); +void g_blow_chunks (void); +GAllocator*g_allocator_new (const gchar *name, + guint n_preallocs); +void g_allocator_free (GAllocator *allocator); +#define G_ALLOCATOR_LIST (1) +#define G_ALLOCATOR_SLIST (2) +#define G_ALLOCATOR_NODE (3) +#endif /* G_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __G_MEM_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gmessages.h b/protocols/Sametime/src/glib/include/glib/gmessages.h new file mode 100644 index 0000000000..9acaec6375 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gmessages.h @@ -0,0 +1,343 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_MESSAGES_H__ +#define __G_MESSAGES_H__ + +#include <stdarg.h> +#include <glib/gtypes.h> +#include <glib/gmacros.h> + +/* Suppress warnings when GCC is in -pedantic mode and not -std=c99 + */ +#if (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) +#pragma GCC system_header +#endif + +G_BEGIN_DECLS + +/* calculate a string size, guaranteed to fit format + args. + */ +gsize g_printf_string_upper_bound (const gchar* format, + va_list args); + +/* Log level shift offset for user defined + * log levels (0-7 are used by GLib). + */ +#define G_LOG_LEVEL_USER_SHIFT (8) + +/* Glib log levels and flags. + */ +typedef enum +{ + /* log flags */ + G_LOG_FLAG_RECURSION = 1 << 0, + G_LOG_FLAG_FATAL = 1 << 1, + + /* GLib log levels */ + G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */ + G_LOG_LEVEL_CRITICAL = 1 << 3, + G_LOG_LEVEL_WARNING = 1 << 4, + G_LOG_LEVEL_MESSAGE = 1 << 5, + G_LOG_LEVEL_INFO = 1 << 6, + G_LOG_LEVEL_DEBUG = 1 << 7, + + G_LOG_LEVEL_MASK = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL) +} GLogLevelFlags; + +/* GLib log levels that are considered fatal by default */ +#define G_LOG_FATAL_MASK (G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR) + +typedef void (*GLogFunc) (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); + +/* Logging mechanism + */ +guint g_log_set_handler (const gchar *log_domain, + GLogLevelFlags log_levels, + GLogFunc log_func, + gpointer user_data); +void g_log_remove_handler (const gchar *log_domain, + guint handler_id); +void g_log_default_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer unused_data); +GLogFunc g_log_set_default_handler (GLogFunc log_func, + gpointer user_data); +void g_log (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *format, + ...) G_GNUC_PRINTF (3, 4); +void g_logv (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *format, + va_list args); +GLogLevelFlags g_log_set_fatal_mask (const gchar *log_domain, + GLogLevelFlags fatal_mask); +GLogLevelFlags g_log_set_always_fatal (GLogLevelFlags fatal_mask); + +/* internal */ +G_GNUC_INTERNAL void _g_log_fallback_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer unused_data); + +/* Internal functions, used to implement the following macros */ +void g_return_if_fail_warning (const char *log_domain, + const char *pretty_function, + const char *expression); +void g_warn_message (const char *domain, + const char *file, + int line, + const char *func, + const char *warnexpr); +#ifndef G_DISABLE_DEPRECATED +void g_assert_warning (const char *log_domain, + const char *file, + const int line, + const char *pretty_function, + const char *expression) G_GNUC_NORETURN; +#endif /* !G_DISABLE_DEPRECATED */ + + +#ifndef G_LOG_DOMAIN +#define G_LOG_DOMAIN ((gchar*) 0) +#endif /* G_LOG_DOMAIN */ +#ifdef G_HAVE_ISO_VARARGS +/* for(;;) ; so that GCC knows that control doesn't go past g_error(). + * Put space before ending semicolon to avoid C++ build warnings. + */ +#define g_error(...) G_STMT_START { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_ERROR, \ + __VA_ARGS__); \ + for (;;) ; \ + } G_STMT_END + +#define g_message(...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_MESSAGE, \ + __VA_ARGS__) +#define g_critical(...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + __VA_ARGS__) +#define g_warning(...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_WARNING, \ + __VA_ARGS__) +#define g_debug(...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_DEBUG, \ + __VA_ARGS__) +#elif defined(G_HAVE_GNUC_VARARGS) +#define g_error(format...) G_STMT_START { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_ERROR, \ + format); \ + for (;;) ; \ + } G_STMT_END + +#define g_message(format...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_MESSAGE, \ + format) +#define g_critical(format...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + format) +#define g_warning(format...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_WARNING, \ + format) +#define g_debug(format...) g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_DEBUG, \ + format) +#else /* no varargs macros */ +static void +g_error (const gchar *format, + ...) +{ + va_list args; + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args); + va_end (args); + + for(;;) ; +} +static void +g_message (const gchar *format, + ...) +{ + va_list args; + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, args); + va_end (args); +} +static void +g_critical (const gchar *format, + ...) +{ + va_list args; + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, format, args); + va_end (args); +} +static void +g_warning (const gchar *format, + ...) +{ + va_list args; + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, args); + va_end (args); +} +static void +g_debug (const gchar *format, + ...) +{ + va_list args; + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); + va_end (args); +} +#endif /* !__GNUC__ */ + +typedef void (*GPrintFunc) (const gchar *string); +void g_print (const gchar *format, + ...) G_GNUC_PRINTF (1, 2); +GPrintFunc g_set_print_handler (GPrintFunc func); +void g_printerr (const gchar *format, + ...) G_GNUC_PRINTF (1, 2); +GPrintFunc g_set_printerr_handler (GPrintFunc func); + + +/* Provide macros for graceful error handling. + * The "return" macros will return from the current function. + * Two different definitions are given for the macros in + * order to support gcc's __PRETTY_FUNCTION__ capability. + */ + +#define g_warn_if_reached() do { g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, NULL); } while (0) +#define g_warn_if_fail(expr) do { if G_LIKELY (expr) ; else \ + g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #expr); } while (0) + +#ifdef G_DISABLE_CHECKS + +#define g_return_if_fail(expr) G_STMT_START{ (void)0; }G_STMT_END +#define g_return_val_if_fail(expr,val) G_STMT_START{ (void)0; }G_STMT_END +#define g_return_if_reached() G_STMT_START{ return; }G_STMT_END +#define g_return_val_if_reached(val) G_STMT_START{ return (val); }G_STMT_END + +#else /* !G_DISABLE_CHECKS */ + +#ifdef __GNUC__ + +#define g_return_if_fail(expr) G_STMT_START{ \ + if G_LIKELY(expr) { } else \ + { \ + g_return_if_fail_warning (G_LOG_DOMAIN, \ + __PRETTY_FUNCTION__, \ + #expr); \ + return; \ + }; }G_STMT_END + +#define g_return_val_if_fail(expr,val) G_STMT_START{ \ + if G_LIKELY(expr) { } else \ + { \ + g_return_if_fail_warning (G_LOG_DOMAIN, \ + __PRETTY_FUNCTION__, \ + #expr); \ + return (val); \ + }; }G_STMT_END + +#define g_return_if_reached() G_STMT_START{ \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__); \ + return; }G_STMT_END + +#define g_return_val_if_reached(val) G_STMT_START{ \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__); \ + return (val); }G_STMT_END + +#else /* !__GNUC__ */ + +#define g_return_if_fail(expr) G_STMT_START{ \ + if (expr) { } else \ + { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d: assertion `%s' failed", \ + __FILE__, \ + __LINE__, \ + #expr); \ + return; \ + }; }G_STMT_END + +#define g_return_val_if_fail(expr, val) G_STMT_START{ \ + if (expr) { } else \ + { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d: assertion `%s' failed", \ + __FILE__, \ + __LINE__, \ + #expr); \ + return (val); \ + }; }G_STMT_END + +#define g_return_if_reached() G_STMT_START{ \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d: should not be reached", \ + __FILE__, \ + __LINE__); \ + return; }G_STMT_END + +#define g_return_val_if_reached(val) G_STMT_START{ \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d: should not be reached", \ + __FILE__, \ + __LINE__); \ + return (val); }G_STMT_END + +#endif /* !__GNUC__ */ + +#endif /* !G_DISABLE_CHECKS */ + +G_END_DECLS + +#endif /* __G_MESSAGES_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gnode.h b/protocols/Sametime/src/glib/include/glib/gnode.h new file mode 100644 index 0000000000..205d47c763 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gnode.h @@ -0,0 +1,290 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_NODE_H__ +#define __G_NODE_H__ + +#include <glib/gmem.h> + +G_BEGIN_DECLS + +typedef struct _GNode GNode; + +/* Tree traverse flags */ +typedef enum +{ + G_TRAVERSE_LEAVES = 1 << 0, + G_TRAVERSE_NON_LEAVES = 1 << 1, + G_TRAVERSE_ALL = G_TRAVERSE_LEAVES | G_TRAVERSE_NON_LEAVES, + G_TRAVERSE_MASK = 0x03, + G_TRAVERSE_LEAFS = G_TRAVERSE_LEAVES, + G_TRAVERSE_NON_LEAFS = G_TRAVERSE_NON_LEAVES +} GTraverseFlags; + +/* Tree traverse orders */ +typedef enum +{ + G_IN_ORDER, + G_PRE_ORDER, + G_POST_ORDER, + G_LEVEL_ORDER +} GTraverseType; + +typedef gboolean (*GNodeTraverseFunc) (GNode *node, + gpointer data); +typedef void (*GNodeForeachFunc) (GNode *node, + gpointer data); + +/** + * GCopyFunc: + * @src: A pointer to the data which should be copied + * @data: Additional data + * + * A function of this signature is used to copy the node data + * when doing a deep-copy of a tree. + * + * Returns: A pointer to the copy + * + * Since: 2.4 + */ +typedef gpointer (*GCopyFunc) (gconstpointer src, + gpointer data); + +/* N-way tree implementation + */ +struct _GNode +{ + gpointer data; + GNode *next; + GNode *prev; + GNode *parent; + GNode *children; +}; + +/** + * G_NODE_IS_ROOT: + * @node: a #GNode + * + * Returns %TRUE if a #GNode is the root of a tree. + * + * Returns: %TRUE if the #GNode is the root of a tree + * (i.e. it has no parent or siblings) + */ +#define G_NODE_IS_ROOT(node) (((GNode*) (node))->parent == NULL && \ + ((GNode*) (node))->prev == NULL && \ + ((GNode*) (node))->next == NULL) + +/** + * G_NODE_IS_LEAF: + * @node: a #GNode + * + * Returns %TRUE if a #GNode is a leaf node. + * + * Returns: %TRUE if the #GNode is a leaf node + * (i.e. it has no children) + */ +#define G_NODE_IS_LEAF(node) (((GNode*) (node))->children == NULL) + +GNode* g_node_new (gpointer data); +void g_node_destroy (GNode *root); +void g_node_unlink (GNode *node); +GNode* g_node_copy_deep (GNode *node, + GCopyFunc copy_func, + gpointer data); +GNode* g_node_copy (GNode *node); +GNode* g_node_insert (GNode *parent, + gint position, + GNode *node); +GNode* g_node_insert_before (GNode *parent, + GNode *sibling, + GNode *node); +GNode* g_node_insert_after (GNode *parent, + GNode *sibling, + GNode *node); +GNode* g_node_prepend (GNode *parent, + GNode *node); +guint g_node_n_nodes (GNode *root, + GTraverseFlags flags); +GNode* g_node_get_root (GNode *node); +gboolean g_node_is_ancestor (GNode *node, + GNode *descendant); +guint g_node_depth (GNode *node); +GNode* g_node_find (GNode *root, + GTraverseType order, + GTraverseFlags flags, + gpointer data); + +/* convenience macros */ +/** + * g_node_append: + * @parent: the #GNode to place the new #GNode under + * @node: the #GNode to insert + * + * Inserts a #GNode as the last child of the given parent. + * + * Returns: the inserted #GNode + */ +#define g_node_append(parent, node) \ + g_node_insert_before ((parent), NULL, (node)) + +/** + * g_node_insert_data: + * @parent: the #GNode to place the new #GNode under + * @position: the position to place the new #GNode at. If position is -1, + * the new #GNode is inserted as the last child of @parent + * @data: the data for the new #GNode + * + * Inserts a new #GNode at the given position. + * + * Returns: the new #GNode + */ +#define g_node_insert_data(parent, position, data) \ + g_node_insert ((parent), (position), g_node_new (data)) + +/** + * g_node_insert_data_before: + * @parent: the #GNode to place the new #GNode under + * @sibling: the sibling #GNode to place the new #GNode before + * @data: the data for the new #GNode + * + * Inserts a new #GNode before the given sibling. + * + * Returns: the new #GNode + */ +#define g_node_insert_data_before(parent, sibling, data) \ + g_node_insert_before ((parent), (sibling), g_node_new (data)) + +/** + * g_node_prepend_data: + * @parent: the #GNode to place the new #GNode under + * @data: the data for the new #GNode + * + * Inserts a new #GNode as the first child of the given parent. + * + * Returns: the new #GNode + */ +#define g_node_prepend_data(parent, data) \ + g_node_prepend ((parent), g_node_new (data)) + +/** + * g_node_append_data: + * @parent: the #GNode to place the new #GNode under + * @data: the data for the new #GNode + * + * Inserts a new #GNode as the last child of the given parent. + * + * Returns: the new #GNode + */ +#define g_node_append_data(parent, data) \ + g_node_insert_before ((parent), NULL, g_node_new (data)) + +/* traversal function, assumes that `node' is root + * (only traverses `node' and its subtree). + * this function is just a high level interface to + * low level traversal functions, optimized for speed. + */ +void g_node_traverse (GNode *root, + GTraverseType order, + GTraverseFlags flags, + gint max_depth, + GNodeTraverseFunc func, + gpointer data); + +/* return the maximum tree height starting with `node', this is an expensive + * operation, since we need to visit all nodes. this could be shortened by + * adding `guint height' to struct _GNode, but then again, this is not very + * often needed, and would make g_node_insert() more time consuming. + */ +guint g_node_max_height (GNode *root); + +void g_node_children_foreach (GNode *node, + GTraverseFlags flags, + GNodeForeachFunc func, + gpointer data); +void g_node_reverse_children (GNode *node); +guint g_node_n_children (GNode *node); +GNode* g_node_nth_child (GNode *node, + guint n); +GNode* g_node_last_child (GNode *node); +GNode* g_node_find_child (GNode *node, + GTraverseFlags flags, + gpointer data); +gint g_node_child_position (GNode *node, + GNode *child); +gint g_node_child_index (GNode *node, + gpointer data); + +GNode* g_node_first_sibling (GNode *node); +GNode* g_node_last_sibling (GNode *node); + +/** + * g_node_prev_sibling: + * @node: a #GNode + * + * Gets the previous sibling of a #GNode. + * + * Returns: the previous sibling of @node, or %NULL if @node is the first + * node or %NULL + */ +#define g_node_prev_sibling(node) ((node) ? \ + ((GNode*) (node))->prev : NULL) + +/** + * g_node_next_sibling: + * @node: a #GNode + * + * Gets the next sibling of a #GNode. + * + * Returns: the next sibling of @node, or %NULL if @node is the last node + * or %NULL + */ +#define g_node_next_sibling(node) ((node) ? \ + ((GNode*) (node))->next : NULL) + +/** + * g_node_first_child: + * @node: a #GNode + * + * Gets the first child of a #GNode. + * + * Returns: the first child of @node, or %NULL if @node is %NULL + * or has no children + */ +#define g_node_first_child(node) ((node) ? \ + ((GNode*) (node))->children : NULL) + +#ifndef G_DISABLE_DEPRECATED +void g_node_push_allocator (gpointer dummy); +void g_node_pop_allocator (void); +#endif + +G_END_DECLS + +#endif /* __G_NODE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/goption.h b/protocols/Sametime/src/glib/include/glib/goption.h new file mode 100644 index 0000000000..557d8f7130 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/goption.h @@ -0,0 +1,370 @@ +/* goption.h - Option parser + * + * Copyright (C) 2004 Anders Carlsson <andersca@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_OPTION_H__ +#define __G_OPTION_H__ + +#include <glib/gerror.h> +#include <glib/gquark.h> + +G_BEGIN_DECLS + +/** + * GOptionContext: + * + * A <structname>GOptionContext</structname> struct defines which options + * are accepted by the commandline option parser. The struct has only private + * fields and should not be directly accessed. + */ +typedef struct _GOptionContext GOptionContext; + +/** + * GOptionGroup: + * + * A <structname>GOptionGroup</structname> struct defines the options in a single + * group. The struct has only private fields and should not be directly accessed. + * + * All options in a group share the same translation function. Libraries which + * need to parse commandline options are expected to provide a function for + * getting a <structname>GOptionGroup</structname> holding their options, which + * the application can then add to its #GOptionContext. + */ +typedef struct _GOptionGroup GOptionGroup; +typedef struct _GOptionEntry GOptionEntry; + +/** + * GOptionFlags: + * @G_OPTION_FLAG_HIDDEN: The option doesn't appear in <option>--help</option> + * output. + * @G_OPTION_FLAG_IN_MAIN: The option appears in the main section of the + * <option>--help</option> output, even if it is defined in a group. + * @G_OPTION_FLAG_REVERSE: For options of the %G_OPTION_ARG_NONE kind, this flag + * indicates that the sense of the option is reversed. + * @G_OPTION_FLAG_NO_ARG: For options of the %G_OPTION_ARG_CALLBACK kind, + * this flag indicates that the callback does not take any argument + * (like a %G_OPTION_ARG_NONE option). Since 2.8 + * @G_OPTION_FLAG_FILENAME: For options of the %G_OPTION_ARG_CALLBACK + * kind, this flag indicates that the argument should be passed to the + * callback in the GLib filename encoding rather than UTF-8. Since 2.8 + * @G_OPTION_FLAG_OPTIONAL_ARG: For options of the %G_OPTION_ARG_CALLBACK + * kind, this flag indicates that the argument supply is optional. If no argument + * is given then data of %GOptionParseFunc will be set to NULL. Since 2.8 + * @G_OPTION_FLAG_NOALIAS: This flag turns off the automatic conflict resolution + * which prefixes long option names with <literal>groupname-</literal> if + * there is a conflict. This option should only be used in situations where + * aliasing is necessary to model some legacy commandline interface. It is + * not safe to use this option, unless all option groups are under your + * direct control. Since 2.8. + * + * Flags which modify individual options. + */ +typedef enum +{ + G_OPTION_FLAG_HIDDEN = 1 << 0, + G_OPTION_FLAG_IN_MAIN = 1 << 1, + G_OPTION_FLAG_REVERSE = 1 << 2, + G_OPTION_FLAG_NO_ARG = 1 << 3, + G_OPTION_FLAG_FILENAME = 1 << 4, + G_OPTION_FLAG_OPTIONAL_ARG = 1 << 5, + G_OPTION_FLAG_NOALIAS = 1 << 6 +} GOptionFlags; + +/** + * GOptionArg: + * @G_OPTION_ARG_NONE: No extra argument. This is useful for simple flags. + * @G_OPTION_ARG_STRING: The option takes a string argument. + * @G_OPTION_ARG_INT: The option takes an integer argument. + * @G_OPTION_ARG_CALLBACK: The option provides a callback to parse the + * extra argument. + * @G_OPTION_ARG_FILENAME: The option takes a filename as argument. + * @G_OPTION_ARG_STRING_ARRAY: The option takes a string argument, multiple + * uses of the option are collected into an array of strings. + * @G_OPTION_ARG_FILENAME_ARRAY: The option takes a filename as argument, + * multiple uses of the option are collected into an array of strings. + * @G_OPTION_ARG_DOUBLE: The option takes a double argument. The argument + * can be formatted either for the user's locale or for the "C" locale. Since 2.12 + * @G_OPTION_ARG_INT64: The option takes a 64-bit integer. Like %G_OPTION_ARG_INT + * but for larger numbers. The number can be in decimal base, or in hexadecimal + * (when prefixed with <literal>0x</literal>, for example, <literal>0xffffffff</literal>). + * Since 2.12 + * + * The #GOptionArg enum values determine which type of extra argument the + * options expect to find. If an option expects an extra argument, it + * can be specified in several ways; with a short option: + * <option>-x arg</option>, with a long option: <option>--name arg</option> + * or combined in a single argument: <option>--name=arg</option>. + */ +typedef enum +{ + G_OPTION_ARG_NONE, + G_OPTION_ARG_STRING, + G_OPTION_ARG_INT, + G_OPTION_ARG_CALLBACK, + G_OPTION_ARG_FILENAME, + G_OPTION_ARG_STRING_ARRAY, + G_OPTION_ARG_FILENAME_ARRAY, + G_OPTION_ARG_DOUBLE, + G_OPTION_ARG_INT64 +} GOptionArg; + +/** + * GOptionArgFunc: + * @option_name: The name of the option being parsed. This will be either a + * single dash followed by a single letter (for a short name) or two dashes + * followed by a long option name. + * @value: The value to be parsed. + * @data: User data added to the #GOptionGroup containing the option when it + * was created with g_option_group_new() + * @error: A return location for errors. The error code %G_OPTION_ERROR_FAILED + * is intended to be used for errors in #GOptionArgFunc callbacks. + * + * The type of function to be passed as callback for %G_OPTION_ARG_CALLBACK + * options. + * + * Returns: %TRUE if the option was successfully parsed, %FALSE if an error + * occurred, in which case @error should be set with g_set_error() + */ +typedef gboolean (*GOptionArgFunc) (const gchar *option_name, + const gchar *value, + gpointer data, + GError **error); + +/** + * GOptionParseFunc: + * @context: The active #GOptionContext + * @group: The group to which the function belongs + * @data: User data added to the #GOptionGroup containing the option when it + * was created with g_option_group_new() + * @error: A return location for error details + * + * The type of function that can be called before and after parsing. + * + * Returns: %TRUE if the function completed successfully, %FALSE if an error + * occurred, in which case @error should be set with g_set_error() + */ +typedef gboolean (*GOptionParseFunc) (GOptionContext *context, + GOptionGroup *group, + gpointer data, + GError **error); + +/** + * GOptionErrorFunc: + * @context: The active #GOptionContext + * @group: The group to which the function belongs + * @data: User data added to the #GOptionGroup containing the option when it + * was created with g_option_group_new() + * @error: The #GError containing details about the parse error + * + * The type of function to be used as callback when a parse error occurs. + */ +typedef void (*GOptionErrorFunc) (GOptionContext *context, + GOptionGroup *group, + gpointer data, + GError **error); + +/** + * G_OPTION_ERROR: + * + * Error domain for option parsing. Errors in this domain will + * be from the #GOptionError enumeration. See #GError for information on + * error domains. + */ +#define G_OPTION_ERROR (g_option_error_quark ()) + +/** + * GOptionError: + * @G_OPTION_ERROR_UNKNOWN_OPTION: An option was not known to the parser. + * This error will only be reported, if the parser hasn't been instructed + * to ignore unknown options, see g_option_context_set_ignore_unknown_options(). + * @G_OPTION_ERROR_BAD_VALUE: A value couldn't be parsed. + * @G_OPTION_ERROR_FAILED: A #GOptionArgFunc callback failed. + * + * Error codes returned by option parsing. + */ +typedef enum +{ + G_OPTION_ERROR_UNKNOWN_OPTION, + G_OPTION_ERROR_BAD_VALUE, + G_OPTION_ERROR_FAILED +} GOptionError; + +GQuark g_option_error_quark (void); + +/** + * GOptionEntry: + * @long_name: The long name of an option can be used to specify it + * in a commandline as --<replaceable>long_name</replaceable>. Every + * option must have a long name. To resolve conflicts if multiple + * option groups contain the same long name, it is also possible to + * specify the option as + * --<replaceable>groupname</replaceable>-<replaceable>long_name</replaceable>. + * @short_name: If an option has a short name, it can be specified + * -<replaceable>short_name</replaceable> in a commandline. @short_name must be + * a printable ASCII character different from '-', or zero if the option has no + * short name. + * @flags: Flags from #GOptionFlags. + * @arg: The type of the option, as a #GOptionArg. + * @arg_data: If the @arg type is %G_OPTION_ARG_CALLBACK, then @arg_data must + * point to a #GOptionArgFunc callback function, which will be called to handle + * the extra argument. Otherwise, @arg_data is a pointer to a location to store + * the value, the required type of the location depends on the @arg type: + * <variablelist> + * <varlistentry> + * <term>%G_OPTION_ARG_NONE</term> + * <listitem><para>%gboolean</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_STRING</term> + * <listitem><para>%gchar*</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_INT</term> + * <listitem><para>%gint</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_FILENAME</term> + * <listitem><para>%gchar*</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_STRING_ARRAY</term> + * <listitem><para>%gchar**</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_FILENAME_ARRAY</term> + * <listitem><para>%gchar**</para></listitem> + * </varlistentry> + * <varlistentry> + * <term>%G_OPTION_ARG_DOUBLE</term> + * <listitem><para>%gdouble</para></listitem> + * </varlistentry> + * </variablelist> + * If @arg type is %G_OPTION_ARG_STRING or %G_OPTION_ARG_FILENAME the location + * will contain a newly allocated string if the option was given. That string + * needs to be freed by the callee using g_free(). Likewise if @arg type is + * %G_OPTION_ARG_STRING_ARRAY or %G_OPTION_ARG_FILENAME_ARRAY, the data should + * be freed using g_strfreev(). + * @description: the description for the option in <option>--help</option> + * output. The @description is translated using the @translate_func of the + * group, see g_option_group_set_translation_domain(). + * @arg_description: The placeholder to use for the extra argument parsed + * by the option in <option>--help</option> + * output. The @arg_description is translated using the @translate_func of the + * group, see g_option_group_set_translation_domain(). + * + * A <structname>GOptionEntry</structname> defines a single option. + * To have an effect, they must be added to a #GOptionGroup with + * g_option_context_add_main_entries() or g_option_group_add_entries(). + */ +struct _GOptionEntry +{ + const gchar *long_name; + gchar short_name; + gint flags; + + GOptionArg arg; + gpointer arg_data; + + const gchar *description; + const gchar *arg_description; +}; + +/** + * G_OPTION_REMAINING: + * + * If a long option in the main group has this name, it is not treated as a + * regular option. Instead it collects all non-option arguments which would + * otherwise be left in <literal>argv</literal>. The option must be of type + * %G_OPTION_ARG_CALLBACK, %G_OPTION_ARG_STRING_ARRAY + * or %G_OPTION_ARG_FILENAME_ARRAY. + * + * + * Using #G_OPTION_REMAINING instead of simply scanning <literal>argv</literal> + * for leftover arguments has the advantage that GOption takes care of + * necessary encoding conversions for strings or filenames. + * + * Since: 2.6 + */ +#define G_OPTION_REMAINING "" + +GOptionContext *g_option_context_new (const gchar *parameter_string); +void g_option_context_set_summary (GOptionContext *context, + const gchar *summary); +G_CONST_RETURN gchar *g_option_context_get_summary (GOptionContext *context); +void g_option_context_set_description (GOptionContext *context, + const gchar *description); +G_CONST_RETURN gchar *g_option_context_get_description (GOptionContext *context); +void g_option_context_free (GOptionContext *context); +void g_option_context_set_help_enabled (GOptionContext *context, + gboolean help_enabled); +gboolean g_option_context_get_help_enabled (GOptionContext *context); +void g_option_context_set_ignore_unknown_options (GOptionContext *context, + gboolean ignore_unknown); +gboolean g_option_context_get_ignore_unknown_options (GOptionContext *context); + +void g_option_context_add_main_entries (GOptionContext *context, + const GOptionEntry *entries, + const gchar *translation_domain); +gboolean g_option_context_parse (GOptionContext *context, + gint *argc, + gchar ***argv, + GError **error); +void g_option_context_set_translate_func (GOptionContext *context, + GTranslateFunc func, + gpointer data, + GDestroyNotify destroy_notify); +void g_option_context_set_translation_domain (GOptionContext *context, + const gchar *domain); + +void g_option_context_add_group (GOptionContext *context, + GOptionGroup *group); +void g_option_context_set_main_group (GOptionContext *context, + GOptionGroup *group); +GOptionGroup *g_option_context_get_main_group (GOptionContext *context); +gchar *g_option_context_get_help (GOptionContext *context, + gboolean main_help, + GOptionGroup *group); + +GOptionGroup *g_option_group_new (const gchar *name, + const gchar *description, + const gchar *help_description, + gpointer user_data, + GDestroyNotify destroy); +void g_option_group_set_parse_hooks (GOptionGroup *group, + GOptionParseFunc pre_parse_func, + GOptionParseFunc post_parse_func); +void g_option_group_set_error_hook (GOptionGroup *group, + GOptionErrorFunc error_func); +void g_option_group_free (GOptionGroup *group); +void g_option_group_add_entries (GOptionGroup *group, + const GOptionEntry *entries); +void g_option_group_set_translate_func (GOptionGroup *group, + GTranslateFunc func, + gpointer data, + GDestroyNotify destroy_notify); +void g_option_group_set_translation_domain (GOptionGroup *group, + const gchar *domain); + +G_END_DECLS + +#endif /* __G_OPTION_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gpattern.h b/protocols/Sametime/src/glib/include/glib/gpattern.h new file mode 100644 index 0000000000..b653d713f0 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gpattern.h @@ -0,0 +1,49 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997, 1999 Peter Mattis, Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_PATTERN_H__ +#define __G_PATTERN_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + + +typedef struct _GPatternSpec GPatternSpec; + +GPatternSpec* g_pattern_spec_new (const gchar *pattern); +void g_pattern_spec_free (GPatternSpec *pspec); +gboolean g_pattern_spec_equal (GPatternSpec *pspec1, + GPatternSpec *pspec2); +gboolean g_pattern_match (GPatternSpec *pspec, + guint string_length, + const gchar *string, + const gchar *string_reversed); +gboolean g_pattern_match_string (GPatternSpec *pspec, + const gchar *string); +gboolean g_pattern_match_simple (const gchar *pattern, + const gchar *string); + +G_END_DECLS + +#endif /* __G_PATTERN_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gpoll.h b/protocols/Sametime/src/glib/include/glib/gpoll.h new file mode 100644 index 0000000000..cc79381a69 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gpoll.h @@ -0,0 +1,117 @@ +/* gpoll.h - poll(2) support + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GLIB_H_INSIDE__) && !defined (__G_MAIN_H__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_POLL_H__ +#define __G_POLL_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/* Any definitions using GPollFD or GPollFunc are primarily + * for Unix and not guaranteed to be the compatible on all + * operating systems on which GLib runs. Right now, the + * GLib does use these functions on Win32 as well, but interprets + * them in a fairly different way than on Unix. If you use + * these definitions, you are should be prepared to recode + * for different operating systems. + * + * Note that on systems with a working poll(2), that function is used + * in place of g_poll(). Thus g_poll() must have the same signature as + * poll(), meaning GPollFD must have the same layout as struct pollfd. + * + * + * On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file + * descriptor as provided by the C runtime) that can be used by + * MsgWaitForMultipleObjects. This does *not* include file handles + * from CreateFile, SOCKETs, nor pipe handles. (But you can use + * WSAEventSelect to signal events when a SOCKET is readable). + * + * On Win32, fd can also be the special value G_WIN32_MSG_HANDLE to + * indicate polling for messages. + * + * But note that G_WIN32_MSG_HANDLE GPollFDs should not be used by GDK + * (GTK) programs, as GDK itself wants to read messages and convert them + * to GDK events. + * + * So, unless you really know what you are doing, it's best not to try + * to use the main loop polling stuff for your own needs on + * Windows. + */ +typedef struct _GPollFD GPollFD; + +/** + * GPollFunc: + * @ufds: an array of #GPollFD elements + * @nfsd: the number of elements in @ufds + * @timeout_: the maximum time to wait for an event of the file descriptors. + * A negative value indicates an infinite timeout. + * + * Specifies the type of function passed to g_main_context_set_poll_func(). + * The semantics of the function should match those of the poll() system call. + * + * Returns: the number of #GPollFD elements which have events or errors + * reported, or -1 if an error occurred. + */ +typedef gint (*GPollFunc) (GPollFD *ufds, + guint nfsd, + gint timeout_); + +/** + * GPollFD: + * @fd: the file descriptor to poll (or a <type>HANDLE</type> on Win32) + * @events: a bitwise combination from #GIOCondition, specifying which + * events should be polled for. Typically for reading from a file + * descriptor you would use %G_IO_IN | %G_IO_HUP | %G_IO_ERR, and + * for writing you would use %G_IO_OUT | %G_IO_ERR. + * @revents: a bitwise combination of flags from #GIOCondition, returned + * from the poll() function to indicate which events occurred. + */ +struct _GPollFD +{ +#if defined (G_OS_WIN32) && GLIB_SIZEOF_VOID_P == 8 + gint64 fd; +#else + gint fd; +#endif + gushort events; + gushort revents; +}; + +#ifdef G_OS_WIN32 +#if GLIB_SIZEOF_VOID_P == 8 +#define G_POLLFD_FORMAT "%#I64x" +#else +#define G_POLLFD_FORMAT "%#x" +#endif +#else +#define G_POLLFD_FORMAT "%d" +#endif + +gint g_poll (GPollFD *fds, + guint nfds, + gint timeout); + +G_END_DECLS + +#endif /* __G_POLL_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gprimes.h b/protocols/Sametime/src/glib/include/glib/gprimes.h new file mode 100644 index 0000000000..af5728602b --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gprimes.h @@ -0,0 +1,51 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_PRIMES_H__ +#define __G_PRIMES_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/* Prime numbers. + */ + +/* This function returns prime numbers spaced by approximately 1.5-2.0 + * and is for use in resizing data structures which prefer + * prime-valued sizes. The closest spaced prime function returns the + * next largest prime, or the highest it knows about which is about + * MAXINT/4. + */ +guint g_spaced_primes_closest (guint num) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __G_PRIMES_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gqsort.h b/protocols/Sametime/src/glib/include/glib/gqsort.h new file mode 100644 index 0000000000..3a47a584ee --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gqsort.h @@ -0,0 +1,46 @@ + /* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_QSORT_H__ +#define __G_QSORT_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +void g_qsort_with_data (gconstpointer pbase, + gint total_elems, + gsize size, + GCompareDataFunc compare_func, + gpointer user_data); + +G_END_DECLS + +#endif /* __G_QSORT_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gquark.h b/protocols/Sametime/src/glib/include/glib/gquark.h new file mode 100644 index 0000000000..a0cbe2fd72 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gquark.h @@ -0,0 +1,52 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_QUARK_H__ +#define __G_QUARK_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef guint32 GQuark; + +/* Quarks (string<->id association) + */ +GQuark g_quark_try_string (const gchar *string); +GQuark g_quark_from_static_string (const gchar *string); +GQuark g_quark_from_string (const gchar *string); +G_CONST_RETURN gchar* g_quark_to_string (GQuark quark) G_GNUC_CONST; + +G_CONST_RETURN gchar* g_intern_string (const gchar *string); +G_CONST_RETURN gchar* g_intern_static_string (const gchar *string); + +G_END_DECLS + +#endif /* __G_QUARK_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gqueue.h b/protocols/Sametime/src/glib/include/glib/gqueue.h new file mode 100644 index 0000000000..e78488fb65 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gqueue.h @@ -0,0 +1,127 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_QUEUE_H__ +#define __G_QUEUE_H__ + +#include <glib/glist.h> + +G_BEGIN_DECLS + +typedef struct _GQueue GQueue; + +struct _GQueue +{ + GList *head; + GList *tail; + guint length; +}; + +#define G_QUEUE_INIT { NULL, NULL, 0 } + +/* Queues + */ +GQueue* g_queue_new (void); +void g_queue_free (GQueue *queue); +void g_queue_init (GQueue *queue); +void g_queue_clear (GQueue *queue); +gboolean g_queue_is_empty (GQueue *queue); +guint g_queue_get_length (GQueue *queue); +void g_queue_reverse (GQueue *queue); +GQueue * g_queue_copy (GQueue *queue); +void g_queue_foreach (GQueue *queue, + GFunc func, + gpointer user_data); +GList * g_queue_find (GQueue *queue, + gconstpointer data); +GList * g_queue_find_custom (GQueue *queue, + gconstpointer data, + GCompareFunc func); +void g_queue_sort (GQueue *queue, + GCompareDataFunc compare_func, + gpointer user_data); + +void g_queue_push_head (GQueue *queue, + gpointer data); +void g_queue_push_tail (GQueue *queue, + gpointer data); +void g_queue_push_nth (GQueue *queue, + gpointer data, + gint n); +gpointer g_queue_pop_head (GQueue *queue); +gpointer g_queue_pop_tail (GQueue *queue); +gpointer g_queue_pop_nth (GQueue *queue, + guint n); +gpointer g_queue_peek_head (GQueue *queue); +gpointer g_queue_peek_tail (GQueue *queue); +gpointer g_queue_peek_nth (GQueue *queue, + guint n); +gint g_queue_index (GQueue *queue, + gconstpointer data); +void g_queue_remove (GQueue *queue, + gconstpointer data); +void g_queue_remove_all (GQueue *queue, + gconstpointer data); +void g_queue_insert_before (GQueue *queue, + GList *sibling, + gpointer data); +void g_queue_insert_after (GQueue *queue, + GList *sibling, + gpointer data); +void g_queue_insert_sorted (GQueue *queue, + gpointer data, + GCompareDataFunc func, + gpointer user_data); + +void g_queue_push_head_link (GQueue *queue, + GList *link_); +void g_queue_push_tail_link (GQueue *queue, + GList *link_); +void g_queue_push_nth_link (GQueue *queue, + gint n, + GList *link_); +GList* g_queue_pop_head_link (GQueue *queue); +GList* g_queue_pop_tail_link (GQueue *queue); +GList* g_queue_pop_nth_link (GQueue *queue, + guint n); +GList* g_queue_peek_head_link (GQueue *queue); +GList* g_queue_peek_tail_link (GQueue *queue); +GList* g_queue_peek_nth_link (GQueue *queue, + guint n); +gint g_queue_link_index (GQueue *queue, + GList *link_); +void g_queue_unlink (GQueue *queue, + GList *link_); +void g_queue_delete_link (GQueue *queue, + GList *link_); + +G_END_DECLS + +#endif /* __G_QUEUE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/grand.h b/protocols/Sametime/src/glib/include/glib/grand.h new file mode 100644 index 0000000000..07907dfc17 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/grand.h @@ -0,0 +1,85 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_RAND_H__ +#define __G_RAND_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef struct _GRand GRand; + +/* GRand - a good and fast random number generator: Mersenne Twister + * see http://www.math.keio.ac.jp/~matumoto/emt.html for more info. + * The range functions return a value in the intervall [begin, end). + * int -> [0..2^32-1] + * int_range -> [begin..end-1] + * double -> [0..1) + * double_range -> [begin..end) + */ + +GRand* g_rand_new_with_seed (guint32 seed); +GRand* g_rand_new_with_seed_array (const guint32 *seed, + guint seed_length); +GRand* g_rand_new (void); +void g_rand_free (GRand *rand_); +GRand* g_rand_copy (GRand *rand_); +void g_rand_set_seed (GRand *rand_, + guint32 seed); +void g_rand_set_seed_array (GRand *rand_, + const guint32 *seed, + guint seed_length); + +#define g_rand_boolean(rand_) ((g_rand_int (rand_) & (1 << 15)) != 0) + +guint32 g_rand_int (GRand *rand_); +gint32 g_rand_int_range (GRand *rand_, + gint32 begin, + gint32 end); +gdouble g_rand_double (GRand *rand_); +gdouble g_rand_double_range (GRand *rand_, + gdouble begin, + gdouble end); +void g_random_set_seed (guint32 seed); + +#define g_random_boolean() ((g_random_int () & (1 << 15)) != 0) + +guint32 g_random_int (void); +gint32 g_random_int_range (gint32 begin, + gint32 end); +gdouble g_random_double (void); +gdouble g_random_double_range (gdouble begin, + gdouble end); + + +G_END_DECLS + +#endif /* __G_RAND_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gregex.h b/protocols/Sametime/src/glib/include/glib/gregex.h new file mode 100644 index 0000000000..ce1b44a972 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gregex.h @@ -0,0 +1,471 @@ +/* GRegex -- regular expression API wrapper around PCRE. + * + * Copyright (C) 1999, 2000 Scott Wimer + * Copyright (C) 2004, Matthias Clasen <mclasen@redhat.com> + * Copyright (C) 2005 - 2007, Marco Barisione <marco@barisione.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_REGEX_H__ +#define __G_REGEX_H__ + +#include <glib/gerror.h> +#include <glib/gstring.h> + +G_BEGIN_DECLS + +/** + * GRegexError: + * @G_REGEX_ERROR_COMPILE: Compilation of the regular expression failed. + * @G_REGEX_ERROR_OPTIMIZE: Optimization of the regular expression failed. + * @G_REGEX_ERROR_REPLACE: Replacement failed due to an ill-formed replacement + * string. + * @G_REGEX_ERROR_MATCH: The match process failed. + * @G_REGEX_ERROR_INTERNAL: Internal error of the regular expression engine. + * Since 2.16 + * @G_REGEX_ERROR_STRAY_BACKSLASH: "\\" at end of pattern. Since 2.16 + * @G_REGEX_ERROR_MISSING_CONTROL_CHAR: "\\c" at end of pattern. Since 2.16 + * @G_REGEX_ERROR_UNRECOGNIZED_ESCAPE: Unrecognized character follows "\\". + * Since 2.16 + * @G_REGEX_ERROR_QUANTIFIERS_OUT_OF_ORDER: Numbers out of order in "{}" + * quantifier. Since 2.16 + * @G_REGEX_ERROR_QUANTIFIER_TOO_BIG: Number too big in "{}" quantifier. + * Since 2.16 + * @G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS: Missing terminating "]" for + * character class. Since 2.16 + * @G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS: Invalid escape sequence + * in character class. Since 2.16 + * @G_REGEX_ERROR_RANGE_OUT_OF_ORDER: Range out of order in character class. + * Since 2.16 + * @G_REGEX_ERROR_NOTHING_TO_REPEAT: Nothing to repeat. Since 2.16 + * @G_REGEX_ERROR_UNRECOGNIZED_CHARACTER: Unrecognized character after "(?", + * "(?<" or "(?P". Since 2.16 + * @G_REGEX_ERROR_POSIX_NAMED_CLASS_OUTSIDE_CLASS: POSIX named classes are + * supported only within a class. Since 2.16 + * @G_REGEX_ERROR_UNMATCHED_PARENTHESIS: Missing terminating ")" or ")" + * without opening "(". Since 2.16 + * @G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE: Reference to non-existent + * subpattern. Since 2.16 + * @G_REGEX_ERROR_UNTERMINATED_COMMENT: Missing terminating ")" after comment. + * Since 2.16 + * @G_REGEX_ERROR_EXPRESSION_TOO_LARGE: Regular expression too large. + * Since 2.16 + * @G_REGEX_ERROR_MEMORY_ERROR: Failed to get memory. Since 2.16 + * @G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND: Lookbehind assertion is not + * fixed length. Since 2.16 + * @G_REGEX_ERROR_MALFORMED_CONDITION: Malformed number or name after "(?(". + * Since 2.16 + * @G_REGEX_ERROR_TOO_MANY_CONDITIONAL_BRANCHES: Conditional group contains + * more than two branches. Since 2.16 + * @G_REGEX_ERROR_ASSERTION_EXPECTED: Assertion expected after "(?(". + * Since 2.16 + * @G_REGEX_ERROR_UNKNOWN_POSIX_CLASS_NAME: Unknown POSIX class name. + * Since 2.16 + * @G_REGEX_ERROR_POSIX_COLLATING_ELEMENTS_NOT_SUPPORTED: POSIX collating + * elements are not supported. Since 2.16 + * @G_REGEX_ERROR_HEX_CODE_TOO_LARGE: Character value in "\\x{...}" sequence + * is too large. Since 2.16 + * @G_REGEX_ERROR_INVALID_CONDITION: Invalid condition "(?(0)". Since 2.16 + * @G_REGEX_ERROR_SINGLE_BYTE_MATCH_IN_LOOKBEHIND: \\C not allowed in + * lookbehind assertion. Since 2.16 + * @G_REGEX_ERROR_INFINITE_LOOP: Recursive call could loop indefinitely. + * Since 2.16 + * @G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR: Missing terminator + * in subpattern name. Since 2.16 + * @G_REGEX_ERROR_DUPLICATE_SUBPATTERN_NAME: Two named subpatterns have + * the same name. Since 2.16 + * @G_REGEX_ERROR_MALFORMED_PROPERTY: Malformed "\\P" or "\\p" sequence. + * Since 2.16 + * @G_REGEX_ERROR_UNKNOWN_PROPERTY: Unknown property name after "\\P" or + * "\\p". Since 2.16 + * @G_REGEX_ERROR_SUBPATTERN_NAME_TOO_LONG: Subpattern name is too long + * (maximum 32 characters). Since 2.16 + * @G_REGEX_ERROR_TOO_MANY_SUBPATTERNS: Too many named subpatterns (maximum + * 10,000). Since 2.16 + * @G_REGEX_ERROR_INVALID_OCTAL_VALUE: Octal value is greater than "\\377". + * Since 2.16 + * @G_REGEX_ERROR_TOO_MANY_BRANCHES_IN_DEFINE: "DEFINE" group contains more + * than one branch. Since 2.16 + * @G_REGEX_ERROR_DEFINE_REPETION: Repeating a "DEFINE" group is not allowed. + * Since 2.16 + * @G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS: Inconsistent newline options. + * Since 2.16 + * @G_REGEX_ERROR_MISSING_BACK_REFERENCE: "\\g" is not followed by a braced + * name or an optionally braced non-zero number. Since 2.16 + * + * Error codes returned by regular expressions functions. + * + * Since: 2.14 + */ +typedef enum +{ + G_REGEX_ERROR_COMPILE, + G_REGEX_ERROR_OPTIMIZE, + G_REGEX_ERROR_REPLACE, + G_REGEX_ERROR_MATCH, + G_REGEX_ERROR_INTERNAL, + + /* These are the error codes from PCRE + 100 */ + G_REGEX_ERROR_STRAY_BACKSLASH = 101, + G_REGEX_ERROR_MISSING_CONTROL_CHAR = 102, + G_REGEX_ERROR_UNRECOGNIZED_ESCAPE = 103, + G_REGEX_ERROR_QUANTIFIERS_OUT_OF_ORDER = 104, + G_REGEX_ERROR_QUANTIFIER_TOO_BIG = 105, + G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS = 106, + G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS = 107, + G_REGEX_ERROR_RANGE_OUT_OF_ORDER = 108, + G_REGEX_ERROR_NOTHING_TO_REPEAT = 109, + G_REGEX_ERROR_UNRECOGNIZED_CHARACTER = 112, + G_REGEX_ERROR_POSIX_NAMED_CLASS_OUTSIDE_CLASS = 113, + G_REGEX_ERROR_UNMATCHED_PARENTHESIS = 114, + G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE = 115, + G_REGEX_ERROR_UNTERMINATED_COMMENT = 118, + G_REGEX_ERROR_EXPRESSION_TOO_LARGE = 120, + G_REGEX_ERROR_MEMORY_ERROR = 121, + G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND = 125, + G_REGEX_ERROR_MALFORMED_CONDITION = 126, + G_REGEX_ERROR_TOO_MANY_CONDITIONAL_BRANCHES = 127, + G_REGEX_ERROR_ASSERTION_EXPECTED = 128, + G_REGEX_ERROR_UNKNOWN_POSIX_CLASS_NAME = 130, + G_REGEX_ERROR_POSIX_COLLATING_ELEMENTS_NOT_SUPPORTED = 131, + G_REGEX_ERROR_HEX_CODE_TOO_LARGE = 134, + G_REGEX_ERROR_INVALID_CONDITION = 135, + G_REGEX_ERROR_SINGLE_BYTE_MATCH_IN_LOOKBEHIND = 136, + G_REGEX_ERROR_INFINITE_LOOP = 140, + G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR = 142, + G_REGEX_ERROR_DUPLICATE_SUBPATTERN_NAME = 143, + G_REGEX_ERROR_MALFORMED_PROPERTY = 146, + G_REGEX_ERROR_UNKNOWN_PROPERTY = 147, + G_REGEX_ERROR_SUBPATTERN_NAME_TOO_LONG = 148, + G_REGEX_ERROR_TOO_MANY_SUBPATTERNS = 149, + G_REGEX_ERROR_INVALID_OCTAL_VALUE = 151, + G_REGEX_ERROR_TOO_MANY_BRANCHES_IN_DEFINE = 154, + G_REGEX_ERROR_DEFINE_REPETION = 155, + G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS = 156, + G_REGEX_ERROR_MISSING_BACK_REFERENCE = 157 +} GRegexError; + +/** + * G_REGEX_ERROR: + * + * Error domain for regular expressions. Errors in this domain will be + * from the #GRegexError enumeration. See #GError for information on + * error domains. + * + * Since: 2.14 + */ +#define G_REGEX_ERROR g_regex_error_quark () + +GQuark g_regex_error_quark (void); + +/** + * GRegexCompileFlags: + * @G_REGEX_CASELESS: Letters in the pattern match both upper- and + * lowercase letters. This option can be changed within a pattern + * by a "(?i)" option setting. + * @G_REGEX_MULTILINE: By default, GRegex treats the strings as consisting + * of a single line of characters (even if it actually contains + * newlines). The "start of line" metacharacter ("^") matches only + * at the start of the string, while the "end of line" metacharacter + * ("$") matches only at the end of the string, or before a terminating + * newline (unless #G_REGEX_DOLLAR_ENDONLY is set). When + * #G_REGEX_MULTILINE is set, the "start of line" and "end of line" + * constructs match immediately following or immediately before any + * newline in the string, respectively, as well as at the very start + * and end. This can be changed within a pattern by a "(?m)" option + * setting. + * @G_REGEX_DOTALL: A dot metacharater (".") in the pattern matches all + * characters, including newlines. Without it, newlines are excluded. + * This option can be changed within a pattern by a ("?s") option setting. + * @G_REGEX_EXTENDED: Whitespace data characters in the pattern are + * totally ignored except when escaped or inside a character class. + * Whitespace does not include the VT character (code 11). In addition, + * characters between an unescaped "#" outside a character class and + * the next newline character, inclusive, are also ignored. This can + * be changed within a pattern by a "(?x)" option setting. + * @G_REGEX_ANCHORED: The pattern is forced to be "anchored", that is, + * it is constrained to match only at the first matching point in the + * string that is being searched. This effect can also be achieved by + * appropriate constructs in the pattern itself such as the "^" + * metacharater. + * @G_REGEX_DOLLAR_ENDONLY: A dollar metacharacter ("$") in the pattern + * matches only at the end of the string. Without this option, a + * dollar also matches immediately before the final character if + * it is a newline (but not before any other newlines). This option + * is ignored if #G_REGEX_MULTILINE is set. + * @G_REGEX_UNGREEDY: Inverts the "greediness" of the quantifiers so that + * they are not greedy by default, but become greedy if followed by "?". + * It can also be set by a "(?U)" option setting within the pattern. + * @G_REGEX_RAW: Usually strings must be valid UTF-8 strings, using this + * flag they are considered as a raw sequence of bytes. + * @G_REGEX_NO_AUTO_CAPTURE: Disables the use of numbered capturing + * parentheses in the pattern. Any opening parenthesis that is not + * followed by "?" behaves as if it were followed by "?:" but named + * parentheses can still be used for capturing (and they acquire numbers + * in the usual way). + * @G_REGEX_OPTIMIZE: Optimize the regular expression. If the pattern will + * be used many times, then it may be worth the effort to optimize it + * to improve the speed of matches. + * @G_REGEX_DUPNAMES: Names used to identify capturing subpatterns need not + * be unique. This can be helpful for certain types of pattern when it + * is known that only one instance of the named subpattern can ever be + * matched. + * @G_REGEX_NEWLINE_CR: Usually any newline character is recognized, if this + * option is set, the only recognized newline character is '\r'. + * @G_REGEX_NEWLINE_LF: Usually any newline character is recognized, if this + * option is set, the only recognized newline character is '\n'. + * @G_REGEX_NEWLINE_CRLF: Usually any newline character is recognized, if this + * option is set, the only recognized newline character sequence is '\r\n'. + * + * Flags specifying compile-time options. + * + * Since: 2.14 + */ +/* Remember to update G_REGEX_COMPILE_MASK in gregex.c after + * adding a new flag. */ +typedef enum +{ + G_REGEX_CASELESS = 1 << 0, + G_REGEX_MULTILINE = 1 << 1, + G_REGEX_DOTALL = 1 << 2, + G_REGEX_EXTENDED = 1 << 3, + G_REGEX_ANCHORED = 1 << 4, + G_REGEX_DOLLAR_ENDONLY = 1 << 5, + G_REGEX_UNGREEDY = 1 << 9, + G_REGEX_RAW = 1 << 11, + G_REGEX_NO_AUTO_CAPTURE = 1 << 12, + G_REGEX_OPTIMIZE = 1 << 13, + G_REGEX_DUPNAMES = 1 << 19, + G_REGEX_NEWLINE_CR = 1 << 20, + G_REGEX_NEWLINE_LF = 1 << 21, + G_REGEX_NEWLINE_CRLF = G_REGEX_NEWLINE_CR | G_REGEX_NEWLINE_LF +} GRegexCompileFlags; + +/** + * GRegexMatchFlags: + * @G_REGEX_MATCH_ANCHORED: The pattern is forced to be "anchored", that is, + * it is constrained to match only at the first matching point in the + * string that is being searched. This effect can also be achieved by + * appropriate constructs in the pattern itself such as the "^" + * metacharater. + * @G_REGEX_MATCH_NOTBOL: Specifies that first character of the string is + * not the beginning of a line, so the circumflex metacharacter should + * not match before it. Setting this without #G_REGEX_MULTILINE (at + * compile time) causes circumflex never to match. This option affects + * only the behaviour of the circumflex metacharacter, it does not + * affect "\A". + * @G_REGEX_MATCH_NOTEOL: Specifies that the end of the subject string is + * not the end of a line, so the dollar metacharacter should not match + * it nor (except in multiline mode) a newline immediately before it. + * Setting this without #G_REGEX_MULTILINE (at compile time) causes + * dollar never to match. This option affects only the behaviour of + * the dollar metacharacter, it does not affect "\Z" or "\z". + * @G_REGEX_MATCH_NOTEMPTY: An empty string is not considered to be a valid + * match if this option is set. If there are alternatives in the pattern, + * they are tried. If all the alternatives match the empty string, the + * entire match fails. For example, if the pattern "a?b?" is applied to + * a string not beginning with "a" or "b", it matches the empty string + * at the start of the string. With this flag set, this match is not + * valid, so GRegex searches further into the string for occurrences + * of "a" or "b". + * @G_REGEX_MATCH_PARTIAL: Turns on the partial matching feature, for more + * documentation on partial matching see g_match_info_is_partial_match(). + * @G_REGEX_MATCH_NEWLINE_CR: Overrides the newline definition set when + * creating a new #GRegex, setting the '\r' character as line terminator. + * @G_REGEX_MATCH_NEWLINE_LF: Overrides the newline definition set when + * creating a new #GRegex, setting the '\n' character as line terminator. + * @G_REGEX_MATCH_NEWLINE_CRLF: Overrides the newline definition set when + * creating a new #GRegex, setting the '\r\n' characters as line terminator. + * @G_REGEX_MATCH_NEWLINE_ANY: Overrides the newline definition set when + * creating a new #GRegex, any newline character or character sequence + * is recognized. + * + * Flags specifying match-time options. + * + * Since: 2.14 + */ +/* Remember to update G_REGEX_MATCH_MASK in gregex.c after + * adding a new flag. */ +typedef enum +{ + G_REGEX_MATCH_ANCHORED = 1 << 4, + G_REGEX_MATCH_NOTBOL = 1 << 7, + G_REGEX_MATCH_NOTEOL = 1 << 8, + G_REGEX_MATCH_NOTEMPTY = 1 << 10, + G_REGEX_MATCH_PARTIAL = 1 << 15, + G_REGEX_MATCH_NEWLINE_CR = 1 << 20, + G_REGEX_MATCH_NEWLINE_LF = 1 << 21, + G_REGEX_MATCH_NEWLINE_CRLF = G_REGEX_MATCH_NEWLINE_CR | G_REGEX_MATCH_NEWLINE_LF, + G_REGEX_MATCH_NEWLINE_ANY = 1 << 22 +} GRegexMatchFlags; + +/** + * GRegex: + * + * A GRegex is the "compiled" form of a regular expression pattern. This + * structure is opaque and its fields cannot be accessed directly. + * + * Since: 2.14 + */ +typedef struct _GRegex GRegex; + + +typedef struct _GMatchInfo GMatchInfo; + +/** + * GRegexEvalCallback: + * @match_info: the #GMatchInfo generated by the match. + * Use g_match_info_get_regex() and g_match_info_get_string() if you + * need the #GRegex or the matched string. + * @result: a #GString containing the new string + * @user_data: user data passed to g_regex_replace_eval() + * + * Specifies the type of the function passed to g_regex_replace_eval(). + * It is called for each occurance of the pattern in the string passed + * to g_regex_replace_eval(), and it should append the replacement to + * @result. + * + * Returns: %FALSE to continue the replacement process, %TRUE to stop it + * + * Since: 2.14 + */ +typedef gboolean (*GRegexEvalCallback) (const GMatchInfo *match_info, + GString *result, + gpointer user_data); + + +GRegex *g_regex_new (const gchar *pattern, + GRegexCompileFlags compile_options, + GRegexMatchFlags match_options, + GError **error); +GRegex *g_regex_ref (GRegex *regex); +void g_regex_unref (GRegex *regex); +const gchar *g_regex_get_pattern (const GRegex *regex); +gint g_regex_get_max_backref (const GRegex *regex); +gint g_regex_get_capture_count (const GRegex *regex); +gint g_regex_get_string_number (const GRegex *regex, + const gchar *name); +gchar *g_regex_escape_string (const gchar *string, + gint length); + +GRegexCompileFlags g_regex_get_compile_flags (const GRegex *regex); +GRegexMatchFlags g_regex_get_match_flags (const GRegex *regex); + +/* Matching. */ +gboolean g_regex_match_simple (const gchar *pattern, + const gchar *string, + GRegexCompileFlags compile_options, + GRegexMatchFlags match_options); +gboolean g_regex_match (const GRegex *regex, + const gchar *string, + GRegexMatchFlags match_options, + GMatchInfo **match_info); +gboolean g_regex_match_full (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + GRegexMatchFlags match_options, + GMatchInfo **match_info, + GError **error); +gboolean g_regex_match_all (const GRegex *regex, + const gchar *string, + GRegexMatchFlags match_options, + GMatchInfo **match_info); +gboolean g_regex_match_all_full (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + GRegexMatchFlags match_options, + GMatchInfo **match_info, + GError **error); + +/* String splitting. */ +gchar **g_regex_split_simple (const gchar *pattern, + const gchar *string, + GRegexCompileFlags compile_options, + GRegexMatchFlags match_options); +gchar **g_regex_split (const GRegex *regex, + const gchar *string, + GRegexMatchFlags match_options); +gchar **g_regex_split_full (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + GRegexMatchFlags match_options, + gint max_tokens, + GError **error); + +/* String replacement. */ +gchar *g_regex_replace (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + const gchar *replacement, + GRegexMatchFlags match_options, + GError **error); +gchar *g_regex_replace_literal (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + const gchar *replacement, + GRegexMatchFlags match_options, + GError **error); +gchar *g_regex_replace_eval (const GRegex *regex, + const gchar *string, + gssize string_len, + gint start_position, + GRegexMatchFlags match_options, + GRegexEvalCallback eval, + gpointer user_data, + GError **error); +gboolean g_regex_check_replacement (const gchar *replacement, + gboolean *has_references, + GError **error); + +/* Match info */ +GRegex *g_match_info_get_regex (const GMatchInfo *match_info); +const gchar *g_match_info_get_string (const GMatchInfo *match_info); + +void g_match_info_free (GMatchInfo *match_info); +gboolean g_match_info_next (GMatchInfo *match_info, + GError **error); +gboolean g_match_info_matches (const GMatchInfo *match_info); +gint g_match_info_get_match_count (const GMatchInfo *match_info); +gboolean g_match_info_is_partial_match (const GMatchInfo *match_info); +gchar *g_match_info_expand_references(const GMatchInfo *match_info, + const gchar *string_to_expand, + GError **error); +gchar *g_match_info_fetch (const GMatchInfo *match_info, + gint match_num); +gboolean g_match_info_fetch_pos (const GMatchInfo *match_info, + gint match_num, + gint *start_pos, + gint *end_pos); +gchar *g_match_info_fetch_named (const GMatchInfo *match_info, + const gchar *name); +gboolean g_match_info_fetch_named_pos (const GMatchInfo *match_info, + const gchar *name, + gint *start_pos, + gint *end_pos); +gchar **g_match_info_fetch_all (const GMatchInfo *match_info); + +G_END_DECLS + +#endif /* __G_REGEX_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/grel.h b/protocols/Sametime/src/glib/include/glib/grel.h new file mode 100644 index 0000000000..5cb8d09d4b --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/grel.h @@ -0,0 +1,101 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_REL_H__ +#define __G_REL_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef struct _GRelation GRelation; +typedef struct _GTuples GTuples; + +struct _GTuples +{ + guint len; +}; + +/* GRelation + * + * Indexed Relations. Imagine a really simple table in a + * database. Relations are not ordered. This data type is meant for + * maintaining a N-way mapping. + * + * g_relation_new() creates a relation with FIELDS fields + * + * g_relation_destroy() frees all resources + * g_tuples_destroy() frees the result of g_relation_select() + * + * g_relation_index() indexes relation FIELD with the provided + * equality and hash functions. this must be done before any + * calls to insert are made. + * + * g_relation_insert() inserts a new tuple. you are expected to + * provide the right number of fields. + * + * g_relation_delete() deletes all relations with KEY in FIELD + * g_relation_select() returns ... + * g_relation_count() counts ... + */ + +#ifndef G_DISABLE_DEPRECATED + +GRelation* g_relation_new (gint fields); +void g_relation_destroy (GRelation *relation); +void g_relation_index (GRelation *relation, + gint field, + GHashFunc hash_func, + GEqualFunc key_equal_func); +void g_relation_insert (GRelation *relation, + ...); +gint g_relation_delete (GRelation *relation, + gconstpointer key, + gint field); +GTuples* g_relation_select (GRelation *relation, + gconstpointer key, + gint field); +gint g_relation_count (GRelation *relation, + gconstpointer key, + gint field); +gboolean g_relation_exists (GRelation *relation, + ...); +void g_relation_print (GRelation *relation); + +void g_tuples_destroy (GTuples *tuples); +gpointer g_tuples_index (GTuples *tuples, + gint index_, + gint field); + +#endif + +G_END_DECLS + +#endif /* __G_REL_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gscanner.h b/protocols/Sametime/src/glib/include/glib/gscanner.h new file mode 100644 index 0000000000..3b7ad6fab0 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gscanner.h @@ -0,0 +1,278 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SCANNER_H__ +#define __G_SCANNER_H__ + +#include <glib/gdataset.h> +#include <glib/ghash.h> + +G_BEGIN_DECLS + +typedef struct _GScanner GScanner; +typedef struct _GScannerConfig GScannerConfig; +typedef union _GTokenValue GTokenValue; + +typedef void (*GScannerMsgFunc) (GScanner *scanner, + gchar *message, + gboolean error); + +/* GScanner: Flexible lexical scanner for general purpose. + */ + +/* Character sets */ +#define G_CSET_A_2_Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define G_CSET_a_2_z "abcdefghijklmnopqrstuvwxyz" +#define G_CSET_DIGITS "0123456789" +#define G_CSET_LATINC "\300\301\302\303\304\305\306"\ + "\307\310\311\312\313\314\315\316\317\320"\ + "\321\322\323\324\325\326"\ + "\330\331\332\333\334\335\336" +#define G_CSET_LATINS "\337\340\341\342\343\344\345\346"\ + "\347\350\351\352\353\354\355\356\357\360"\ + "\361\362\363\364\365\366"\ + "\370\371\372\373\374\375\376\377" + +/* Error types */ +typedef enum +{ + G_ERR_UNKNOWN, + G_ERR_UNEXP_EOF, + G_ERR_UNEXP_EOF_IN_STRING, + G_ERR_UNEXP_EOF_IN_COMMENT, + G_ERR_NON_DIGIT_IN_CONST, + G_ERR_DIGIT_RADIX, + G_ERR_FLOAT_RADIX, + G_ERR_FLOAT_MALFORMED +} GErrorType; + +/* Token types */ +typedef enum +{ + G_TOKEN_EOF = 0, + + G_TOKEN_LEFT_PAREN = '(', + G_TOKEN_RIGHT_PAREN = ')', + G_TOKEN_LEFT_CURLY = '{', + G_TOKEN_RIGHT_CURLY = '}', + G_TOKEN_LEFT_BRACE = '[', + G_TOKEN_RIGHT_BRACE = ']', + G_TOKEN_EQUAL_SIGN = '=', + G_TOKEN_COMMA = ',', + + G_TOKEN_NONE = 256, + + G_TOKEN_ERROR, + + G_TOKEN_CHAR, + G_TOKEN_BINARY, + G_TOKEN_OCTAL, + G_TOKEN_INT, + G_TOKEN_HEX, + G_TOKEN_FLOAT, + G_TOKEN_STRING, + + G_TOKEN_SYMBOL, + G_TOKEN_IDENTIFIER, + G_TOKEN_IDENTIFIER_NULL, + + G_TOKEN_COMMENT_SINGLE, + G_TOKEN_COMMENT_MULTI, + G_TOKEN_LAST +} GTokenType; + +union _GTokenValue +{ + gpointer v_symbol; + gchar *v_identifier; + gulong v_binary; + gulong v_octal; + gulong v_int; + guint64 v_int64; + gdouble v_float; + gulong v_hex; + gchar *v_string; + gchar *v_comment; + guchar v_char; + guint v_error; +}; + +struct _GScannerConfig +{ + /* Character sets + */ + gchar *cset_skip_characters; /* default: " \t\n" */ + gchar *cset_identifier_first; + gchar *cset_identifier_nth; + gchar *cpair_comment_single; /* default: "#\n" */ + + /* Should symbol lookup work case sensitive? + */ + guint case_sensitive : 1; + + /* Boolean values to be adjusted "on the fly" + * to configure scanning behaviour. + */ + guint skip_comment_multi : 1; /* C like comment */ + guint skip_comment_single : 1; /* single line comment */ + guint scan_comment_multi : 1; /* scan multi line comments? */ + guint scan_identifier : 1; + guint scan_identifier_1char : 1; + guint scan_identifier_NULL : 1; + guint scan_symbols : 1; + guint scan_binary : 1; + guint scan_octal : 1; + guint scan_float : 1; + guint scan_hex : 1; /* `0x0ff0' */ + guint scan_hex_dollar : 1; /* `$0ff0' */ + guint scan_string_sq : 1; /* string: 'anything' */ + guint scan_string_dq : 1; /* string: "\\-escapes!\n" */ + guint numbers_2_int : 1; /* bin, octal, hex => int */ + guint int_2_float : 1; /* int => G_TOKEN_FLOAT? */ + guint identifier_2_string : 1; + guint char_2_token : 1; /* return G_TOKEN_CHAR? */ + guint symbol_2_token : 1; + guint scope_0_fallback : 1; /* try scope 0 on lookups? */ + guint store_int64 : 1; /* use value.v_int64 rather than v_int */ + guint padding_dummy; +}; + +struct _GScanner +{ + /* unused fields */ + gpointer user_data; + guint max_parse_errors; + + /* g_scanner_error() increments this field */ + guint parse_errors; + + /* name of input stream, featured by the default message handler */ + const gchar *input_name; + + /* quarked data */ + GData *qdata; + + /* link into the scanner configuration */ + GScannerConfig *config; + + /* fields filled in after g_scanner_get_next_token() */ + GTokenType token; + GTokenValue value; + guint line; + guint position; + + /* fields filled in after g_scanner_peek_next_token() */ + GTokenType next_token; + GTokenValue next_value; + guint next_line; + guint next_position; + + /* to be considered private */ + GHashTable *symbol_table; + gint input_fd; + const gchar *text; + const gchar *text_end; + gchar *buffer; + guint scope_id; + + /* handler function for _warn and _error */ + GScannerMsgFunc msg_handler; +}; + +GScanner* g_scanner_new (const GScannerConfig *config_templ); +void g_scanner_destroy (GScanner *scanner); +void g_scanner_input_file (GScanner *scanner, + gint input_fd); +void g_scanner_sync_file_offset (GScanner *scanner); +void g_scanner_input_text (GScanner *scanner, + const gchar *text, + guint text_len); +GTokenType g_scanner_get_next_token (GScanner *scanner); +GTokenType g_scanner_peek_next_token (GScanner *scanner); +GTokenType g_scanner_cur_token (GScanner *scanner); +GTokenValue g_scanner_cur_value (GScanner *scanner); +guint g_scanner_cur_line (GScanner *scanner); +guint g_scanner_cur_position (GScanner *scanner); +gboolean g_scanner_eof (GScanner *scanner); +guint g_scanner_set_scope (GScanner *scanner, + guint scope_id); +void g_scanner_scope_add_symbol (GScanner *scanner, + guint scope_id, + const gchar *symbol, + gpointer value); +void g_scanner_scope_remove_symbol (GScanner *scanner, + guint scope_id, + const gchar *symbol); +gpointer g_scanner_scope_lookup_symbol (GScanner *scanner, + guint scope_id, + const gchar *symbol); +void g_scanner_scope_foreach_symbol (GScanner *scanner, + guint scope_id, + GHFunc func, + gpointer user_data); +gpointer g_scanner_lookup_symbol (GScanner *scanner, + const gchar *symbol); +void g_scanner_unexp_token (GScanner *scanner, + GTokenType expected_token, + const gchar *identifier_spec, + const gchar *symbol_spec, + const gchar *symbol_name, + const gchar *message, + gint is_error); +void g_scanner_error (GScanner *scanner, + const gchar *format, + ...) G_GNUC_PRINTF (2,3); +void g_scanner_warn (GScanner *scanner, + const gchar *format, + ...) G_GNUC_PRINTF (2,3); + +#ifndef G_DISABLE_DEPRECATED + +/* keep downward source compatibility */ +#define g_scanner_add_symbol( scanner, symbol, value ) G_STMT_START { \ + g_scanner_scope_add_symbol ((scanner), 0, (symbol), (value)); \ +} G_STMT_END +#define g_scanner_remove_symbol( scanner, symbol ) G_STMT_START { \ + g_scanner_scope_remove_symbol ((scanner), 0, (symbol)); \ +} G_STMT_END +#define g_scanner_foreach_symbol( scanner, func, data ) G_STMT_START { \ + g_scanner_scope_foreach_symbol ((scanner), 0, (func), (data)); \ +} G_STMT_END + +/* The following two functions are deprecated and will be removed in + * the next major release. They do no good. */ +#define g_scanner_freeze_symbol_table(scanner) ((void)0) +#define g_scanner_thaw_symbol_table(scanner) ((void)0) + +#endif /* G_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __G_SCANNER_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gsequence.h b/protocols/Sametime/src/glib/include/glib/gsequence.h new file mode 100644 index 0000000000..fa79066e06 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gsequence.h @@ -0,0 +1,128 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + * Soeren Sandmann (sandmann@daimi.au.dk) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SEQUENCE_H__ +#define __G_SEQUENCE_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef struct _GSequence GSequence; +typedef struct _GSequenceNode GSequenceIter; + +typedef gint (* GSequenceIterCompareFunc) (GSequenceIter *a, + GSequenceIter *b, + gpointer data); + + +/* GSequence */ +GSequence * g_sequence_new (GDestroyNotify data_destroy); +void g_sequence_free (GSequence *seq); +gint g_sequence_get_length (GSequence *seq); +void g_sequence_foreach (GSequence *seq, + GFunc func, + gpointer user_data); +void g_sequence_foreach_range (GSequenceIter *begin, + GSequenceIter *end, + GFunc func, + gpointer user_data); +void g_sequence_sort (GSequence *seq, + GCompareDataFunc cmp_func, + gpointer cmp_data); +void g_sequence_sort_iter (GSequence *seq, + GSequenceIterCompareFunc cmp_func, + gpointer cmp_data); + + +/* Getting iters */ +GSequenceIter *g_sequence_get_begin_iter (GSequence *seq); +GSequenceIter *g_sequence_get_end_iter (GSequence *seq); +GSequenceIter *g_sequence_get_iter_at_pos (GSequence *seq, + gint pos); +GSequenceIter *g_sequence_append (GSequence *seq, + gpointer data); +GSequenceIter *g_sequence_prepend (GSequence *seq, + gpointer data); +GSequenceIter *g_sequence_insert_before (GSequenceIter *iter, + gpointer data); +void g_sequence_move (GSequenceIter *src, + GSequenceIter *dest); +void g_sequence_swap (GSequenceIter *a, + GSequenceIter *b); +GSequenceIter *g_sequence_insert_sorted (GSequence *seq, + gpointer data, + GCompareDataFunc cmp_func, + gpointer cmp_data); +GSequenceIter *g_sequence_insert_sorted_iter (GSequence *seq, + gpointer data, + GSequenceIterCompareFunc iter_cmp, + gpointer cmp_data); +void g_sequence_sort_changed (GSequenceIter *iter, + GCompareDataFunc cmp_func, + gpointer cmp_data); +void g_sequence_sort_changed_iter (GSequenceIter *iter, + GSequenceIterCompareFunc iter_cmp, + gpointer cmp_data); +void g_sequence_remove (GSequenceIter *iter); +void g_sequence_remove_range (GSequenceIter *begin, + GSequenceIter *end); +void g_sequence_move_range (GSequenceIter *dest, + GSequenceIter *begin, + GSequenceIter *end); +GSequenceIter *g_sequence_search (GSequence *seq, + gpointer data, + GCompareDataFunc cmp_func, + gpointer cmp_data); +GSequenceIter *g_sequence_search_iter (GSequence *seq, + gpointer data, + GSequenceIterCompareFunc iter_cmp, + gpointer cmp_data); + + +/* Dereferencing */ +gpointer g_sequence_get (GSequenceIter *iter); +void g_sequence_set (GSequenceIter *iter, + gpointer data); + +/* Operations on GSequenceIter * */ +gboolean g_sequence_iter_is_begin (GSequenceIter *iter); +gboolean g_sequence_iter_is_end (GSequenceIter *iter); +GSequenceIter *g_sequence_iter_next (GSequenceIter *iter); +GSequenceIter *g_sequence_iter_prev (GSequenceIter *iter); +gint g_sequence_iter_get_position (GSequenceIter *iter); +GSequenceIter *g_sequence_iter_move (GSequenceIter *iter, + gint delta); +GSequence * g_sequence_iter_get_sequence (GSequenceIter *iter); + + +/* Search */ +gint g_sequence_iter_compare (GSequenceIter *a, + GSequenceIter *b); +GSequenceIter *g_sequence_range_get_midpoint (GSequenceIter *begin, + GSequenceIter *end); + +G_END_DECLS + +#endif /* __G_SEQUENCE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gshell.h b/protocols/Sametime/src/glib/include/glib/gshell.h new file mode 100644 index 0000000000..130f1008c8 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gshell.h @@ -0,0 +1,55 @@ +/* gshell.h - Shell-related utilities + * + * Copyright 2000 Red Hat, Inc. + * + * GLib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * GLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GLib; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SHELL_H__ +#define __G_SHELL_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +#define G_SHELL_ERROR g_shell_error_quark () + +typedef enum +{ + /* mismatched or otherwise mangled quoting */ + G_SHELL_ERROR_BAD_QUOTING, + /* string to be parsed was empty */ + G_SHELL_ERROR_EMPTY_STRING, + G_SHELL_ERROR_FAILED +} GShellError; + +GQuark g_shell_error_quark (void); + +gchar* g_shell_quote (const gchar *unquoted_string); +gchar* g_shell_unquote (const gchar *quoted_string, + GError **error); +gboolean g_shell_parse_argv (const gchar *command_line, + gint *argcp, + gchar ***argvp, + GError **error); + +G_END_DECLS + +#endif /* __G_SHELL_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gslice.h b/protocols/Sametime/src/glib/include/glib/gslice.h new file mode 100644 index 0000000000..962199e099 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gslice.h @@ -0,0 +1,86 @@ +/* GLIB sliced memory - fast threaded memory chunk allocator + * Copyright (C) 2005 Tim Janik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SLICE_H__ +#define __G_SLICE_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/* slices - fast allocation/release of small memory blocks + */ +gpointer g_slice_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_slice_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +gpointer g_slice_copy (gsize block_size, + gconstpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); +void g_slice_free1 (gsize block_size, + gpointer mem_block); +void g_slice_free_chain_with_offset (gsize block_size, + gpointer mem_chain, + gsize next_offset); +#define g_slice_new(type) ((type*) g_slice_alloc (sizeof (type))) +#define g_slice_new0(type) ((type*) g_slice_alloc0 (sizeof (type))) +/* MemoryBlockType * + * g_slice_dup (MemoryBlockType, + * MemoryBlockType *mem_block); + * g_slice_free (MemoryBlockType, + * MemoryBlockType *mem_block); + * g_slice_free_chain (MemoryBlockType, + * MemoryBlockType *first_chain_block, + * memory_block_next_field); + * pseudo prototypes for the macro + * definitions following below. + */ + +/* we go through extra hoops to ensure type safety */ +#define g_slice_dup(type, mem) \ + (1 ? (type*) g_slice_copy (sizeof (type), (mem)) \ + : ((void) ((type*) 0 == (mem)), (type*) 0)) +#define g_slice_free(type, mem) do { \ + if (1) g_slice_free1 (sizeof (type), (mem)); \ + else (void) ((type*) 0 == (mem)); \ +} while (0) +#define g_slice_free_chain(type, mem_chain, next) do { \ + if (1) g_slice_free_chain_with_offset (sizeof (type), \ + (mem_chain), G_STRUCT_OFFSET (type, next)); \ + else (void) ((type*) 0 == (mem_chain)); \ +} while (0) + + +/* --- internal debugging API --- */ +typedef enum { + G_SLICE_CONFIG_ALWAYS_MALLOC = 1, + G_SLICE_CONFIG_BYPASS_MAGAZINES, + G_SLICE_CONFIG_WORKING_SET_MSECS, + G_SLICE_CONFIG_COLOR_INCREMENT, + G_SLICE_CONFIG_CHUNK_SIZES, + G_SLICE_CONFIG_CONTENTION_COUNTER +} GSliceConfig; +void g_slice_set_config (GSliceConfig ckey, gint64 value); +gint64 g_slice_get_config (GSliceConfig ckey); +gint64* g_slice_get_config_state (GSliceConfig ckey, gint64 address, guint *n_values); + +G_END_DECLS + +#endif /* __G_SLICE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gslist.h b/protocols/Sametime/src/glib/include/glib/gslist.h new file mode 100644 index 0000000000..8b01faf5cd --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gslist.h @@ -0,0 +1,114 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SLIST_H__ +#define __G_SLIST_H__ + +#include <glib/gmem.h> + +G_BEGIN_DECLS + +typedef struct _GSList GSList; + +struct _GSList +{ + gpointer data; + GSList *next; +}; + +/* Singly linked lists + */ +GSList* g_slist_alloc (void) G_GNUC_WARN_UNUSED_RESULT; +void g_slist_free (GSList *list); +void g_slist_free_1 (GSList *list); +#define g_slist_free1 g_slist_free_1 +GSList* g_slist_append (GSList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_prepend (GSList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_insert (GSList *list, + gpointer data, + gint position) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_insert_sorted (GSList *list, + gpointer data, + GCompareFunc func) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_insert_sorted_with_data (GSList *list, + gpointer data, + GCompareDataFunc func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_insert_before (GSList *slist, + GSList *sibling, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_concat (GSList *list1, + GSList *list2) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_remove (GSList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_remove_all (GSList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_remove_link (GSList *list, + GSList *link_) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_delete_link (GSList *list, + GSList *link_) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_reverse (GSList *list) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_copy (GSList *list) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_nth (GSList *list, + guint n); +GSList* g_slist_find (GSList *list, + gconstpointer data); +GSList* g_slist_find_custom (GSList *list, + gconstpointer data, + GCompareFunc func); +gint g_slist_position (GSList *list, + GSList *llink); +gint g_slist_index (GSList *list, + gconstpointer data); +GSList* g_slist_last (GSList *list); +guint g_slist_length (GSList *list); +void g_slist_foreach (GSList *list, + GFunc func, + gpointer user_data); +GSList* g_slist_sort (GSList *list, + GCompareFunc compare_func) G_GNUC_WARN_UNUSED_RESULT; +GSList* g_slist_sort_with_data (GSList *list, + GCompareDataFunc compare_func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +gpointer g_slist_nth_data (GSList *list, + guint n); + +#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) + +#ifndef G_DISABLE_DEPRECATED +void g_slist_push_allocator (gpointer dummy); +void g_slist_pop_allocator (void); +#endif + +G_END_DECLS + +#endif /* __G_SLIST_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gspawn.h b/protocols/Sametime/src/glib/include/glib/gspawn.h new file mode 100644 index 0000000000..9836b34242 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gspawn.h @@ -0,0 +1,139 @@ +/* gspawn.h - Process launching + * + * Copyright 2000 Red Hat, Inc. + * + * GLib is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * GLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GLib; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_SPAWN_H__ +#define __G_SPAWN_H__ + +#include <glib/gerror.h> + +G_BEGIN_DECLS + +/* I'm not sure I remember our proposed naming convention here. */ +#define G_SPAWN_ERROR g_spawn_error_quark () + +typedef enum +{ + G_SPAWN_ERROR_FORK, /* fork failed due to lack of memory */ + G_SPAWN_ERROR_READ, /* read or select on pipes failed */ + G_SPAWN_ERROR_CHDIR, /* changing to working dir failed */ + G_SPAWN_ERROR_ACCES, /* execv() returned EACCES */ + G_SPAWN_ERROR_PERM, /* execv() returned EPERM */ + G_SPAWN_ERROR_2BIG, /* execv() returned E2BIG */ + G_SPAWN_ERROR_NOEXEC, /* execv() returned ENOEXEC */ + G_SPAWN_ERROR_NAMETOOLONG, /* "" "" ENAMETOOLONG */ + G_SPAWN_ERROR_NOENT, /* "" "" ENOENT */ + G_SPAWN_ERROR_NOMEM, /* "" "" ENOMEM */ + G_SPAWN_ERROR_NOTDIR, /* "" "" ENOTDIR */ + G_SPAWN_ERROR_LOOP, /* "" "" ELOOP */ + G_SPAWN_ERROR_TXTBUSY, /* "" "" ETXTBUSY */ + G_SPAWN_ERROR_IO, /* "" "" EIO */ + G_SPAWN_ERROR_NFILE, /* "" "" ENFILE */ + G_SPAWN_ERROR_MFILE, /* "" "" EMFLE */ + G_SPAWN_ERROR_INVAL, /* "" "" EINVAL */ + G_SPAWN_ERROR_ISDIR, /* "" "" EISDIR */ + G_SPAWN_ERROR_LIBBAD, /* "" "" ELIBBAD */ + G_SPAWN_ERROR_FAILED /* other fatal failure, error->message + * should explain + */ +} GSpawnError; + +typedef void (* GSpawnChildSetupFunc) (gpointer user_data); + +typedef enum +{ + G_SPAWN_LEAVE_DESCRIPTORS_OPEN = 1 << 0, + G_SPAWN_DO_NOT_REAP_CHILD = 1 << 1, + /* look for argv[0] in the path i.e. use execvp() */ + G_SPAWN_SEARCH_PATH = 1 << 2, + /* Dump output to /dev/null */ + G_SPAWN_STDOUT_TO_DEV_NULL = 1 << 3, + G_SPAWN_STDERR_TO_DEV_NULL = 1 << 4, + G_SPAWN_CHILD_INHERITS_STDIN = 1 << 5, + G_SPAWN_FILE_AND_ARGV_ZERO = 1 << 6 +} GSpawnFlags; + +GQuark g_spawn_error_quark (void); + +#ifdef G_OS_WIN32 +#define g_spawn_async g_spawn_async_utf8 +#define g_spawn_async_with_pipes g_spawn_async_with_pipes_utf8 +#define g_spawn_sync g_spawn_sync_utf8 +#define g_spawn_command_line_sync g_spawn_command_line_sync_utf8 +#define g_spawn_command_line_async g_spawn_command_line_async_utf8 +#endif + +gboolean g_spawn_async (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GPid *child_pid, + GError **error); + + +/* Opens pipes for non-NULL standard_output, standard_input, standard_error, + * and returns the parent's end of the pipes. + */ +gboolean g_spawn_async_with_pipes (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GPid *child_pid, + gint *standard_input, + gint *standard_output, + gint *standard_error, + GError **error); + + +/* If standard_output or standard_error are non-NULL, the full + * standard output or error of the command will be placed there. + */ + +gboolean g_spawn_sync (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error); + +gboolean g_spawn_command_line_sync (const gchar *command_line, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error); +gboolean g_spawn_command_line_async (const gchar *command_line, + GError **error); + +void g_spawn_close_pid (GPid pid); + +G_END_DECLS + +#endif /* __G_SPAWN_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gstrfuncs.h b/protocols/Sametime/src/glib/include/glib/gstrfuncs.h new file mode 100644 index 0000000000..5c7332a3c4 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gstrfuncs.h @@ -0,0 +1,269 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_STRFUNCS_H__ +#define __G_STRFUNCS_H__ + +#include <stdarg.h> +#include <glib/gmacros.h> +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/* Functions like the ones in <ctype.h> that are not affected by locale. */ +typedef enum { + G_ASCII_ALNUM = 1 << 0, + G_ASCII_ALPHA = 1 << 1, + G_ASCII_CNTRL = 1 << 2, + G_ASCII_DIGIT = 1 << 3, + G_ASCII_GRAPH = 1 << 4, + G_ASCII_LOWER = 1 << 5, + G_ASCII_PRINT = 1 << 6, + G_ASCII_PUNCT = 1 << 7, + G_ASCII_SPACE = 1 << 8, + G_ASCII_UPPER = 1 << 9, + G_ASCII_XDIGIT = 1 << 10 +} GAsciiType; + +GLIB_VAR const guint16 * const g_ascii_table; + +#define g_ascii_isalnum(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0) + +#define g_ascii_isalpha(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_ALPHA) != 0) + +#define g_ascii_iscntrl(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_CNTRL) != 0) + +#define g_ascii_isdigit(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0) + +#define g_ascii_isgraph(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_GRAPH) != 0) + +#define g_ascii_islower(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_LOWER) != 0) + +#define g_ascii_isprint(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_PRINT) != 0) + +#define g_ascii_ispunct(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_PUNCT) != 0) + +#define g_ascii_isspace(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0) + +#define g_ascii_isupper(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_UPPER) != 0) + +#define g_ascii_isxdigit(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_XDIGIT) != 0) + +gchar g_ascii_tolower (gchar c) G_GNUC_CONST; +gchar g_ascii_toupper (gchar c) G_GNUC_CONST; + +gint g_ascii_digit_value (gchar c) G_GNUC_CONST; +gint g_ascii_xdigit_value (gchar c) G_GNUC_CONST; + +/* String utility functions that modify a string argument or + * return a constant string that must not be freed. + */ +#define G_STR_DELIMITERS "_-|> <." +gchar* g_strdelimit (gchar *string, + const gchar *delimiters, + gchar new_delimiter); +gchar* g_strcanon (gchar *string, + const gchar *valid_chars, + gchar substitutor); +G_CONST_RETURN gchar* g_strerror (gint errnum) G_GNUC_CONST; +G_CONST_RETURN gchar* g_strsignal (gint signum) G_GNUC_CONST; +gchar* g_strreverse (gchar *string); +gsize g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size); +gsize g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size); +gchar * g_strstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle); +gchar * g_strrstr (const gchar *haystack, + const gchar *needle); +gchar * g_strrstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle); + +gboolean g_str_has_suffix (const gchar *str, + const gchar *suffix); +gboolean g_str_has_prefix (const gchar *str, + const gchar *prefix); + +/* String to/from double conversion functions */ + +gdouble g_strtod (const gchar *nptr, + gchar **endptr); +gdouble g_ascii_strtod (const gchar *nptr, + gchar **endptr); +guint64 g_ascii_strtoull (const gchar *nptr, + gchar **endptr, + guint base); +gint64 g_ascii_strtoll (const gchar *nptr, + gchar **endptr, + guint base); +/* 29 bytes should enough for all possible values that + * g_ascii_dtostr can produce. + * Then add 10 for good measure */ +#define G_ASCII_DTOSTR_BUF_SIZE (29 + 10) +gchar * g_ascii_dtostr (gchar *buffer, + gint buf_len, + gdouble d); +gchar * g_ascii_formatd (gchar *buffer, + gint buf_len, + const gchar *format, + gdouble d); + +/* removes leading spaces */ +gchar* g_strchug (gchar *string); +/* removes trailing spaces */ +gchar* g_strchomp (gchar *string); +/* removes leading & trailing spaces */ +#define g_strstrip( string ) g_strchomp (g_strchug (string)) + +gint g_ascii_strcasecmp (const gchar *s1, + const gchar *s2); +gint g_ascii_strncasecmp (const gchar *s1, + const gchar *s2, + gsize n); +gchar* g_ascii_strdown (const gchar *str, + gssize len) G_GNUC_MALLOC; +gchar* g_ascii_strup (const gchar *str, + gssize len) G_GNUC_MALLOC; + +#ifndef G_DISABLE_DEPRECATED + +/* The following four functions are deprecated and will be removed in + * the next major release. They use the locale-specific tolower and + * toupper, which is almost never the right thing. + */ + +gint g_strcasecmp (const gchar *s1, + const gchar *s2); +gint g_strncasecmp (const gchar *s1, + const gchar *s2, + guint n); +gchar* g_strdown (gchar *string); +gchar* g_strup (gchar *string); + +#endif /* G_DISABLE_DEPRECATED */ + +/* String utility functions that return a newly allocated string which + * ought to be freed with g_free from the caller at some point. + */ +gchar* g_strdup (const gchar *str) G_GNUC_MALLOC; +gchar* g_strdup_printf (const gchar *format, + ...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC; +gchar* g_strdup_vprintf (const gchar *format, + va_list args) G_GNUC_MALLOC; +gchar* g_strndup (const gchar *str, + gsize n) G_GNUC_MALLOC; +gchar* g_strnfill (gsize length, + gchar fill_char) G_GNUC_MALLOC; +gchar* g_strconcat (const gchar *string1, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +gchar* g_strjoin (const gchar *separator, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; + +/* Make a copy of a string interpreting C string -style escape + * sequences. Inverse of g_strescape. The recognized sequences are \b + * \f \n \r \t \\ \" and the octal format. + */ +gchar* g_strcompress (const gchar *source) G_GNUC_MALLOC; + +/* Copy a string escaping nonprintable characters like in C strings. + * Inverse of g_strcompress. The exceptions parameter, if non-NULL, points + * to a string containing characters that are not to be escaped. + * + * Deprecated API: gchar* g_strescape (const gchar *source); + * Luckily this function wasn't used much, using NULL as second parameter + * provides mostly identical semantics. + */ +gchar* g_strescape (const gchar *source, + const gchar *exceptions) G_GNUC_MALLOC; + +gpointer g_memdup (gconstpointer mem, + guint byte_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(2); + +/* NULL terminated string arrays. + * g_strsplit(), g_strsplit_set() split up string into max_tokens tokens + * at delim and return a newly allocated string array. + * g_strjoinv() concatenates all of str_array's strings, sliding in an + * optional separator, the returned string is newly allocated. + * g_strfreev() frees the array itself and all of its strings. + * g_strdupv() copies a NULL-terminated array of strings + * g_strv_length() returns the length of a NULL-terminated array of strings + */ +gchar** g_strsplit (const gchar *string, + const gchar *delimiter, + gint max_tokens) G_GNUC_MALLOC; +gchar ** g_strsplit_set (const gchar *string, + const gchar *delimiters, + gint max_tokens) G_GNUC_MALLOC; +gchar* g_strjoinv (const gchar *separator, + gchar **str_array) G_GNUC_MALLOC; +void g_strfreev (gchar **str_array); +gchar** g_strdupv (gchar **str_array) G_GNUC_MALLOC; +guint g_strv_length (gchar **str_array); + +gchar* g_stpcpy (gchar *dest, + const char *src); + +G_CONST_RETURN gchar *g_strip_context (const gchar *msgid, + const gchar *msgval) G_GNUC_FORMAT(1); + +G_CONST_RETURN gchar *g_dgettext (const gchar *domain, + const gchar *msgid) G_GNUC_FORMAT(2); +G_CONST_RETURN gchar *g_dcgettext (const gchar *domain, + const gchar *msgid, + int category) G_GNUC_FORMAT(2); +G_CONST_RETURN gchar *g_dngettext (const gchar *domain, + const gchar *msgid, + const gchar *msgid_plural, + gulong n) G_GNUC_FORMAT(3); +G_CONST_RETURN gchar *g_dpgettext (const gchar *domain, + const gchar *msgctxtid, + gsize msgidoffset) G_GNUC_FORMAT(2); +G_CONST_RETURN gchar *g_dpgettext2 (const gchar *domain, + const gchar *context, + const gchar *msgid) G_GNUC_FORMAT(3); + +G_END_DECLS + +#endif /* __G_STRFUNCS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gstring.h b/protocols/Sametime/src/glib/include/glib/gstring.h new file mode 100644 index 0000000000..2b1dd6ece2 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gstring.h @@ -0,0 +1,178 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_STRING_H__ +#define __G_STRING_H__ + +#include <glib/gtypes.h> +#include <glib/gunicode.h> +#include <glib/gutils.h> /* for G_CAN_INLINE */ + +G_BEGIN_DECLS + +typedef struct _GString GString; +typedef struct _GStringChunk GStringChunk; + +struct _GString +{ + gchar *str; + gsize len; + gsize allocated_len; +}; + +/* String Chunks + */ +GStringChunk* g_string_chunk_new (gsize size); +void g_string_chunk_free (GStringChunk *chunk); +void g_string_chunk_clear (GStringChunk *chunk); +gchar* g_string_chunk_insert (GStringChunk *chunk, + const gchar *string); +gchar* g_string_chunk_insert_len (GStringChunk *chunk, + const gchar *string, + gssize len); +gchar* g_string_chunk_insert_const (GStringChunk *chunk, + const gchar *string); + + +/* Strings + */ +GString* g_string_new (const gchar *init); +GString* g_string_new_len (const gchar *init, + gssize len); +GString* g_string_sized_new (gsize dfl_size); +gchar* g_string_free (GString *string, + gboolean free_segment); +gboolean g_string_equal (const GString *v, + const GString *v2); +guint g_string_hash (const GString *str); +GString* g_string_assign (GString *string, + const gchar *rval); +GString* g_string_truncate (GString *string, + gsize len); +GString* g_string_set_size (GString *string, + gsize len); +GString* g_string_insert_len (GString *string, + gssize pos, + const gchar *val, + gssize len); +GString* g_string_append (GString *string, + const gchar *val); +GString* g_string_append_len (GString *string, + const gchar *val, + gssize len); +GString* g_string_append_c (GString *string, + gchar c); +GString* g_string_append_unichar (GString *string, + gunichar wc); +GString* g_string_prepend (GString *string, + const gchar *val); +GString* g_string_prepend_c (GString *string, + gchar c); +GString* g_string_prepend_unichar (GString *string, + gunichar wc); +GString* g_string_prepend_len (GString *string, + const gchar *val, + gssize len); +GString* g_string_insert (GString *string, + gssize pos, + const gchar *val); +GString* g_string_insert_c (GString *string, + gssize pos, + gchar c); +GString* g_string_insert_unichar (GString *string, + gssize pos, + gunichar wc); +GString* g_string_overwrite (GString *string, + gsize pos, + const gchar *val); +GString* g_string_overwrite_len (GString *string, + gsize pos, + const gchar *val, + gssize len); +GString* g_string_erase (GString *string, + gssize pos, + gssize len); +GString* g_string_ascii_down (GString *string); +GString* g_string_ascii_up (GString *string); +void g_string_vprintf (GString *string, + const gchar *format, + va_list args); +void g_string_printf (GString *string, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); +void g_string_append_vprintf (GString *string, + const gchar *format, + va_list args); +void g_string_append_printf (GString *string, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); +GString * g_string_append_uri_escaped(GString *string, + const char *unescaped, + const char *reserved_chars_allowed, + gboolean allow_utf8); + +/* -- optimize g_strig_append_c --- */ +#ifdef G_CAN_INLINE +static inline GString* +g_string_append_c_inline (GString *gstring, + gchar c) +{ + if (gstring->len + 1 < gstring->allocated_len) + { + gstring->str[gstring->len++] = c; + gstring->str[gstring->len] = 0; + } + else + g_string_insert_c (gstring, -1, c); + return gstring; +} +#define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c) +#endif /* G_CAN_INLINE */ + + +#ifndef G_DISABLE_DEPRECATED + +/* The following two functions are deprecated and will be removed in + * the next major release. They use the locale-specific tolower and + * toupper, which is almost never the right thing. + */ + +GString* g_string_down (GString *string); +GString* g_string_up (GString *string); + +/* These aliases are included for compatibility. */ +#define g_string_sprintf g_string_printf +#define g_string_sprintfa g_string_append_printf + +#endif /* G_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __G_STRING_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gtestutils.h b/protocols/Sametime/src/glib/include/glib/gtestutils.h new file mode 100644 index 0000000000..b441fe08bc --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gtestutils.h @@ -0,0 +1,297 @@ +/* GLib testing utilities + * Copyright (C) 2007 Imendio AB + * Authors: Tim Janik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_TEST_UTILS_H__ +#define __G_TEST_UTILS_H__ + +#include <glib/gmessages.h> +#include <glib/gstring.h> +#include <glib/gerror.h> +#include <glib/gslist.h> + +G_BEGIN_DECLS + +typedef struct GTestCase GTestCase; +typedef struct GTestSuite GTestSuite; +typedef void (*GTestFunc) (void); +typedef void (*GTestDataFunc) (gconstpointer user_data); +typedef void (*GTestFixtureFunc) (gpointer fixture, + gconstpointer user_data); + +/* assertion API */ +#define g_assert_cmpstr(s1, cmp, s2) do { const char *__s1 = (s1), *__s2 = (s2); \ + if (g_strcmp0 (__s1, __s2) cmp 0) ; else \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #s1 " " #cmp " " #s2, __s1, #cmp, __s2); } while (0) +#define g_assert_cmpint(n1, cmp, n2) do { gint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0) +#define g_assert_cmpuint(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0) +#define g_assert_cmphex(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'x'); } while (0) +#define g_assert_cmpfloat(n1,cmp,n2) do { long double __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'f'); } while (0) +#define g_assert_no_error(err) do { if (err) \ + g_assertion_message_error (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #err, err, 0, 0); } while (0) +#define g_assert_error(err, dom, c) do { if (!err || (err)->domain != dom || (err)->code != c) \ + g_assertion_message_error (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #err, err, dom, c); } while (0) +#ifdef G_DISABLE_ASSERT +#define g_assert_not_reached() do { (void) 0; } while (0) +#define g_assert(expr) do { (void) 0; } while (0) +#else /* !G_DISABLE_ASSERT */ +#define g_assert_not_reached() do { g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, NULL); } while (0) +#define g_assert(expr) do { if G_LIKELY (expr) ; else \ + g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #expr); } while (0) +#endif /* !G_DISABLE_ASSERT */ + +int g_strcmp0 (const char *str1, + const char *str2); + +/* report performance results */ +void g_test_minimized_result (double minimized_quantity, + const char *format, + ...) G_GNUC_PRINTF (2, 3); +void g_test_maximized_result (double maximized_quantity, + const char *format, + ...) G_GNUC_PRINTF (2, 3); + +/* initialize testing framework */ +void g_test_init (int *argc, + char ***argv, + ...); +/* query testing framework config */ +#define g_test_quick() (g_test_config_vars->test_quick) +#define g_test_slow() (!g_test_config_vars->test_quick) +#define g_test_thorough() (!g_test_config_vars->test_quick) +#define g_test_perf() (g_test_config_vars->test_perf) +#define g_test_verbose() (g_test_config_vars->test_verbose) +#define g_test_quiet() (g_test_config_vars->test_quiet) +/* run all tests under toplevel suite (path: /) */ +int g_test_run (void); +/* hook up a test functions under test path */ +void g_test_add_func (const char *testpath, + GTestFunc test_func); + +void g_test_add_data_func (const char *testpath, + gconstpointer test_data, + GTestDataFunc test_func); + +/* hook up a test with fixture under test path */ +#define g_test_add(testpath, Fixture, tdata, fsetup, ftest, fteardown) \ + G_STMT_START { \ + void (*add_vtable) (const char*, \ + gsize, \ + gconstpointer, \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer)) = (void (*) (const gchar *, gsize, gconstpointer, void (*) (Fixture*, gconstpointer), void (*) (Fixture*, gconstpointer), void (*) (Fixture*, gconstpointer))) g_test_add_vtable; \ + add_vtable \ + (testpath, sizeof (Fixture), tdata, fsetup, ftest, fteardown); \ + } G_STMT_END + +/* add test messages to the test report */ +void g_test_message (const char *format, + ...) G_GNUC_PRINTF (1, 2); +void g_test_bug_base (const char *uri_pattern); +void g_test_bug (const char *bug_uri_snippet); +/* measure test timings */ +void g_test_timer_start (void); +double g_test_timer_elapsed (void); /* elapsed seconds */ +double g_test_timer_last (void); /* repeat last elapsed() result */ + +/* automatically g_free or g_object_unref upon teardown */ +void g_test_queue_free (gpointer gfree_pointer); +void g_test_queue_destroy (GDestroyNotify destroy_func, + gpointer destroy_data); +#define g_test_queue_unref(gobject) g_test_queue_destroy (g_object_unref, gobject) + +/* test traps are guards used around forked tests */ +typedef enum { + G_TEST_TRAP_SILENCE_STDOUT = 1 << 7, + G_TEST_TRAP_SILENCE_STDERR = 1 << 8, + G_TEST_TRAP_INHERIT_STDIN = 1 << 9 +} GTestTrapFlags; +gboolean g_test_trap_fork (guint64 usec_timeout, + GTestTrapFlags test_trap_flags); +gboolean g_test_trap_has_passed (void); +gboolean g_test_trap_reached_timeout (void); +#define g_test_trap_assert_passed() g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 0, 0) +#define g_test_trap_assert_failed() g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 1, 0) +#define g_test_trap_assert_stdout(soutpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 2, soutpattern) +#define g_test_trap_assert_stdout_unmatched(soutpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 3, soutpattern) +#define g_test_trap_assert_stderr(serrpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 4, serrpattern) +#define g_test_trap_assert_stderr_unmatched(serrpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 5, serrpattern) + +/* provide seed-able random numbers for tests */ +#define g_test_rand_bit() (0 != (g_test_rand_int() & (1 << 15))) +gint32 g_test_rand_int (void); +gint32 g_test_rand_int_range (gint32 begin, + gint32 end); +double g_test_rand_double (void); +double g_test_rand_double_range (double range_start, + double range_end); + +/* semi-internal API */ +GTestCase* g_test_create_case (const char *test_name, + gsize data_size, + gconstpointer test_data, + GTestFixtureFunc data_setup, + GTestFixtureFunc data_test, + GTestFixtureFunc data_teardown); +GTestSuite* g_test_create_suite (const char *suite_name); +GTestSuite* g_test_get_root (void); +void g_test_suite_add (GTestSuite *suite, + GTestCase *test_case); +void g_test_suite_add_suite (GTestSuite *suite, + GTestSuite *nestedsuite); +int g_test_run_suite (GTestSuite *suite); + +/* internal ABI */ +void g_test_trap_assertions (const char *domain, + const char *file, + int line, + const char *func, + guint64 assertion_flags, /* 0-pass, 1-fail, 2-outpattern, 4-errpattern */ + const char *pattern); +void g_assertion_message (const char *domain, + const char *file, + int line, + const char *func, + const char *message) G_GNUC_NORETURN; +void g_assertion_message_expr (const char *domain, + const char *file, + int line, + const char *func, + const char *expr) G_GNUC_NORETURN; +void g_assertion_message_cmpstr (const char *domain, + const char *file, + int line, + const char *func, + const char *expr, + const char *arg1, + const char *cmp, + const char *arg2) G_GNUC_NORETURN; +void g_assertion_message_cmpnum (const char *domain, + const char *file, + int line, + const char *func, + const char *expr, + long double arg1, + const char *cmp, + long double arg2, + char numtype) G_GNUC_NORETURN; +void g_assertion_message_error (const char *domain, + const char *file, + int line, + const char *func, + const char *expr, + const GError *error, + GQuark error_domain, + int error_code) G_GNUC_NORETURN; +void g_test_add_vtable (const char *testpath, + gsize data_size, + gconstpointer test_data, + GTestFixtureFunc data_setup, + GTestFixtureFunc data_test, + GTestFixtureFunc data_teardown); +typedef struct { + gboolean test_initialized; + gboolean test_quick; /* disable thorough tests */ + gboolean test_perf; /* run performance tests */ + gboolean test_verbose; /* extra info */ + gboolean test_quiet; /* reduce output */ +} GTestConfig; +GLIB_VAR const GTestConfig * const g_test_config_vars; + +/* internal logging API */ +typedef enum { + G_TEST_LOG_NONE, + G_TEST_LOG_ERROR, /* s:msg */ + G_TEST_LOG_START_BINARY, /* s:binaryname s:seed */ + G_TEST_LOG_LIST_CASE, /* s:testpath */ + G_TEST_LOG_SKIP_CASE, /* s:testpath */ + G_TEST_LOG_START_CASE, /* s:testpath */ + G_TEST_LOG_STOP_CASE, /* d:status d:nforks d:elapsed */ + G_TEST_LOG_MIN_RESULT, /* s:blurb d:result */ + G_TEST_LOG_MAX_RESULT, /* s:blurb d:result */ + G_TEST_LOG_MESSAGE /* s:blurb */ +} GTestLogType; + +typedef struct { + GTestLogType log_type; + guint n_strings; + gchar **strings; /* NULL terminated */ + guint n_nums; + long double *nums; +} GTestLogMsg; +typedef struct { + /*< private >*/ + GString *data; + GSList *msgs; +} GTestLogBuffer; + +const char* g_test_log_type_name (GTestLogType log_type); +GTestLogBuffer* g_test_log_buffer_new (void); +void g_test_log_buffer_free (GTestLogBuffer *tbuffer); +void g_test_log_buffer_push (GTestLogBuffer *tbuffer, + guint n_bytes, + const guint8 *bytes); +GTestLogMsg* g_test_log_buffer_pop (GTestLogBuffer *tbuffer); +void g_test_log_msg_free (GTestLogMsg *tmsg); + +/** + * GTestLogFatalFunc: + * @log_domain: the log domain of the message + * @log_level: the log level of the message (including the fatal and recursion flags) + * @message: the message to process + * @user_data: user data, set in g_test_log_set_fatal_handler() + * + * Specifies the prototype of fatal log handler functions. + * + * Return value: %TRUE if the program should abort, %FALSE otherwise + * + * Since: 2.22 + */ +typedef gboolean (*GTestLogFatalFunc) (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); +void +g_test_log_set_fatal_handler (GTestLogFatalFunc log_func, + gpointer user_data); + +G_END_DECLS + +#endif /* __G_TEST_UTILS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gthread.h b/protocols/Sametime/src/glib/include/glib/gthread.h new file mode 100644 index 0000000000..82d40c0b85 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gthread.h @@ -0,0 +1,407 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_THREAD_H__ +#define __G_THREAD_H__ + +#include <glib/gerror.h> +#include <glib/gutils.h> /* for G_INLINE_FUNC */ +#include <glib/gatomic.h> /* for g_atomic_pointer_get */ + +G_BEGIN_DECLS + +/* GLib Thread support + */ + +extern GQuark g_thread_error_quark (void); +#define G_THREAD_ERROR g_thread_error_quark () + +typedef enum +{ + G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */ +} GThreadError; + +typedef gpointer (*GThreadFunc) (gpointer data); + +typedef enum +{ + G_THREAD_PRIORITY_LOW, + G_THREAD_PRIORITY_NORMAL, + G_THREAD_PRIORITY_HIGH, + G_THREAD_PRIORITY_URGENT +} GThreadPriority; + +typedef struct _GThread GThread; +struct _GThread +{ + /*< private >*/ + GThreadFunc func; + gpointer data; + gboolean joinable; + GThreadPriority priority; +}; + +typedef struct _GMutex GMutex; +typedef struct _GCond GCond; +typedef struct _GPrivate GPrivate; +typedef struct _GStaticPrivate GStaticPrivate; + +typedef struct _GThreadFunctions GThreadFunctions; +struct _GThreadFunctions +{ + GMutex* (*mutex_new) (void); + void (*mutex_lock) (GMutex *mutex); + gboolean (*mutex_trylock) (GMutex *mutex); + void (*mutex_unlock) (GMutex *mutex); + void (*mutex_free) (GMutex *mutex); + GCond* (*cond_new) (void); + void (*cond_signal) (GCond *cond); + void (*cond_broadcast) (GCond *cond); + void (*cond_wait) (GCond *cond, + GMutex *mutex); + gboolean (*cond_timed_wait) (GCond *cond, + GMutex *mutex, + GTimeVal *end_time); + void (*cond_free) (GCond *cond); + GPrivate* (*private_new) (GDestroyNotify destructor); + gpointer (*private_get) (GPrivate *private_key); + void (*private_set) (GPrivate *private_key, + gpointer data); + void (*thread_create) (GThreadFunc func, + gpointer data, + gulong stack_size, + gboolean joinable, + gboolean bound, + GThreadPriority priority, + gpointer thread, + GError **error); + void (*thread_yield) (void); + void (*thread_join) (gpointer thread); + void (*thread_exit) (void); + void (*thread_set_priority)(gpointer thread, + GThreadPriority priority); + void (*thread_self) (gpointer thread); + gboolean (*thread_equal) (gpointer thread1, + gpointer thread2); +}; + +GLIB_VAR GThreadFunctions g_thread_functions_for_glib_use; +GLIB_VAR gboolean g_thread_use_default_impl; +GLIB_VAR gboolean g_threads_got_initialized; + +GLIB_VAR guint64 (*g_thread_gettime) (void); + +/* initializes the mutex/cond/private implementation for glib, might + * only be called once, and must not be called directly or indirectly + * from another glib-function, e.g. as a callback. + */ +void g_thread_init (GThreadFunctions *vtable); + +/* Errorcheck mutexes. If you define G_ERRORCHECK_MUTEXES, then all + * mutexes will check for re-locking and re-unlocking */ + +/* Initialize thread system with errorcheck mutexes. vtable must be + * NULL. Do not call directly. Use #define G_ERRORCHECK_MUTEXES + * instead. + */ +void g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable); + +/* Checks if thread support is initialized. Identical to the + * g_thread_supported macro but provided for language bindings. + */ +gboolean g_thread_get_initialized (void); + +/* A random number to recognize debug calls to g_mutex_... */ +#define G_MUTEX_DEBUG_MAGIC 0xf8e18ad7 + +#ifdef G_ERRORCHECK_MUTEXES +#define g_thread_init(vtable) g_thread_init_with_errorcheck_mutexes (vtable) +#endif + +/* internal function for fallback static mutex implementation */ +GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex); + +#define g_static_mutex_get_mutex_impl_shortcut(mutex) \ + (g_atomic_pointer_get (mutex) ? *(mutex) : \ + g_static_mutex_get_mutex_impl (mutex)) + +/* shorthands for conditional and unconditional function calls */ + +#define G_THREAD_UF(op, arglist) \ + (*g_thread_functions_for_glib_use . op) arglist +#define G_THREAD_CF(op, fail, arg) \ + (g_thread_supported () ? G_THREAD_UF (op, arg) : (fail)) +#define G_THREAD_ECF(op, fail, mutex, type) \ + (g_thread_supported () ? \ + ((type(*)(GMutex*, const gulong, gchar const*)) \ + (*g_thread_functions_for_glib_use . op)) \ + (mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (fail)) + +#ifndef G_ERRORCHECK_MUTEXES +# define g_mutex_lock(mutex) \ + G_THREAD_CF (mutex_lock, (void)0, (mutex)) +# define g_mutex_trylock(mutex) \ + G_THREAD_CF (mutex_trylock, TRUE, (mutex)) +# define g_mutex_unlock(mutex) \ + G_THREAD_CF (mutex_unlock, (void)0, (mutex)) +# define g_mutex_free(mutex) \ + G_THREAD_CF (mutex_free, (void)0, (mutex)) +# define g_cond_wait(cond, mutex) \ + G_THREAD_CF (cond_wait, (void)0, (cond, mutex)) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + G_THREAD_CF (cond_timed_wait, TRUE, (cond, mutex, abs_time)) +#else /* G_ERRORCHECK_MUTEXES */ +# define g_mutex_lock(mutex) \ + G_THREAD_ECF (mutex_lock, (void)0, (mutex), void) +# define g_mutex_trylock(mutex) \ + G_THREAD_ECF (mutex_trylock, TRUE, (mutex), gboolean) +# define g_mutex_unlock(mutex) \ + G_THREAD_ECF (mutex_unlock, (void)0, (mutex), void) +# define g_mutex_free(mutex) \ + G_THREAD_ECF (mutex_free, (void)0, (mutex), void) +# define g_cond_wait(cond, mutex) \ + (g_thread_supported () ? ((void(*)(GCond*, GMutex*, gulong, gchar*))\ + g_thread_functions_for_glib_use.cond_wait) \ + (cond, mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (void) 0) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + (g_thread_supported () ? \ + ((gboolean(*)(GCond*, GMutex*, GTimeVal*, gulong, gchar*)) \ + g_thread_functions_for_glib_use.cond_timed_wait) \ + (cond, mutex, abs_time, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : TRUE) +#endif /* G_ERRORCHECK_MUTEXES */ + +#if defined(G_THREADS_ENABLED) && defined(G_THREADS_MANDATORY) +#define g_thread_supported() 1 +#else +#define g_thread_supported() (g_threads_got_initialized) +#endif +#define g_mutex_new() G_THREAD_UF (mutex_new, ()) +#define g_cond_new() G_THREAD_UF (cond_new, ()) +#define g_cond_signal(cond) G_THREAD_CF (cond_signal, (void)0, (cond)) +#define g_cond_broadcast(cond) G_THREAD_CF (cond_broadcast, (void)0, (cond)) +#define g_cond_free(cond) G_THREAD_CF (cond_free, (void)0, (cond)) +#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor)) +#define g_private_get(private_key) G_THREAD_CF (private_get, \ + ((gpointer)private_key), \ + (private_key)) +#define g_private_set(private_key, value) G_THREAD_CF (private_set, \ + (void) (private_key = \ + (GPrivate*) (value)), \ + (private_key, value)) +#define g_thread_yield() G_THREAD_CF (thread_yield, (void)0, ()) + +#define g_thread_create(func, data, joinable, error) \ + (g_thread_create_full (func, data, 0, joinable, FALSE, \ + G_THREAD_PRIORITY_NORMAL, error)) + +GThread* g_thread_create_full (GThreadFunc func, + gpointer data, + gulong stack_size, + gboolean joinable, + gboolean bound, + GThreadPriority priority, + GError **error); +GThread* g_thread_self (void); +void g_thread_exit (gpointer retval); +gpointer g_thread_join (GThread *thread); + +void g_thread_set_priority (GThread *thread, + GThreadPriority priority); + +/* GStaticMutexes can be statically initialized with the value + * G_STATIC_MUTEX_INIT, and then they can directly be used, that is + * much easier, than having to explicitly allocate the mutex before + * use + */ +#define g_static_mutex_lock(mutex) \ + g_mutex_lock (g_static_mutex_get_mutex (mutex)) +#define g_static_mutex_trylock(mutex) \ + g_mutex_trylock (g_static_mutex_get_mutex (mutex)) +#define g_static_mutex_unlock(mutex) \ + g_mutex_unlock (g_static_mutex_get_mutex (mutex)) +void g_static_mutex_init (GStaticMutex *mutex); +void g_static_mutex_free (GStaticMutex *mutex); + +struct _GStaticPrivate +{ + /*< private >*/ + guint index; +}; +#define G_STATIC_PRIVATE_INIT { 0 } +void g_static_private_init (GStaticPrivate *private_key); +gpointer g_static_private_get (GStaticPrivate *private_key); +void g_static_private_set (GStaticPrivate *private_key, + gpointer data, + GDestroyNotify notify); +void g_static_private_free (GStaticPrivate *private_key); + +typedef struct _GStaticRecMutex GStaticRecMutex; +struct _GStaticRecMutex +{ + /*< private >*/ + GStaticMutex mutex; + guint depth; + GSystemThread owner; +}; + +#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT } +void g_static_rec_mutex_init (GStaticRecMutex *mutex); +void g_static_rec_mutex_lock (GStaticRecMutex *mutex); +gboolean g_static_rec_mutex_trylock (GStaticRecMutex *mutex); +void g_static_rec_mutex_unlock (GStaticRecMutex *mutex); +void g_static_rec_mutex_lock_full (GStaticRecMutex *mutex, + guint depth); +guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex); +void g_static_rec_mutex_free (GStaticRecMutex *mutex); + +typedef struct _GStaticRWLock GStaticRWLock; +struct _GStaticRWLock +{ + /*< private >*/ + GStaticMutex mutex; + GCond *read_cond; + GCond *write_cond; + guint read_counter; + gboolean have_writer; + guint want_to_read; + guint want_to_write; +}; + +#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 } + +void g_static_rw_lock_init (GStaticRWLock* lock); +void g_static_rw_lock_reader_lock (GStaticRWLock* lock); +gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock); +void g_static_rw_lock_reader_unlock (GStaticRWLock* lock); +void g_static_rw_lock_writer_lock (GStaticRWLock* lock); +gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock); +void g_static_rw_lock_writer_unlock (GStaticRWLock* lock); +void g_static_rw_lock_free (GStaticRWLock* lock); + +void g_thread_foreach (GFunc thread_func, + gpointer user_data); + +typedef enum +{ + G_ONCE_STATUS_NOTCALLED, + G_ONCE_STATUS_PROGRESS, + G_ONCE_STATUS_READY +} GOnceStatus; + +typedef struct _GOnce GOnce; +struct _GOnce +{ + volatile GOnceStatus status; + volatile gpointer retval; +}; + +#define G_ONCE_INIT { G_ONCE_STATUS_NOTCALLED, NULL } + +gpointer g_once_impl (GOnce *once, GThreadFunc func, gpointer arg); + +#ifdef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED +# define g_once(once, func, arg) g_once_impl ((once), (func), (arg)) +#else /* !G_ATOMIC_OP_MEMORY_BARRIER_NEEDED*/ +# define g_once(once, func, arg) \ + (((once)->status == G_ONCE_STATUS_READY) ? \ + (once)->retval : \ + g_once_impl ((once), (func), (arg))) +#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ + +/* initialize-once guards, keyed by value_location */ +G_INLINE_FUNC gboolean g_once_init_enter (volatile gsize *value_location); +gboolean g_once_init_enter_impl (volatile gsize *value_location); +void g_once_init_leave (volatile gsize *value_location, + gsize initialization_value); +#if defined (G_CAN_INLINE) || defined (__G_THREAD_C__) +G_INLINE_FUNC gboolean +g_once_init_enter (volatile gsize *value_location) +{ + if G_LIKELY ((gpointer) g_atomic_pointer_get (value_location) != NULL) + return FALSE; + else + return g_once_init_enter_impl (value_location); +} +#endif /* G_CAN_INLINE || __G_THREAD_C__ */ + +/* these are some convenience macros that expand to nothing if GLib + * was configured with --disable-threads. for using StaticMutexes, + * you define them with G_LOCK_DEFINE_STATIC (name) or G_LOCK_DEFINE (name) + * if you need to export the mutex. With G_LOCK_EXTERN (name) you can + * declare such an globally defined lock. name is a unique identifier + * for the protected varibale or code portion. locking, testing and + * unlocking of such mutexes can be done with G_LOCK(), G_UNLOCK() and + * G_TRYLOCK() respectively. + */ +extern void glib_dummy_decl (void); +#define G_LOCK_NAME(name) g__ ## name ## _lock +#ifdef G_THREADS_ENABLED +# define G_LOCK_DEFINE_STATIC(name) static G_LOCK_DEFINE (name) +# define G_LOCK_DEFINE(name) \ + GStaticMutex G_LOCK_NAME (name) = G_STATIC_MUTEX_INIT +# define G_LOCK_EXTERN(name) extern GStaticMutex G_LOCK_NAME (name) + +# ifdef G_DEBUG_LOCKS +# define G_LOCK(name) G_STMT_START{ \ + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \ + "file %s: line %d (%s): locking: %s ", \ + __FILE__, __LINE__, G_STRFUNC, \ + #name); \ + g_static_mutex_lock (&G_LOCK_NAME (name)); \ + }G_STMT_END +# define G_UNLOCK(name) G_STMT_START{ \ + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \ + "file %s: line %d (%s): unlocking: %s ", \ + __FILE__, __LINE__, G_STRFUNC, \ + #name); \ + g_static_mutex_unlock (&G_LOCK_NAME (name)); \ + }G_STMT_END +# define G_TRYLOCK(name) \ + (g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \ + "file %s: line %d (%s): try locking: %s ", \ + __FILE__, __LINE__, G_STRFUNC, \ + #name), g_static_mutex_trylock (&G_LOCK_NAME (name))) +# else /* !G_DEBUG_LOCKS */ +# define G_LOCK(name) g_static_mutex_lock (&G_LOCK_NAME (name)) +# define G_UNLOCK(name) g_static_mutex_unlock (&G_LOCK_NAME (name)) +# define G_TRYLOCK(name) g_static_mutex_trylock (&G_LOCK_NAME (name)) +# endif /* !G_DEBUG_LOCKS */ +#else /* !G_THREADS_ENABLED */ +# define G_LOCK_DEFINE_STATIC(name) extern void glib_dummy_decl (void) +# define G_LOCK_DEFINE(name) extern void glib_dummy_decl (void) +# define G_LOCK_EXTERN(name) extern void glib_dummy_decl (void) +# define G_LOCK(name) +# define G_UNLOCK(name) +# define G_TRYLOCK(name) (TRUE) +#endif /* !G_THREADS_ENABLED */ + +G_END_DECLS + +#endif /* __G_THREAD_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gthreadpool.h b/protocols/Sametime/src/glib/include/glib/gthreadpool.h new file mode 100644 index 0000000000..d5864241e6 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gthreadpool.h @@ -0,0 +1,114 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_THREADPOOL_H__ +#define __G_THREADPOOL_H__ + +#include <glib/gthread.h> + +G_BEGIN_DECLS + +typedef struct _GThreadPool GThreadPool; + +/* Thread Pools + */ + +/* The real GThreadPool is bigger, so you may only create a thread + * pool with the constructor function */ +struct _GThreadPool +{ + GFunc func; + gpointer user_data; + gboolean exclusive; +}; + +/* Get a thread pool with the function func, at most max_threads may + * run at a time (max_threads == -1 means no limit), exclusive == TRUE + * means, that the threads shouldn't be shared and that they will be + * prestarted (otherwise they are started as needed) user_data is the + * 2nd argument to the func */ +GThreadPool* g_thread_pool_new (GFunc func, + gpointer user_data, + gint max_threads, + gboolean exclusive, + GError **error); + +/* Push new data into the thread pool. This task is assigned to a thread later + * (when the maximal number of threads is reached for that pool) or now + * (otherwise). If necessary a new thread will be started. The function + * returns immediatly */ +void g_thread_pool_push (GThreadPool *pool, + gpointer data, + GError **error); + +/* Set the number of threads, which can run concurrently for that pool, -1 + * means no limit. 0 means has the effect, that the pool won't process + * requests until the limit is set higher again */ +void g_thread_pool_set_max_threads (GThreadPool *pool, + gint max_threads, + GError **error); +gint g_thread_pool_get_max_threads (GThreadPool *pool); + +/* Get the number of threads assigned to that pool. This number doesn't + * necessarily represent the number of working threads in that pool */ +guint g_thread_pool_get_num_threads (GThreadPool *pool); + +/* Get the number of unprocessed items in the pool */ +guint g_thread_pool_unprocessed (GThreadPool *pool); + +/* Free the pool, immediate means, that all unprocessed items in the queue + * wont be processed, wait means, that the function doesn't return immediatly, + * but after all threads in the pool are ready processing items. immediate + * does however not mean, that threads are killed. */ +void g_thread_pool_free (GThreadPool *pool, + gboolean immediate, + gboolean wait_); + +/* Set the maximal number of unused threads before threads will be stopped by + * GLib, -1 means no limit */ +void g_thread_pool_set_max_unused_threads (gint max_threads); +gint g_thread_pool_get_max_unused_threads (void); +guint g_thread_pool_get_num_unused_threads (void); + +/* Stop all currently unused threads, but leave the limit untouched */ +void g_thread_pool_stop_unused_threads (void); + +/* Set sort function for priority threading */ +void g_thread_pool_set_sort_function (GThreadPool *pool, + GCompareDataFunc func, + gpointer user_data); + +/* Set maximum time a thread can be idle in the pool before it is stopped */ +void g_thread_pool_set_max_idle_time (guint interval); +guint g_thread_pool_get_max_idle_time (void); + +G_END_DECLS + +#endif /* __G_THREADPOOL_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gtimer.h b/protocols/Sametime/src/glib/include/glib/gtimer.h new file mode 100644 index 0000000000..743eed1f90 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gtimer.h @@ -0,0 +1,65 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_TIMER_H__ +#define __G_TIMER_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/* Timer + */ + +/* microseconds per second */ +typedef struct _GTimer GTimer; + +#define G_USEC_PER_SEC 1000000 + +GTimer* g_timer_new (void); +void g_timer_destroy (GTimer *timer); +void g_timer_start (GTimer *timer); +void g_timer_stop (GTimer *timer); +void g_timer_reset (GTimer *timer); +void g_timer_continue (GTimer *timer); +gdouble g_timer_elapsed (GTimer *timer, + gulong *microseconds); + +void g_usleep (gulong microseconds); + +void g_time_val_add (GTimeVal *time_, + glong microseconds); +gboolean g_time_val_from_iso8601 (const gchar *iso_date, + GTimeVal *time_); +gchar* g_time_val_to_iso8601 (GTimeVal *time_) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __G_TIMER_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gtimezone.h b/protocols/Sametime/src/glib/include/glib/gtimezone.h new file mode 100644 index 0000000000..1032a3c09c --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gtimezone.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2010 Codethink Limited + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_TIME_ZONE_H__ +#define __G_TIME_ZONE_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef struct _GTimeZone GTimeZone; + +GTimeZone * g_time_zone_new (const gchar *identifier); +GTimeZone * g_time_zone_new_utc (void); +GTimeZone * g_time_zone_new_local (void); + +GTimeZone * g_time_zone_ref (GTimeZone *tz); +void g_time_zone_unref (GTimeZone *tz); + +G_END_DECLS + +#endif /* __G_TIME_ZONE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gtree.h b/protocols/Sametime/src/glib/include/glib/gtree.h new file mode 100644 index 0000000000..db06ba3b82 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gtree.h @@ -0,0 +1,91 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_TREE_H__ +#define __G_TREE_H__ + +#include <glib/gnode.h> + +G_BEGIN_DECLS + +typedef struct _GTree GTree; + +typedef gboolean (*GTraverseFunc) (gpointer key, + gpointer value, + gpointer data); + +/* Balanced binary trees + */ +GTree* g_tree_new (GCompareFunc key_compare_func); +GTree* g_tree_new_with_data (GCompareDataFunc key_compare_func, + gpointer key_compare_data); +GTree* g_tree_new_full (GCompareDataFunc key_compare_func, + gpointer key_compare_data, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func); +GTree* g_tree_ref (GTree *tree); +void g_tree_unref (GTree *tree); +void g_tree_destroy (GTree *tree); +void g_tree_insert (GTree *tree, + gpointer key, + gpointer value); +void g_tree_replace (GTree *tree, + gpointer key, + gpointer value); +gboolean g_tree_remove (GTree *tree, + gconstpointer key); +gboolean g_tree_steal (GTree *tree, + gconstpointer key); +gpointer g_tree_lookup (GTree *tree, + gconstpointer key); +gboolean g_tree_lookup_extended (GTree *tree, + gconstpointer lookup_key, + gpointer *orig_key, + gpointer *value); +void g_tree_foreach (GTree *tree, + GTraverseFunc func, + gpointer user_data); + +#ifndef G_DISABLE_DEPRECATED +void g_tree_traverse (GTree *tree, + GTraverseFunc traverse_func, + GTraverseType traverse_type, + gpointer user_data); +#endif /* G_DISABLE_DEPRECATED */ + +gpointer g_tree_search (GTree *tree, + GCompareFunc search_func, + gconstpointer user_data); +gint g_tree_height (GTree *tree); +gint g_tree_nnodes (GTree *tree); + +G_END_DECLS + +#endif /* __G_TREE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gtypes.h b/protocols/Sametime/src/glib/include/glib/gtypes.h new file mode 100644 index 0000000000..e616f9988c --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gtypes.h @@ -0,0 +1,451 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_TYPES_H__ +#define __G_TYPES_H__ + +#include <glibconfig.h> +#include <glib/gmacros.h> + +G_BEGIN_DECLS + +/* Provide type definitions for commonly used types. + * These are useful because a "gint8" can be adjusted + * to be 1 byte (8 bits) on all platforms. Similarly and + * more importantly, "gint32" can be adjusted to be + * 4 bytes (32 bits) on all platforms. + */ + +typedef char gchar; +typedef short gshort; +typedef long glong; +typedef int gint; +typedef gint gboolean; + +typedef unsigned char guchar; +typedef unsigned short gushort; +typedef unsigned long gulong; +typedef unsigned int guint; + +typedef float gfloat; +typedef double gdouble; + +/* Define min and max constants for the fixed size numerical types */ +#define G_MININT8 ((gint8) 0x80) +#define G_MAXINT8 ((gint8) 0x7f) +#define G_MAXUINT8 ((guint8) 0xff) + +#define G_MININT16 ((gint16) 0x8000) +#define G_MAXINT16 ((gint16) 0x7fff) +#define G_MAXUINT16 ((guint16) 0xffff) + +#define G_MININT32 ((gint32) 0x80000000) +#define G_MAXINT32 ((gint32) 0x7fffffff) +#define G_MAXUINT32 ((guint32) 0xffffffff) + +#define G_MININT64 ((gint64) G_GINT64_CONSTANT(0x8000000000000000)) +#define G_MAXINT64 G_GINT64_CONSTANT(0x7fffffffffffffff) +#define G_MAXUINT64 G_GINT64_CONSTANT(0xffffffffffffffffU) + +typedef void* gpointer; +typedef const void *gconstpointer; + +typedef gint (*GCompareFunc) (gconstpointer a, + gconstpointer b); +typedef gint (*GCompareDataFunc) (gconstpointer a, + gconstpointer b, + gpointer user_data); +typedef gboolean (*GEqualFunc) (gconstpointer a, + gconstpointer b); +typedef void (*GDestroyNotify) (gpointer data); +typedef void (*GFunc) (gpointer data, + gpointer user_data); +typedef guint (*GHashFunc) (gconstpointer key); +typedef void (*GHFunc) (gpointer key, + gpointer value, + gpointer user_data); +typedef void (*GFreeFunc) (gpointer data); + +/** + * GTranslateFunc: + * @str: the untranslated string + * @data: user data specified when installing the function, e.g. + * in g_option_group_set_translate_func() + * + * The type of functions which are used to translate user-visible + * strings, for <option>--help</option> output. + * + * Returns: a translation of the string for the current locale. + * The returned string is owned by GLib and must not be freed. + */ +typedef const gchar * (*GTranslateFunc) (const gchar *str, + gpointer data); + + +/* Define some mathematical constants that aren't available + * symbolically in some strict ISO C implementations. + * + * Note that the large number of digits used in these definitions + * doesn't imply that GLib or current computers in general would be + * able to handle floating point numbers with an accuracy like this. + * It's mostly an exercise in futility and future proofing. For + * extended precision floating point support, look somewhere else + * than GLib. + */ +#define G_E 2.7182818284590452353602874713526624977572470937000 +#define G_LN2 0.69314718055994530941723212145817656807550013436026 +#define G_LN10 2.3025850929940456840179914546843642076011014886288 +#define G_PI 3.1415926535897932384626433832795028841971693993751 +#define G_PI_2 1.5707963267948966192313216916397514420985846996876 +#define G_PI_4 0.78539816339744830961566084581987572104929234984378 +#define G_SQRT2 1.4142135623730950488016887242096980785696718753769 + +/* Portable endian checks and conversions + * + * glibconfig.h defines G_BYTE_ORDER which expands to one of + * the below macros. + */ +#define G_LITTLE_ENDIAN 1234 +#define G_BIG_ENDIAN 4321 +#define G_PDP_ENDIAN 3412 /* unused, need specific PDP check */ + + +/* Basic bit swapping functions + */ +#define GUINT16_SWAP_LE_BE_CONSTANT(val) ((guint16) ( \ + (guint16) ((guint16) (val) >> 8) | \ + (guint16) ((guint16) (val) << 8))) + +#define GUINT32_SWAP_LE_BE_CONSTANT(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \ + (((guint32) (val) & (guint32) 0x0000ff00U) << 8) | \ + (((guint32) (val) & (guint32) 0x00ff0000U) >> 8) | \ + (((guint32) (val) & (guint32) 0xff000000U) >> 24))) + +#define GUINT64_SWAP_LE_BE_CONSTANT(val) ((guint64) ( \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00000000000000ffU)) << 56) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x000000000000ff00U)) << 40) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x0000000000ff0000U)) << 24) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00000000ff000000U)) << 8) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x000000ff00000000U)) >> 8) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x0000ff0000000000U)) >> 24) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00ff000000000000U)) >> 40) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0xff00000000000000U)) >> 56))) + +/* Arch specific stuff for speed + */ +#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) +# if defined (__i386__) +# define GUINT16_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint16 __v, __x = ((guint16) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT16_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# if !defined (__i486__) && !defined (__i586__) \ + && !defined (__pentium__) && !defined (__i686__) \ + && !defined (__pentiumpro__) && !defined (__pentium4__) +# define GUINT32_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("rorw $8, %w0\n\t" \ + "rorl $16, %0\n\t" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else /* 486 and higher has bswap */ +# define GUINT32_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswap %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# endif /* processor specific 32-bit stuff */ +# define GUINT64_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ union { guint64 __ll; \ + guint32 __l[2]; } __w, __r; \ + __w.__ll = ((guint64) (val)); \ + if (__builtin_constant_p (__w.__ll)) \ + __r.__ll = GUINT64_SWAP_LE_BE_CONSTANT (__w.__ll); \ + else \ + { \ + __r.__l[0] = GUINT32_SWAP_LE_BE (__w.__l[1]); \ + __r.__l[1] = GUINT32_SWAP_LE_BE (__w.__l[0]); \ + } \ + __r.__ll; })) + /* Possibly just use the constant version and let gcc figure it out? */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA32 (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA32 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA32 (val)) +# elif defined (__ia64__) +# define GUINT16_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint16 __v, __x = ((guint16) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT16_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 48 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT32_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 32 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT64_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint64 __v, __x = ((guint64) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT64_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("mux1 %0 = %1, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA64 (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA64 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA64 (val)) +# elif defined (__x86_64__) +# define GUINT32_SWAP_LE_BE_X86_64(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswapl %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# define GUINT64_SWAP_LE_BE_X86_64(val) \ + (__extension__ \ + ({ register guint64 __v, __x = ((guint64) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT64_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswapq %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) + /* gcc seems to figure out optimal code for this on its own */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86_64 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86_64 (val)) +# else /* generic gcc */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val)) +# endif +#else /* generic */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val)) +#endif /* generic */ + +#define GUINT16_SWAP_LE_PDP(val) ((guint16) (val)) +#define GUINT16_SWAP_BE_PDP(val) (GUINT16_SWAP_LE_BE (val)) +#define GUINT32_SWAP_LE_PDP(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x0000ffffU) << 16) | \ + (((guint32) (val) & (guint32) 0xffff0000U) >> 16))) +#define GUINT32_SWAP_BE_PDP(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x00ff00ffU) << 8) | \ + (((guint32) (val) & (guint32) 0xff00ff00U) >> 8))) + +/* The G*_TO_?E() macros are defined in glibconfig.h. + * The transformation is symmetric, so the FROM just maps to the TO. + */ +#define GINT16_FROM_LE(val) (GINT16_TO_LE (val)) +#define GUINT16_FROM_LE(val) (GUINT16_TO_LE (val)) +#define GINT16_FROM_BE(val) (GINT16_TO_BE (val)) +#define GUINT16_FROM_BE(val) (GUINT16_TO_BE (val)) +#define GINT32_FROM_LE(val) (GINT32_TO_LE (val)) +#define GUINT32_FROM_LE(val) (GUINT32_TO_LE (val)) +#define GINT32_FROM_BE(val) (GINT32_TO_BE (val)) +#define GUINT32_FROM_BE(val) (GUINT32_TO_BE (val)) + +#define GINT64_FROM_LE(val) (GINT64_TO_LE (val)) +#define GUINT64_FROM_LE(val) (GUINT64_TO_LE (val)) +#define GINT64_FROM_BE(val) (GINT64_TO_BE (val)) +#define GUINT64_FROM_BE(val) (GUINT64_TO_BE (val)) + +#define GLONG_FROM_LE(val) (GLONG_TO_LE (val)) +#define GULONG_FROM_LE(val) (GULONG_TO_LE (val)) +#define GLONG_FROM_BE(val) (GLONG_TO_BE (val)) +#define GULONG_FROM_BE(val) (GULONG_TO_BE (val)) + +#define GINT_FROM_LE(val) (GINT_TO_LE (val)) +#define GUINT_FROM_LE(val) (GUINT_TO_LE (val)) +#define GINT_FROM_BE(val) (GINT_TO_BE (val)) +#define GUINT_FROM_BE(val) (GUINT_TO_BE (val)) + +#define GSIZE_FROM_LE(val) (GSIZE_TO_LE (val)) +#define GSSIZE_FROM_LE(val) (GSSIZE_TO_LE (val)) +#define GSIZE_FROM_BE(val) (GSIZE_TO_BE (val)) +#define GSSIZE_FROM_BE(val) (GSSIZE_TO_BE (val)) + + +/* Portable versions of host-network order stuff + */ +#define g_ntohl(val) (GUINT32_FROM_BE (val)) +#define g_ntohs(val) (GUINT16_FROM_BE (val)) +#define g_htonl(val) (GUINT32_TO_BE (val)) +#define g_htons(val) (GUINT16_TO_BE (val)) + +/* IEEE Standard 754 Single Precision Storage Format (gfloat): + * + * 31 30 23 22 0 + * +--------+---------------+---------------+ + * | s 1bit | e[30:23] 8bit | f[22:0] 23bit | + * +--------+---------------+---------------+ + * B0------------------->B1------->B2-->B3--> + * + * IEEE Standard 754 Double Precision Storage Format (gdouble): + * + * 63 62 52 51 32 31 0 + * +--------+----------------+----------------+ +---------------+ + * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit | + * +--------+----------------+----------------+ +---------------+ + * B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7-> + */ +/* subtract from biased_exponent to form base2 exponent (normal numbers) */ +typedef union _GDoubleIEEE754 GDoubleIEEE754; +typedef union _GFloatIEEE754 GFloatIEEE754; +#define G_IEEE754_FLOAT_BIAS (127) +#define G_IEEE754_DOUBLE_BIAS (1023) +/* multiply with base2 exponent to get base10 exponent (normal numbers) */ +#define G_LOG_2_BASE_10 (0.30102999566398119521) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint mantissa : 23; + guint biased_exponent : 8; + guint sign : 1; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint mantissa_low : 32; + guint mantissa_high : 20; + guint biased_exponent : 11; + guint sign : 1; + } mpn; +}; +#elif G_BYTE_ORDER == G_BIG_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint sign : 1; + guint biased_exponent : 8; + guint mantissa : 23; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint sign : 1; + guint biased_exponent : 11; + guint mantissa_high : 20; + guint mantissa_low : 32; + } mpn; +}; +#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ +#error unknown ENDIAN type +#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ + +typedef struct _GTimeVal GTimeVal; + +struct _GTimeVal +{ + glong tv_sec; + glong tv_usec; +}; + +G_END_DECLS + +/* We prefix variable declarations so they can + * properly get exported in Windows DLLs. + */ +#ifndef GLIB_VAR +# ifdef G_PLATFORM_WIN32 +# ifdef GLIB_STATIC_COMPILATION +# define GLIB_VAR extern +# else /* !GLIB_STATIC_COMPILATION */ +# ifdef GLIB_COMPILATION +# ifdef DLL_EXPORT +# define GLIB_VAR __declspec(dllexport) +# else /* !DLL_EXPORT */ +# define GLIB_VAR extern +# endif /* !DLL_EXPORT */ +# else /* !GLIB_COMPILATION */ +# define GLIB_VAR extern __declspec(dllimport) +# endif /* !GLIB_COMPILATION */ +# endif /* !GLIB_STATIC_COMPILATION */ +# else /* !G_PLATFORM_WIN32 */ +# define GLIB_VAR extern +# endif /* !G_PLATFORM_WIN32 */ +#endif /* GLIB_VAR */ + +#endif /* __G_TYPES_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gunicode.h b/protocols/Sametime/src/glib/include/glib/gunicode.h new file mode 100644 index 0000000000..4ca7bd3017 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gunicode.h @@ -0,0 +1,421 @@ +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright 2000, 2005 Red Hat, Inc. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_UNICODE_H__ +#define __G_UNICODE_H__ + +#include <glib/gerror.h> +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +typedef guint32 gunichar; +typedef guint16 gunichar2; + +/* These are the possible character classifications. + * See http://www.unicode.org/Public/UNIDATA/UCD.html#General_Category_Values + */ +typedef enum +{ + G_UNICODE_CONTROL, + G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, + G_UNICODE_PRIVATE_USE, + G_UNICODE_SURROGATE, + G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, + G_UNICODE_TITLECASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_COMBINING_MARK, + G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, + G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_LETTER_NUMBER, + G_UNICODE_OTHER_NUMBER, + G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, + G_UNICODE_LINE_SEPARATOR, + G_UNICODE_PARAGRAPH_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR +} GUnicodeType; + +/* These are the possible line break classifications. + * Note that new types may be added in the future. + * Implementations may regard unknown values like G_UNICODE_BREAK_UNKNOWN + * See http://www.unicode.org/unicode/reports/tr14/ + */ +typedef enum +{ + G_UNICODE_BREAK_MANDATORY, + G_UNICODE_BREAK_CARRIAGE_RETURN, + G_UNICODE_BREAK_LINE_FEED, + G_UNICODE_BREAK_COMBINING_MARK, + G_UNICODE_BREAK_SURROGATE, + G_UNICODE_BREAK_ZERO_WIDTH_SPACE, + G_UNICODE_BREAK_INSEPARABLE, + G_UNICODE_BREAK_NON_BREAKING_GLUE, + G_UNICODE_BREAK_CONTINGENT, + G_UNICODE_BREAK_SPACE, + G_UNICODE_BREAK_AFTER, + G_UNICODE_BREAK_BEFORE, + G_UNICODE_BREAK_BEFORE_AND_AFTER, + G_UNICODE_BREAK_HYPHEN, + G_UNICODE_BREAK_NON_STARTER, + G_UNICODE_BREAK_OPEN_PUNCTUATION, + G_UNICODE_BREAK_CLOSE_PUNCTUATION, + G_UNICODE_BREAK_QUOTATION, + G_UNICODE_BREAK_EXCLAMATION, + G_UNICODE_BREAK_IDEOGRAPHIC, + G_UNICODE_BREAK_NUMERIC, + G_UNICODE_BREAK_INFIX_SEPARATOR, + G_UNICODE_BREAK_SYMBOL, + G_UNICODE_BREAK_ALPHABETIC, + G_UNICODE_BREAK_PREFIX, + G_UNICODE_BREAK_POSTFIX, + G_UNICODE_BREAK_COMPLEX_CONTEXT, + G_UNICODE_BREAK_AMBIGUOUS, + G_UNICODE_BREAK_UNKNOWN, + G_UNICODE_BREAK_NEXT_LINE, + G_UNICODE_BREAK_WORD_JOINER, + G_UNICODE_BREAK_HANGUL_L_JAMO, + G_UNICODE_BREAK_HANGUL_V_JAMO, + G_UNICODE_BREAK_HANGUL_T_JAMO, + G_UNICODE_BREAK_HANGUL_LV_SYLLABLE, + G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE +} GUnicodeBreakType; + +typedef enum +{ /* ISO 15924 code */ + G_UNICODE_SCRIPT_INVALID_CODE = -1, + G_UNICODE_SCRIPT_COMMON = 0, /* Zyyy */ + G_UNICODE_SCRIPT_INHERITED, /* Qaai */ + G_UNICODE_SCRIPT_ARABIC, /* Arab */ + G_UNICODE_SCRIPT_ARMENIAN, /* Armn */ + G_UNICODE_SCRIPT_BENGALI, /* Beng */ + G_UNICODE_SCRIPT_BOPOMOFO, /* Bopo */ + G_UNICODE_SCRIPT_CHEROKEE, /* Cher */ + G_UNICODE_SCRIPT_COPTIC, /* Qaac */ + G_UNICODE_SCRIPT_CYRILLIC, /* Cyrl (Cyrs) */ + G_UNICODE_SCRIPT_DESERET, /* Dsrt */ + G_UNICODE_SCRIPT_DEVANAGARI, /* Deva */ + G_UNICODE_SCRIPT_ETHIOPIC, /* Ethi */ + G_UNICODE_SCRIPT_GEORGIAN, /* Geor (Geon, Geoa) */ + G_UNICODE_SCRIPT_GOTHIC, /* Goth */ + G_UNICODE_SCRIPT_GREEK, /* Grek */ + G_UNICODE_SCRIPT_GUJARATI, /* Gujr */ + G_UNICODE_SCRIPT_GURMUKHI, /* Guru */ + G_UNICODE_SCRIPT_HAN, /* Hani */ + G_UNICODE_SCRIPT_HANGUL, /* Hang */ + G_UNICODE_SCRIPT_HEBREW, /* Hebr */ + G_UNICODE_SCRIPT_HIRAGANA, /* Hira */ + G_UNICODE_SCRIPT_KANNADA, /* Knda */ + G_UNICODE_SCRIPT_KATAKANA, /* Kana */ + G_UNICODE_SCRIPT_KHMER, /* Khmr */ + G_UNICODE_SCRIPT_LAO, /* Laoo */ + G_UNICODE_SCRIPT_LATIN, /* Latn (Latf, Latg) */ + G_UNICODE_SCRIPT_MALAYALAM, /* Mlym */ + G_UNICODE_SCRIPT_MONGOLIAN, /* Mong */ + G_UNICODE_SCRIPT_MYANMAR, /* Mymr */ + G_UNICODE_SCRIPT_OGHAM, /* Ogam */ + G_UNICODE_SCRIPT_OLD_ITALIC, /* Ital */ + G_UNICODE_SCRIPT_ORIYA, /* Orya */ + G_UNICODE_SCRIPT_RUNIC, /* Runr */ + G_UNICODE_SCRIPT_SINHALA, /* Sinh */ + G_UNICODE_SCRIPT_SYRIAC, /* Syrc (Syrj, Syrn, Syre) */ + G_UNICODE_SCRIPT_TAMIL, /* Taml */ + G_UNICODE_SCRIPT_TELUGU, /* Telu */ + G_UNICODE_SCRIPT_THAANA, /* Thaa */ + G_UNICODE_SCRIPT_THAI, /* Thai */ + G_UNICODE_SCRIPT_TIBETAN, /* Tibt */ + G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL, /* Cans */ + G_UNICODE_SCRIPT_YI, /* Yiii */ + G_UNICODE_SCRIPT_TAGALOG, /* Tglg */ + G_UNICODE_SCRIPT_HANUNOO, /* Hano */ + G_UNICODE_SCRIPT_BUHID, /* Buhd */ + G_UNICODE_SCRIPT_TAGBANWA, /* Tagb */ + + /* Unicode-4.0 additions */ + G_UNICODE_SCRIPT_BRAILLE, /* Brai */ + G_UNICODE_SCRIPT_CYPRIOT, /* Cprt */ + G_UNICODE_SCRIPT_LIMBU, /* Limb */ + G_UNICODE_SCRIPT_OSMANYA, /* Osma */ + G_UNICODE_SCRIPT_SHAVIAN, /* Shaw */ + G_UNICODE_SCRIPT_LINEAR_B, /* Linb */ + G_UNICODE_SCRIPT_TAI_LE, /* Tale */ + G_UNICODE_SCRIPT_UGARITIC, /* Ugar */ + + /* Unicode-4.1 additions */ + G_UNICODE_SCRIPT_NEW_TAI_LUE, /* Talu */ + G_UNICODE_SCRIPT_BUGINESE, /* Bugi */ + G_UNICODE_SCRIPT_GLAGOLITIC, /* Glag */ + G_UNICODE_SCRIPT_TIFINAGH, /* Tfng */ + G_UNICODE_SCRIPT_SYLOTI_NAGRI, /* Sylo */ + G_UNICODE_SCRIPT_OLD_PERSIAN, /* Xpeo */ + G_UNICODE_SCRIPT_KHAROSHTHI, /* Khar */ + + /* Unicode-5.0 additions */ + G_UNICODE_SCRIPT_UNKNOWN, /* Zzzz */ + G_UNICODE_SCRIPT_BALINESE, /* Bali */ + G_UNICODE_SCRIPT_CUNEIFORM, /* Xsux */ + G_UNICODE_SCRIPT_PHOENICIAN, /* Phnx */ + G_UNICODE_SCRIPT_PHAGS_PA, /* Phag */ + G_UNICODE_SCRIPT_NKO, /* Nkoo */ + + /* Unicode-5.1 additions */ + G_UNICODE_SCRIPT_KAYAH_LI, /* Kali */ + G_UNICODE_SCRIPT_LEPCHA, /* Lepc */ + G_UNICODE_SCRIPT_REJANG, /* Rjng */ + G_UNICODE_SCRIPT_SUNDANESE, /* Sund */ + G_UNICODE_SCRIPT_SAURASHTRA, /* Saur */ + G_UNICODE_SCRIPT_CHAM, /* Cham */ + G_UNICODE_SCRIPT_OL_CHIKI, /* Olck */ + G_UNICODE_SCRIPT_VAI, /* Vaii */ + G_UNICODE_SCRIPT_CARIAN, /* Cari */ + G_UNICODE_SCRIPT_LYCIAN, /* Lyci */ + G_UNICODE_SCRIPT_LYDIAN, /* Lydi */ + + /* Unicode-5.2 additions */ + G_UNICODE_SCRIPT_AVESTAN, /* Avestan */ + G_UNICODE_SCRIPT_BAMUM, /* Bamum */ + G_UNICODE_SCRIPT_EGYPTIAN_HIEROGLYPHS, /* Egyptian Hieroglyphs */ + G_UNICODE_SCRIPT_IMPERIAL_ARAMAIC, /* Imperial Aramaic */ + G_UNICODE_SCRIPT_INSCRIPTIONAL_PAHLAVI, /* Inscriptional Pahlavi */ + G_UNICODE_SCRIPT_INSCRIPTIONAL_PARTHIAN, /* Inscriptional Parthian */ + G_UNICODE_SCRIPT_JAVANESE, /* Javanese */ + G_UNICODE_SCRIPT_KAITHI, /* Kaithi */ + G_UNICODE_SCRIPT_LISU, /* Lisu */ + G_UNICODE_SCRIPT_MEETEI_MAYEK, /* Meetei Mayek */ + G_UNICODE_SCRIPT_OLD_SOUTH_ARABIAN, /* Old South Arabian */ + G_UNICODE_SCRIPT_OLD_TURKISH, /* Old Turkish */ + G_UNICODE_SCRIPT_SAMARITAN, /* Samaritan */ + G_UNICODE_SCRIPT_TAI_THAM, /* Tai Tham */ + G_UNICODE_SCRIPT_TAI_VIET /* Tai Viet */ +} GUnicodeScript; + +/* Returns TRUE if current locale uses UTF-8 charset. If CHARSET is + * not null, sets *CHARSET to the name of the current locale's + * charset. This value is statically allocated, and should be copied + * in case the locale's charset will be changed later using setlocale() + * or in some other way. + */ +gboolean g_get_charset (G_CONST_RETURN char **charset); + +/* These are all analogs of the <ctype.h> functions. + */ +gboolean g_unichar_isalnum (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isalpha (gunichar c) G_GNUC_CONST; +gboolean g_unichar_iscntrl (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isdigit (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isgraph (gunichar c) G_GNUC_CONST; +gboolean g_unichar_islower (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isprint (gunichar c) G_GNUC_CONST; +gboolean g_unichar_ispunct (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isspace (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isupper (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isxdigit (gunichar c) G_GNUC_CONST; +gboolean g_unichar_istitle (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isdefined (gunichar c) G_GNUC_CONST; +gboolean g_unichar_iswide (gunichar c) G_GNUC_CONST; +gboolean g_unichar_iswide_cjk(gunichar c) G_GNUC_CONST; +gboolean g_unichar_iszerowidth(gunichar c) G_GNUC_CONST; +gboolean g_unichar_ismark (gunichar c) G_GNUC_CONST; + +/* More <ctype.h> functions. These convert between the three cases. + * See the Unicode book to understand title case. */ +gunichar g_unichar_toupper (gunichar c) G_GNUC_CONST; +gunichar g_unichar_tolower (gunichar c) G_GNUC_CONST; +gunichar g_unichar_totitle (gunichar c) G_GNUC_CONST; + +/* If C is a digit (according to `g_unichar_isdigit'), then return its + numeric value. Otherwise return -1. */ +gint g_unichar_digit_value (gunichar c) G_GNUC_CONST; + +gint g_unichar_xdigit_value (gunichar c) G_GNUC_CONST; + +/* Return the Unicode character type of a given character. */ +GUnicodeType g_unichar_type (gunichar c) G_GNUC_CONST; + +/* Return the line break property for a given character */ +GUnicodeBreakType g_unichar_break_type (gunichar c) G_GNUC_CONST; + +/* Returns the combining class for a given character */ +gint g_unichar_combining_class (gunichar uc) G_GNUC_CONST; + + +/* Compute canonical ordering of a string in-place. This rearranges + decomposed characters in the string according to their combining + classes. See the Unicode manual for more information. */ +void g_unicode_canonical_ordering (gunichar *string, + gsize len); + +/* Compute canonical decomposition of a character. Returns g_malloc()d + string of Unicode characters. RESULT_LEN is set to the resulting + length of the string. */ +gunichar *g_unicode_canonical_decomposition (gunichar ch, + gsize *result_len) G_GNUC_MALLOC; + +/* Array of skip-bytes-per-initial character. + */ +GLIB_VAR const gchar * const g_utf8_skip; + +#define g_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(const guchar *)(p)]) + +gunichar g_utf8_get_char (const gchar *p) G_GNUC_PURE; +gunichar g_utf8_get_char_validated (const gchar *p, + gssize max_len) G_GNUC_PURE; + +gchar* g_utf8_offset_to_pointer (const gchar *str, + glong offset) G_GNUC_PURE; +glong g_utf8_pointer_to_offset (const gchar *str, + const gchar *pos) G_GNUC_PURE; +gchar* g_utf8_prev_char (const gchar *p) G_GNUC_PURE; +gchar* g_utf8_find_next_char (const gchar *p, + const gchar *end) G_GNUC_PURE; +gchar* g_utf8_find_prev_char (const gchar *str, + const gchar *p) G_GNUC_PURE; + +glong g_utf8_strlen (const gchar *p, + gssize max) G_GNUC_PURE; + +/* Copies n characters from src to dest */ +gchar* g_utf8_strncpy (gchar *dest, + const gchar *src, + gsize n); + +/* Find the UTF-8 character corresponding to ch, in string p. These + functions are equivalants to strchr and strrchr */ +gchar* g_utf8_strchr (const gchar *p, + gssize len, + gunichar c); +gchar* g_utf8_strrchr (const gchar *p, + gssize len, + gunichar c); +gchar* g_utf8_strreverse (const gchar *str, + gssize len); + +gunichar2 *g_utf8_to_utf16 (const gchar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; +gunichar * g_utf8_to_ucs4 (const gchar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; +gunichar * g_utf8_to_ucs4_fast (const gchar *str, + glong len, + glong *items_written) G_GNUC_MALLOC; +gunichar * g_utf16_to_ucs4 (const gunichar2 *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; +gchar* g_utf16_to_utf8 (const gunichar2 *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; +gunichar2 *g_ucs4_to_utf16 (const gunichar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; +gchar* g_ucs4_to_utf8 (const gunichar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error) G_GNUC_MALLOC; + +/* Convert a single character into UTF-8. outbuf must have at + * least 6 bytes of space. Returns the number of bytes in the + * result. + */ +gint g_unichar_to_utf8 (gunichar c, + gchar *outbuf); + +/* Validate a UTF8 string, return TRUE if valid, put pointer to + * first invalid char in **end + */ + +gboolean g_utf8_validate (const gchar *str, + gssize max_len, + const gchar **end); + +/* Validate a Unicode character */ +gboolean g_unichar_validate (gunichar ch) G_GNUC_CONST; + +gchar *g_utf8_strup (const gchar *str, + gssize len) G_GNUC_MALLOC; +gchar *g_utf8_strdown (const gchar *str, + gssize len) G_GNUC_MALLOC; +gchar *g_utf8_casefold (const gchar *str, + gssize len) G_GNUC_MALLOC; + +typedef enum { + G_NORMALIZE_DEFAULT, + G_NORMALIZE_NFD = G_NORMALIZE_DEFAULT, + G_NORMALIZE_DEFAULT_COMPOSE, + G_NORMALIZE_NFC = G_NORMALIZE_DEFAULT_COMPOSE, + G_NORMALIZE_ALL, + G_NORMALIZE_NFKD = G_NORMALIZE_ALL, + G_NORMALIZE_ALL_COMPOSE, + G_NORMALIZE_NFKC = G_NORMALIZE_ALL_COMPOSE +} GNormalizeMode; + +gchar *g_utf8_normalize (const gchar *str, + gssize len, + GNormalizeMode mode) G_GNUC_MALLOC; + +gint g_utf8_collate (const gchar *str1, + const gchar *str2) G_GNUC_PURE; +gchar *g_utf8_collate_key (const gchar *str, + gssize len) G_GNUC_MALLOC; +gchar *g_utf8_collate_key_for_filename (const gchar *str, + gssize len) G_GNUC_MALLOC; + +gboolean g_unichar_get_mirror_char (gunichar ch, + gunichar *mirrored_ch); + +GUnicodeScript g_unichar_get_script (gunichar ch) G_GNUC_CONST; + + +/* private */ + +gchar *_g_utf8_make_valid (const gchar *name); + +G_END_DECLS + +#endif /* __G_UNICODE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gurifuncs.h b/protocols/Sametime/src/glib/include/glib/gurifuncs.h new file mode 100644 index 0000000000..bbc8f8800a --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gurifuncs.h @@ -0,0 +1,81 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexander Larsson <alexl@redhat.com> + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_URI_FUNCS_H__ +#define __G_URI_FUNCS_H__ + +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/** + * G_URI_RESERVED_CHARS_GENERIC_DELIMITERS: + * + * Generic delimiters characters as defined in RFC 3986. Includes ":/?#[]@". + **/ +#define G_URI_RESERVED_CHARS_GENERIC_DELIMITERS ":/?#[]@" + +/** + * G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS + * + * Subcomponent delimiter characters as defined in RFC 3986. Includes "!$&'()*+,;=". + **/ +#define G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS "!$&'()*+,;=" + +/** + * G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT: + * + * Allowed characters in path elements. Includes "!$&'()*+,;=:@". + **/ +#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":@" + +/** + * G_URI_RESERVED_CHARS_ALLOWED_IN_PATH: + * + * Allowed characters in a path. Includes "!$&'()*+,;=:@/". + **/ +#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT "/" + +/** + * G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO: + * + * Allowed characters in userinfo as defined in RFC 3986. Includes "!$&'()*+,;=:". + **/ +#define G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":" + +char * g_uri_unescape_string (const char *escaped_string, + const char *illegal_characters); +char * g_uri_unescape_segment (const char *escaped_string, + const char *escaped_string_end, + const char *illegal_characters); +char * g_uri_parse_scheme (const char *uri); +char * g_uri_escape_string (const char *unescaped, + const char *reserved_chars_allowed, + gboolean allow_utf8); + +G_END_DECLS + +#endif /* __G_URI_FUNCS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gutils.h b/protocols/Sametime/src/glib/include/glib/gutils.h new file mode 100644 index 0000000000..90281579c6 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gutils.h @@ -0,0 +1,490 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_UTILS_H__ +#define __G_UTILS_H__ + +#include <glib/gtypes.h> +#include <stdarg.h> + +G_BEGIN_DECLS + +#ifdef G_OS_WIN32 + +/* On Win32, the canonical directory separator is the backslash, and + * the search path separator is the semicolon. Note that also the + * (forward) slash works as directory separator. + */ +#define G_DIR_SEPARATOR '\\' +#define G_DIR_SEPARATOR_S "\\" +#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/') +#define G_SEARCHPATH_SEPARATOR ';' +#define G_SEARCHPATH_SEPARATOR_S ";" + +#else /* !G_OS_WIN32 */ + +/* Unix */ + +#define G_DIR_SEPARATOR '/' +#define G_DIR_SEPARATOR_S "/" +#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR) +#define G_SEARCHPATH_SEPARATOR ':' +#define G_SEARCHPATH_SEPARATOR_S ":" + +#endif /* !G_OS_WIN32 */ + +/* Define G_VA_COPY() to do the right thing for copying va_list variables. + * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy. + */ +#if !defined (G_VA_COPY) +# if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)) +# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) +# elif defined (G_VA_COPY_AS_ARRAY) +# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) +# else /* va_list is a pointer */ +# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) +# endif /* va_list is a pointer */ +#endif /* !G_VA_COPY */ + +/* inlining hassle. for compilers that don't allow the `inline' keyword, + * mostly because of strict ANSI C compliance or dumbness, we try to fall + * back to either `__inline__' or `__inline'. + * G_CAN_INLINE is defined in glibconfig.h if the compiler seems to be + * actually *capable* to do function inlining, in which case inline + * function bodies do make sense. we also define G_INLINE_FUNC to properly + * export the function prototypes if no inlining can be performed. + * inline function bodies have to be special cased with G_CAN_INLINE and a + * .c file specific macro to allow one compiled instance with extern linkage + * of the functions by defining G_IMPLEMENT_INLINES and the .c file macro. + */ +#if defined (G_HAVE_INLINE) && defined (__GNUC__) && defined (__STRICT_ANSI__) +# undef inline +# define inline __inline__ +#elif !defined (G_HAVE_INLINE) +# undef inline +# if defined (G_HAVE___INLINE__) +# define inline __inline__ +# elif defined (G_HAVE___INLINE) +# define inline __inline +# else /* !inline && !__inline__ && !__inline */ +# define inline /* don't inline, then */ +# endif +#endif +#ifdef G_IMPLEMENT_INLINES +# define G_INLINE_FUNC +# undef G_CAN_INLINE +#elif defined (__GNUC__) +# define G_INLINE_FUNC static __inline __attribute__ ((unused)) +#elif defined (G_CAN_INLINE) +# define G_INLINE_FUNC static inline +#else /* can't inline */ +# define G_INLINE_FUNC +#endif /* !G_INLINE_FUNC */ + +/* Retrive static string info + */ +#ifdef G_OS_WIN32 +#define g_get_user_name g_get_user_name_utf8 +#define g_get_real_name g_get_real_name_utf8 +#define g_get_home_dir g_get_home_dir_utf8 +#define g_get_tmp_dir g_get_tmp_dir_utf8 +#endif + +G_CONST_RETURN gchar* g_get_user_name (void); +G_CONST_RETURN gchar* g_get_real_name (void); +G_CONST_RETURN gchar* g_get_home_dir (void); +G_CONST_RETURN gchar* g_get_tmp_dir (void); +G_CONST_RETURN gchar* g_get_host_name (void); +gchar* g_get_prgname (void); +void g_set_prgname (const gchar *prgname); +G_CONST_RETURN gchar* g_get_application_name (void); +void g_set_application_name (const gchar *application_name); + +void g_reload_user_special_dirs_cache (void); +G_CONST_RETURN gchar* g_get_user_data_dir (void); +G_CONST_RETURN gchar* g_get_user_config_dir (void); +G_CONST_RETURN gchar* g_get_user_cache_dir (void); +G_CONST_RETURN gchar* G_CONST_RETURN * g_get_system_data_dirs (void); + +#ifdef G_OS_WIN32 +/* This functions is not part of the public GLib API */ +G_CONST_RETURN gchar* G_CONST_RETURN * g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void)); +#endif + +#if defined (G_OS_WIN32) && defined (G_CAN_INLINE) && !defined (__cplusplus) +/* This function is not part of the public GLib API either. Just call + * g_get_system_data_dirs() in your code, never mind that that is + * actually a macro and you will in fact call this inline function. + */ +static inline G_CONST_RETURN gchar * G_CONST_RETURN * +_g_win32_get_system_data_dirs (void) +{ + return g_win32_get_system_data_dirs_for_module ((void (*)(void)) &_g_win32_get_system_data_dirs); +} +#define g_get_system_data_dirs _g_win32_get_system_data_dirs +#endif + +G_CONST_RETURN gchar* G_CONST_RETURN * g_get_system_config_dirs (void); + +G_CONST_RETURN gchar* G_CONST_RETURN * g_get_language_names (void); + +/** + * GUserDirectory: + * @G_USER_DIRECTORY_DESKTOP: the user's Desktop directory + * @G_USER_DIRECTORY_DOCUMENTS: the user's Documents directory + * @G_USER_DIRECTORY_DOWNLOAD: the user's Downloads directory + * @G_USER_DIRECTORY_MUSIC: the user's Music directory + * @G_USER_DIRECTORY_PICTURES: the user's Pictures directory + * @G_USER_DIRECTORY_PUBLIC_SHARE: the user's shared directory + * @G_USER_DIRECTORY_TEMPLATES: the user's Templates directory + * @G_USER_DIRECTORY_VIDEOS: the user's Movies directory + * @G_USER_N_DIRECTORIES: the number of enum values + * + * These are logical ids for special directories which are defined + * depending on the platform used. You should use g_get_user_special_dir() + * to retrieve the full path associated to the logical id. + * + * The #GUserDirectory enumeration can be extended at later date. Not + * every platform has a directory for every logical id in this + * enumeration. + * + * Since: 2.14 + */ +typedef enum { + G_USER_DIRECTORY_DESKTOP, + G_USER_DIRECTORY_DOCUMENTS, + G_USER_DIRECTORY_DOWNLOAD, + G_USER_DIRECTORY_MUSIC, + G_USER_DIRECTORY_PICTURES, + G_USER_DIRECTORY_PUBLIC_SHARE, + G_USER_DIRECTORY_TEMPLATES, + G_USER_DIRECTORY_VIDEOS, + + G_USER_N_DIRECTORIES +} GUserDirectory; + +G_CONST_RETURN gchar* g_get_user_special_dir (GUserDirectory directory); + +typedef struct _GDebugKey GDebugKey; +struct _GDebugKey +{ + const gchar *key; + guint value; +}; + +/* Miscellaneous utility functions + */ +guint g_parse_debug_string (const gchar *string, + const GDebugKey *keys, + guint nkeys); + +gint g_snprintf (gchar *string, + gulong n, + gchar const *format, + ...) G_GNUC_PRINTF (3, 4); +gint g_vsnprintf (gchar *string, + gulong n, + gchar const *format, + va_list args); + +/* Check if a file name is an absolute path */ +gboolean g_path_is_absolute (const gchar *file_name); + +/* In case of absolute paths, skip the root part */ +G_CONST_RETURN gchar* g_path_skip_root (const gchar *file_name); + +#ifndef G_DISABLE_DEPRECATED + +/* These two functions are deprecated and will be removed in the next + * major release of GLib. Use g_path_get_dirname/g_path_get_basename + * instead. Whatch out! The string returned by g_path_get_basename + * must be g_freed, while the string returned by g_basename must not.*/ +G_CONST_RETURN gchar* g_basename (const gchar *file_name); +#define g_dirname g_path_get_dirname + +#endif /* G_DISABLE_DEPRECATED */ + +#ifdef G_OS_WIN32 +#define g_get_current_dir g_get_current_dir_utf8 +#endif + +/* The returned strings are newly allocated with g_malloc() */ +gchar* g_get_current_dir (void); +gchar* g_path_get_basename (const gchar *file_name) G_GNUC_MALLOC; +gchar* g_path_get_dirname (const gchar *file_name) G_GNUC_MALLOC; + +/* Set the pointer at the specified location to NULL */ +void g_nullify_pointer (gpointer *nullify_location); + +/* return the environment string for the variable. The returned memory + * must not be freed. */ +#ifdef G_OS_WIN32 +#define g_getenv g_getenv_utf8 +#define g_setenv g_setenv_utf8 +#define g_unsetenv g_unsetenv_utf8 +#define g_find_program_in_path g_find_program_in_path_utf8 +#endif + +G_CONST_RETURN gchar* g_getenv (const gchar *variable); +gboolean g_setenv (const gchar *variable, + const gchar *value, + gboolean overwrite); +void g_unsetenv (const gchar *variable); +gchar** g_listenv (void); + +/* private */ +const gchar* _g_getenv_nomalloc (const gchar *variable, + gchar buffer[1024]); + +/* we try to provide a useful equivalent for ATEXIT if it is + * not defined, but use is actually abandoned. people should + * use g_atexit() instead. + */ +typedef void (*GVoidFunc) (void); +#ifndef ATEXIT +# define ATEXIT(proc) g_ATEXIT(proc) +#else +# define G_NATIVE_ATEXIT +#endif /* ATEXIT */ +/* we use a GLib function as a replacement for ATEXIT, so + * the programmer is not required to check the return value + * (if there is any in the implementation) and doesn't encounter + * missing include files. + */ +void g_atexit (GVoidFunc func); + +#ifdef G_OS_WIN32 +/* It's a bad idea to wrap atexit() on Windows. If the GLib DLL calls + * atexit(), the function will be called when the GLib DLL is detached + * from the program, which is not what the caller wants. The caller + * wants the function to be called when it *itself* exits (or is + * detached, in case the caller, too, is a DLL). + */ +#if (defined(__MINGW_H) && !defined(_STDLIB_H_)) || (defined(_MSC_VER) && !defined(_INC_STDLIB)) +int atexit (void (*)(void)); +#endif +#define g_atexit(func) atexit(func) +#endif + +/* Look for an executable in PATH, following execvp() rules */ +gchar* g_find_program_in_path (const gchar *program); + +/* Bit tests + */ +G_INLINE_FUNC gint g_bit_nth_lsf (gulong mask, + gint nth_bit) G_GNUC_CONST; +G_INLINE_FUNC gint g_bit_nth_msf (gulong mask, + gint nth_bit) G_GNUC_CONST; +G_INLINE_FUNC guint g_bit_storage (gulong number) G_GNUC_CONST; + +/* Trash Stacks + * elements need to be >= sizeof (gpointer) + */ +typedef struct _GTrashStack GTrashStack; +struct _GTrashStack +{ + GTrashStack *next; +}; + +G_INLINE_FUNC void g_trash_stack_push (GTrashStack **stack_p, + gpointer data_p); +G_INLINE_FUNC gpointer g_trash_stack_pop (GTrashStack **stack_p); +G_INLINE_FUNC gpointer g_trash_stack_peek (GTrashStack **stack_p); +G_INLINE_FUNC guint g_trash_stack_height (GTrashStack **stack_p); + +/* inline function implementations + */ +#if defined (G_CAN_INLINE) || defined (__G_UTILS_C__) +G_INLINE_FUNC gint +g_bit_nth_lsf (gulong mask, + gint nth_bit) +{ + if (G_UNLIKELY (nth_bit < -1)) + nth_bit = -1; + while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1)) + { + nth_bit++; + if (mask & (1UL << nth_bit)) + return nth_bit; + } + return -1; +} +G_INLINE_FUNC gint +g_bit_nth_msf (gulong mask, + gint nth_bit) +{ + if (nth_bit < 0 || G_UNLIKELY (nth_bit > GLIB_SIZEOF_LONG * 8)) + nth_bit = GLIB_SIZEOF_LONG * 8; + while (nth_bit > 0) + { + nth_bit--; + if (mask & (1UL << nth_bit)) + return nth_bit; + } + return -1; +} +G_INLINE_FUNC guint +g_bit_storage (gulong number) +{ +#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) + return G_LIKELY (number) ? + ((GLIB_SIZEOF_LONG * 8U - 1) ^ __builtin_clzl(number)) + 1 : 1; +#else + register guint n_bits = 0; + + do + { + n_bits++; + number >>= 1; + } + while (number); + return n_bits; +#endif +} +G_INLINE_FUNC void +g_trash_stack_push (GTrashStack **stack_p, + gpointer data_p) +{ + GTrashStack *data = (GTrashStack *) data_p; + + data->next = *stack_p; + *stack_p = data; +} +G_INLINE_FUNC gpointer +g_trash_stack_pop (GTrashStack **stack_p) +{ + GTrashStack *data; + + data = *stack_p; + if (data) + { + *stack_p = data->next; + /* NULLify private pointer here, most platforms store NULL as + * subsequent 0 bytes + */ + data->next = NULL; + } + + return data; +} +G_INLINE_FUNC gpointer +g_trash_stack_peek (GTrashStack **stack_p) +{ + GTrashStack *data; + + data = *stack_p; + + return data; +} +G_INLINE_FUNC guint +g_trash_stack_height (GTrashStack **stack_p) +{ + GTrashStack *data; + guint i = 0; + + for (data = *stack_p; data; data = data->next) + i++; + + return i; +} +#endif /* G_CAN_INLINE || __G_UTILS_C__ */ + +/* Glib version. + * we prefix variable declarations so they can + * properly get exported in windows dlls. + */ +GLIB_VAR const guint glib_major_version; +GLIB_VAR const guint glib_minor_version; +GLIB_VAR const guint glib_micro_version; +GLIB_VAR const guint glib_interface_age; +GLIB_VAR const guint glib_binary_age; + +const gchar * glib_check_version (guint required_major, + guint required_minor, + guint required_micro); + +#define GLIB_CHECK_VERSION(major,minor,micro) \ + (GLIB_MAJOR_VERSION > (major) || \ + (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION > (minor)) || \ + (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION == (minor) && \ + GLIB_MICRO_VERSION >= (micro))) + +G_END_DECLS + +#ifndef G_DISABLE_DEPRECATED + +/* + * This macro is deprecated. This DllMain() is too complex. It is + * recommended to write an explicit minimal DLlMain() that just saves + * the handle to the DLL and then use that handle instead, for + * instance passing it to + * g_win32_get_package_installation_directory_of_module(). + * + * On Windows, this macro defines a DllMain function that stores the + * actual DLL name that the code being compiled will be included in. + * STATIC should be empty or 'static'. DLL_NAME is the name of the + * (pointer to the) char array where the DLL name will be stored. If + * this is used, you must also include <windows.h>. If you need a more complex + * DLL entry point function, you cannot use this. + * + * On non-Windows platforms, expands to nothing. + */ + +#ifndef G_PLATFORM_WIN32 +# define G_WIN32_DLLMAIN_FOR_DLL_NAME(static, dll_name) +#else +# define G_WIN32_DLLMAIN_FOR_DLL_NAME(static, dll_name) \ +static char *dll_name; \ + \ +BOOL WINAPI \ +DllMain (HINSTANCE hinstDLL, \ + DWORD fdwReason, \ + LPVOID lpvReserved) \ +{ \ + wchar_t wcbfr[1000]; \ + char *tem; \ + switch (fdwReason) \ + { \ + case DLL_PROCESS_ATTACH: \ + GetModuleFileNameW ((HMODULE) hinstDLL, wcbfr, G_N_ELEMENTS (wcbfr)); \ + tem = g_utf16_to_utf8 (wcbfr, -1, NULL, NULL, NULL); \ + dll_name = g_path_get_basename (tem); \ + g_free (tem); \ + break; \ + } \ + \ + return TRUE; \ +} + +#endif /* !G_DISABLE_DEPRECATED */ + +#endif /* G_PLATFORM_WIN32 */ + +#endif /* __G_UTILS_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gvariant.h b/protocols/Sametime/src/glib/include/glib/gvariant.h new file mode 100644 index 0000000000..528492b685 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gvariant.h @@ -0,0 +1,248 @@ +/* + * Copyright © 2007, 2008 Ryan Lortie + * Copyright © 2009, 2010 Codethink Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_VARIANT_H__ +#define __G_VARIANT_H__ + +#include <glib/gvarianttype.h> +#include <glib/gstring.h> + +G_BEGIN_DECLS + +typedef struct _GVariant GVariant; + +typedef enum +{ + G_VARIANT_CLASS_BOOLEAN = 'b', + G_VARIANT_CLASS_BYTE = 'y', + G_VARIANT_CLASS_INT16 = 'n', + G_VARIANT_CLASS_UINT16 = 'q', + G_VARIANT_CLASS_INT32 = 'i', + G_VARIANT_CLASS_UINT32 = 'u', + G_VARIANT_CLASS_INT64 = 'x', + G_VARIANT_CLASS_UINT64 = 't', + G_VARIANT_CLASS_HANDLE = 'h', + G_VARIANT_CLASS_DOUBLE = 'd', + G_VARIANT_CLASS_STRING = 's', + G_VARIANT_CLASS_OBJECT_PATH = 'o', + G_VARIANT_CLASS_SIGNATURE = 'g', + G_VARIANT_CLASS_VARIANT = 'v', + G_VARIANT_CLASS_MAYBE = 'm', + G_VARIANT_CLASS_ARRAY = 'a', + G_VARIANT_CLASS_TUPLE = '(', + G_VARIANT_CLASS_DICT_ENTRY = '{' +} GVariantClass; + +void g_variant_unref (GVariant *value); +GVariant * g_variant_ref (GVariant *value); +GVariant * g_variant_ref_sink (GVariant *value); +gboolean g_variant_is_floating (GVariant *value); + +const GVariantType * g_variant_get_type (GVariant *value); +const gchar * g_variant_get_type_string (GVariant *value); +gboolean g_variant_is_of_type (GVariant *value, + const GVariantType *type); +gboolean g_variant_is_container (GVariant *value); +GVariantClass g_variant_classify (GVariant *value); +GVariant * g_variant_new_boolean (gboolean boolean); +GVariant * g_variant_new_byte (guchar byte); +GVariant * g_variant_new_int16 (gint16 int16); +GVariant * g_variant_new_uint16 (guint16 uint16); +GVariant * g_variant_new_int32 (gint32 int32); +GVariant * g_variant_new_uint32 (guint32 uint32); +GVariant * g_variant_new_int64 (gint64 int64); +GVariant * g_variant_new_uint64 (guint64 uint64); +GVariant * g_variant_new_handle (gint32 handle); +GVariant * g_variant_new_double (gdouble floating); +GVariant * g_variant_new_string (const gchar *string); +GVariant * g_variant_new_object_path (const gchar *object_path); +gboolean g_variant_is_object_path (const gchar *string); +GVariant * g_variant_new_signature (const gchar *signature); +gboolean g_variant_is_signature (const gchar *string); +GVariant * g_variant_new_variant (GVariant *value); +GVariant * g_variant_new_strv (const gchar * const *strv, + gssize length); +GVariant * g_variant_new_bytestring (const gchar *string); +GVariant * g_variant_new_bytestring_array (const gchar * const *strv, + gssize length); + +gboolean g_variant_get_boolean (GVariant *value); +guchar g_variant_get_byte (GVariant *value); +gint16 g_variant_get_int16 (GVariant *value); +guint16 g_variant_get_uint16 (GVariant *value); +gint32 g_variant_get_int32 (GVariant *value); +guint32 g_variant_get_uint32 (GVariant *value); +gint64 g_variant_get_int64 (GVariant *value); +guint64 g_variant_get_uint64 (GVariant *value); +gint32 g_variant_get_handle (GVariant *value); +gdouble g_variant_get_double (GVariant *value); +GVariant * g_variant_get_variant (GVariant *value); +const gchar * g_variant_get_string (GVariant *value, + gsize *length); +gchar * g_variant_dup_string (GVariant *value, + gsize *length); +const gchar ** g_variant_get_strv (GVariant *value, + gsize *length); +gchar ** g_variant_dup_strv (GVariant *value, + gsize *length); +const gchar * g_variant_get_bytestring (GVariant *value); +gchar * g_variant_dup_bytestring (GVariant *value, + gsize *length); +const gchar ** g_variant_get_bytestring_array (GVariant *value, + gsize *length); +gchar ** g_variant_dup_bytestring_array (GVariant *value, + gsize *length); + +GVariant * g_variant_new_maybe (const GVariantType *child_type, + GVariant *child); +GVariant * g_variant_new_array (const GVariantType *child_type, + GVariant * const *children, + gsize n_children); +GVariant * g_variant_new_tuple (GVariant * const *children, + gsize n_children); +GVariant * g_variant_new_dict_entry (GVariant *key, + GVariant *value); + +GVariant * g_variant_get_maybe (GVariant *value); +gsize g_variant_n_children (GVariant *value); +void g_variant_get_child (GVariant *value, + gsize index_, + const gchar *format_string, + ...); +GVariant * g_variant_get_child_value (GVariant *value, + gsize index_); +gconstpointer g_variant_get_fixed_array (GVariant *value, + gsize *n_elements, + gsize element_size); + +gsize g_variant_get_size (GVariant *value); +gconstpointer g_variant_get_data (GVariant *value); +void g_variant_store (GVariant *value, + gpointer data); + +gchar * g_variant_print (GVariant *value, + gboolean type_annotate); +GString * g_variant_print_string (GVariant *value, + GString *string, + gboolean type_annotate); + +guint g_variant_hash (gconstpointer value); +gboolean g_variant_equal (gconstpointer one, + gconstpointer two); + +GVariant * g_variant_get_normal_form (GVariant *value); +gboolean g_variant_is_normal_form (GVariant *value); +GVariant * g_variant_byteswap (GVariant *value); +GVariant * g_variant_new_from_data (const GVariantType *type, + gconstpointer data, + gsize size, + gboolean trusted, + GDestroyNotify notify, + gpointer user_data); + +typedef struct _GVariantIter GVariantIter; +struct _GVariantIter { + /*< private >*/ + gsize x[16]; +}; + +GVariantIter * g_variant_iter_new (GVariant *value); +gsize g_variant_iter_init (GVariantIter *iter, + GVariant *value); +GVariantIter * g_variant_iter_copy (GVariantIter *iter); +gsize g_variant_iter_n_children (GVariantIter *iter); +void g_variant_iter_free (GVariantIter *iter); +GVariant * g_variant_iter_next_value (GVariantIter *iter); +gboolean g_variant_iter_next (GVariantIter *iter, + const gchar *format_string, + ...); +gboolean g_variant_iter_loop (GVariantIter *iter, + const gchar *format_string, + ...); + + +typedef struct _GVariantBuilder GVariantBuilder; +struct _GVariantBuilder { + /*< private >*/ + gsize x[16]; +}; + +typedef enum +{ + G_VARIANT_PARSE_ERROR_FAILED +} GVariantParseError; +#define G_VARIANT_PARSE_ERROR (g_variant_parser_get_error_quark ()) + +GQuark g_variant_parser_get_error_quark (void); + +GVariantBuilder * g_variant_builder_new (const GVariantType *type); +void g_variant_builder_unref (GVariantBuilder *builder); +GVariantBuilder * g_variant_builder_ref (GVariantBuilder *builder); +void g_variant_builder_init (GVariantBuilder *builder, + const GVariantType *type); +GVariant * g_variant_builder_end (GVariantBuilder *builder); +void g_variant_builder_clear (GVariantBuilder *builder); +void g_variant_builder_open (GVariantBuilder *builder, + const GVariantType *type); +void g_variant_builder_close (GVariantBuilder *builder); +void g_variant_builder_add_value (GVariantBuilder *builder, + GVariant *value); +void g_variant_builder_add (GVariantBuilder *builder, + const gchar *format_string, + ...); +void g_variant_builder_add_parsed (GVariantBuilder *builder, + const gchar *format, + ...); + +GVariant * g_variant_new (const gchar *format_string, + ...); +void g_variant_get (GVariant *value, + const gchar *format_string, + ...); +GVariant * g_variant_new_va (const gchar *format_string, + const gchar **endptr, + va_list *app); +void g_variant_get_va (GVariant *value, + const gchar *format_string, + const gchar **endptr, + va_list *app); + + +GVariant * g_variant_parse (const GVariantType *type, + const gchar *text, + const gchar *limit, + const gchar **endptr, + GError **error); +GVariant * g_variant_new_parsed (const gchar *format, + ...); +GVariant * g_variant_new_parsed_va (const gchar *format, + va_list *app); + +gint g_variant_compare (gconstpointer one, + gconstpointer two); +G_END_DECLS + +#endif /* __G_VARIANT_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gvarianttype.h b/protocols/Sametime/src/glib/include/glib/gvarianttype.h new file mode 100644 index 0000000000..124fa46b59 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gvarianttype.h @@ -0,0 +1,334 @@ +/* + * Copyright © 2007, 2008 Ryan Lortie + * Copyright © 2009, 2010 Codethink Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ryan Lortie <desrt@desrt.ca> + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_VARIANT_TYPE_H__ +#define __G_VARIANT_TYPE_H__ + +#include <glib/gmessages.h> +#include <glib/gtypes.h> + +G_BEGIN_DECLS + +/** + * GVariantType: + * + * A type in the GVariant type system. + * + * Two types may not be compared by value; use g_variant_type_equal() or + * g_variant_type_is_subtype(). May be copied using + * g_variant_type_copy() and freed using g_variant_type_free(). + **/ +typedef struct _GVariantType GVariantType; + +/** + * G_VARIANT_TYPE_BOOLEAN: + * + * The type of a value that can be either %TRUE or %FALSE. + **/ +#define G_VARIANT_TYPE_BOOLEAN ((const GVariantType *) "b") + +/** + * G_VARIANT_TYPE_BYTE: + * + * The type of an integer value that can range from 0 to 255. + **/ +#define G_VARIANT_TYPE_BYTE ((const GVariantType *) "y") + +/** + * G_VARIANT_TYPE_INT16: + * + * The type of an integer value that can range from -32768 to 32767. + **/ +#define G_VARIANT_TYPE_INT16 ((const GVariantType *) "n") + +/** + * G_VARIANT_TYPE_UINT16: + * + * The type of an integer value that can range from 0 to 65535. + * There were about this many people living in Toronto in the 1870s. + **/ +#define G_VARIANT_TYPE_UINT16 ((const GVariantType *) "q") + +/** + * G_VARIANT_TYPE_INT32: + * + * The type of an integer value that can range from -2147483648 to + * 2147483647. + **/ +#define G_VARIANT_TYPE_INT32 ((const GVariantType *) "i") + +/** + * G_VARIANT_TYPE_UINT32: + * + * The type of an integer value that can range from 0 to 4294967295. + * That's one number for everyone who was around in the late 1970s. + **/ +#define G_VARIANT_TYPE_UINT32 ((const GVariantType *) "u") + +/** + * G_VARIANT_TYPE_INT64: + * + * The type of an integer value that can range from + * -9223372036854775808 to 9223372036854775807. + **/ +#define G_VARIANT_TYPE_INT64 ((const GVariantType *) "x") + +/** + * G_VARIANT_TYPE_UINT64: + * + * The type of an integer value that can range from 0 to + * 18446744073709551616. That's a really big number, but a Rubik's + * cube can have a bit more than twice as many possible positions. + **/ +#define G_VARIANT_TYPE_UINT64 ((const GVariantType *) "t") + +/** + * G_VARIANT_TYPE_DOUBLE: + * + * The type of a double precision IEEE754 floating point number. + * These guys go up to about 1.80e308 (plus and minus) but miss out on + * some numbers in between. In any case, that's far greater than the + * estimated number of fundamental particles in the observable + * universe. + **/ +#define G_VARIANT_TYPE_DOUBLE ((const GVariantType *) "d") + +/** + * G_VARIANT_TYPE_STRING: + * + * The type of a string. "" is a string. %NULL is not a string. + **/ +#define G_VARIANT_TYPE_STRING ((const GVariantType *) "s") + +/** + * G_VARIANT_TYPE_OBJECT_PATH: + * + * The type of a DBus object reference. These are strings of a + * specific format used to identify objects at a given destination on + * the bus. + * + * If you are not interacting with DBus, then there is no reason to make + * use of this type. If you are, then the DBus specification contains a + * precise description of valid object paths. + **/ +#define G_VARIANT_TYPE_OBJECT_PATH ((const GVariantType *) "o") + +/** + * G_VARIANT_TYPE_SIGNATURE: + * + * The type of a DBus type signature. These are strings of a specific + * format used as type signatures for DBus methods and messages. + * + * If you are not interacting with DBus, then there is no reason to make + * use of this type. If you are, then the DBus specification contains a + * precise description of valid signature strings. + **/ +#define G_VARIANT_TYPE_SIGNATURE ((const GVariantType *) "g") + +/** + * G_VARIANT_TYPE_VARIANT: + * + * The type of a box that contains any other value (including another + * variant). + **/ +#define G_VARIANT_TYPE_VARIANT ((const GVariantType *) "v") + +/** + * G_VARIANT_TYPE_HANDLE: + * + * The type of a 32bit signed integer value, that by convention, is used + * as an index into an array of file descriptors that are sent alongside + * a DBus message. + * + * If you are not interacting with DBus, then there is no reason to make + * use of this type. + **/ +#define G_VARIANT_TYPE_HANDLE ((const GVariantType *) "h") + +/** + * G_VARIANT_TYPE_UNIT: + * + * The empty tuple type. Has only one instance. Known also as "triv" + * or "void". + **/ +#define G_VARIANT_TYPE_UNIT ((const GVariantType *) "()") + +/** + * G_VARIANT_TYPE_ANY: + * + * An indefinite type that is a supertype of every type (including + * itself). + **/ +#define G_VARIANT_TYPE_ANY ((const GVariantType *) "*") + +/** + * G_VARIANT_TYPE_BASIC: + * + * An indefinite type that is a supertype of every basic (ie: + * non-container) type. + **/ +#define G_VARIANT_TYPE_BASIC ((const GVariantType *) "?") + +/** + * G_VARIANT_TYPE_MAYBE: + * + * An indefinite type that is a supertype of every maybe type. + **/ +#define G_VARIANT_TYPE_MAYBE ((const GVariantType *) "m*") + +/** + * G_VARIANT_TYPE_ARRAY: + * + * An indefinite type that is a supertype of every array type. + **/ +#define G_VARIANT_TYPE_ARRAY ((const GVariantType *) "a*") + +/** + * G_VARIANT_TYPE_TUPLE: + * + * An indefinite type that is a supertype of every tuple type, + * regardless of the number of items in the tuple. + **/ +#define G_VARIANT_TYPE_TUPLE ((const GVariantType *) "r") + +/** + * G_VARIANT_TYPE_DICT_ENTRY: + * + * An indefinite type that is a supertype of every dictionary entry + * type. + **/ +#define G_VARIANT_TYPE_DICT_ENTRY ((const GVariantType *) "{?*}") + +/** + * G_VARIANT_TYPE_DICTIONARY: + * + * An indefinite type that is a supertype of every dictionary type -- + * that is, any array type that has an element type equal to any + * dictionary entry type. + **/ +#define G_VARIANT_TYPE_DICTIONARY ((const GVariantType *) "a{?*}") + +/** + * G_VARIANT_TYPE_STRING_ARRAY: + * + * The type of an array of strings. + **/ +#define G_VARIANT_TYPE_STRING_ARRAY ((const GVariantType *) "as") + +/** + * G_VARIANT_TYPE_BYTESTRING: + * + * The type of an array of bytes. This type is commonly used to pass + * around strings that may not be valid utf8. In that case, the + * convention is that the nul terminator character should be included as + * the last character in the array. + **/ +#define G_VARIANT_TYPE_BYTESTRING ((const GVariantType *) "ay") + +/** + * G_VARIANT_TYPE_BYTESTRING_ARRAY: + * + * The type of an array of byte strings (an array of arrays of bytes). + **/ +#define G_VARIANT_TYPE_BYTESTRING_ARRAY ((const GVariantType *) "aay") + + +/** + * G_VARIANT_TYPE: + * @type_string: a well-formed #GVariantType type string + * + * Converts a string to a const #GVariantType. Depending on the + * current debugging level, this function may perform a runtime check + * to ensure that @string is a valid GVariant type string. + * + * It is always a programmer error to use this macro with an invalid + * type string. + * + * Since 2.24 + **/ +#ifndef G_DISABLE_CHECKS +# define G_VARIANT_TYPE(type_string) (g_variant_type_checked_ ((type_string))) +#else +# define G_VARIANT_TYPE(type_string) ((const GVariantType *) (type_string)) +#endif + +/* type string checking */ +gboolean g_variant_type_string_is_valid (const gchar *type_string); +gboolean g_variant_type_string_scan (const gchar *string, + const gchar *limit, + const gchar **endptr); + +/* create/destroy */ +void g_variant_type_free (GVariantType *type); +GVariantType * g_variant_type_copy (const GVariantType *type); +GVariantType * g_variant_type_new (const gchar *type_string); + +/* getters */ +gsize g_variant_type_get_string_length (const GVariantType *type); +const gchar * g_variant_type_peek_string (const GVariantType *type); +gchar * g_variant_type_dup_string (const GVariantType *type); + +/* classification */ +gboolean g_variant_type_is_definite (const GVariantType *type); +gboolean g_variant_type_is_container (const GVariantType *type); +gboolean g_variant_type_is_basic (const GVariantType *type); +gboolean g_variant_type_is_maybe (const GVariantType *type); +gboolean g_variant_type_is_array (const GVariantType *type); +gboolean g_variant_type_is_tuple (const GVariantType *type); +gboolean g_variant_type_is_dict_entry (const GVariantType *type); +gboolean g_variant_type_is_variant (const GVariantType *type); + +/* for hash tables */ +guint g_variant_type_hash (gconstpointer type); +gboolean g_variant_type_equal (gconstpointer type1, + gconstpointer type2); + +/* subtypes */ +gboolean g_variant_type_is_subtype_of (const GVariantType *type, + const GVariantType *supertype); + +/* type iterator interface */ +const GVariantType * g_variant_type_element (const GVariantType *type); +const GVariantType * g_variant_type_first (const GVariantType *type); +const GVariantType * g_variant_type_next (const GVariantType *type); +gsize g_variant_type_n_items (const GVariantType *type); +const GVariantType * g_variant_type_key (const GVariantType *type); +const GVariantType * g_variant_type_value (const GVariantType *type); + +/* constructors */ +GVariantType * g_variant_type_new_array (const GVariantType *element); +GVariantType * g_variant_type_new_maybe (const GVariantType *element); +GVariantType * g_variant_type_new_tuple (const GVariantType * const *items, + gint length); +GVariantType * g_variant_type_new_dict_entry (const GVariantType *key, + const GVariantType *value); + +/*< private >*/ +const GVariantType * g_variant_type_checked_ (const gchar *); + +G_END_DECLS + +#endif /* __G_VARIANT_TYPE_H__ */ diff --git a/protocols/Sametime/src/glib/include/glib/gwin32.h b/protocols/Sametime/src/glib/include/glib/gwin32.h new file mode 100644 index 0000000000..5793335478 --- /dev/null +++ b/protocols/Sametime/src/glib/include/glib/gwin32.h @@ -0,0 +1,114 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#ifndef __G_WIN32_H__ +#define __G_WIN32_H__ + +#include <glib/gtypes.h> + +#ifdef G_PLATFORM_WIN32 + +G_BEGIN_DECLS + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#ifdef G_OS_WIN32 + +/* + * To get prototypes for the following POSIXish functions, you have to + * include the indicated non-POSIX headers. The functions are defined + * in OLDNAMES.LIB (MSVC) or -lmoldname-msvc (mingw32). But note that + * for POSIX functions that take or return file names in the system + * codepage, in many cases you would want to use the GLib wrappers in + * gstdio.h and UTF-8 instead. + * + * getcwd: <direct.h> (MSVC), <io.h> (mingw32) + * getpid: <process.h> + * access: <io.h> + * unlink: <stdio.h> or <io.h> + * open, read, write, lseek, close: <io.h> + * rmdir: <io.h> + * pipe: <io.h> (actually, _pipe()) + */ + +/* For some POSIX functions that are not provided by the MS runtime, + * we provide emulation functions in glib, which are prefixed with + * g_win32_. Or that was the idea at some time, but there is just one + * of those: + */ +gint g_win32_ftruncate (gint f, + guint size); +#endif /* G_OS_WIN32 */ + +/* The MS setlocale uses locale names of the form "English_United + * States.1252" etc. We want the Unixish standard form "en", "zh_TW" + * etc. This function gets the current thread locale from Windows and + * returns it as a string of the above form for use in forming file + * names etc. The returned string should be deallocated with g_free(). + */ +gchar* g_win32_getlocale (void); + +/* Translate a Win32 error code (as returned by GetLastError()) into + * the corresponding message. The returned string should be deallocated + * with g_free(). + */ +gchar* g_win32_error_message (gint error); + +#ifndef G_DISABLE_DEPRECATED + +#define g_win32_get_package_installation_directory g_win32_get_package_installation_directory_utf8 +#define g_win32_get_package_installation_subdirectory g_win32_get_package_installation_subdirectory_utf8 + +gchar* g_win32_get_package_installation_directory (const gchar *package, + const gchar *dll_name); + +gchar* g_win32_get_package_installation_subdirectory (const gchar *package, + const gchar *dll_name, + const gchar *subdir); + +#endif + +gchar* g_win32_get_package_installation_directory_of_module (gpointer hmodule); + +guint g_win32_get_windows_version (void); + +gchar* g_win32_locale_filename_from_utf8 (const gchar *utf8filename); + +/* As of GLib 2.14 we only support NT-based Windows */ +#define G_WIN32_IS_NT_BASED() TRUE +#define G_WIN32_HAVE_WIDECHAR_API() TRUE + +G_END_DECLS + +#endif /* G_PLATFORM_WIN32 */ + +#endif /* __G_WIN32_H__ */ diff --git a/protocols/Sametime/src/glib/include/glibconfig.h b/protocols/Sametime/src/glib/include/glibconfig.h new file mode 100644 index 0000000000..2fa4af628f --- /dev/null +++ b/protocols/Sametime/src/glib/include/glibconfig.h @@ -0,0 +1,284 @@ +/* glibconfig.h.win32.in. Originally merged from two versions of + * glibconfig.h, generated by the GLib configure script, for gcc and + * MSVC. + */ + +/* glibconfig.h + * + * This is a generated file. Please modify 'glibconfig.h.win32.in' + */ + +#ifndef __G_LIBCONFIG_H__ +#define __G_LIBCONFIG_H__ + +#include <glib/gmacros.h> + +#include <limits.h> +#include <float.h> + +G_BEGIN_DECLS + +#define G_MINFLOAT FLT_MIN +#define G_MAXFLOAT FLT_MAX +#define G_MINDOUBLE DBL_MIN +#define G_MAXDOUBLE DBL_MAX +#define G_MINSHORT SHRT_MIN +#define G_MAXSHORT SHRT_MAX +#define G_MAXUSHORT USHRT_MAX +#define G_MININT INT_MIN +#define G_MAXINT INT_MAX +#define G_MAXUINT UINT_MAX +#define G_MINLONG LONG_MIN +#define G_MAXLONG LONG_MAX +#define G_MAXULONG ULONG_MAX + +typedef signed char gint8; +typedef unsigned char guint8; +typedef signed short gint16; +typedef unsigned short guint16; +#define G_GINT16_MODIFIER "h" +#define G_GINT16_FORMAT "hi" +#define G_GUINT16_FORMAT "hu" +typedef signed int gint32; +typedef unsigned int guint32; +#define G_GINT32_MODIFIER "" +#define G_GINT32_FORMAT "i" +#define G_GUINT32_FORMAT "u" +#define G_HAVE_GINT64 1 /* deprecated, always true */ + +#ifndef _MSC_VER +G_GNUC_EXTENSION typedef signed long long gint64; +G_GNUC_EXTENSION typedef unsigned long long guint64; +#else /* _MSC_VER */ +typedef signed __int64 gint64; +typedef unsigned __int64 guint64; +#endif /* _MSC_VER */ + +#ifndef _MSC_VER +#define G_GINT64_CONSTANT(val) (G_GNUC_EXTENSION (val##LL)) +#else /* _MSC_VER */ +#define G_GINT64_CONSTANT(val) (val##i64) +#endif /* _MSC_VER */ +#ifndef _MSC_VER +#define G_GUINT64_CONSTANT(val) (G_GNUC_EXTENSION (val##ULL)) +#else /* _MSC_VER */ +#define G_GUINT64_CONSTANT(val) (val##Ui64) +#endif /* _MSC_VER */ +#define G_GINT64_MODIFIER "I64" +#define G_GINT64_FORMAT "I64i" +#define G_GUINT64_FORMAT "I64u" + +#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) + +#define GLIB_SIZEOF_VOID_P 8 +#define GLIB_SIZEOF_LONG 4 +#define GLIB_SIZEOF_SIZE_T 8 + +typedef signed long long gssize; +typedef unsigned long long gsize; +#define G_GSIZE_MODIFIER "I64" +#define G_GSSIZE_FORMAT "I64d" +#define G_GSIZE_FORMAT "I64u" + +#define G_MAXSIZE G_MAXUINT64 +#define G_MINSSIZE G_MININT64 +#define G_MAXSSIZE G_MAXINT64 + +#else + +#define GLIB_SIZEOF_VOID_P 4 +#define GLIB_SIZEOF_LONG 4 +#define GLIB_SIZEOF_SIZE_T 4 + +typedef signed int gssize; +typedef unsigned int gsize; +#define G_GSIZE_MODIFIER "" +#define G_GSSIZE_FORMAT "i" +#define G_GSIZE_FORMAT "u" + +#define G_MAXSIZE G_MAXUINT +#define G_MINSSIZE G_MININT +#define G_MAXSSIZE G_MAXINT + +#endif + +typedef gint64 goffset; +#define G_MINOFFSET G_MININT64 +#define G_MAXOFFSET G_MAXINT64 + +#define G_GOFFSET_MODIFIER G_GINT64_MODIFIER +#define G_GOFFSET_FORMAT G_GINT64_FORMAT +#define G_GOFFSET_CONSTANT(val) G_GINT64_CONSTANT(val) + + +#ifndef _WIN64 + +#define GPOINTER_TO_INT(p) ((gint) (p)) +#define GPOINTER_TO_UINT(p) ((guint) (p)) + +#define GINT_TO_POINTER(i) ((gpointer) (i)) +#define GUINT_TO_POINTER(u) ((gpointer) (u)) + +typedef signed int gintptr; +typedef unsigned int guintptr; + +#define G_GINTPTR_MODIFIER "" +#define G_GINTPTR_FORMAT "i" +#define G_GUINTPTR_FORMAT "u" + +#else + +#define GPOINTER_TO_INT(p) ((gint) (gint64) (p)) +#define GPOINTER_TO_UINT(p) ((guint) (guint64) (p)) + +#define GINT_TO_POINTER(i) ((gpointer) (gint64) (i)) +#define GUINT_TO_POINTER(u) ((gpointer) (guint64) (u)) + +#ifndef _MSC_VER +typedef signed long long gintptr; +typedef unsigned long long guintptr; +#else +typedef signed __int64 gintptr; +typedef unsigned __int64 guintptr; +#endif + +#define G_GINTPTR_MODIFIER "I64" +#define G_GINTPTR_FORMAT "I64i" +#define G_GUINTPTR_FORMAT "I64u" + +#endif + +#ifdef NeXT /* @#%@! NeXTStep */ +# define g_ATEXIT(proc) (!atexit (proc)) +#else +# define g_ATEXIT(proc) (atexit (proc)) +#endif + +#define g_memmove(dest,src,len) G_STMT_START { memmove ((dest), (src), (len)); } G_STMT_END + +#define GLIB_MAJOR_VERSION 2 +#define GLIB_MINOR_VERSION 26 +#define GLIB_MICRO_VERSION 1 + +#define G_OS_WIN32 +#define G_PLATFORM_WIN32 + + +#ifndef _MSC_VER +#define G_VA_COPY va_copy +#endif /* not _MSC_VER */ + +#ifdef __cplusplus +#define G_HAVE_INLINE 1 +#else /* !__cplusplus */ +#ifndef _MSC_VER +#define G_HAVE_INLINE 1 +#endif /* _MSC_VER */ +#define G_HAVE___INLINE 1 +#if !defined(_MSC_VER) && !defined(__DMC__) +#define G_HAVE___INLINE__ 1 +#endif /* !_MSC_VER and !__DMC__ */ +#endif /* !__cplusplus */ + +#define G_CAN_INLINE 1 + +#ifndef _MSC_VER +#define G_HAVE_ISO_VARARGS 1 + +/* gcc-2.95.x supports both gnu style and ISO varargs, but if -ansi + * is passed ISO vararg support is turned off, and there is no work + * around to turn it on, so we unconditionally turn it off. + */ +#if __GNUC__ == 2 && __GNUC_MINOR__ == 95 +# undef G_HAVE_ISO_VARARGS +#endif + +#define G_HAVE_GNUC_VARARGS 1 +#else /* _MSC_VER */ +/* varargs macros available since msvc8 (vs2005) */ +# if _MSC_VER >= 1400 +# define G_HAVE_ISO_VARARGS 1 +# endif +#endif /* not _MSC_VER */ +#define G_HAVE_GROWING_STACK 0 + +#define G_GNUC_INTERNAL + +#define G_THREADS_ENABLED +#define G_THREADS_IMPL_WIN32 +typedef struct _GMutex* GStaticMutex; +#define G_STATIC_MUTEX_INIT NULL +#define g_static_mutex_get_mutex(mutex) \ + (g_static_mutex_get_mutex_impl_shortcut (mutex)) +/* This represents a system thread as used by the implementation. An + * alien implementaion, as loaded by g_thread_init can only count on + * "sizeof (gpointer)" bytes to store their info. We however need more + * for some of our native implementations. */ +typedef union _GSystemThread GSystemThread; +union _GSystemThread +{ +#ifndef _WIN64 + char data[4]; +#else + char data[8]; +#endif + double dummy_double; + void *dummy_pointer; + long dummy_long; +}; + +#define GINT16_TO_LE(val) ((gint16) (val)) +#define GUINT16_TO_LE(val) ((guint16) (val)) +#define GINT16_TO_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val)) +#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val)) +#define GINT32_TO_LE(val) ((gint32) (val)) +#define GUINT32_TO_LE(val) ((guint32) (val)) +#define GINT32_TO_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val)) +#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val)) +#define GINT64_TO_LE(val) ((gint64) (val)) +#define GUINT64_TO_LE(val) ((guint64) (val)) +#define GINT64_TO_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val)) +#define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE (val)) +#define GLONG_TO_LE(val) ((glong) GINT32_TO_LE (val)) +#define GULONG_TO_LE(val) ((gulong) GUINT32_TO_LE (val)) +#define GLONG_TO_BE(val) ((glong) GINT32_TO_BE (val)) +#define GULONG_TO_BE(val) ((gulong) GUINT32_TO_BE (val)) +#define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val)) +#define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val)) +#define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val)) +#define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val)) +#define GSIZE_TO_LE(val) ((gsize) GUINT32_TO_LE (val)) +#define GSSIZE_TO_LE(val) ((gssize) GINT32_TO_LE (val)) +#define GSIZE_TO_BE(val) ((gsize) GUINT32_TO_BE (val)) +#define GSSIZE_TO_BE(val) ((gssize) GINT32_TO_BE (val)) +#define G_BYTE_ORDER G_LITTLE_ENDIAN + +#define GLIB_SYSDEF_POLLIN =1 +#define GLIB_SYSDEF_POLLOUT =4 +#define GLIB_SYSDEF_POLLPRI =2 +#define GLIB_SYSDEF_POLLHUP =16 +#define GLIB_SYSDEF_POLLERR =8 +#define GLIB_SYSDEF_POLLNVAL =32 + +#define G_MODULE_SUFFIX "dll" + +/* A GPid is an abstraction for a process "handle". It is *not* an + * abstraction for a process identifier in general. GPid is used in + * GLib only for descendant processes spawned with the g_spawn* + * functions. On POSIX there is no "process handle" concept as such, + * but on Windows a GPid is a handle to a process, a kind of pointer, + * not a process identifier. + */ +typedef void * GPid; + +#define GLIB_SYSDEF_AF_UNIX 1 +#define GLIB_SYSDEF_AF_INET 2 +#define GLIB_SYSDEF_AF_INET6 23 + +#define GLIB_SYSDEF_MSG_OOB 1 +#define GLIB_SYSDEF_MSG_PEEK 2 +#define GLIB_SYSDEF_MSG_DONTROUTE 4 + +G_END_DECLS + +#endif /* GLIBCONFIG_H */ diff --git a/protocols/Sametime/src/glib/lib32/glib-2.0.lib b/protocols/Sametime/src/glib/lib32/glib-2.0.lib Binary files differnew file mode 100644 index 0000000000..9ba0ee06e7 --- /dev/null +++ b/protocols/Sametime/src/glib/lib32/glib-2.0.lib diff --git a/protocols/Sametime/src/glib/lib64/glib-2.0.lib b/protocols/Sametime/src/glib/lib64/glib-2.0.lib Binary files differnew file mode 100644 index 0000000000..52616ec596 --- /dev/null +++ b/protocols/Sametime/src/glib/lib64/glib-2.0.lib diff --git a/protocols/Sametime/src/meanwhile/AUTHORS b/protocols/Sametime/src/meanwhile/AUTHORS new file mode 100644 index 0000000000..76f993f550 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/AUTHORS @@ -0,0 +1,10 @@ + +Maintainer: +Christopher (siege) O'Brien <siege@preoccupied.net> + +Packager: +Stepher Dawkins + +Patches: +Chris Ross +Jeremy Kerr diff --git a/protocols/Sametime/src/meanwhile/LICENSE b/protocols/Sametime/src/meanwhile/LICENSE new file mode 100644 index 0000000000..92b8903ff3 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/LICENSE @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 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. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/protocols/Sametime/src/meanwhile/README b/protocols/Sametime/src/meanwhile/README new file mode 100644 index 0000000000..fb83fec75e --- /dev/null +++ b/protocols/Sametime/src/meanwhile/README @@ -0,0 +1,39 @@ + +===================== +The Meanwhile Project +===================== + +http://meanwhile.sourceforge.net/ +Christopher (siege) O'Brien <siege@preoccupied.net> + +Meanwhile is a library for connecting to a LIM (Lotus Instant +Messaging, formerly Lotus Sametime, formerly VPBuddy) community. It +uses a protocol based in part off of the IMPP draft(*1), and in part +off of traces of TCP sessions from existing clients. + +Meanwhile-python is a set of Python wrappers for the Meanwhile library + +The gaim-meanwhile plugin allows Gaim to connect to a Lotus Sametime +(tm) community using a compiled-in version of libMeanwhile. + +See INSTALL for instructions on building and installing + + +======= +License +======= + +Meanwhile and Meanwhile-python are released under the LGPL. See +LICENSE for the full license text and terms. + +Meanwhile-gaim is released under the GPL + + +========= +Footnotes +========= + +(*1) draft-houri-sametime-community-client-00.txt submitted to the +IETF as a draft proposal for the IMPP working group charter. + + diff --git a/protocols/Sametime/src/meanwhile/src/channel.c b/protocols/Sametime/src/meanwhile/src/channel.c new file mode 100644 index 0000000000..a9dc2836be --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/channel.c @@ -0,0 +1,972 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <glib/ghash.h> +#include <glib/glist.h> +#include <string.h> + +#include "mw_channel.h" +#include "mw_cipher.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_util.h" + + +/** @todo reorganize this file, stuff is just strewn about */ + + +struct mwChannel { + + /** session this channel belongs to */ + struct mwSession *session; + + enum mwChannelState state; + + /** creator for incoming channel, target for outgoing channel */ + struct mwLoginInfo user; + + /* similar to data from the CreateCnl message in 8.4.1.7 */ + guint32 reserved; /**< special, unknown meaning */ + guint32 id; /**< channel ID */ + guint32 service; /**< service ID */ + guint32 proto_type; /**< service protocol type */ + guint32 proto_ver; /**< service protocol version */ + guint32 options; /**< channel options */ + + struct mwOpaque addtl_create; + struct mwOpaque addtl_accept; + + /** all those supported ciphers */ + GHashTable *supported; + guint16 offered_policy; /**< @see enum mwEncryptPolicy */ + guint16 policy; /**< @see enum mwEncryptPolicy */ + + /** cipher information determined at channel acceptance */ + struct mwCipherInstance *cipher; + + /** statistics table */ + GHashTable *stats; + + GSList *outgoing_queue; /**< queued outgoing messages */ + GSList *incoming_queue; /**< queued incoming messages */ + + struct mw_datum srvc_data; /**< service-specific data */ +}; + + +struct mwChannelSet { + struct mwSession *session; /**< owning session */ + GHashTable *map; /**< map of all channels, by ID */ + guint32 counter; /**< counter for outgoing ID */ +}; + + +static void flush_channel(struct mwChannel *); + + +static const char *state_str(enum mwChannelState state) { + switch(state) { + case mwChannel_NEW: return "new"; + case mwChannel_INIT: return "initializing"; + case mwChannel_WAIT: return "waiting"; + case mwChannel_OPEN: return "open"; + case mwChannel_DESTROY: return "closing"; + case mwChannel_ERROR: return "error"; + + case mwChannel_UNKNOWN: /* fall through */ + default: return "UNKNOWN"; + } +} + + +static void state(struct mwChannel *chan, enum mwChannelState state, + guint32 err_code) { + + g_return_if_fail(chan != NULL); + + if(chan->state == state) return; + + chan->state = state; + + if(err_code) { + g_message("channel 0x%08x state: %s (0x%08x)", + chan->id, state_str(state), err_code); + } else { + g_message("channel 0x%08x state: %s", chan->id, state_str(state)); + } +} + + +static gpointer get_stat(struct mwChannel *chan, + enum mwChannelStatField field) { + + return g_hash_table_lookup(chan->stats, (gpointer) field); +} + + +static void set_stat(struct mwChannel *chan, enum mwChannelStatField field, + gpointer val) { + + g_hash_table_insert(chan->stats, (gpointer) field, val); +} + +/// Miranda NG adaptation start - MSVC +//#define incr_stat(chan, field, incr) \ +// set_stat(chan, field, get_stat(chan, field) + incr) +#define incr_stat(chan, field, incr) \ + set_stat(chan, field, (char*)get_stat(chan, field) + incr) +/// Miranda NG adaptation end + +#define timestamp_stat(chan, field) \ + set_stat(chan, field, (gpointer) time(NULL)) + + +static void sup_free(gpointer a) { + mwCipherInstance_free(a); +} + + +static struct mwCipherInstance * +get_supported(struct mwChannel *chan, guint16 id) { + + guint32 cid = (guint32) id; + return g_hash_table_lookup(chan->supported, GUINT_TO_POINTER(cid)); +} + + +static void put_supported(struct mwChannel *chan, + struct mwCipherInstance *ci) { + + struct mwCipher *cipher = mwCipherInstance_getCipher(ci); + guint32 cid = (guint32) mwCipher_getType(cipher); + g_hash_table_insert(chan->supported, GUINT_TO_POINTER(cid), ci); +} + + +struct mwChannel *mwChannel_newIncoming(struct mwChannelSet *cs, guint32 id) { + struct mwChannel *chan; + + g_return_val_if_fail(cs != NULL, NULL); + g_return_val_if_fail(cs->session != NULL, NULL); + + chan = g_new0(struct mwChannel, 1); + chan->state = mwChannel_NEW; + chan->session = cs->session; + chan->id = id; + + chan->stats = g_hash_table_new(g_direct_hash, g_direct_equal); + + chan->supported = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, sup_free); + + g_hash_table_insert(cs->map, GUINT_TO_POINTER(id), chan); + + state(chan, mwChannel_WAIT, 0); + + return chan; +} + + +struct mwChannel *mwChannel_newOutgoing(struct mwChannelSet *cs) { + guint32 id; + struct mwChannel *chan; + + g_return_val_if_fail(cs != NULL, NULL); + g_return_val_if_fail(cs->map != NULL, NULL); + + /* grab the next id, and try to make sure there isn't already a + channel using it */ + do { + id = ++cs->counter; + } while(g_hash_table_lookup(cs->map, GUINT_TO_POINTER(id))); + + chan = mwChannel_newIncoming(cs, id); + state(chan, mwChannel_INIT, 0); + + return chan; +} + + +guint32 mwChannel_getId(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0); + return chan->id; +} + + +struct mwSession *mwChannel_getSession(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return chan->session; +} + + +guint32 mwChannel_getServiceId(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0); + return chan->service; +} + + +struct mwService *mwChannel_getService(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return mwSession_getService(chan->session, chan->service); +} + + +void mwChannel_setService(struct mwChannel *chan, struct mwService *srvc) { + g_return_if_fail(chan != NULL); + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan->state == mwChannel_INIT); + chan->service = mwService_getType(srvc); +} + + +gpointer mwChannel_getServiceData(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return mw_datum_get(&chan->srvc_data); +} + + +void mwChannel_setServiceData(struct mwChannel *chan, + gpointer data, GDestroyNotify clean) { + + g_return_if_fail(chan != NULL); + mw_datum_set(&chan->srvc_data, data, clean); +} + + +void mwChannel_removeServiceData(struct mwChannel *chan) { + g_return_if_fail(chan != NULL); + mw_datum_clear(&chan->srvc_data); +} + + +guint32 mwChannel_getProtoType(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0x00); + return chan->proto_type; +} + + +void mwChannel_setProtoType(struct mwChannel *chan, guint32 proto_type) { + g_return_if_fail(chan != NULL); + g_return_if_fail(chan->state == mwChannel_INIT); + chan->proto_type = proto_type; +} + + +guint32 mwChannel_getProtoVer(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0x00); + return chan->proto_ver; +} + + +void mwChannel_setProtoVer(struct mwChannel *chan, guint32 proto_ver) { + g_return_if_fail(chan != NULL); + g_return_if_fail(chan->state == mwChannel_INIT); + chan->proto_ver = proto_ver; +} + + +guint16 mwChannel_getEncryptPolicy(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0x00); + return chan->policy; +} + + +guint32 mwChannel_getOptions(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, 0x00); + return chan->options; +} + + +void mwChannel_setOptions(struct mwChannel *chan, guint32 options) { + g_return_if_fail(chan != NULL); + g_return_if_fail(chan->state == mwChannel_INIT); + chan->options = options; +} + + +struct mwLoginInfo *mwChannel_getUser(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return &chan->user; +} + + +struct mwOpaque *mwChannel_getAddtlCreate(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return &chan->addtl_create; +} + + +struct mwOpaque *mwChannel_getAddtlAccept(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, NULL); + return &chan->addtl_accept; +} + + +struct mwCipherInstance * +mwChannel_getCipherInstance(struct mwChannel *chan) { + + g_return_val_if_fail(chan != NULL, NULL); + return chan->cipher; +} + + +enum mwChannelState mwChannel_getState(struct mwChannel *chan) { + g_return_val_if_fail(chan != NULL, mwChannel_UNKNOWN); + return chan->state; +} + + +gpointer mwChannel_getStatistic(struct mwChannel *chan, + enum mwChannelStatField stat) { + + g_return_val_if_fail(chan != NULL, 0); + g_return_val_if_fail(chan->stats != NULL, 0); + + return get_stat(chan, stat); +} + + +/* send a channel create message */ +int mwChannel_create(struct mwChannel *chan) { + struct mwMsgChannelCreate *msg; + GList *list, *l; + int ret; + + g_return_val_if_fail(chan != NULL, -1); + g_return_val_if_fail(chan->state == mwChannel_INIT, -1); + g_return_val_if_fail(mwChannel_isOutgoing(chan), -1); + + msg = (struct mwMsgChannelCreate *) + mwMessage_new(mwMessage_CHANNEL_CREATE); + + msg->channel = chan->id; + msg->target.user = g_strdup(chan->user.user_id); + msg->target.community = g_strdup(chan->user.community); + msg->service = chan->service; + msg->proto_type = chan->proto_type; + msg->proto_ver = chan->proto_ver; + msg->options = chan->options; + mwOpaque_clone(&msg->addtl, &chan->addtl_create); + + list = mwChannel_getSupportedCipherInstances(chan); + if(list) { + /* offer what we have */ + for(l = list; l; l = l->next) { + struct mwEncryptItem *ei = mwCipherInstance_offer(l->data); + msg->encrypt.items = g_list_append(msg->encrypt.items, ei); + } + + /* we're easy to get along with */ + chan->offered_policy = mwEncrypt_WHATEVER; + g_list_free(list); + + } else { + /* we apparently don't support anything */ + chan->offered_policy = mwEncrypt_NONE; + } + + msg->encrypt.mode = chan->offered_policy; + msg->encrypt.extra = chan->offered_policy; + + ret = mwSession_send(chan->session, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + state(chan, (ret)? mwChannel_ERROR: mwChannel_WAIT, ret); + + return ret; +} + + +static void channel_open(struct mwChannel *chan) { + state(chan, mwChannel_OPEN, 0); + timestamp_stat(chan, mwChannelStat_OPENED_AT); + flush_channel(chan); +} + + +int mwChannel_accept(struct mwChannel *chan) { + struct mwSession *session; + struct mwMsgChannelAccept *msg; + struct mwCipherInstance *ci; + + int ret; + + g_return_val_if_fail(chan != NULL, -1); + g_return_val_if_fail(mwChannel_isIncoming(chan), -1); + g_return_val_if_fail(chan->state == mwChannel_WAIT, -1); + + session = chan->session; + g_return_val_if_fail(session != NULL, -1); + + msg = (struct mwMsgChannelAccept *) + mwMessage_new(mwMessage_CHANNEL_ACCEPT); + + msg->head.channel = chan->id; + msg->service = chan->service; + msg->proto_type = chan->proto_type; + msg->proto_ver = chan->proto_ver; + mwOpaque_clone(&msg->addtl, &chan->addtl_accept); + + ci = chan->cipher; + + if(! ci) { + /* automatically select a cipher if one hasn't been already */ + + switch(chan->offered_policy) { + case mwEncrypt_NONE: + mwChannel_selectCipherInstance(chan, NULL); + break; + + case mwEncrypt_RC2_40: + ci = get_supported(chan, mwCipher_RC2_40); + mwChannel_selectCipherInstance(chan, ci); + break; + + case mwEncrypt_RC2_128: + ci = get_supported(chan, mwCipher_RC2_128); + mwChannel_selectCipherInstance(chan, ci); + break; + + case mwEncrypt_WHATEVER: + case mwEncrypt_ALL: + default: + { + GList *l, *ll; + + l = mwChannel_getSupportedCipherInstances(chan); + if(l) { + /* nobody selected a cipher, so we'll just pick the last in + the list of available ones */ + for(ll = l; ll->next; ll = ll->next); + ci = ll->data; + g_list_free(l); + + mwChannel_selectCipherInstance(chan, ci); + + } else { + /* this may cause breakage, but there's really nothing else + we can do. They want something we can't provide. If they + don't like it, then they'll error the channel out */ + mwChannel_selectCipherInstance(chan, NULL); + } + } + } + } + + msg->encrypt.mode = chan->policy; /* set in selectCipherInstance */ + msg->encrypt.extra = chan->offered_policy; + + if(chan->cipher) { + msg->encrypt.item = mwCipherInstance_accept(chan->cipher); + } + + ret = mwSession_send(session, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + if(ret) { + state(chan, mwChannel_ERROR, ret); + } else { + channel_open(chan); + } + + return ret; +} + + +static void channel_free(struct mwChannel *chan) { + struct mwSession *s; + struct mwMessage *msg; + GSList *l; + + /* maybe no warning in the future */ + g_return_if_fail(chan != NULL); + + s = chan->session; + + mwLoginInfo_clear(&chan->user); + mwOpaque_clear(&chan->addtl_create); + mwOpaque_clear(&chan->addtl_accept); + + if(chan->supported) { + g_hash_table_destroy(chan->supported); + chan->supported = NULL; + } + + if(chan->stats) { + g_hash_table_destroy(chan->stats); + chan->stats = NULL; + } + + mwCipherInstance_free(chan->cipher); + + /* clean up the outgoing queue */ + for(l = chan->outgoing_queue; l; l = l->next) { + msg = (struct mwMessage *) l->data; + l->data = NULL; + mwMessage_free(msg); + } + g_slist_free(chan->outgoing_queue); + + /* clean up the incoming queue */ + for(l = chan->incoming_queue; l; l = l->next) { + msg = (struct mwMessage *) l->data; + l->data = NULL; + mwMessage_free(msg); + } + g_slist_free(chan->incoming_queue); + + g_free(chan); +} + + +int mwChannel_destroy(struct mwChannel *chan, + guint32 reason, struct mwOpaque *info) { + + struct mwMsgChannelDestroy *msg; + struct mwSession *session; + struct mwChannelSet *cs; + int ret; + + /* may make this not a warning in the future */ + g_return_val_if_fail(chan != NULL, 0); + + state(chan, reason? mwChannel_ERROR: mwChannel_DESTROY, reason); + + session = chan->session; + g_return_val_if_fail(session != NULL, -1); + + cs = mwSession_getChannels(session); + g_return_val_if_fail(cs != NULL, -1); + + /* compose the message */ + msg = (struct mwMsgChannelDestroy *) + mwMessage_new(mwMessage_CHANNEL_DESTROY); + msg->head.channel = chan->id; + msg->reason = reason; + if(info) mwOpaque_clone(&msg->data, info); + + /* remove the channel from the channel set */ + g_hash_table_remove(cs->map, GUINT_TO_POINTER(chan->id)); + + /* send the message */ + ret = mwSession_send(session, (struct mwMessage *) msg); + mwMessage_free(MW_MESSAGE(msg)); + + return ret; +} + + +static void queue_outgoing(struct mwChannel *chan, + struct mwMsgChannelSend *msg) { + // Miranda NG adaptation + //g_info("queue_outgoing, channel 0x%08x", chan->id); + g_message("queue_outgoing, channel 0x%08x", chan->id); + chan->outgoing_queue = g_slist_append(chan->outgoing_queue, msg); +} + + +static int channel_send(struct mwChannel *chan, + struct mwMsgChannelSend *msg) { + + int ret = 0; + + /* if the channel is open, send and free the message. Otherwise, + queue the message to be sent once the channel is finally + opened */ + + if(chan->state == mwChannel_OPEN) { + ret = mwSession_send(chan->session, (struct mwMessage *) msg); + mwMessage_free(MW_MESSAGE(msg)); + + } else { + queue_outgoing(chan, msg); + } + + return ret; +} + + +int mwChannel_sendEncrypted(struct mwChannel *chan, + guint32 type, struct mwOpaque *data, + gboolean encrypt) { + + struct mwMsgChannelSend *msg; + + g_return_val_if_fail(chan != NULL, -1); + + msg = (struct mwMsgChannelSend *) mwMessage_new(mwMessage_CHANNEL_SEND); + msg->head.channel = chan->id; + msg->type = type; + + mwOpaque_clone(&msg->data, data); + + if(encrypt && chan->cipher) { + msg->head.options = mwMessageOption_ENCRYPT; + mwCipherInstance_encrypt(chan->cipher, &msg->data); + } + + return channel_send(chan, msg); +} + + +int mwChannel_send(struct mwChannel *chan, guint32 type, + struct mwOpaque *data) { + + return mwChannel_sendEncrypted(chan, type, data, TRUE); +} + + +static void queue_incoming(struct mwChannel *chan, + struct mwMsgChannelSend *msg) { + + /* we clone the message, because session_process will clear it once + we return */ + + struct mwMsgChannelSend *m = g_new0(struct mwMsgChannelSend, 1); + m->head.type = msg->head.type; + m->head.options = msg->head.options; + m->head.channel = msg->head.channel; + mwOpaque_clone(&m->head.attribs, &msg->head.attribs); + + m->type = msg->type; + mwOpaque_clone(&m->data, &msg->data); + + // Miranda NG adaptation + //g_info("queue_incoming, channel 0x%08x", chan->id); + g_message("queue_incoming, channel 0x%08x", chan->id); + chan->incoming_queue = g_slist_append(chan->incoming_queue, m); +} + + +static void channel_recv(struct mwChannel *chan, + struct mwMsgChannelSend *msg) { + + struct mwService *srvc; + + srvc = mwChannel_getService(chan); + incr_stat(chan, mwChannelStat_MSG_RECV, 1); + + if(msg->head.options & mwMessageOption_ENCRYPT) { + struct mwOpaque data = { 0, 0 }; + mwOpaque_clone(&data, &msg->data); + + mwCipherInstance_decrypt(chan->cipher, &data); + mwService_recv(srvc, chan, msg->type, &data); + mwOpaque_clear(&data); + + } else { + mwService_recv(srvc, chan, msg->type, &msg->data); + } +} + + +static void flush_channel(struct mwChannel *chan) { + GSList *l; + + for(l = chan->incoming_queue; l; l = l->next) { + struct mwMsgChannelSend *msg = (struct mwMsgChannelSend *) l->data; + l->data = NULL; + + channel_recv(chan, msg); + mwMessage_free(MW_MESSAGE(msg)); + } + g_slist_free(chan->incoming_queue); + chan->incoming_queue = NULL; + + for(l = chan->outgoing_queue; l; l = l->next) { + struct mwMessage *msg = (struct mwMessage *) l->data; + l->data = NULL; + + mwSession_send(chan->session, msg); + mwMessage_free(msg); + } + g_slist_free(chan->outgoing_queue); + chan->outgoing_queue = NULL; +} + + +void mwChannel_recv(struct mwChannel *chan, struct mwMsgChannelSend *msg) { + if(chan->state == mwChannel_OPEN) { + channel_recv(chan, msg); + + } else { + queue_incoming(chan, msg); + } +} + + +struct mwChannel *mwChannel_find(struct mwChannelSet *cs, guint32 chan) { + g_return_val_if_fail(cs != NULL, NULL); + g_return_val_if_fail(cs->map != NULL, NULL); + return g_hash_table_lookup(cs->map, GUINT_TO_POINTER(chan)); +} + + +void mwChannelSet_free(struct mwChannelSet *cs) { + if(! cs) return; + if(cs->map) g_hash_table_destroy(cs->map); + g_free(cs); +} + + +struct mwChannelSet *mwChannelSet_new(struct mwSession *s) { + struct mwChannelSet *cs = g_new0(struct mwChannelSet, 1); + cs->session = s; + + /* for some reason, g_int_hash/g_int_equal cause a SIGSEGV */ + cs->map = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) channel_free); + return cs; +} + + +void mwChannel_recvCreate(struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + struct mwSession *session; + GList *list; + struct mwService *srvc; + + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(chan->id == msg->channel); + + session = chan->session; + g_return_if_fail(session != NULL); + + if(mwChannel_isOutgoing(chan)) { + g_warning("channel 0x%08x not an incoming channel", chan->id); + mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); + return; + } + + chan->offered_policy = msg->encrypt.mode; + g_message("channel offered with encrypt policy 0x%04x", chan->policy); + + for(list = msg->encrypt.items; list; list = list->next) { + struct mwEncryptItem *ei = list->data; + struct mwCipher *cipher; + struct mwCipherInstance *ci; + + g_message("channel offered cipher id 0x%04x", ei->id); + cipher = mwSession_getCipher(session, ei->id); + if(! cipher) { + g_message("no such cipher found in session"); + continue; + } + + ci = mwCipher_newInstance(cipher, chan); + mwCipherInstance_offered(ci, ei); + mwChannel_addSupportedCipherInstance(chan, ci); + } + + mwLoginInfo_clone(&chan->user, &msg->creator); + chan->service = msg->service; + chan->proto_type = msg->proto_type; + chan->proto_ver = msg->proto_ver; + + srvc = mwSession_getService(session, msg->service); + if(srvc) { + mwService_recvCreate(srvc, chan, msg); + + } else { + mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL); + } +} + + +void mwChannel_recvAccept(struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + struct mwService *srvc; + + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(chan->id == msg->head.channel); + + if(mwChannel_isIncoming(chan)) { + g_warning("channel 0x%08x not an outgoing channel", chan->id); + mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); + return; + } + + if(chan->state != mwChannel_WAIT) { + g_warning("channel 0x%08x state not WAIT: %s", + chan->id, state_str(chan->state)); + mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); + return; + } + + mwLoginInfo_clone(&chan->user, &msg->acceptor); + + srvc = mwSession_getService(chan->session, chan->service); + if(! srvc) { + g_warning("no service: 0x%08x", chan->service); + mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL); + return; + } + + chan->policy = msg->encrypt.mode; + g_message("channel accepted with encrypt policy 0x%04x", chan->policy); + + if(! msg->encrypt.mode || ! msg->encrypt.item) { + /* no mode or no item means no encryption */ + mwChannel_selectCipherInstance(chan, NULL); + + } else { + guint16 cid = msg->encrypt.item->id; + struct mwCipherInstance *ci = get_supported(chan, cid); + + if(! ci) { + g_warning("not an offered cipher: 0x%04x", cid); + mwChannel_destroy(chan, ERR_REQUEST_INVALID, NULL); + return; + } + + mwCipherInstance_accepted(ci, msg->encrypt.item); + mwChannel_selectCipherInstance(chan, ci); + } + + /* mark it as open for the service */ + state(chan, mwChannel_OPEN, 0); + + /* let the service know */ + mwService_recvAccept(srvc, chan, msg); + + /* flush it if the service didn't just immediately close it */ + if(mwChannel_isState(chan, mwChannel_OPEN)) { + channel_open(chan); + } +} + + +void mwChannel_recvDestroy(struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + struct mwChannelSet *cs; + struct mwService *srvc; + + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(chan->id == msg->head.channel); + + state(chan, msg->reason? mwChannel_ERROR: mwChannel_DESTROY, msg->reason); + + srvc = mwChannel_getService(chan); + if(srvc) mwService_recvDestroy(srvc, chan, msg); + + cs = mwSession_getChannels(chan->session); + g_return_if_fail(cs != NULL); + g_return_if_fail(cs->map != NULL); + + g_hash_table_remove(cs->map, GUINT_TO_POINTER(chan->id)); +} + + +void mwChannel_populateSupportedCipherInstances(struct mwChannel *chan) { + struct mwSession *session; + GList *list; + + g_return_if_fail(chan != NULL); + + session = chan->session; + g_return_if_fail(session != NULL); + + for(list = mwSession_getCiphers(session); list; list = list->next) { + struct mwCipherInstance *ci = mwCipher_newInstance(list->data, chan); + if(! ci) continue; + put_supported(chan, ci); + } +} + + +void mwChannel_addSupportedCipherInstance(struct mwChannel *chan, + struct mwCipherInstance *ci) { + g_return_if_fail(chan != NULL); + g_message("channel 0x%08x added cipher %s", chan->id, + NSTR(mwCipher_getName(mwCipherInstance_getCipher(ci)))); + put_supported(chan, ci); +} + + +static void collect(gpointer a, gpointer b, gpointer c) { + GList **list = c; + *list = g_list_append(*list, b); +} + + +GList *mwChannel_getSupportedCipherInstances(struct mwChannel *chan) { + GList *list = NULL; + + g_return_val_if_fail(chan != NULL, NULL); + g_hash_table_foreach(chan->supported, collect, &list); + + return list; +} + + +void mwChannel_selectCipherInstance(struct mwChannel *chan, + struct mwCipherInstance *ci) { + struct mwCipher *c; + + g_return_if_fail(chan != NULL); + g_return_if_fail(chan->supported != NULL); + + chan->cipher = ci; + if(ci) { + guint cid; + + c = mwCipherInstance_getCipher(ci); + cid = mwCipher_getType(c); + + g_hash_table_steal(chan->supported, GUINT_TO_POINTER(cid)); + + switch(mwCipher_getType(c)) { + case mwCipher_RC2_40: + chan->policy = mwEncrypt_RC2_40; + break; + + case mwCipher_RC2_128: + chan->policy = mwEncrypt_RC2_128; + break; + + default: + /* unsure if this is bad */ + chan->policy = mwEncrypt_WHATEVER; + } + + g_message("channel 0x%08x selected cipher %s", + chan->id, NSTR(mwCipher_getName(c))); + + } else { + + chan->policy = mwEncrypt_NONE; + g_message("channel 0x%08x selected no cipher", chan->id); + } + + g_hash_table_destroy(chan->supported); + chan->supported = NULL; +} + + diff --git a/protocols/Sametime/src/meanwhile/src/cipher.c b/protocols/Sametime/src/meanwhile/src/cipher.c new file mode 100644 index 0000000000..8e5bd6f042 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/cipher.c @@ -0,0 +1,982 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdlib.h> +#include <time.h> + +#include "mpi/mpi.h" + +#include "mw_channel.h" +#include "mw_cipher.h" +#include "mw_debug.h" +#include "mw_session.h" + + +struct mwMpi { + mw_mp_int i; +}; + + +/** From RFC2268 */ +static guchar PT[] = { + 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, + 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, + 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, + 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, + 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, + 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, + 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, + 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, + 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, + 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, + 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, + 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, + 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, + 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, + 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, + 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, + 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, + 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, + 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, + 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, + 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, + 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, + 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, + 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, + 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, + 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, + 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, + 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, + 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, + 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, + 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, + 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD +}; + + +/** prime number used in DH exchange */ +static guchar dh_prime[] = { + 0xCF, 0x84, 0xAF, 0xCE, 0x86, 0xDD, 0xFA, 0x52, + 0x7F, 0x13, 0x6D, 0x10, 0x35, 0x75, 0x28, 0xEE, + 0xFB, 0xA0, 0xAF, 0xEF, 0x80, 0x8F, 0x29, 0x17, + 0x4E, 0x3B, 0x6A, 0x9E, 0x97, 0x00, 0x01, 0x71, + 0x7C, 0x8F, 0x10, 0x6C, 0x41, 0xC1, 0x61, 0xA6, + 0xCE, 0x91, 0x05, 0x7B, 0x34, 0xDA, 0x62, 0xCB, + 0xB8, 0x7B, 0xFD, 0xC1, 0xB3, 0x5C, 0x1B, 0x91, + 0x0F, 0xEA, 0x72, 0x24, 0x9D, 0x56, 0x6B, 0x9F +}; + + +/** base used in DH exchange */ +#define DH_BASE 3 + + +struct mwMpi *mwMpi_new() { + struct mwMpi *i; + i = g_new0(struct mwMpi, 1); + mw_mp_init(&i->i); + return i; +} + + +void mwMpi_free(struct mwMpi *i) { + if(! i) return; + mw_mp_clear(&i->i); + g_free(i); +} + + +static void mwInitDHPrime(mw_mp_int *i) { + mw_mp_init(i); + mw_mp_read_unsigned_bin(i, dh_prime, 64); +} + + +void mwMpi_setDHPrime(struct mwMpi *i) { + g_return_if_fail(i != NULL); + mw_mp_read_unsigned_bin(&i->i, dh_prime, 64); +} + + +static void mwInitDHBase(mw_mp_int *i) { + mw_mp_init(i); + mw_mp_set_int(i, DH_BASE); +} + + +void mwMpi_setDHBase(struct mwMpi *i) { + g_return_if_fail(i != NULL); + mw_mp_set_int(&i->i, DH_BASE); +} + + +static void mw_mp_set_rand(mw_mp_int *i, guint bits) { + size_t len, l; + guchar *buf; + + l = len = (bits / 8) + 1; + buf = g_malloc(len); + + /// Miranda NG adaptation start - MSVC + //srand(time(NULL)); + srand((unsigned int)time(NULL)); + /// Miranda NG adaptation end + + while(l--) buf[l] = rand() & 0xff; + + buf[0] &= (0xff >> (8 - (bits % 8))); + + mw_mp_read_unsigned_bin(i, buf, len); + g_free(buf); +} + + +static void mwDHRandKeypair(mw_mp_int *private_key, mw_mp_int *public_key) { + mw_mp_int prime, base; + + mwInitDHPrime(&prime); + mwInitDHBase(&base); + + mw_mp_set_rand(private_key, 512); + mw_mp_exptmod(&base, private_key, &prime, public_key); + + mw_mp_clear(&prime); + mw_mp_clear(&base); +} + + +void mwMpi_randDHKeypair(struct mwMpi *private_key, struct mwMpi *public_key) { + g_return_if_fail(private_key != NULL); + g_return_if_fail(public_key != NULL); + + mwDHRandKeypair(&private_key->i, &public_key->i); +} + + +static void mwDHCalculateShared(mw_mp_int *shared_key, mw_mp_int *remote_key, + mw_mp_int *private_key) { + mw_mp_int prime; + + mwInitDHPrime(&prime); + mw_mp_exptmod(remote_key, private_key, &prime, shared_key); + mw_mp_clear(&prime); +} + + +void mwMpi_calculateDHShared(struct mwMpi *shared_key, struct mwMpi *remote_key, + struct mwMpi *private_key) { + + g_return_if_fail(shared_key != NULL); + g_return_if_fail(remote_key != NULL); + g_return_if_fail(private_key != NULL); + + mwDHCalculateShared(&shared_key->i, &remote_key->i, &private_key->i); +} + + +static void mwDHImportKey(mw_mp_int *key, struct mwOpaque *o) { + mw_mp_read_unsigned_bin(key, o->data, o->len); +} + + +void mwMpi_import(struct mwMpi *i, struct mwOpaque *o) { + g_return_if_fail(i != NULL); + g_return_if_fail(o != NULL); + + mwDHImportKey(&i->i, o); +} + + +static void mwDHExportKey(mw_mp_int *key, struct mwOpaque *o) { + o->len = mw_mp_unsigned_bin_size(key); + o->data = g_malloc0(o->len); + mw_mp_to_unsigned_bin(key, o->data); +} + + +void mwMpi_export(struct mwMpi *i, struct mwOpaque *o) { + g_return_if_fail(i != NULL); + g_return_if_fail(o != NULL); + + mwDHExportKey(&i->i, o); +} + + +void mwKeyRandom(guchar *key, gsize keylen) { + g_return_if_fail(key != NULL); + + /// Miranda NG adaptation start - MSVC + //srand(time(NULL)); + srand((unsigned int)time(NULL)); + /// Miranda NG adaptation end + while(keylen--) key[keylen] = rand() & 0xff; +} + + +void mwIV_init(guchar *iv) { + iv[0] = 0x01; + iv[1] = 0x23; + iv[2] = 0x45; + iv[3] = 0x67; + iv[4] = 0x89; + iv[5] = 0xab; + iv[6] = 0xcd; + iv[7] = 0xef; +} + + +/* This does not seem to produce the same results as normal RC2 key + expansion would, but it works, so eh. It might be smart to farm + this out to mozilla or openssl */ +void mwKeyExpand(int *ekey, const guchar *key, gsize keylen) { + guchar tmp[128]; + int i, j; + + g_return_if_fail(keylen > 0); + g_return_if_fail(key != NULL); + + if(keylen > 128) keylen = 128; + + /* fill the first chunk with what key bytes we have */ + for(i = keylen; i--; tmp[i] = key[i]); + /* memcpy(tmp, key, keylen); */ + + /* build the remaining key from the given data */ + for(i = 0; keylen < 128; i++) { + tmp[keylen] = PT[ (tmp[keylen - 1] + tmp[i]) & 0xff ]; + keylen++; + } + + tmp[0] = PT[ tmp[0] & 0xff ]; + + for(i = 0, j = 0; i < 64; i++) { + ekey[i] = (tmp[j] & 0xff) | (tmp[j+1] << 8); + j += 2; + } +} + + +/* normal RC2 encryption given a full 128-byte (as 64 ints) key */ +static void mwEncryptBlock(const int *ekey, guchar *out) { + + int a, b, c, d; + int i, j; + + a = (out[7] << 8) | (out[6] & 0xff); + b = (out[5] << 8) | (out[4] & 0xff); + c = (out[3] << 8) | (out[2] & 0xff); + d = (out[1] << 8) | (out[0] & 0xff); + + for(i = 0; i < 16; i++) { + j = i * 4; + + d += ((c & (a ^ 0xffff)) + (b & a) + ekey[j++]); + d = (d << 1) | (d >> 15 & 0x0001); + + c += ((b & (d ^ 0xffff)) + (a & d) + ekey[j++]); + c = (c << 2) | (c >> 14 & 0x0003); + + b += ((a & (c ^ 0xffff)) + (d & c) + ekey[j++]); + b = (b << 3) | (b >> 13 & 0x0007); + + a += ((d & (b ^ 0xffff)) + (c & b) + ekey[j++]); + a = (a << 5) | (a >> 11 & 0x001f); + + if(i == 4 || i == 10) { + d += ekey[a & 0x003f]; + c += ekey[d & 0x003f]; + b += ekey[c & 0x003f]; + a += ekey[b & 0x003f]; + } + } + + *out++ = d & 0xff; + *out++ = (d >> 8) & 0xff; + *out++ = c & 0xff; + *out++ = (c >> 8) & 0xff; + *out++ = b & 0xff; + *out++ = (b >> 8) & 0xff; + *out++ = a & 0xff; + *out++ = (a >> 8) & 0xff; +} + + +void mwEncryptExpanded(const int *ekey, guchar *iv, + struct mwOpaque *in_data, + struct mwOpaque *out_data) { + + guchar *i = in_data->data; + gsize i_len = in_data->len; + + guchar *o; + gsize o_len; + + /// Miranda NG adaptation start - MSVC + ///int x, y; + gsize x; + int y; + /// Miranda NG adaptation end + + /* pad upwards to a multiple of 8 */ + /* o_len = (i_len & -8) + 8; */ + o_len = i_len + (8 - (i_len % 8)); + o = g_malloc(o_len); + + out_data->data = o; + out_data->len = o_len; + + /* figure out the amount of padding */ + y = o_len - i_len; + + /* copy in to out, and write padding bytes */ + for(x = i_len; x--; o[x] = i[x]); + for(x = i_len; x < o_len; o[x++] = y); + /* memcpy(o, i, i_len); + memset(o + i_len, y, y); */ + + /* encrypt in blocks */ + for(x = o_len; x > 0; x -= 8) { + for(y = 8; y--; o[y] ^= iv[y]); + mwEncryptBlock(ekey, o); + for(y = 8; y--; iv[y] = o[y]); + /* memcpy(iv, o, 8); */ + o += 8; + } +} + + +void mwEncrypt(const guchar *key, gsize keylen, guchar *iv, + struct mwOpaque *in, struct mwOpaque *out) { + + int ekey[64]; + mwKeyExpand(ekey, key, keylen); + mwEncryptExpanded(ekey, iv, in, out); +} + + +static void mwDecryptBlock(const int *ekey, guchar *out) { + + int a, b, c, d; + int i, j; + + a = (out[7] << 8) | (out[6] & 0xff); + b = (out[5] << 8) | (out[4] & 0xff); + c = (out[3] << 8) | (out[2] & 0xff); + d = (out[1] << 8) | (out[0] & 0xff); + + for(i = 16; i--; ) { + j = i * 4 + 3; + + a = (a << 11) | (a >> 5 & 0x07ff); + a -= ((d & (b ^ 0xffff)) + (c & b) + ekey[j--]); + + b = (b << 13) | (b >> 3 & 0x1fff); + b -= ((a & (c ^ 0xffff)) + (d & c) + ekey[j--]); + + c = (c << 14) | (c >> 2 & 0x3fff); + c -= ((b & (d ^ 0xffff)) + (a & d) + ekey[j--]); + + d = (d << 15) | (d >> 1 & 0x7fff); + d -= ((c & (a ^ 0xffff)) + (b & a) + ekey[j--]); + + if(i == 5 || i == 11) { + a -= ekey[b & 0x003f]; + b -= ekey[c & 0x003f]; + c -= ekey[d & 0x003f]; + d -= ekey[a & 0x003f]; + } + } + + *out++ = d & 0xff; + *out++ = (d >> 8) & 0xff; + *out++ = c & 0xff; + *out++ = (c >> 8) & 0xff; + *out++ = b & 0xff; + *out++ = (b >> 8) & 0xff; + *out++ = a & 0xff; + *out++ = (a >> 8) & 0xff; +} + + +void mwDecryptExpanded(const int *ekey, guchar *iv, + struct mwOpaque *in_data, + struct mwOpaque *out_data) { + + guchar *i = in_data->data; + gsize i_len = in_data->len; + + guchar *o; + gsize o_len; + + int x, y; + + if(i_len % 8) { + /* this doesn't check to ensure that in_data->len is a multiple of + 8, which is damn well ought to be. */ + g_warning("attempting decryption of mis-sized data, %u bytes", + (guint) i_len); + } + + o = g_malloc(i_len); + o_len = i_len; + for(x = i_len; x--; o[x] = i[x]); + /* memcpy(o, i, i_len); */ + + out_data->data = o; + out_data->len = o_len; + + for(x = o_len; x > 0; x -= 8) { + /* decrypt a block */ + mwDecryptBlock(ekey, o); + + /* modify the initialization vector */ + for(y = 8; y--; o[y] ^= iv[y]); + for(y = 8; y--; iv[y] = i[y]); + /* memcpy(iv, i, 8); */ + i += 8; + o += 8; + } + + /* shorten the length by the value of the filler in the padding + bytes */ + out_data->len -= *(o - 1); +} + + +void mwDecrypt(const guchar *key, gsize keylen, guchar *iv, + struct mwOpaque *in, struct mwOpaque *out) { + + int ekey[64]; + mwKeyExpand(ekey, key, keylen); + mwDecryptExpanded(ekey, iv, in, out); +} + + + +struct mwCipher_RC2_40 { + struct mwCipher cipher; + int session_key[64]; + gboolean ready; +}; + + +struct mwCipherInstance_RC2_40 { + struct mwCipherInstance instance; + int incoming_key[64]; + guchar outgoing_iv[8]; + guchar incoming_iv[8]; +}; + + +static const char *get_name_RC2_40() { + return "RC2/40 Cipher"; +} + + +static const char *get_desc_RC2_40() { + return "RC2, 40-bit effective key"; +} + + +static int encrypt_RC2_40(struct mwCipherInstance *ci, + struct mwOpaque *data) { + + struct mwCipherInstance_RC2_40 *cir; + struct mwCipher_RC2_40 *cr; + struct mwOpaque o = { 0, 0 }; + + cir = (struct mwCipherInstance_RC2_40 *) ci; + cr = (struct mwCipher_RC2_40 *) ci->cipher; + + mwEncryptExpanded(cr->session_key, cir->outgoing_iv, data, &o); + + mwOpaque_clear(data); + data->data = o.data; + data->len = o.len; + + return 0; +} + + +static int decrypt_RC2_40(struct mwCipherInstance *ci, + struct mwOpaque *data) { + + struct mwCipherInstance_RC2_40 *cir; + struct mwCipher_RC2_40 *cr; + struct mwOpaque o = { 0, 0 }; + + cir = (struct mwCipherInstance_RC2_40 *) ci; + cr = (struct mwCipher_RC2_40 *) ci->cipher; + + mwDecryptExpanded(cir->incoming_key, cir->incoming_iv, data, &o); + + mwOpaque_clear(data); + data->data = o.data; + data->len = o.len; + + return 0; +} + + +static struct mwCipherInstance * +new_instance_RC2_40(struct mwCipher *cipher, + struct mwChannel *chan) { + + struct mwCipher_RC2_40 *cr; + struct mwCipherInstance_RC2_40 *cir; + struct mwCipherInstance *ci; + + cr = (struct mwCipher_RC2_40 *) cipher; + + /* a bit of lazy initialization here */ + if(! cr->ready) { + struct mwLoginInfo *info = mwSession_getLoginInfo(cipher->session); + mwKeyExpand(cr->session_key, (guchar *) info->login_id, 5); + cr->ready = TRUE; + } + + cir = g_new0(struct mwCipherInstance_RC2_40, 1); + ci = &cir->instance; + + ci->cipher = cipher; + ci->channel = chan; + + mwIV_init(cir->incoming_iv); + mwIV_init(cir->outgoing_iv); + + return ci; +} + + +static struct mwEncryptItem *new_item_RC2_40(struct mwCipherInstance *ci) { + struct mwEncryptItem *e; + + e = g_new0(struct mwEncryptItem, 1); + e->id = mwCipher_RC2_40; + return e; +} + + +static struct mwEncryptItem * +offer_RC2_40(struct mwCipherInstance *ci) { + return new_item_RC2_40(ci); +} + + +static void accepted_RC2_40(struct mwCipherInstance *ci, + struct mwEncryptItem *item) { + + struct mwCipherInstance_RC2_40 *cir; + struct mwLoginInfo *info; + + cir = (struct mwCipherInstance_RC2_40 *) ci; + info = mwChannel_getUser(ci->channel); + + if(info->login_id) { + mwKeyExpand(cir->incoming_key, (guchar *) info->login_id, 5); + } +} + + +static struct mwEncryptItem * +accept_RC2_40(struct mwCipherInstance *ci) { + + accepted_RC2_40(ci, NULL); + return new_item_RC2_40(ci); +} + + +struct mwCipher *mwCipher_new_RC2_40(struct mwSession *s) { + struct mwCipher_RC2_40 *cr = g_new0(struct mwCipher_RC2_40, 1); + struct mwCipher *c = &cr->cipher; + + c->session = s; + c->type = mwCipher_RC2_40; + c->get_name = get_name_RC2_40; + c->get_desc = get_desc_RC2_40; + c->new_instance = new_instance_RC2_40; + + c->offer = offer_RC2_40; + + c->accepted = accepted_RC2_40; + c->accept = accept_RC2_40; + + c->encrypt = encrypt_RC2_40; + c->decrypt = decrypt_RC2_40; + + return c; +} + + +struct mwCipher_RC2_128 { + struct mwCipher cipher; + mw_mp_int private_key; + struct mwOpaque public_key; +}; + + +struct mwCipherInstance_RC2_128 { + struct mwCipherInstance instance; + int shared[64]; /* shared secret determined via DH exchange */ + guchar outgoing_iv[8]; + guchar incoming_iv[8]; +}; + + +static const char *get_name_RC2_128() { + return "RC2/128 Cipher"; +} + + +static const char *get_desc_RC2_128() { + return "RC2, DH shared secret key"; +} + + +static struct mwCipherInstance * +new_instance_RC2_128(struct mwCipher *cipher, + struct mwChannel *chan) { + + struct mwCipher_RC2_128 *cr; + struct mwCipherInstance_RC2_128 *cir; + struct mwCipherInstance *ci; + + cr = (struct mwCipher_RC2_128 *) cipher; + + cir = g_new0(struct mwCipherInstance_RC2_128, 1); + ci = &cir->instance; + + ci->cipher = cipher; + ci->channel = chan; + + mwIV_init(cir->incoming_iv); + mwIV_init(cir->outgoing_iv); + + return ci; +} + + +static void offered_RC2_128(struct mwCipherInstance *ci, + struct mwEncryptItem *item) { + + mw_mp_int remote_key; + mw_mp_int shared; + struct mwOpaque sho = { 0, 0 }; + + struct mwCipher *c; + struct mwCipher_RC2_128 *cr; + struct mwCipherInstance_RC2_128 *cir; + + c = ci->cipher; + cr = (struct mwCipher_RC2_128 *) c; + cir = (struct mwCipherInstance_RC2_128 *) ci; + + mw_mp_init(&remote_key); + mw_mp_init(&shared); + + mwDHImportKey(&remote_key, &item->info); + mwDHCalculateShared(&shared, &remote_key, &cr->private_key); + mwDHExportKey(&shared, &sho); + + /* key expanded from the last 16 bytes of the DH shared secret. This + took me forever to figure out. 16 bytes is 128 bit. */ + /* the sh_len-16 is important, because the key len could + hypothetically start with 8bits or more unset, meaning the + exported key might be less than 64 bytes in length */ + mwKeyExpand(cir->shared, sho.data+(sho.len-16), 16); + + mw_mp_clear(&remote_key); + mw_mp_clear(&shared); + mwOpaque_clear(&sho); +} + + +static struct mwEncryptItem * +offer_RC2_128(struct mwCipherInstance *ci) { + + struct mwCipher *c; + struct mwCipher_RC2_128 *cr; + struct mwEncryptItem *ei; + + c = ci->cipher; + cr = (struct mwCipher_RC2_128 *) c; + + ei = g_new0(struct mwEncryptItem, 1); + ei->id = mwCipher_RC2_128; + mwOpaque_clone(&ei->info, &cr->public_key); + + return ei; +} + + +static void accepted_RC2_128(struct mwCipherInstance *ci, + struct mwEncryptItem *item) { + + /// Miranda NG adaptation start - MSVC + ///return offered_RC2_128(ci, item); + offered_RC2_128(ci, item); + /// Miranda NG adaptation end +} + + +static struct mwEncryptItem * +accept_RC2_128(struct mwCipherInstance *ci) { + + return offer_RC2_128(ci); +} + + +static int encrypt_RC2_128(struct mwCipherInstance *ci, + struct mwOpaque *data) { + + struct mwCipherInstance_RC2_128 *cir; + struct mwOpaque o = { 0, 0 }; + + cir = (struct mwCipherInstance_RC2_128 *) ci; + + mwEncryptExpanded(cir->shared, cir->outgoing_iv, data, &o); + + mwOpaque_clear(data); + data->data = o.data; + data->len = o.len; + + return 0; +} + + +static int decrypt_RC2_128(struct mwCipherInstance *ci, + struct mwOpaque *data) { + + struct mwCipherInstance_RC2_128 *cir; + struct mwOpaque o = { 0, 0 }; + + cir = (struct mwCipherInstance_RC2_128 *) ci; + + mwDecryptExpanded(cir->shared, cir->incoming_iv, data, &o); + + mwOpaque_clear(data); + data->data = o.data; + data->len = o.len; + + return 0; +} + + +static void clear_RC2_128(struct mwCipher *c) { + struct mwCipher_RC2_128 *cr; + cr = (struct mwCipher_RC2_128 *) c; + + mw_mp_clear(&cr->private_key); + mwOpaque_clear(&cr->public_key); +} + + +struct mwCipher *mwCipher_new_RC2_128(struct mwSession *s) { + struct mwCipher_RC2_128 *cr; + struct mwCipher *c; + + mw_mp_int pubkey; + + cr = g_new0(struct mwCipher_RC2_128, 1); + c = &cr->cipher; + + c->session = s; + c->type = mwCipher_RC2_128; + c->get_name = get_name_RC2_128; + c->get_desc = get_desc_RC2_128; + c->new_instance = new_instance_RC2_128; + + c->offered = offered_RC2_128; + c->offer = offer_RC2_128; + + c->accepted = accepted_RC2_128; + c->accept = accept_RC2_128; + + c->encrypt = encrypt_RC2_128; + c->decrypt = decrypt_RC2_128; + + c->clear = clear_RC2_128; + + mw_mp_init(&cr->private_key); + mw_mp_init(&pubkey); + mwDHRandKeypair(&cr->private_key, &pubkey); + mwDHExportKey(&pubkey, &cr->public_key); + mw_mp_clear(&pubkey); + + return c; +} + + +struct mwSession *mwCipher_getSession(struct mwCipher *cipher) { + g_return_val_if_fail(cipher != NULL, NULL); + return cipher->session; +} + + +guint16 mwCipher_getType(struct mwCipher *cipher) { + /* oh man, this is a bad failover... who the hell decided to make + zero a real cipher id? */ + g_return_val_if_fail(cipher != NULL, 0xffff); + return cipher->type; +} + + +const char *mwCipher_getName(struct mwCipher *cipher) { + g_return_val_if_fail(cipher != NULL, NULL); + g_return_val_if_fail(cipher->get_name != NULL, NULL); + return cipher->get_name(); +} + + +const char *mwCipher_getDesc(struct mwCipher *cipher) { + g_return_val_if_fail(cipher != NULL, NULL); + g_return_val_if_fail(cipher->get_desc != NULL, NULL); + return cipher->get_desc(); +} + + +void mwCipher_free(struct mwCipher *cipher) { + if(! cipher) return; + + if(cipher->clear) + cipher->clear(cipher); + + g_free(cipher); +} + + +struct mwCipherInstance *mwCipher_newInstance(struct mwCipher *cipher, + struct mwChannel *chan) { + g_return_val_if_fail(cipher != NULL, NULL); + g_return_val_if_fail(chan != NULL, NULL); + g_return_val_if_fail(cipher->new_instance != NULL, NULL); + return cipher->new_instance(cipher, chan); +} + + +struct mwCipher *mwCipherInstance_getCipher(struct mwCipherInstance *ci) { + g_return_val_if_fail(ci != NULL, NULL); + return ci->cipher; +} + + +struct mwChannel *mwCipherInstance_getChannel(struct mwCipherInstance *ci) { + g_return_val_if_fail(ci != NULL, NULL); + return ci->channel; +} + + +void mwCipherInstance_offered(struct mwCipherInstance *ci, + struct mwEncryptItem *item) { + struct mwCipher *cipher; + + g_return_if_fail(ci != NULL); + + cipher = ci->cipher; + g_return_if_fail(cipher != NULL); + + if(cipher->offered) cipher->offered(ci, item); +} + + +struct mwEncryptItem * +mwCipherInstance_offer(struct mwCipherInstance *ci) { + struct mwCipher *cipher; + + g_return_val_if_fail(ci != NULL, NULL); + + cipher = ci->cipher; + g_return_val_if_fail(cipher != NULL, NULL); + + return cipher->offer(ci); +} + + +void mwCipherInstance_accepted(struct mwCipherInstance *ci, + struct mwEncryptItem *item) { + struct mwCipher *cipher; + + g_return_if_fail(ci != NULL); + + cipher = ci->cipher; + g_return_if_fail(cipher != NULL); + + if(cipher->accepted) cipher->accepted(ci, item); +} + + +struct mwEncryptItem * +mwCipherInstance_accept(struct mwCipherInstance *ci) { + struct mwCipher *cipher; + + g_return_val_if_fail(ci != NULL, NULL); + + cipher = ci->cipher; + g_return_val_if_fail(cipher != NULL, NULL); + + return cipher->accept(ci); +} + + +int mwCipherInstance_encrypt(struct mwCipherInstance *ci, + struct mwOpaque *data) { + struct mwCipher *cipher; + + g_return_val_if_fail(data != NULL, 0); + + if(! ci) return 0; + cipher = ci->cipher; + + g_return_val_if_fail(cipher != NULL, -1); + + return (cipher->encrypt)? + cipher->encrypt(ci, data): 0; +} + + +int mwCipherInstance_decrypt(struct mwCipherInstance *ci, + struct mwOpaque *data) { + struct mwCipher *cipher; + + g_return_val_if_fail(data != NULL, 0); + + if(! ci) return 0; + cipher = ci->cipher; + + g_return_val_if_fail(cipher != NULL, -1); + + return (cipher->decrypt)? + cipher->decrypt(ci, data): 0; +} + + +void mwCipherInstance_free(struct mwCipherInstance *ci) { + struct mwCipher *cipher; + + if(! ci) return; + + cipher = ci->cipher; + + if(cipher && cipher->clear_instance) + cipher->clear_instance(ci); + + g_free(ci); +} + diff --git a/protocols/Sametime/src/meanwhile/src/common.c b/protocols/Sametime/src/meanwhile/src/common.c new file mode 100644 index 0000000000..555edd2c1c --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/common.c @@ -0,0 +1,947 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <string.h> + +#include "mw_common.h" + + +/** @todo the *_get functions should make sure to clear their + structures in the event of failure, to prevent memory leaks */ + + +#define MW16_PUT(b, val) \ + *(b)++ = ((val) >> 0x08) & 0xff; \ + *(b)++ = (val) & 0xff; + + +#define MW16_GET(b, val) \ + val = (*(b)++ & 0xff) << 8; \ + val = val | (*(b)++ & 0xff); + + +#define MW32_PUT(b, val) \ + *(b)++ = ((val) >> 0x18) & 0xff; \ + *(b)++ = ((val) >> 0x10) & 0xff; \ + *(b)++ = ((val) >> 0x08) & 0xff; \ + *(b)++ = (val) & 0xff; + + +#define MW32_GET(b, val) \ + val = (*(b)++ & 0xff) << 0x18; \ + val = val | (*(b)++ & 0xff) << 0x10; \ + val = val | (*(b)++ & 0xff) << 0x08; \ + val = val | (*(b)++ & 0xff); + + +struct mwPutBuffer { + guchar *buf; /**< head of buffer */ + gsize len; /**< length of buffer */ + + guchar *ptr; /**< offset to first unused byte */ + gsize rem; /**< count of unused bytes remaining */ +}; + + +struct mwGetBuffer { + guchar *buf; /**< head of buffer */ + gsize len; /**< length of buffer */ + + guchar *ptr; /**< offset to first unused byte */ + gsize rem; /**< count of unused bytes remaining */ + + gboolean wrap; /**< TRUE to indicate buf shouldn't be freed */ + gboolean error; /**< TRUE to indicate an error */ +}; + + +#define BUFFER_USED(buffer) \ + ((buffer)->len - (buffer)->rem) + + +/** ensure that there's at least enough space remaining in the put + buffer to fit needed. */ +static void ensure_buffer(struct mwPutBuffer *b, gsize needed) { + if(b->rem < needed) { + gsize len = b->len, use = BUFFER_USED(b); + guchar *buf; + + /* newly created buffers are empty until written to, and then they + have 1024 available */ + if(! len) len = 1024; + + /* double len until it's large enough to fit needed */ + while( (len - use) < needed ) len = len << 1; + + /* create the new buffer. if there was anything in the old buffer, + copy it into the new buffer and free the old copy */ + buf = g_malloc(len); + if(b->buf) { + memcpy(buf, b->buf, use); + g_free(b->buf); + } + + /* put the new buffer into b */ + b->buf = buf; + b->len = len; + b->ptr = buf + use; + b->rem = len - use; + } +} + + +/** determine if there are at least needed bytes available in the + buffer. sets the error flag if there's not at least needed bytes + left in the buffer + + @returns true if there's enough data, false if not */ +static gboolean check_buffer(struct mwGetBuffer *b, gsize needed) { + if(! b->error) b->error = (b->rem < needed); + return ! b->error; +} + + +struct mwPutBuffer *mwPutBuffer_new() { + return g_new0(struct mwPutBuffer, 1); +} + + +void mwPutBuffer_write(struct mwPutBuffer *b, gpointer data, gsize len) { + g_return_if_fail(b != NULL); + g_return_if_fail(data != NULL); + + if(! len) return; + + ensure_buffer(b, len); + memcpy(b->ptr, data, len); + b->ptr += len; + b->rem -= len; +} + + +void mwPutBuffer_free(struct mwPutBuffer *b) { + if(! b) return; + g_free(b->buf); + g_free(b); +} + + +void mwPutBuffer_finalize(struct mwOpaque *to, struct mwPutBuffer *from) { + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->len = BUFFER_USED(from); + to->data = from->buf; + + g_free(from); +} + + +struct mwGetBuffer *mwGetBuffer_new(struct mwOpaque *o) { + struct mwGetBuffer *b = g_new0(struct mwGetBuffer, 1); + + if(o && o->len) { + b->buf = b->ptr = g_memdup(o->data, o->len); + b->len = b->rem = o->len; + } + + return b; +} + + +struct mwGetBuffer *mwGetBuffer_wrap(const struct mwOpaque *o) { + struct mwGetBuffer *b = g_new0(struct mwGetBuffer, 1); + + if(o && o->len) { + b->buf = b->ptr = o->data; + b->len = b->rem = o->len; + } + b->wrap = TRUE; + + return b; +} + + +gsize mwGetBuffer_read(struct mwGetBuffer *b, gpointer data, gsize len) { + g_return_val_if_fail(b != NULL, 0); + g_return_val_if_fail(data != NULL, 0); + + if(b->error) return 0; + if(! len) return 0; + + if(b->rem < len) + len = b->rem; + + memcpy(data, b->ptr, len); + b->ptr += len; + b->rem -= len; + + return len; +} + + +gsize mwGetBuffer_advance(struct mwGetBuffer *b, gsize len) { + g_return_val_if_fail(b != NULL, 0); + + if(b->error) return 0; + if(! len) return 0; + + if(b->rem < len) + len = b->rem; + + b->ptr += len; + b->rem -= len; + + return len; +} + + +void mwGetBuffer_reset(struct mwGetBuffer *b) { + g_return_if_fail(b != NULL); + + b->rem = b->len; + b->ptr = b->buf; + b->error = FALSE; +} + + +gsize mwGetBuffer_remaining(struct mwGetBuffer *b) { + g_return_val_if_fail(b != NULL, 0); + return b->rem; +} + + +gboolean mwGetBuffer_error(struct mwGetBuffer *b) { + g_return_val_if_fail(b != NULL, TRUE); + return b->error; +} + + +void mwGetBuffer_free(struct mwGetBuffer *b) { + if(! b) return; + if(! b->wrap) g_free(b->buf); + g_free(b); +} + + +#define guint16_buflen() 2 + + +void guint16_put(struct mwPutBuffer *b, guint16 val) { + g_return_if_fail(b != NULL); + + ensure_buffer(b, guint16_buflen()); + MW16_PUT(b->ptr, val); + b->rem -= guint16_buflen(); +} + + +void guint16_get(struct mwGetBuffer *b, guint16 *val) { + g_return_if_fail(b != NULL); + + if(b->error) return; + g_return_if_fail(check_buffer(b, guint16_buflen())); + + MW16_GET(b->ptr, *val); + b->rem -= guint16_buflen(); +} + + +guint16 guint16_peek(struct mwGetBuffer *b) { + guchar *buf = b->buf; + guint16 r = 0; + + if(b->rem >= guint16_buflen()) + MW16_GET(buf, r); + + return r; +} + + +#define guint32_buflen() 4 + + +void guint32_put(struct mwPutBuffer *b, guint32 val) { + g_return_if_fail(b != NULL); + + ensure_buffer(b, guint32_buflen()); + MW32_PUT(b->ptr, val); + b->rem -= guint32_buflen(); +} + + +void guint32_get(struct mwGetBuffer *b, guint32 *val) { + g_return_if_fail(b != NULL); + + if(b->error) return; + g_return_if_fail(check_buffer(b, guint32_buflen())); + + MW32_GET(b->ptr, *val); + b->rem -= guint32_buflen(); +} + + +guint32 guint32_peek(struct mwGetBuffer *b) { + guchar *buf = b->buf; + guint32 r = 0; + + if(b->rem >= guint32_buflen()) + MW32_GET(buf, r); + + return r; +} + + +#define gboolean_buflen() 1 + + +void gboolean_put(struct mwPutBuffer *b, gboolean val) { + g_return_if_fail(b != NULL); + + ensure_buffer(b, gboolean_buflen()); + *(b->ptr) = !! val; + b->ptr++; + b->rem--; +} + + +void gboolean_get(struct mwGetBuffer *b, gboolean *val) { + g_return_if_fail(b != NULL); + + if(b->error) return; + g_return_if_fail(check_buffer(b, gboolean_buflen())); + + *val = !! *(b->ptr); + b->ptr++; + b->rem--; +} + + +gboolean gboolean_peek(struct mwGetBuffer *b) { + gboolean v = FALSE; + + if(b->rem >= gboolean_buflen()) + v = !! *(b->ptr); + + return v; +} + + +static gboolean mw_streq(const char *a, const char *b) { + return (a == b) || (a && b && !strcmp(a, b)); +} + + +void mwString_put(struct mwPutBuffer *b, const char *val) { + gsize len = 0; + + g_return_if_fail(b != NULL); + + if(val) len = strlen(val); + + guint16_put(b, (guint16) len); + + if(len) { + ensure_buffer(b, len); + memcpy(b->ptr, val, len); + b->ptr += len; + b->rem -= len; + } +} + + +void mwString_get(struct mwGetBuffer *b, char **val) { + guint16 len = 0; + + g_return_if_fail(b != NULL); + g_return_if_fail(val != NULL); + + *val = NULL; + + if(b->error) return; + guint16_get(b, &len); + + g_return_if_fail(check_buffer(b, (gsize) len)); + + if(len) { + *val = g_malloc0(len + 1); + memcpy(*val, b->ptr, len); + b->ptr += len; + b->rem -= len; + } +} + + +void mwOpaque_put(struct mwPutBuffer *b, const struct mwOpaque *o) { + gsize len; + + g_return_if_fail(b != NULL); + + if(! o) { + guint32_put(b, 0x00); + return; + } + + len = o->len; + if(len) + g_return_if_fail(o->data != NULL); + + guint32_put(b, (guint32) len); + + if(len) { + ensure_buffer(b, len); + memcpy(b->ptr, o->data, len); + b->ptr += len; + b->rem -= len; + } +} + + +void mwOpaque_get(struct mwGetBuffer *b, struct mwOpaque *o) { + guint32 tmp = 0; + + g_return_if_fail(b != NULL); + g_return_if_fail(o != NULL); + + o->len = 0; + o->data = NULL; + + if(b->error) return; + guint32_get(b, &tmp); + + g_return_if_fail(check_buffer(b, (gsize) tmp)); + + o->len = (gsize) tmp; + if(tmp > 0) { + o->data = g_memdup(b->ptr, tmp); + b->ptr += tmp; + b->rem -= tmp; + } +} + + +void mwOpaque_clear(struct mwOpaque *o) { + if(! o) return; + g_free(o->data); + o->data = NULL; + o->len = 0; +} + + +void mwOpaque_free(struct mwOpaque *o) { + if(! o) return; + g_free(o->data); + g_free(o); +} + + +void mwOpaque_clone(struct mwOpaque *to, const struct mwOpaque *from) { + g_return_if_fail(to != NULL); + + to->len = 0; + to->data = NULL; + + if(from) { + to->len = from->len; + if(to->len) + to->data = g_memdup(from->data, to->len); + } +} + + +/* 8.2 Common Structures */ +/* 8.2.1 Login Info block */ + + +void mwLoginInfo_put(struct mwPutBuffer *b, const struct mwLoginInfo *login) { + g_return_if_fail(b != NULL); + g_return_if_fail(login != NULL); + + mwString_put(b, login->login_id); + guint16_put(b, login->type); + mwString_put(b, login->user_id); + mwString_put(b, login->user_name); + mwString_put(b, login->community); + gboolean_put(b, login->full); + + if(login->full) { + mwString_put(b, login->desc); + guint32_put(b, login->ip_addr); + mwString_put(b, login->server_id); + } +} + + +void mwLoginInfo_get(struct mwGetBuffer *b, struct mwLoginInfo *login) { + g_return_if_fail(b != NULL); + g_return_if_fail(login != NULL); + + if(b->error) return; + + mwString_get(b, &login->login_id); + guint16_get(b, &login->type); + mwString_get(b, &login->user_id); + mwString_get(b, &login->user_name); + mwString_get(b, &login->community); + gboolean_get(b, &login->full); + + if(login->full) { + mwString_get(b, &login->desc); + guint32_get(b, &login->ip_addr); + mwString_get(b, &login->server_id); + } +} + + +void mwLoginInfo_clear(struct mwLoginInfo *login) { + if(! login) return; + + g_free(login->login_id); + g_free(login->user_id); + g_free(login->user_name); + g_free(login->community); + g_free(login->desc); + g_free(login->server_id); + + memset(login, 0x00, sizeof(struct mwLoginInfo)); +} + + +void mwLoginInfo_clone(struct mwLoginInfo *to, + const struct mwLoginInfo *from) { + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->login_id= g_strdup(from->login_id); + to->type = from->type; + to->user_id = g_strdup(from->user_id); + to->user_name = g_strdup(from->user_name); + to->community = g_strdup(from->community); + + if( (to->full = from->full) ) { + to->desc = g_strdup(from->desc); + to->ip_addr = from->ip_addr; + to->server_id = g_strdup(from->server_id); + } +} + + +/* 8.2.2 Private Info Block */ + + +void mwUserItem_put(struct mwPutBuffer *b, const struct mwUserItem *user) { + g_return_if_fail(b != NULL); + g_return_if_fail(user != NULL); + + gboolean_put(b, user->full); + mwString_put(b, user->id); + mwString_put(b, user->community); + + if(user->full) + mwString_put(b, user->name); +} + + +void mwUserItem_get(struct mwGetBuffer *b, struct mwUserItem *user) { + g_return_if_fail(b != NULL); + g_return_if_fail(user != NULL); + + if(b->error) return; + + gboolean_get(b, &user->full); + mwString_get(b, &user->id); + mwString_get(b, &user->community); + + if(user->full) + mwString_get(b, &user->name); +} + + +void mwUserItem_clear(struct mwUserItem *user) { + if(! user) return; + + g_free(user->id); + g_free(user->community); + g_free(user->name); + + memset(user, 0x00, sizeof(struct mwUserItem)); +} + + +void mwUserItem_clone(struct mwUserItem *to, + const struct mwUserItem *from) { + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->full = from->full; + to->id = g_strdup(from->id); + to->community = g_strdup(from->community); + to->name = (to->full)? g_strdup(from->name): NULL; +} + + +void mwPrivacyInfo_put(struct mwPutBuffer *b, + const struct mwPrivacyInfo *info) { + guint32 c; + + g_return_if_fail(b != NULL); + g_return_if_fail(info != NULL); + + gboolean_put(b, info->deny); + guint32_put(b, info->count); + + for(c = info->count; c--; ) mwUserItem_put(b, info->users + c); +} + + +void mwPrivacyInfo_get(struct mwGetBuffer *b, struct mwPrivacyInfo *info) { + g_return_if_fail(b != NULL); + g_return_if_fail(info != NULL); + + if(b->error) return; + + gboolean_get(b, &info->deny); + guint32_get(b, &info->count); + + if(info->count) { + guint32 c = info->count; + info->users = g_new0(struct mwUserItem, c); + while(c--) mwUserItem_get(b, info->users + c); + } +} + + +void mwPrivacyInfo_clone(struct mwPrivacyInfo *to, + const struct mwPrivacyInfo *from) { + + guint32 c; + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->deny = from->deny; + c = to->count = from->count; + + to->users = g_new0(struct mwUserItem, c); + while(c--) mwUserItem_clone(to->users+c, from->users+c); +} + + +void mwPrivacyInfo_clear(struct mwPrivacyInfo *info) { + struct mwUserItem *u; + guint32 c; + + g_return_if_fail(info != NULL); + + u = info->users; + c = info->count; + + while(c--) mwUserItem_clear(u + c); + g_free(u); + + info->count = 0; + info->users = NULL; +} + + +/* 8.2.3 User Status Block */ + + +void mwUserStatus_put(struct mwPutBuffer *b, + const struct mwUserStatus *stat) { + + g_return_if_fail(b != NULL); + g_return_if_fail(stat != NULL); + + guint16_put(b, stat->status); + guint32_put(b, stat->time); + mwString_put(b, stat->desc); +} + + +void mwUserStatus_get(struct mwGetBuffer *b, struct mwUserStatus *stat) { + g_return_if_fail(b != NULL); + g_return_if_fail(stat != NULL); + + if(b->error) return; + + guint16_get(b, &stat->status); + guint32_get(b, &stat->time); + mwString_get(b, &stat->desc); + + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/status_timestamp_workaround.diff + // Quick'n ugly hack for recent Sametime clients + stat->time = 0; + /// Miranda NG adaptation - end +} + + +void mwUserStatus_clear(struct mwUserStatus *stat) { + if(! stat) return; + g_free(stat->desc); + memset(stat, 0x00, sizeof(struct mwUserStatus)); +} + + +void mwUserStatus_clone(struct mwUserStatus *to, + const struct mwUserStatus *from) { + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->status = from->status; + to->time = from->time; + to->desc = g_strdup(from->desc); +} + + +/* 8.2.4 ID Block */ + + +void mwIdBlock_put(struct mwPutBuffer *b, const struct mwIdBlock *id) { + g_return_if_fail(b != NULL); + g_return_if_fail(id != NULL); + + mwString_put(b, id->user); + mwString_put(b, id->community); +} + + +void mwIdBlock_get(struct mwGetBuffer *b, struct mwIdBlock *id) { + g_return_if_fail(b != NULL); + g_return_if_fail(id != NULL); + + if(b->error) return; + + mwString_get(b, &id->user); + mwString_get(b, &id->community); +} + + +void mwIdBlock_clear(struct mwIdBlock *id) { + if(! id) return; + + g_free(id->user); + id->user = NULL; + + g_free(id->community); + id->community = NULL; +} + + +void mwIdBlock_clone(struct mwIdBlock *to, const struct mwIdBlock *from) { + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->user = g_strdup(from->user); + to->community = g_strdup(from->community); +} + + +guint mwIdBlock_hash(const struct mwIdBlock *idb) { + return (idb)? g_str_hash(idb->user): 0; +} + + +gboolean mwIdBlock_equal(const struct mwIdBlock *a, + const struct mwIdBlock *b) { + + g_return_val_if_fail(a != NULL, FALSE); + g_return_val_if_fail(b != NULL, FALSE); + + return ( mw_streq(a->user, b->user) && + mw_streq(a->community, b->community) ); +} + + +/* 8.2.5 Encryption Block */ + +/** @todo I think this can be put into cipher */ + +void mwEncryptItem_put(struct mwPutBuffer *b, + const struct mwEncryptItem *ei) { + + g_return_if_fail(b != NULL); + g_return_if_fail(ei != NULL); + + guint16_put(b, ei->id); + mwOpaque_put(b, &ei->info); + +} + + +void mwEncryptItem_get(struct mwGetBuffer *b, struct mwEncryptItem *ei) { + g_return_if_fail(b != NULL); + g_return_if_fail(ei != NULL); + + if(b->error) return; + + guint16_get(b, &ei->id); + mwOpaque_get(b, &ei->info); +} + + +void mwEncryptItem_clear(struct mwEncryptItem *ei) { + if(! ei) return; + ei->id = 0x0000; + mwOpaque_clear(&ei->info); +} + + +void mwEncryptItem_free(struct mwEncryptItem *ei) { + mwEncryptItem_clear(ei); + g_free(ei); +} + + +/* 8.4.2.1 Awareness ID Block */ + + +/** @todo move this into srvc_aware */ + +void mwAwareIdBlock_put(struct mwPutBuffer *b, + const struct mwAwareIdBlock *idb) { + + g_return_if_fail(b != NULL); + g_return_if_fail(idb != NULL); + + guint16_put(b, idb->type); + mwString_put(b, idb->user); + mwString_put(b, idb->community); +} + + +void mwAwareIdBlock_get(struct mwGetBuffer *b, struct mwAwareIdBlock *idb) { + g_return_if_fail(b != NULL); + g_return_if_fail(idb != NULL); + + if(b->error) return; + + guint16_get(b, &idb->type); + mwString_get(b, &idb->user); + mwString_get(b, &idb->community); +} + + +void mwAwareIdBlock_clone(struct mwAwareIdBlock *to, + const struct mwAwareIdBlock *from) { + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + to->type = from->type; + to->user = g_strdup(from->user); + to->community = g_strdup(from->community); +} + + +void mwAwareIdBlock_clear(struct mwAwareIdBlock *idb) { + if(! idb) return; + g_free(idb->user); + g_free(idb->community); + memset(idb, 0x00, sizeof(struct mwAwareIdBlock)); +} + + +guint mwAwareIdBlock_hash(const struct mwAwareIdBlock *a) { + return (a)? g_str_hash(a->user): 0; +} + + +gboolean mwAwareIdBlock_equal(const struct mwAwareIdBlock *a, + const struct mwAwareIdBlock *b) { + + g_return_val_if_fail(a != NULL, FALSE); + g_return_val_if_fail(b != NULL, FALSE); + + return ( (a->type == b->type) && + mw_streq(a->user, b->user) && + mw_streq(a->community, b->community) ); +} + + +/* 8.4.2.4 Snapshot */ + +void mwAwareSnapshot_get(struct mwGetBuffer *b, struct mwAwareSnapshot *idb) { + + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/presence_fix_v2.diff + //guint32 junk; + //char *empty = NULL; + guint32 end_of_block; + /// Miranda NG adaptation - end + + g_return_if_fail(b != NULL); + g_return_if_fail(idb != NULL); + + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/presence_fix_v2.diff + //guint32_get(b, &junk); + guint32_get(b, &end_of_block); + /// Miranda NG adaptation - end + mwAwareIdBlock_get(b, &idb->id); + mwString_get(b, &idb->group); + gboolean_get(b, &idb->online); + + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/presence_fix_v2.diff + //g_free(empty); + /// Miranda NG adaptation - end + + if(idb->online) { + mwString_get(b, &idb->alt_id); + mwUserStatus_get(b, &idb->status); + mwString_get(b, &idb->name); + } + + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/presence_fix_v2.diff + if(b->ptr < b->buf + end_of_block) { + mwGetBuffer_advance(b, b->buf + end_of_block - b->ptr); + } + /// Miranda NG adaptation - end +} + + +void mwAwareSnapshot_clone(struct mwAwareSnapshot *to, + const struct mwAwareSnapshot *from) { + + g_return_if_fail(to != NULL); + g_return_if_fail(from != NULL); + + mwAwareIdBlock_clone(&to->id, &from->id); + if( (to->online = from->online) ) { + to->alt_id = g_strdup(from->alt_id); + mwUserStatus_clone(&to->status, &from->status); + to->name = g_strdup(from->name); + to->group = g_strdup(from->group); + } +} + + +void mwAwareSnapshot_clear(struct mwAwareSnapshot *idb) { + if(! idb) return; + mwAwareIdBlock_clear(&idb->id); + mwUserStatus_clear(&idb->status); + g_free(idb->alt_id); + g_free(idb->name); + g_free(idb->group); + memset(idb, 0x00, sizeof(struct mwAwareSnapshot)); +} + diff --git a/protocols/Sametime/src/meanwhile/src/error.c b/protocols/Sametime/src/meanwhile/src/error.c new file mode 100644 index 0000000000..23c9559802 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/error.c @@ -0,0 +1,97 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <string.h> + +#include "mw_error.h" + + +static char *err_to_str(guint32 code) { + static char b[11]; /* 0x12345678 + NULL terminator */ + sprintf((char *) b, "0x%08x", code); + b[10] = '\0'; + return b; +} + + +#define CASE(val, str) \ +case val: \ + m = str; \ + break; + + +char* mwError(guint32 code) { + const char *m; + + switch(code) { + + /* 8.3.1.1 General error/success codes */ + CASE(ERR_SUCCESS, "Success"); + CASE(ERR_FAILURE, "General failure"); + CASE(ERR_REQUEST_DELAY, "Request delayed"); + CASE(ERR_REQUEST_INVALID, "Request is invalid"); + CASE(ERR_NOT_AUTHORIZED, "Not authorized"); + CASE(ERR_NO_USER, "User is not online"); + CASE(ERR_CHANNEL_NO_SUPPORT, "Requested channel is not supported"); + CASE(ERR_CHANNEL_EXISTS, "Requested channel already exists"); + CASE(ERR_SERVICE_NO_SUPPORT, "Requested service is not supported"); + CASE(ERR_PROTOCOL_NO_SUPPORT, "Requested protocol is not supported"); + CASE(ERR_VERSION_NO_SUPPORT, "Version is not supported"); + CASE(ERR_USER_SKETCHY, "User is invalid or not trusted"); + CASE(ERR_ALREADY_INITIALIZED, "Already initialized"); + CASE(ERR_ENCRYPT_NO_SUPPORT, "Encryption method not supported"); + CASE(ERR_NO_COMMON_ENCRYPT, "No common encryption method"); + + /* 8.3.1.2 Connection/disconnection errors */ + CASE(VERSION_MISMATCH, "Version mismatch"); + CASE(FAT_MESSAGE, "Message is too large"); + CASE(CONNECTION_BROKEN, "Connection broken"); + CASE(CONNECTION_ABORTED, "Connection aborted"); + CASE(CONNECTION_REFUSED, "Connection refused"); + CASE(CONNECTION_RESET, "Connection reset"); + CASE(CONNECTION_TIMED, "Connection timed out"); + CASE(CONNECTION_CLOSED, "Connection closed"); + CASE(INCORRECT_LOGIN, "Incorrect Username/Password"); + CASE(VERIFICATION_DOWN, "Login verification down or unavailable"); + CASE(GUEST_IN_USE, "The guest name is currently being used"); + CASE(MULTI_SERVER_LOGIN, "Login to two different servers concurrently"); + CASE(MULTI_SERVER_LOGIN2, "Login to two different servers concurrently"); + CASE(SERVER_BROKEN, "Server misconfiguration"); + + /* 8.3.1.3 Client error codes */ + CASE(ERR_CLIENT_USER_GONE, "User is not online"); + CASE(ERR_CLIENT_USER_DND, "User is in Do Not Disturb mode"); + CASE(ERR_CLIENT_USER_ELSEWHERE, "Already logged in elsewhere"); + + /* 8.3.1.4 IM error codes */ + CASE(ERR_IM_COULDNT_REGISTER, "Cannot register a reserved type"); + CASE(ERR_IM_ALREADY_REGISTERED, "Requested type is already registered"); + CASE(ERR_IM_NOT_REGISTERED, "Requested type is not registered"); + + default: + m = err_to_str(code); + } + + return g_strdup(m); +} + + +#undef CASE diff --git a/protocols/Sametime/src/meanwhile/src/message.c b/protocols/Sametime/src/meanwhile/src/message.c new file mode 100644 index 0000000000..f9afec4c9b --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/message.c @@ -0,0 +1,853 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> + +#include "mw_debug.h" +#include "mw_message.h" + + +/* 7.1 Layering and message encapsulation */ +/* 7.1.1 The Sametime Message Header */ + + +static void mwMessageHead_put(struct mwPutBuffer *b, struct mwMessage *msg) { + guint16_put(b, msg->type); + guint16_put(b, msg->options); + guint32_put(b, msg->channel); + + if(msg->options & mwMessageOption_HAS_ATTRIBS) + mwOpaque_put(b, &msg->attribs); +} + + +static void mwMessageHead_get(struct mwGetBuffer *b, struct mwMessage *msg) { + + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &msg->type); + guint16_get(b, &msg->options); + guint32_get(b, &msg->channel); + + if(msg->options & mwMessageOption_HAS_ATTRIBS) + mwOpaque_get(b, &msg->attribs); +} + + +static void mwMessageHead_clone(struct mwMessage *to, + struct mwMessage *from) { + + to->type = from->type; + to->options = from->options; + to->channel = from->channel; + mwOpaque_clone(&to->attribs, &from->attribs); +} + + +static void mwMessageHead_clear(struct mwMessage *msg) { + mwOpaque_clear(&msg->attribs); +} + + +/* 8.4 Messages */ +/* 8.4.1 Basic Community Messages */ +/* 8.4.1.1 Handshake */ + + +static void HANDSHAKE_put(struct mwPutBuffer *b, struct mwMsgHandshake *msg) { + guint16_put(b, msg->major); + guint16_put(b, msg->minor); + guint32_put(b, msg->head.channel); + guint32_put(b, msg->srvrcalc_addr); + guint16_put(b, msg->login_type); + guint32_put(b, msg->loclcalc_addr); + + if(msg->major >= 0x001e && msg->minor >= 0x001d) { + guint16_put(b, msg->unknown_a); + guint32_put(b, msg->unknown_b); + mwString_put(b, msg->local_host); + } +} + + +static void HANDSHAKE_get(struct mwGetBuffer *b, struct mwMsgHandshake *msg) { + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &msg->major); + guint16_get(b, &msg->minor); + guint32_get(b, &msg->head.channel); + guint32_get(b, &msg->srvrcalc_addr); + guint16_get(b, &msg->login_type); + guint32_get(b, &msg->loclcalc_addr); + + if(msg->major >= 0x001e && msg->minor >= 0x001d) { + guint16_get(b, &msg->unknown_a); + guint32_get(b, &msg->unknown_b); + mwString_get(b, &msg->local_host); + } +} + + +static void HANDSHAKE_clear(struct mwMsgHandshake *msg) { + ; /* nothing to clean up */ +} + + +/* 8.4.1.2 HandshakeAck */ + + +static void HANDSHAKE_ACK_get(struct mwGetBuffer *b, + struct mwMsgHandshakeAck *msg) { + + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &msg->major); + guint16_get(b, &msg->minor); + guint32_get(b, &msg->srvrcalc_addr); + + /** @todo: get a better handle on what versions support what parts + of this message. eg: minor version 0x0018 doesn't send the + following */ + if(msg->major >= 0x1e && msg->minor > 0x18) { + guint32_get(b, &msg->magic); + mwOpaque_get(b, &msg->data); + } +} + + +static void HANDSHAKE_ACK_put(struct mwPutBuffer *b, + struct mwMsgHandshakeAck *msg) { + + guint16_put(b, msg->major); + guint16_put(b, msg->minor); + guint32_put(b, msg->srvrcalc_addr); + + if(msg->major >= 0x1e && msg->minor > 0x18) { + guint32_put(b, msg->magic); + mwOpaque_put(b, &msg->data); + } +} + + +static void HANDSHAKE_ACK_clear(struct mwMsgHandshakeAck *msg) { + mwOpaque_clear(&msg->data); +} + + +/* 8.4.1.3 Login */ + + +static void LOGIN_put(struct mwPutBuffer *b, struct mwMsgLogin *msg) { + guint16_put(b, msg->login_type); + mwString_put(b, msg->name); + + /* ordering reversed from houri draft?? */ + mwOpaque_put(b, &msg->auth_data); + guint16_put(b, msg->auth_type); + + guint16_put(b, 0x0000); /* unknown */ +} + + +static void LOGIN_get(struct mwGetBuffer *b, struct mwMsgLogin *msg) { + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &msg->login_type); + mwString_get(b, &msg->name); + mwOpaque_get(b, &msg->auth_data); + guint16_get(b, &msg->auth_type); +} + + +static void LOGIN_clear(struct mwMsgLogin *msg) { + g_free(msg->name); msg->name = NULL; + mwOpaque_clear(&msg->auth_data); +} + + +/* 8.4.1.4 LoginAck */ + + +static void LOGIN_ACK_get(struct mwGetBuffer *b, struct mwMsgLoginAck *msg) { + guint16 junk; + + if(mwGetBuffer_error(b)) return; + + mwLoginInfo_get(b, &msg->login); + guint16_get(b, &junk); + mwPrivacyInfo_get(b, &msg->privacy); + mwUserStatus_get(b, &msg->status); +} + + +static void LOGIN_ACK_clear(struct mwMsgLoginAck *msg) { + mwLoginInfo_clear(&msg->login); + mwPrivacyInfo_clear(&msg->privacy); + mwUserStatus_clear(&msg->status); +} + + +/* 8.4.1.5 LoginCont */ + + +static void LOGIN_CONTINUE_put(struct mwPutBuffer *b, + struct mwMsgLoginContinue *msg) { + + ; /* nothing but a message header */ +} + + +static void LOGIN_CONTINUE_get(struct mwGetBuffer *b, + struct mwMsgLoginContinue *msg) { + + ; /* nothing but a message header */ +} + + +static void LOGIN_CONTINUE_clear(struct mwMsgLoginContinue *msg) { + ; /* this is a very simple message */ +} + + +/* 8.4.1.6 AuthPassed */ + + +static void LOGIN_REDIRECT_get(struct mwGetBuffer *b, + struct mwMsgLoginRedirect *msg) { + + if(mwGetBuffer_error(b)) return; + mwString_get(b, &msg->host); + mwString_get(b, &msg->server_id); +} + + +static void LOGIN_REDIRECT_put(struct mwPutBuffer *b, + struct mwMsgLoginRedirect *msg) { + mwString_put(b, msg->host); + mwString_put(b, msg->server_id); +} + + +static void LOGIN_REDIRECT_clear(struct mwMsgLoginRedirect *msg) { + g_free(msg->host); + msg->host = NULL; + + g_free(msg->server_id); + msg->server_id = NULL; +} + + +/* 8.4.1.7 CreateCnl */ + + +static void enc_offer_put(struct mwPutBuffer *b, struct mwEncryptOffer *enc) { + guint16_put(b, enc->mode); + + if(enc->items) { + guint32 count; + struct mwPutBuffer *p; + struct mwOpaque o; + GList *list; + + /* write the count, items, extra, and flag into a tmp buffer, + render that buffer into an opaque, and write it into b */ + + count = g_list_length(enc->items); + p = mwPutBuffer_new(); + + guint32_put(p, count); + for(list = enc->items; list; list = list->next) { + mwEncryptItem_put(p, list->data); + } + + guint16_put(p, enc->extra); + gboolean_put(p, enc->flag); + + mwPutBuffer_finalize(&o, p); + mwOpaque_put(b, &o); + mwOpaque_clear(&o); + } +} + + +static void CHANNEL_CREATE_put(struct mwPutBuffer *b, + struct mwMsgChannelCreate *msg) { + + guint32_put(b, msg->reserved); + guint32_put(b, msg->channel); + mwIdBlock_put(b, &msg->target); + guint32_put(b, msg->service); + guint32_put(b, msg->proto_type); + guint32_put(b, msg->proto_ver); + guint32_put(b, msg->options); + mwOpaque_put(b, &msg->addtl); + gboolean_put(b, msg->creator_flag); + + if(msg->creator_flag) + mwLoginInfo_put(b, &msg->creator); + + enc_offer_put(b, &msg->encrypt); + + guint32_put(b, 0x00); + guint32_put(b, 0x00); + guint16_put(b, 0x07); +} + + +static void enc_offer_get(struct mwGetBuffer *b, + struct mwEncryptOffer *enc) { + guint32 skip; + + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &enc->mode); + guint32_get(b, &skip); + + if(skip >= 7) { + guint32 count; + + guint32_get(b, &count); + + while(count-- && (! mwGetBuffer_error(b))) { + struct mwEncryptItem *ei = g_new0(struct mwEncryptItem, 1); + mwEncryptItem_get(b, ei); + enc->items = g_list_append(enc->items, ei); + } + + guint16_get(b, &enc->extra); + gboolean_get(b, &enc->flag); + } +} + + +static void CHANNEL_CREATE_get(struct mwGetBuffer *b, + struct mwMsgChannelCreate *msg) { + + if(mwGetBuffer_error(b)) return; + + guint32_get(b, &msg->reserved); + guint32_get(b, &msg->channel); + mwIdBlock_get(b, &msg->target); + guint32_get(b, &msg->service); + guint32_get(b, &msg->proto_type); + guint32_get(b, &msg->proto_ver); + guint32_get(b, &msg->options); + mwOpaque_get(b, &msg->addtl); + gboolean_get(b, &msg->creator_flag); + + if(msg->creator_flag) + mwLoginInfo_get(b, &msg->creator); + + enc_offer_get(b, &msg->encrypt); +} + + +static void CHANNEL_CREATE_clear(struct mwMsgChannelCreate *msg) { + GList *list; + + mwIdBlock_clear(&msg->target); + mwOpaque_clear(&msg->addtl); + mwLoginInfo_clear(&msg->creator); + + for(list = msg->encrypt.items; list; list = list->next) { + mwEncryptItem_clear(list->data); + g_free(list->data); + } + g_list_free(msg->encrypt.items); +} + + +/* 8.4.1.8 AcceptCnl */ + + +static void enc_accept_put(struct mwPutBuffer *b, + struct mwEncryptAccept *enc) { + + guint16_put(b, enc->mode); + + if(enc->item) { + struct mwPutBuffer *p; + struct mwOpaque o; + + p = mwPutBuffer_new(); + + mwEncryptItem_put(p, enc->item); + guint16_put(p, enc->extra); + gboolean_put(p, enc->flag); + + mwPutBuffer_finalize(&o, p); + mwOpaque_put(b, &o); + mwOpaque_clear(&o); + } +} + + +static void CHANNEL_ACCEPT_put(struct mwPutBuffer *b, + struct mwMsgChannelAccept *msg) { + + guint32_put(b, msg->service); + guint32_put(b, msg->proto_type); + guint32_put(b, msg->proto_ver); + mwOpaque_put(b, &msg->addtl); + gboolean_put(b, msg->acceptor_flag); + + if(msg->acceptor_flag) + mwLoginInfo_put(b, &msg->acceptor); + + enc_accept_put(b, &msg->encrypt); + + guint32_put(b, 0x00); + guint32_put(b, 0x00); + guint16_put(b, 0x07); +} + + +static void enc_accept_get(struct mwGetBuffer *b, + struct mwEncryptAccept *enc) { + guint32 skip; + + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &enc->mode); + guint32_get(b, &skip); + + if(skip >= 6) { + enc->item = g_new0(struct mwEncryptItem, 1); + mwEncryptItem_get(b, enc->item); + } + + if(skip >= 9) { + guint16_get(b, &enc->extra); + gboolean_get(b, &enc->flag); + } +} + + +static void CHANNEL_ACCEPT_get(struct mwGetBuffer *b, + struct mwMsgChannelAccept *msg) { + + if(mwGetBuffer_error(b)) return; + + guint32_get(b, &msg->service); + guint32_get(b, &msg->proto_type); + guint32_get(b, &msg->proto_ver); + mwOpaque_get(b, &msg->addtl); + gboolean_get(b, &msg->acceptor_flag); + + if(msg->acceptor_flag) + mwLoginInfo_get(b, &msg->acceptor); + + enc_accept_get(b, &msg->encrypt); +} + + +static void CHANNEL_ACCEPT_clear(struct mwMsgChannelAccept *msg) { + mwOpaque_clear(&msg->addtl); + mwLoginInfo_clear(&msg->acceptor); + + if(msg->encrypt.item) { + mwEncryptItem_clear(msg->encrypt.item); + g_free(msg->encrypt.item); + } +} + + +/* 8.4.1.9 SendOnCnl */ + + +static void CHANNEL_SEND_put(struct mwPutBuffer *b, + struct mwMsgChannelSend *msg) { + + guint16_put(b, msg->type); + mwOpaque_put(b, &msg->data); +} + + +static void CHANNEL_SEND_get(struct mwGetBuffer *b, + struct mwMsgChannelSend *msg) { + + if(mwGetBuffer_error(b)) return; + + guint16_get(b, &msg->type); + mwOpaque_get(b, &msg->data); +} + + +static void CHANNEL_SEND_clear(struct mwMsgChannelSend *msg) { + mwOpaque_clear(&msg->data); +} + + +/* 8.4.1.10 DestroyCnl */ + + +static void CHANNEL_DESTROY_put(struct mwPutBuffer *b, + struct mwMsgChannelDestroy *msg) { + guint32_put(b, msg->reason); + mwOpaque_put(b, &msg->data); +} + + +static void CHANNEL_DESTROY_get(struct mwGetBuffer *b, + struct mwMsgChannelDestroy *msg) { + + if(mwGetBuffer_error(b)) return; + + guint32_get(b, &msg->reason); + mwOpaque_get(b, &msg->data); +} + + +static void CHANNEL_DESTROY_clear(struct mwMsgChannelDestroy *msg) { + mwOpaque_clear(&msg->data); +} + + +/* 8.4.1.11 SetUserStatus */ + + +static void SET_USER_STATUS_put(struct mwPutBuffer *b, + struct mwMsgSetUserStatus *msg) { + mwUserStatus_put(b, &msg->status); +} + + +static void SET_USER_STATUS_get(struct mwGetBuffer *b, + struct mwMsgSetUserStatus *msg) { + + if(mwGetBuffer_error(b)) return; + mwUserStatus_get(b, &msg->status); +} + + +static void SET_USER_STATUS_clear(struct mwMsgSetUserStatus *msg) { + mwUserStatus_clear(&msg->status); +} + + +/* 8.4.1.12 SetPrivacyList */ + + +static void SET_PRIVACY_LIST_put(struct mwPutBuffer *b, + struct mwMsgSetPrivacyList *msg) { + mwPrivacyInfo_put(b, &msg->privacy); +} + + +static void SET_PRIVACY_LIST_get(struct mwGetBuffer *b, + struct mwMsgSetPrivacyList *msg) { + + if(mwGetBuffer_error(b)) return; + mwPrivacyInfo_get(b, &msg->privacy); +} + + +static void SET_PRIVACY_LIST_clear(struct mwMsgSetPrivacyList *msg) { + mwPrivacyInfo_clear(&msg->privacy); +} + + +/* Sense Service messages */ + + +static void SENSE_SERVICE_put(struct mwPutBuffer *b, + struct mwMsgSenseService *msg) { + guint32_put(b, msg->service); +} + + +static void SENSE_SERVICE_get(struct mwGetBuffer *b, + struct mwMsgSenseService *msg) { + + if(mwGetBuffer_error(b)) return; + guint32_get(b, &msg->service); +} + + +static void SENSE_SERVICE_clear(struct mwMsgSenseService *msg) { + ; +} + + +/* Admin messages */ + + +static void ADMIN_get(struct mwGetBuffer *b, struct mwMsgAdmin *msg) { + mwString_get(b, &msg->text); +} + + +static void ADMIN_clear(struct mwMsgAdmin *msg) { + g_free(msg->text); + msg->text = NULL; +} + + +/* Announcement messages */ + + +static void ANNOUNCE_get(struct mwGetBuffer *b, struct mwMsgAnnounce *msg) { + struct mwOpaque o = { 0, 0 }; + struct mwGetBuffer *gb; + guint32 count; + + gboolean_get(b, &msg->sender_present); + if(msg->sender_present) + mwLoginInfo_get(b, &msg->sender); + guint16_get(b, &msg->unknown_a); + + mwOpaque_get(b, &o); + gb = mwGetBuffer_wrap(&o); + + gboolean_get(gb, &msg->may_reply); + mwString_get(gb, &msg->text); + + mwGetBuffer_free(gb); + mwOpaque_clear(&o); + + guint32_get(b, &count); + while(count--) { + char *r = NULL; + mwString_get(b, &r); + msg->recipients = g_list_prepend(msg->recipients, r); + } +} + + +static void ANNOUNCE_put(struct mwPutBuffer *b, struct mwMsgAnnounce *msg) { + struct mwOpaque o = { 0, 0 }; + struct mwPutBuffer *pb; + GList *l; + + gboolean_put(b, msg->sender_present); + if(msg->sender_present) + mwLoginInfo_put(b, &msg->sender); + guint16_put(b, msg->unknown_a); + + pb = mwPutBuffer_new(); + + gboolean_put(pb, msg->may_reply); + mwString_put(pb, msg->text); + + mwPutBuffer_finalize(&o, pb); + mwOpaque_put(b, &o); + mwOpaque_clear(&o); + + guint32_put(b, g_list_length(msg->recipients)); + for(l = msg->recipients; l; l = l->next) { + mwString_put(b, l->data); + } +} + + +static void ANNOUNCE_clear(struct mwMsgAnnounce *msg) { + mwLoginInfo_clear(&msg->sender); + + g_free(msg->text); + msg->text = NULL; + + while(msg->recipients) { + g_free(msg->recipients->data); + msg->recipients = g_list_delete_link(msg->recipients, msg->recipients); + } +} + + +/* general functions */ + + +#define CASE(v, t) \ +case mwMessage_ ## v: \ + msg = (struct mwMessage *) g_new0(struct t, 1); \ + msg->type = type; \ + break; + + +struct mwMessage *mwMessage_new(enum mwMessageType type) { + struct mwMessage *msg = NULL; + + switch(type) { + CASE(HANDSHAKE, mwMsgHandshake); + CASE(HANDSHAKE_ACK, mwMsgHandshakeAck); + CASE(LOGIN, mwMsgLogin); + CASE(LOGIN_REDIRECT, mwMsgLoginRedirect); + CASE(LOGIN_CONTINUE, mwMsgLoginContinue); + CASE(LOGIN_ACK, mwMsgLoginAck); + CASE(CHANNEL_CREATE, mwMsgChannelCreate); + CASE(CHANNEL_DESTROY, mwMsgChannelDestroy); + CASE(CHANNEL_SEND, mwMsgChannelSend); + CASE(CHANNEL_ACCEPT, mwMsgChannelAccept); + CASE(SET_USER_STATUS, mwMsgSetUserStatus); + CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList); + CASE(SENSE_SERVICE, mwMsgSenseService); + CASE(ADMIN, mwMsgAdmin); + CASE(ANNOUNCE, mwMsgAnnounce); + + default: + g_warning("unknown message type 0x%02x\n", type); + } + + return msg; +} + + +#undef CASE + + +/* each type needs to be passed to a specially named _get functions, + and cast to a specific subclass of mwMessage. */ +#define CASE(v, t) \ +case mwMessage_ ## v: \ + msg = (struct mwMessage *) g_new0(struct t, 1); \ + mwMessageHead_clone(msg, &head); \ + v ## _get(b, (struct t *) msg); \ + break; + + +struct mwMessage *mwMessage_get(struct mwGetBuffer *b) { + struct mwMessage *msg = NULL; + struct mwMessage head; + + g_return_val_if_fail(b != NULL, NULL); + + head.attribs.len = 0; + head.attribs.data = NULL; + + /* attempt to read the header first */ + mwMessageHead_get(b, &head); + + if(mwGetBuffer_error(b)) { + mwMessageHead_clear(&head); + g_warning("problem parsing message head from buffer"); + return NULL; + } + + /* load the rest of the message depending on the header type */ + switch(head.type) { + CASE(HANDSHAKE, mwMsgHandshake); + CASE(HANDSHAKE_ACK, mwMsgHandshakeAck); + CASE(LOGIN, mwMsgLogin); + CASE(LOGIN_REDIRECT, mwMsgLoginRedirect); + CASE(LOGIN_CONTINUE, mwMsgLoginContinue); + CASE(LOGIN_ACK, mwMsgLoginAck); + CASE(CHANNEL_CREATE, mwMsgChannelCreate); + CASE(CHANNEL_DESTROY, mwMsgChannelDestroy); + CASE(CHANNEL_SEND, mwMsgChannelSend); + CASE(CHANNEL_ACCEPT, mwMsgChannelAccept); + CASE(SET_USER_STATUS, mwMsgSetUserStatus); + CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList); + CASE(SENSE_SERVICE, mwMsgSenseService); + CASE(ADMIN, mwMsgAdmin); + CASE(ANNOUNCE, mwMsgAnnounce); + + default: + g_warning("unknown message type 0x%02x, no parse handler", head.type); + } + + if(mwGetBuffer_error(b)) { + g_warning("problem parsing message type 0x%02x, not enough data", + head.type); + } + + mwMessageHead_clear(&head); + + return msg; +} + + +#undef CASE + + +#define CASE(v, t) \ +case mwMessage_ ## v: \ + v ## _put(b, (struct t *) msg); \ + break; + + +void mwMessage_put(struct mwPutBuffer *b, struct mwMessage *msg) { + + g_return_if_fail(b != NULL); + g_return_if_fail(msg != NULL); + + mwMessageHead_put(b, msg); + + switch(msg->type) { + CASE(HANDSHAKE, mwMsgHandshake); + CASE(HANDSHAKE_ACK, mwMsgHandshakeAck); + CASE(LOGIN, mwMsgLogin); + CASE(LOGIN_REDIRECT, mwMsgLoginRedirect); + CASE(LOGIN_CONTINUE, mwMsgLoginContinue); + CASE(CHANNEL_CREATE, mwMsgChannelCreate); + CASE(CHANNEL_DESTROY, mwMsgChannelDestroy); + CASE(CHANNEL_SEND, mwMsgChannelSend); + CASE(CHANNEL_ACCEPT, mwMsgChannelAccept); + CASE(SET_USER_STATUS, mwMsgSetUserStatus); + CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList); + CASE(SENSE_SERVICE, mwMsgSenseService); + CASE(ANNOUNCE, mwMsgAnnounce); + + default: + ; /* hrm. */ + } +} + + +#undef CASE + + +#define CASE(v, t) \ +case mwMessage_ ## v: \ + v ## _clear((struct t *) msg); \ + break; + + +void mwMessage_free(struct mwMessage *msg) { + if(! msg) return; + + mwMessageHead_clear(msg); + + switch(msg->type) { + CASE(HANDSHAKE, mwMsgHandshake); + CASE(HANDSHAKE_ACK, mwMsgHandshakeAck); + CASE(LOGIN, mwMsgLogin); + CASE(LOGIN_REDIRECT, mwMsgLoginRedirect); + CASE(LOGIN_CONTINUE, mwMsgLoginContinue); + CASE(LOGIN_ACK, mwMsgLoginAck); + CASE(CHANNEL_CREATE, mwMsgChannelCreate); + CASE(CHANNEL_DESTROY, mwMsgChannelDestroy); + CASE(CHANNEL_SEND, mwMsgChannelSend); + CASE(CHANNEL_ACCEPT, mwMsgChannelAccept); + CASE(SET_USER_STATUS, mwMsgSetUserStatus); + CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList); + CASE(SENSE_SERVICE, mwMsgSenseService); + CASE(ADMIN, mwMsgAdmin); + CASE(ANNOUNCE, mwMsgAnnounce); + + default: + ; /* hrm. */ + } + + g_free(msg); +} + + +#undef CASE + + diff --git a/protocols/Sametime/src/meanwhile/src/mpi/mpi-config.h b/protocols/Sametime/src/meanwhile/src/mpi/mpi-config.h new file mode 100644 index 0000000000..6972c8878d --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mpi/mpi-config.h @@ -0,0 +1,84 @@ +/* Default configuration for MPI library */ + +#ifndef MPI_CONFIG_H_ +#define MPI_CONFIG_H_ + +/* + For boolean options, + 0 = no + 1 = yes + + Other options are documented individually. + + */ + +#ifndef MP_IOFUNC +#define MP_IOFUNC 0 /* include mp_print() ? */ +#endif + +#ifndef MP_MODARITH +#define MP_MODARITH 1 /* include modular arithmetic ? */ +#endif + +#ifndef MP_NUMTH +#define MP_NUMTH 1 /* include number theoretic functions? */ +#endif + +#ifndef MP_LOGTAB +#define MP_LOGTAB 0 /* use table of logs instead of log()? */ +#endif + +#ifndef MP_MEMSET +#define MP_MEMSET 1 /* use memset() to zero buffers? */ +#endif + +#ifndef MP_MEMCPY +#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */ +#endif + +#ifndef MP_CRYPTO +#define MP_CRYPTO 0 /* erase memory on free? */ +#endif + +#ifndef MP_ARGCHK +/* + 0 = no parameter checks + 1 = runtime checks, continue execution and return an error to caller + 2 = assertions; dump core on parameter errors + */ +#define MP_ARGCHK 2 /* how to check input arguments */ +#endif + +#ifndef MP_DEBUG +#define MP_DEBUG 0 /* print diagnostic output? */ +#endif + +#ifndef MP_DEFPREC +#define MP_DEFPREC 32 /* default precision, in digits */ +#endif + +#ifndef MP_MACRO +#define MP_MACRO 1 /* use macros for frequent calls? */ +#endif + +#ifndef MP_SQUARE +#define MP_SQUARE 1 /* use separate squaring code? */ +#endif + +#ifndef MP_PTAB_SIZE +/* + When building mpprime.c, we build in a table of small prime + values to use for primality testing. The more you include, + the more space they take up. See primes.c for the possible + values (currently 16, 32, 64, 128, 256, and 6542) + */ +#define MP_PTAB_SIZE 128 /* how many built-in primes? */ +#endif + +#ifndef MP_COMPAT_MACROS +#define MP_COMPAT_MACROS 0 /* define compatibility macros? */ +#endif + +#endif /* ifndef MPI_CONFIG_H_ */ + + diff --git a/protocols/Sametime/src/meanwhile/src/mpi/mpi-types.h b/protocols/Sametime/src/meanwhile/src/mpi/mpi-types.h new file mode 100644 index 0000000000..137047ca77 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mpi/mpi-types.h @@ -0,0 +1,18 @@ + +#include <glib.h> + +typedef gchar mw_mp_sign; +typedef guint16 mw_mp_digit; /* 2 byte type */ +typedef guint32 mw_mp_word; /* 4 byte type */ +typedef gsize mw_mp_size; +typedef gint mw_mp_err; + +#define MP_DIGIT_BIT 16 +#define MP_DIGIT_MAX G_MAXUINT16 +#define MP_WORD_BIT 32 +#define MP_WORD_MAX G_MAXUINT32 + +#define RADIX (MP_DIGIT_MAX+1) + +#define MP_DIGIT_SIZE 2 +#define DIGIT_FMT "%04X" diff --git a/protocols/Sametime/src/meanwhile/src/mpi/mpi.c b/protocols/Sametime/src/meanwhile/src/mpi/mpi.c new file mode 100644 index 0000000000..1a33e98525 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mpi/mpi.c @@ -0,0 +1,4022 @@ +/* + mpi.c + + by Michael J. Fromberger <http://www.dartmouth.edu/~sting/> + Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + + Arbitrary precision integer arithmetic library + + modified for use in Meanwhile as a convenience library +*/ + +#include "mpi.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#if MP_DEBUG +#include <stdio.h> + +#define DIAG(T,V) {fprintf(stderr,T);mw_mp_print(V,stderr);fputc('\n',stderr);} +#else +#define DIAG(T,V) +#endif + +/* + If MP_LOGTAB is not defined, use the math library to compute the + logarithms on the fly. Otherwise, use the static table below. + Pick which works best for your system. + */ +#if MP_LOGTAB + +/* {{{ s_logv_2[] - log table for 2 in various bases */ + +/* + A table of the logs of 2 for various bases (the 0 and 1 entries of + this table are meaningless and should not be referenced). + + This table is used to compute output lengths for the mw_mp_toradix() + function. Since a number n in radix r takes up about log_r(n) + digits, we estimate the output size by taking the least integer + greater than log_r(n), where: + + log_r(n) = log_2(n) * log_r(2) + + This table, therefore, is a table of log_r(2) for 2 <= r <= 36, + which are the output bases supported. + */ + +#include "logtab.h" + +/* }}} */ +#define LOG_V_2(R) s_logv_2[(R)] + +#else + +#include <math.h> +#define LOG_V_2(R) (log(2.0)/log(R)) + +#endif + +/* Default precision for newly created mw_mp_int's */ +static unsigned int s_mw_mp_defprec = MP_DEFPREC; + +/* {{{ Digit arithmetic macros */ + +/* + When adding and multiplying digits, the results can be larger than + can be contained in an mw_mp_digit. Thus, an mw_mp_word is used. These + macros mask off the upper and lower digits of the mw_mp_word (the + mw_mp_word may be more than 2 mw_mp_digits wide, but we only concern + ourselves with the low-order 2 mw_mp_digits) + + If your mw_mp_word DOES have more than 2 mw_mp_digits, you need to + uncomment the first line, and comment out the second. + */ + +/* #define CARRYOUT(W) (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */ +#define CARRYOUT(W) ((W)>>DIGIT_BIT) +#define ACCUM(W) ((W)&MP_DIGIT_MAX) + +/* }}} */ + +/* {{{ Comparison constants */ + +#define MP_LT -1 +#define MP_EQ 0 +#define MP_GT 1 + +/* }}} */ + +/* {{{ Constant strings */ + +/* Constant strings returned by mw_mp_strerror() */ +static const char *mw_mp_err_string[] = { + "unknown result code", /* say what? */ + "boolean true", /* MP_OKAY, MP_YES */ + "boolean false", /* MP_NO */ + "out of memory", /* MP_MEM */ + "argument out of range", /* MP_RANGE */ + "invalid input parameter", /* MP_BADARG */ + "result is undefined" /* MP_UNDEF */ +}; + +/* Value to digit maps for radix conversion */ + +/* s_dmap_1 - standard digits and letters */ +static const char *s_dmap_1 = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +#if 0 +/* s_dmap_2 - base64 ordering for digits */ +static const char *s_dmap_2 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#endif + +/* }}} */ + +/* {{{ Static function declarations */ + +/* + If MP_MACRO is false, these will be defined as actual functions; + otherwise, suitable macro definitions will be used. This works + around the fact that ANSI C89 doesn't support an 'inline' keyword + (although I hear C9x will ... about bloody time). At present, the + macro definitions are identical to the function bodies, but they'll + expand in place, instead of generating a function call. + + I chose these particular functions to be made into macros because + some profiling showed they are called a lot on a typical workload, + and yet they are primarily housekeeping. + */ +#if MP_MACRO == 0 + void s_mw_mp_setz(mw_mp_digit *dp, mw_mp_size count); /* zero digits */ + void s_mw_mp_copy(mw_mp_digit *sp, mw_mp_digit *dp, mw_mp_size count); /* copy */ + void *s_mw_mp_alloc(size_t nb, size_t ni); /* general allocator */ + void s_mw_mp_free(void *ptr); /* general free function */ +#else + + /* Even if these are defined as macros, we need to respect the settings + of the MP_MEMSET and MP_MEMCPY configuration options... + */ + #if MP_MEMSET == 0 + #define s_mw_mp_setz(dp, count) \ + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;} + #else + #define s_mw_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mw_mp_digit)) + #endif /* MP_MEMSET */ + + #if MP_MEMCPY == 0 + #define s_mw_mp_copy(sp, dp, count) \ + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];} + #else + #define s_mw_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mw_mp_digit)) + #endif /* MP_MEMCPY */ + + #define s_mw_mp_alloc(nb, ni) calloc(nb, ni) + #define s_mw_mp_free(ptr) {if(ptr) free(ptr);} +#endif /* MP_MACRO */ + +mw_mp_err s_mw_mp_grow(mw_mp_int *mp, mw_mp_size min); /* increase allocated size */ +mw_mp_err s_mw_mp_pad(mw_mp_int *mp, mw_mp_size min); /* left pad with zeroes */ + +void s_mw_mp_clamp(mw_mp_int *mp); /* clip leading zeroes */ + +void s_mw_mp_exch(mw_mp_int *a, mw_mp_int *b); /* swap a and b in place */ + +mw_mp_err s_mw_mp_lshd(mw_mp_int *mp, mw_mp_size p); /* left-shift by p digits */ +void s_mw_mp_rshd(mw_mp_int *mp, mw_mp_size p); /* right-shift by p digits */ +void s_mw_mp_div_2d(mw_mp_int *mp, mw_mp_digit d); /* divide by 2^d in place */ +void s_mw_mp_mod_2d(mw_mp_int *mp, mw_mp_digit d); /* modulo 2^d in place */ +mw_mp_err s_mw_mp_mul_2d(mw_mp_int *mp, mw_mp_digit d); /* multiply by 2^d in place*/ +void s_mw_mp_div_2(mw_mp_int *mp); /* divide by 2 in place */ +mw_mp_err s_mw_mp_mul_2(mw_mp_int *mp); /* multiply by 2 in place */ +mw_mp_digit s_mw_mp_norm(mw_mp_int *a, mw_mp_int *b); /* normalize for division */ +mw_mp_err s_mw_mp_add_d(mw_mp_int *mp, mw_mp_digit d); /* unsigned digit addition */ +mw_mp_err s_mw_mp_sub_d(mw_mp_int *mp, mw_mp_digit d); /* unsigned digit subtract */ +mw_mp_err s_mw_mp_mul_d(mw_mp_int *mp, mw_mp_digit d); /* unsigned digit multiply */ +mw_mp_err s_mw_mp_div_d(mw_mp_int *mp, mw_mp_digit d, mw_mp_digit *r); + /* unsigned digit divide */ +mw_mp_err s_mw_mp_reduce(mw_mp_int *x, mw_mp_int *m, mw_mp_int *mu); + /* Barrett reduction */ +mw_mp_err s_mw_mp_add(mw_mp_int *a, mw_mp_int *b); /* magnitude addition */ +mw_mp_err s_mw_mp_sub(mw_mp_int *a, mw_mp_int *b); /* magnitude subtract */ +mw_mp_err s_mw_mp_mul(mw_mp_int *a, mw_mp_int *b); /* magnitude multiply */ +#if 0 +void s_mw_mp_kmul(mw_mp_digit *a, mw_mp_digit *b, mw_mp_digit *out, mw_mp_size len); + /* multiply buffers in place */ +#endif +#if MP_SQUARE +mw_mp_err s_mw_mp_sqr(mw_mp_int *a); /* magnitude square */ +#else +#define s_mw_mp_sqr(a) s_mw_mp_mul(a, a) +#endif +mw_mp_err s_mw_mp_div(mw_mp_int *a, mw_mp_int *b); /* magnitude divide */ +mw_mp_err s_mw_mp_2expt(mw_mp_int *a, mw_mp_digit k); /* a = 2^k */ +int s_mw_mp_cmp(mw_mp_int *a, mw_mp_int *b); /* magnitude comparison */ +int s_mw_mp_cmw_mp_d(mw_mp_int *a, mw_mp_digit d); /* magnitude digit compare */ +int s_mw_mp_ispow2(mw_mp_int *v); /* is v a power of 2? */ +int s_mw_mp_ispow2d(mw_mp_digit d); /* is d a power of 2? */ + +int s_mw_mp_tovalue(char ch, int r); /* convert ch to value */ +char s_mw_mp_todigit(int val, int r, int low); /* convert val to digit */ +int s_mw_mp_outlen(int bits, int r); /* output length in bytes */ + +/* }}} */ + +/* {{{ Default precision manipulation */ + +unsigned int mw_mp_get_prec(void) +{ + return s_mw_mp_defprec; + +} /* end mw_mp_get_prec() */ + +void mw_mp_set_prec(unsigned int prec) +{ + if(prec == 0) + s_mw_mp_defprec = MP_DEFPREC; + else + s_mw_mp_defprec = prec; + +} /* end mw_mp_set_prec() */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ mw_mp_init(mp) */ + +/* + mw_mp_init(mp) + + Initialize a new zero-valued mw_mp_int. Returns MP_OKAY if successful, + MP_MEM if memory could not be allocated for the structure. + */ + +mw_mp_err mw_mp_init(mw_mp_int *mp) +{ + return mw_mp_init_size(mp, s_mw_mp_defprec); + +} /* end mw_mp_init() */ + +/* }}} */ + +/* {{{ mw_mp_init_array(mp[], count) */ + +mw_mp_err mw_mp_init_array(mw_mp_int mp[], int count) +{ + mw_mp_err res; + int pos; + + ARGCHK(mp !=NULL && count > 0, MP_BADARG); + + for(pos = 0; pos < count; ++pos) { + if((res = mw_mp_init(&mp[pos])) != MP_OKAY) + goto CLEANUP; + } + + return MP_OKAY; + + CLEANUP: + while(--pos >= 0) + mw_mp_clear(&mp[pos]); + + return res; + +} /* end mw_mp_init_array() */ + +/* }}} */ + +/* {{{ mw_mp_init_size(mp, prec) */ + +/* + mw_mp_init_size(mp, prec) + + Initialize a new zero-valued mw_mp_int with at least the given + precision; returns MP_OKAY if successful, or MP_MEM if memory could + not be allocated for the structure. + */ + +mw_mp_err mw_mp_init_size(mw_mp_int *mp, mw_mp_size prec) +{ + ARGCHK(mp != NULL && prec > 0, MP_BADARG); + + if((DIGITS(mp) = s_mw_mp_alloc(prec, sizeof(mw_mp_digit))) == NULL) + return MP_MEM; + + SIGN(mp) = MP_ZPOS; + USED(mp) = 1; + ALLOC(mp) = prec; + + return MP_OKAY; + +} /* end mw_mp_init_size() */ + +/* }}} */ + +/* {{{ mw_mp_init_copy(mp, from) */ + +/* + mw_mp_init_copy(mp, from) + + Initialize mp as an exact copy of from. Returns MP_OKAY if + successful, MP_MEM if memory could not be allocated for the new + structure. + */ + +mw_mp_err mw_mp_init_copy(mw_mp_int *mp, mw_mp_int *from) +{ + ARGCHK(mp != NULL && from != NULL, MP_BADARG); + + if(mp == from) + return MP_OKAY; + + if((DIGITS(mp) = s_mw_mp_alloc(USED(from), sizeof(mw_mp_digit))) == NULL) + return MP_MEM; + + s_mw_mp_copy(DIGITS(from), DIGITS(mp), USED(from)); + USED(mp) = USED(from); + ALLOC(mp) = USED(from); + SIGN(mp) = SIGN(from); + + return MP_OKAY; + +} /* end mw_mp_init_copy() */ + +/* }}} */ + +/* {{{ mw_mp_copy(from, to) */ + +/* + mw_mp_copy(from, to) + + Copies the mw_mp_int 'from' to the mw_mp_int 'to'. It is presumed that + 'to' has already been initialized (if not, use mw_mp_init_copy() + instead). If 'from' and 'to' are identical, nothing happens. + */ + +mw_mp_err mw_mp_copy(mw_mp_int *from, mw_mp_int *to) +{ + ARGCHK(from != NULL && to != NULL, MP_BADARG); + + if(from == to) + return MP_OKAY; + + { /* copy */ + mw_mp_digit *tmp; + + /* + If the allocated buffer in 'to' already has enough space to hold + all the used digits of 'from', we'll re-use it to avoid hitting + the memory allocater more than necessary; otherwise, we'd have + to grow anyway, so we just allocate a hunk and make the copy as + usual + */ + if(ALLOC(to) >= USED(from)) { + s_mw_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from)); + s_mw_mp_copy(DIGITS(from), DIGITS(to), USED(from)); + + } else { + if((tmp = s_mw_mp_alloc(USED(from), sizeof(mw_mp_digit))) == NULL) + return MP_MEM; + + s_mw_mp_copy(DIGITS(from), tmp, USED(from)); + + if(DIGITS(to) != NULL) { +#if MP_CRYPTO + s_mw_mp_setz(DIGITS(to), ALLOC(to)); +#endif + s_mw_mp_free(DIGITS(to)); + } + + DIGITS(to) = tmp; + ALLOC(to) = USED(from); + } + + /* Copy the precision and sign from the original */ + USED(to) = USED(from); + SIGN(to) = SIGN(from); + } /* end copy */ + + return MP_OKAY; + +} /* end mw_mp_copy() */ + +/* }}} */ + +/* {{{ mw_mp_exch(mp1, mp2) */ + +/* + mw_mp_exch(mp1, mp2) + + Exchange mp1 and mp2 without allocating any intermediate memory + (well, unless you count the stack space needed for this call and the + locals it creates...). This cannot fail. + */ + +void mw_mp_exch(mw_mp_int *mp1, mw_mp_int *mp2) +{ +#if MP_ARGCHK == 2 + assert(mp1 != NULL && mp2 != NULL); +#else + if(mp1 == NULL || mp2 == NULL) + return; +#endif + + s_mw_mp_exch(mp1, mp2); + +} /* end mw_mp_exch() */ + +/* }}} */ + +/* {{{ mw_mp_clear(mp) */ + +/* + mw_mp_clear(mp) + + Release the storage used by an mw_mp_int, and void its fields so that + if someone calls mw_mp_clear() again for the same int later, we won't + get tollchocked. + */ + +void mw_mp_clear(mw_mp_int *mp) +{ + if(mp == NULL) + return; + + if(DIGITS(mp) != NULL) { +#if MP_CRYPTO + s_mw_mp_setz(DIGITS(mp), ALLOC(mp)); +#endif + s_mw_mp_free(DIGITS(mp)); + DIGITS(mp) = NULL; + } + + USED(mp) = 0; + ALLOC(mp) = 0; + +} /* end mw_mp_clear() */ + +/* }}} */ + +/* {{{ mw_mp_clear_array(mp[], count) */ + +void mw_mp_clear_array(mw_mp_int mp[], int count) +{ + ARGCHK(mp != NULL && count > 0, MP_BADARG); + + while(--count >= 0) + mw_mp_clear(&mp[count]); + +} /* end mw_mp_clear_array() */ + +/* }}} */ + +/* {{{ mw_mp_zero(mp) */ + +/* + mw_mp_zero(mp) + + Set mp to zero. Does not change the allocated size of the structure, + and therefore cannot fail (except on a bad argument, which we ignore) + */ +void mw_mp_zero(mw_mp_int *mp) +{ + if(mp == NULL) + return; + + s_mw_mp_setz(DIGITS(mp), ALLOC(mp)); + USED(mp) = 1; + SIGN(mp) = MP_ZPOS; + +} /* end mw_mp_zero() */ + +/* }}} */ + +/* {{{ mw_mp_set(mp, d) */ + +void mw_mp_set(mw_mp_int *mp, mw_mp_digit d) +{ + if(mp == NULL) + return; + + mw_mp_zero(mp); + DIGIT(mp, 0) = d; + +} /* end mw_mp_set() */ + +/* }}} */ + +/* {{{ mw_mp_set_int(mp, z) */ + +mw_mp_err mw_mp_set_int(mw_mp_int *mp, long z) +{ + int ix; + unsigned long v = abs(z); + mw_mp_err res; + + ARGCHK(mp != NULL, MP_BADARG); + + mw_mp_zero(mp); + if(z == 0) + return MP_OKAY; /* shortcut for zero */ + + for(ix = sizeof(long) - 1; ix >= 0; ix--) { + + if((res = s_mw_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY) + return res; + + res = s_mw_mp_add_d(mp, + (mw_mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX)); + if(res != MP_OKAY) + return res; + + } + + if(z < 0) + SIGN(mp) = MP_NEG; + + return MP_OKAY; + +} /* end mw_mp_set_int() */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Digit arithmetic */ + +/* {{{ mw_mp_add_d(a, d, b) */ + +/* + mw_mp_add_d(a, d, b) + + Compute the sum b = a + d, for a single digit d. Respects the sign of + its primary addend (single digits are unsigned anyway). + */ + +mw_mp_err mw_mp_add_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b) +{ + mw_mp_err res = MP_OKAY; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + if(SIGN(b) == MP_ZPOS) { + res = s_mw_mp_add_d(b, d); + } else if(s_mw_mp_cmw_mp_d(b, d) >= 0) { + res = s_mw_mp_sub_d(b, d); + } else { + SIGN(b) = MP_ZPOS; + + DIGIT(b, 0) = d - DIGIT(b, 0); + } + + return res; + +} /* end mw_mp_add_d() */ + +/* }}} */ + +/* {{{ mw_mp_sub_d(a, d, b) */ + +/* + mw_mp_sub_d(a, d, b) + + Compute the difference b = a - d, for a single digit d. Respects the + sign of its subtrahend (single digits are unsigned anyway). + */ + +mw_mp_err mw_mp_sub_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + if(SIGN(b) == MP_NEG) { + if((res = s_mw_mp_add_d(b, d)) != MP_OKAY) + return res; + + } else if(s_mw_mp_cmw_mp_d(b, d) >= 0) { + if((res = s_mw_mp_sub_d(b, d)) != MP_OKAY) + return res; + + } else { + mw_mp_neg(b, b); + + DIGIT(b, 0) = d - DIGIT(b, 0); + SIGN(b) = MP_NEG; + } + + if(s_mw_mp_cmw_mp_d(b, 0) == 0) + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mw_mp_sub_d() */ + +/* }}} */ + +/* {{{ mw_mp_mul_d(a, d, b) */ + +/* + mw_mp_mul_d(a, d, b) + + Compute the product b = a * d, for a single digit d. Respects the sign + of its multiplicand (single digits are unsigned anyway) + */ + +mw_mp_err mw_mp_mul_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if(d == 0) { + mw_mp_zero(b); + return MP_OKAY; + } + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + res = s_mw_mp_mul_d(b, d); + + return res; + +} /* end mw_mp_mul_d() */ + +/* }}} */ + +/* {{{ mw_mp_mul_2(a, c) */ + +mw_mp_err mw_mp_mul_2(mw_mp_int *a, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + return s_mw_mp_mul_2(c); + +} /* end mw_mp_mul_2() */ + +/* }}} */ + +/* {{{ mw_mp_div_d(a, d, q, r) */ + +/* + mw_mp_div_d(a, d, q, r) + + Compute the quotient q = a / d and remainder r = a mod d, for a + single digit d. Respects the sign of its divisor (single digits are + unsigned anyway). + */ + +mw_mp_err mw_mp_div_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *q, mw_mp_digit *r) +{ + mw_mp_err res; + mw_mp_digit rem; + int pow; + + ARGCHK(a != NULL, MP_BADARG); + + if(d == 0) + return MP_RANGE; + + /* Shortcut for powers of two ... */ + if((pow = s_mw_mp_ispow2d(d)) >= 0) { + mw_mp_digit mask; + + mask = (1 << pow) - 1; + rem = DIGIT(a, 0) & mask; + + if(q) { + mw_mp_copy(a, q); + s_mw_mp_div_2d(q, pow); + } + + if(r) + *r = rem; + + return MP_OKAY; + } + + /* + If the quotient is actually going to be returned, we'll try to + avoid hitting the memory allocator by copying the dividend into it + and doing the division there. This can't be any _worse_ than + always copying, and will sometimes be better (since it won't make + another copy) + + If it's not going to be returned, we need to allocate a temporary + to hold the quotient, which will just be discarded. + */ + if(q) { + if((res = mw_mp_copy(a, q)) != MP_OKAY) + return res; + + res = s_mw_mp_div_d(q, d, &rem); + if(s_mw_mp_cmw_mp_d(q, 0) == MP_EQ) + SIGN(q) = MP_ZPOS; + + } else { + mw_mp_int qp; + + if((res = mw_mp_init_copy(&qp, a)) != MP_OKAY) + return res; + + res = s_mw_mp_div_d(&qp, d, &rem); + if(s_mw_mp_cmw_mp_d(&qp, 0) == 0) + SIGN(&qp) = MP_ZPOS; + + mw_mp_clear(&qp); + } + + if(r) + *r = rem; + + return res; + +} /* end mw_mp_div_d() */ + +/* }}} */ + +/* {{{ mw_mp_div_2(a, c) */ + +/* + mw_mp_div_2(a, c) + + Compute c = a / 2, disregarding the remainder. + */ + +mw_mp_err mw_mp_div_2(mw_mp_int *a, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + s_mw_mp_div_2(c); + + return MP_OKAY; + +} /* end mw_mp_div_2() */ + +/* }}} */ + +/* {{{ mw_mp_expt_d(a, d, b) */ + +mw_mp_err mw_mp_expt_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *c) +{ + mw_mp_int s, x; + mw_mp_err res; + mw_mp_sign cs = MP_ZPOS; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_init(&s)) != MP_OKAY) + return res; + if((res = mw_mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + DIGIT(&s, 0) = 1; + + if((d % 2) == 1) + cs = SIGN(a); + + while(d != 0) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + + SIGN(&s) = cs; + + s_mw_mp_exch(&s, c); + +CLEANUP: + mw_mp_clear(&x); +X: + mw_mp_clear(&s); + + return res; + +} /* end mw_mp_expt_d() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Full arithmetic */ + +/* {{{ mw_mp_abs(a, b) */ + +/* + mw_mp_abs(a, b) + + Compute b = |a|. 'a' and 'b' may be identical. + */ + +mw_mp_err mw_mp_abs(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mw_mp_abs() */ + +/* }}} */ + +/* {{{ mw_mp_neg(a, b) */ + +/* + mw_mp_neg(a, b) + + Compute b = -a. 'a' and 'b' may be identical. + */ + +mw_mp_err mw_mp_neg(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + if(s_mw_mp_cmw_mp_d(b, 0) == MP_EQ) + SIGN(b) = MP_ZPOS; + else + SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG; + + return MP_OKAY; + +} /* end mw_mp_neg() */ + +/* }}} */ + +/* {{{ mw_mp_add(a, b, c) */ + +/* + mw_mp_add(a, b, c) + + Compute c = a + b. All parameters may be identical. + */ + +mw_mp_err mw_mp_add(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_err res; + int cmp; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(SIGN(a) == SIGN(b)) { /* same sign: add values, keep sign */ + + /* Commutativity of addition lets us do this in either order, + so we avoid having to use a temporary even if the result + is supposed to replace the output + */ + if(c == b) { + if((res = s_mw_mp_add(c, a)) != MP_OKAY) + return res; + } else { + if(c != a && (res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + if((res = s_mw_mp_add(c, b)) != MP_OKAY) + return res; + } + + } else if((cmp = s_mw_mp_cmp(a, b)) > 0) { /* different sign: a > b */ + + /* If the output is going to be clobbered, we will use a temporary + variable; otherwise, we'll do it without touching the memory + allocator at all, if possible + */ + if(c == b) { + mw_mp_int tmp; + + if((res = mw_mp_init_copy(&tmp, a)) != MP_OKAY) + return res; + if((res = s_mw_mp_sub(&tmp, b)) != MP_OKAY) { + mw_mp_clear(&tmp); + return res; + } + + s_mw_mp_exch(&tmp, c); + mw_mp_clear(&tmp); + + } else { + + if(c != a && (res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + if((res = s_mw_mp_sub(c, b)) != MP_OKAY) + return res; + + } + + } else if(cmp == 0) { /* different sign, a == b */ + + mw_mp_zero(c); + return MP_OKAY; + + } else { /* different sign: a < b */ + + /* See above... */ + if(c == a) { + mw_mp_int tmp; + + if((res = mw_mp_init_copy(&tmp, b)) != MP_OKAY) + return res; + if((res = s_mw_mp_sub(&tmp, a)) != MP_OKAY) { + mw_mp_clear(&tmp); + return res; + } + + s_mw_mp_exch(&tmp, c); + mw_mp_clear(&tmp); + + } else { + + if(c != b && (res = mw_mp_copy(b, c)) != MP_OKAY) + return res; + if((res = s_mw_mp_sub(c, a)) != MP_OKAY) + return res; + + } + } + + if(USED(c) == 1 && DIGIT(c, 0) == 0) + SIGN(c) = MP_ZPOS; + + return MP_OKAY; + +} /* end mw_mp_add() */ + +/* }}} */ + +/* {{{ mw_mp_sub(a, b, c) */ + +/* + mw_mp_sub(a, b, c) + + Compute c = a - b. All parameters may be identical. + */ + +mw_mp_err mw_mp_sub(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_err res; + int cmp; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(SIGN(a) != SIGN(b)) { + if(c == a) { + if((res = s_mw_mp_add(c, b)) != MP_OKAY) + return res; + } else { + if(c != b && ((res = mw_mp_copy(b, c)) != MP_OKAY)) + return res; + if((res = s_mw_mp_add(c, a)) != MP_OKAY) + return res; + SIGN(c) = SIGN(a); + } + + } else if((cmp = s_mw_mp_cmp(a, b)) > 0) { /* Same sign, a > b */ + if(c == b) { + mw_mp_int tmp; + + if((res = mw_mp_init_copy(&tmp, a)) != MP_OKAY) + return res; + if((res = s_mw_mp_sub(&tmp, b)) != MP_OKAY) { + mw_mp_clear(&tmp); + return res; + } + s_mw_mp_exch(&tmp, c); + mw_mp_clear(&tmp); + + } else { + if(c != a && ((res = mw_mp_copy(a, c)) != MP_OKAY)) + return res; + + if((res = s_mw_mp_sub(c, b)) != MP_OKAY) + return res; + } + + } else if(cmp == 0) { /* Same sign, equal magnitude */ + mw_mp_zero(c); + return MP_OKAY; + + } else { /* Same sign, b > a */ + if(c == a) { + mw_mp_int tmp; + + if((res = mw_mp_init_copy(&tmp, b)) != MP_OKAY) + return res; + + if((res = s_mw_mp_sub(&tmp, a)) != MP_OKAY) { + mw_mp_clear(&tmp); + return res; + } + s_mw_mp_exch(&tmp, c); + mw_mp_clear(&tmp); + + } else { + if(c != b && ((res = mw_mp_copy(b, c)) != MP_OKAY)) + return res; + + if((res = s_mw_mp_sub(c, a)) != MP_OKAY) + return res; + } + + SIGN(c) = !SIGN(b); + } + + if(USED(c) == 1 && DIGIT(c, 0) == 0) + SIGN(c) = MP_ZPOS; + + return MP_OKAY; + +} /* end mw_mp_sub() */ + +/* }}} */ + +/* {{{ mw_mp_mul(a, b, c) */ + +/* + mw_mp_mul(a, b, c) + + Compute c = a * b. All parameters may be identical. + */ + +mw_mp_err mw_mp_mul(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_err res; + mw_mp_sign sgn; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG; + + if(c == b) { + if((res = s_mw_mp_mul(c, a)) != MP_OKAY) + return res; + + } else { + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + if((res = s_mw_mp_mul(c, b)) != MP_OKAY) + return res; + } + + if(sgn == MP_ZPOS || s_mw_mp_cmw_mp_d(c, 0) == MP_EQ) + SIGN(c) = MP_ZPOS; + else + SIGN(c) = sgn; + + return MP_OKAY; + +} /* end mw_mp_mul() */ + +/* }}} */ + +/* {{{ mw_mp_mul_2d(a, d, c) */ + +/* + mw_mp_mul_2d(a, d, c) + + Compute c = a * 2^d. a may be the same as c. + */ + +mw_mp_err mw_mp_mul_2d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + if(d == 0) + return MP_OKAY; + + return s_mw_mp_mul_2d(c, d); + +} /* end mw_mp_mul() */ + +/* }}} */ + +/* {{{ mw_mp_sqr(a, b) */ + +#if MP_SQUARE +mw_mp_err mw_mp_sqr(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mw_mp_copy(a, b)) != MP_OKAY) + return res; + + if((res = s_mw_mp_sqr(b)) != MP_OKAY) + return res; + + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mw_mp_sqr() */ +#endif + +/* }}} */ + +/* {{{ mw_mp_div(a, b, q, r) */ + +/* + mw_mp_div(a, b, q, r) + + Compute q = a / b and r = a mod b. Input parameters may be re-used + as output parameters. If q or r is NULL, that portion of the + computation will be discarded (although it will still be computed) + + Pay no attention to the hacker behind the curtain. + */ + +mw_mp_err mw_mp_div(mw_mp_int *a, mw_mp_int *b, mw_mp_int *q, mw_mp_int *r) +{ + mw_mp_err res; + mw_mp_int qtmp, rtmp; + int cmp; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if(mw_mp_cmw_mp_z(b) == MP_EQ) + return MP_RANGE; + + /* If a <= b, we can compute the solution without division, and + avoid any memory allocation + */ + if((cmp = s_mw_mp_cmp(a, b)) < 0) { + if(r) { + if((res = mw_mp_copy(a, r)) != MP_OKAY) + return res; + } + + if(q) + mw_mp_zero(q); + + return MP_OKAY; + + } else if(cmp == 0) { + + /* Set quotient to 1, with appropriate sign */ + if(q) { + int qneg = (SIGN(a) != SIGN(b)); + + mw_mp_set(q, 1); + if(qneg) + SIGN(q) = MP_NEG; + } + + if(r) + mw_mp_zero(r); + + return MP_OKAY; + } + + /* If we get here, it means we actually have to do some division */ + + /* Set up some temporaries... */ + if((res = mw_mp_init_copy(&qtmp, a)) != MP_OKAY) + return res; + if((res = mw_mp_init_copy(&rtmp, b)) != MP_OKAY) + goto CLEANUP; + + if((res = s_mw_mp_div(&qtmp, &rtmp)) != MP_OKAY) + goto CLEANUP; + + /* Compute the signs for the output */ + SIGN(&rtmp) = SIGN(a); /* Sr = Sa */ + if(SIGN(a) == SIGN(b)) + SIGN(&qtmp) = MP_ZPOS; /* Sq = MP_ZPOS if Sa = Sb */ + else + SIGN(&qtmp) = MP_NEG; /* Sq = MP_NEG if Sa != Sb */ + + if(s_mw_mp_cmw_mp_d(&qtmp, 0) == MP_EQ) + SIGN(&qtmp) = MP_ZPOS; + if(s_mw_mp_cmw_mp_d(&rtmp, 0) == MP_EQ) + SIGN(&rtmp) = MP_ZPOS; + + /* Copy output, if it is needed */ + if(q) + s_mw_mp_exch(&qtmp, q); + + if(r) + s_mw_mp_exch(&rtmp, r); + +CLEANUP: + mw_mp_clear(&rtmp); + mw_mp_clear(&qtmp); + + return res; + +} /* end mw_mp_div() */ + +/* }}} */ + +/* {{{ mw_mp_div_2d(a, d, q, r) */ + +mw_mp_err mw_mp_div_2d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *q, mw_mp_int *r) +{ + mw_mp_err res; + + ARGCHK(a != NULL, MP_BADARG); + + if(q) { + if((res = mw_mp_copy(a, q)) != MP_OKAY) + return res; + + s_mw_mp_div_2d(q, d); + } + + if(r) { + if((res = mw_mp_copy(a, r)) != MP_OKAY) + return res; + + s_mw_mp_mod_2d(r, d); + } + + return MP_OKAY; + +} /* end mw_mp_div_2d() */ + +/* }}} */ + +/* {{{ mw_mp_expt(a, b, c) */ + +/* + mw_mp_expt(a, b, c) + + Compute c = a ** b, that is, raise a to the b power. Uses a + standard iterative square-and-multiply technique. + */ + +mw_mp_err mw_mp_expt(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_int s, x; + mw_mp_err res; + mw_mp_digit d; + + /// Miranda NG adaptation start - MSVC + ///int dig, bit; + int bit; + mw_mp_size dig; + /// Miranda NG adaptation end + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mw_mp_cmw_mp_z(b) < 0) + return MP_RANGE; + + if((res = mw_mp_init(&s)) != MP_OKAY) + return res; + + mw_mp_set(&s, 1); + + if((res = mw_mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + /* Loop over low-order digits in ascending order */ + for(dig = 0; dig < (USED(b) - 1); dig++) { + d = DIGIT(b, dig); + + /* Loop over bits of each non-maximal digit */ + for(bit = 0; bit < DIGIT_BIT; bit++) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + } + + /* Consider now the last digit... */ + d = DIGIT(b, dig); + + while(d) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + + if(mw_mp_iseven(b)) + SIGN(&s) = SIGN(a); + + res = mw_mp_copy(&s, c); + +CLEANUP: + mw_mp_clear(&x); +X: + mw_mp_clear(&s); + + return res; + +} /* end mw_mp_expt() */ + +/* }}} */ + +/* {{{ mw_mp_2expt(a, k) */ + +/* Compute a = 2^k */ + +mw_mp_err mw_mp_2expt(mw_mp_int *a, mw_mp_digit k) +{ + ARGCHK(a != NULL, MP_BADARG); + + return s_mw_mp_2expt(a, k); + +} /* end mw_mp_2expt() */ + +/* }}} */ + +/* {{{ mw_mp_mod(a, m, c) */ + +/* + mw_mp_mod(a, m, c) + + Compute c = a (mod m). Result will always be 0 <= c < m. + */ + +mw_mp_err mw_mp_mod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_err res; + int mag; + + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); + + if(SIGN(m) == MP_NEG) + return MP_RANGE; + + /* + If |a| > m, we need to divide to get the remainder and take the + absolute value. + + If |a| < m, we don't need to do any division, just copy and adjust + the sign (if a is negative). + + If |a| == m, we can simply set the result to zero. + + This order is intended to minimize the average path length of the + comparison chain on common workloads -- the most frequent cases are + that |a| != m, so we do those first. + */ + if((mag = s_mw_mp_cmp(a, m)) > 0) { + if((res = mw_mp_div(a, m, NULL, c)) != MP_OKAY) + return res; + + if(SIGN(c) == MP_NEG) { + if((res = mw_mp_add(c, m, c)) != MP_OKAY) + return res; + } + + } else if(mag < 0) { + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + + if(mw_mp_cmw_mp_z(a) < 0) { + if((res = mw_mp_add(c, m, c)) != MP_OKAY) + return res; + + } + + } else { + mw_mp_zero(c); + + } + + return MP_OKAY; + +} /* end mw_mp_mod() */ + +/* }}} */ + +/* {{{ mw_mp_mod_d(a, d, c) */ + +/* + mw_mp_mod_d(a, d, c) + + Compute c = a (mod d). Result will always be 0 <= c < d + */ +mw_mp_err mw_mp_mod_d(mw_mp_int *a, mw_mp_digit d, mw_mp_digit *c) +{ + mw_mp_err res; + mw_mp_digit rem; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if(s_mw_mp_cmw_mp_d(a, d) > 0) { + if((res = mw_mp_div_d(a, d, NULL, &rem)) != MP_OKAY) + return res; + + } else { + if(SIGN(a) == MP_NEG) + rem = d - DIGIT(a, 0); + else + rem = DIGIT(a, 0); + } + + if(c) + *c = rem; + + return MP_OKAY; + +} /* end mw_mp_mod_d() */ + +/* }}} */ + +/* {{{ mw_mp_sqrt(a, b) */ + +/* + mw_mp_sqrt(a, b) + + Compute the integer square root of a, and store the result in b. + Uses an integer-arithmetic version of Newton's iterative linear + approximation technique to determine this value; the result has the + following two properties: + + b^2 <= a + (b+1)^2 >= a + + It is a range error to pass a negative value. + */ +mw_mp_err mw_mp_sqrt(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_int x, t; + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + /* Cannot take square root of a negative value */ + if(SIGN(a) == MP_NEG) + return MP_RANGE; + + /* Special cases for zero and one, trivial */ + if(mw_mp_cmw_mp_d(a, 0) == MP_EQ || mw_mp_cmw_mp_d(a, 1) == MP_EQ) + return mw_mp_copy(a, b); + + /* Initialize the temporaries we'll use below */ + if((res = mw_mp_init_size(&t, USED(a))) != MP_OKAY) + return res; + + /* Compute an initial guess for the iteration as a itself */ + if((res = mw_mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + for(;;) { + /* t = (x * x) - a */ + mw_mp_copy(&x, &t); /* can't fail, t is big enough for original x */ + if((res = mw_mp_sqr(&t, &t)) != MP_OKAY || + (res = mw_mp_sub(&t, a, &t)) != MP_OKAY) + goto CLEANUP; + + /* t = t / 2x */ + s_mw_mp_mul_2(&x); + if((res = mw_mp_div(&t, &x, &t, NULL)) != MP_OKAY) + goto CLEANUP; + s_mw_mp_div_2(&x); + + /* Terminate the loop, if the quotient is zero */ + if(mw_mp_cmw_mp_z(&t) == MP_EQ) + break; + + /* x = x - t */ + if((res = mw_mp_sub(&x, &t, &x)) != MP_OKAY) + goto CLEANUP; + + } + + /* Copy result to output parameter */ + mw_mp_sub_d(&x, 1, &x); + s_mw_mp_exch(&x, b); + + CLEANUP: + mw_mp_clear(&x); + X: + mw_mp_clear(&t); + + return res; + +} /* end mw_mp_sqrt() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Modular arithmetic */ + +#if MP_MODARITH +/* {{{ mw_mp_addmod(a, b, m, c) */ + +/* + mw_mp_addmod(a, b, m, c) + + Compute c = (a + b) mod m + */ + +mw_mp_err mw_mp_addmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_add(a, b, c)) != MP_OKAY) + return res; + if((res = mw_mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mw_mp_submod(a, b, m, c) */ + +/* + mw_mp_submod(a, b, m, c) + + Compute c = (a - b) mod m + */ + +mw_mp_err mw_mp_submod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_sub(a, b, c)) != MP_OKAY) + return res; + if((res = mw_mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mw_mp_mulmod(a, b, m, c) */ + +/* + mw_mp_mulmod(a, b, m, c) + + Compute c = (a * b) mod m + */ + +mw_mp_err mw_mp_mulmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_mul(a, b, c)) != MP_OKAY) + return res; + if((res = mw_mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mw_mp_sqrmod(a, m, c) */ + +#if MP_SQUARE +mw_mp_err mw_mp_sqrmod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_err res; + + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_sqr(a, c)) != MP_OKAY) + return res; + if((res = mw_mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} /* end mw_mp_sqrmod() */ +#endif + +/* }}} */ + +/* {{{ mw_mp_exptmod(a, b, m, c) */ + +/* + mw_mp_exptmod(a, b, m, c) + + Compute c = (a ** b) mod m. Uses a standard square-and-multiply + method with modular reductions at each step. (This is basically the + same code as mw_mp_expt(), except for the addition of the reductions) + + The modular reductions are done using Barrett's algorithm (see + s_mw_mp_reduce() below for details) + */ + +mw_mp_err mw_mp_exptmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_int s, x, mu; + mw_mp_err res; + mw_mp_digit d, *db = DIGITS(b); + mw_mp_size ub = USED(b); + /// Miranda NG adaptation start - MSVC
+ ///int dig, bit;
+ int bit;
+ mw_mp_size dig; + /// Miranda NG adaptation end + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mw_mp_cmw_mp_z(b) < 0 || mw_mp_cmw_mp_z(m) <= 0) + return MP_RANGE; + + if((res = mw_mp_init(&s)) != MP_OKAY) + return res; + if((res = mw_mp_init_copy(&x, a)) != MP_OKAY) + goto X; + if((res = mw_mp_mod(&x, m, &x)) != MP_OKAY || + (res = mw_mp_init(&mu)) != MP_OKAY) + goto MU; + + mw_mp_set(&s, 1); + + /* mu = b^2k / m */ + s_mw_mp_add_d(&mu, 1); + s_mw_mp_lshd(&mu, 2 * USED(m)); + if((res = mw_mp_div(&mu, m, &mu, NULL)) != MP_OKAY) + goto CLEANUP; + + /* Loop over digits of b in ascending order, except highest order */ + for(dig = 0; dig < (ub - 1); dig++) { + d = *db++; + + /* Loop over the bits of the lower-order digits */ + for(bit = 0; bit < DIGIT_BIT; bit++) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mw_mp_reduce(&s, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mw_mp_reduce(&x, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + } + + /* Now do the last digit... */ + d = *db; + + while(d) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mw_mp_reduce(&s, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mw_mp_reduce(&x, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + s_mw_mp_exch(&s, c); + + CLEANUP: + mw_mp_clear(&mu); + MU: + mw_mp_clear(&x); + X: + mw_mp_clear(&s); + + return res; + +} /* end mw_mp_exptmod() */ + +/* }}} */ + +/* {{{ mw_mp_exptmod_d(a, d, m, c) */ + +mw_mp_err mw_mp_exptmod_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_int s, x; + mw_mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mw_mp_init(&s)) != MP_OKAY) + return res; + if((res = mw_mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + mw_mp_set(&s, 1); + + while(d != 0) { + if(d & 1) { + if((res = s_mw_mp_mul(&s, &x)) != MP_OKAY || + (res = mw_mp_mod(&s, m, &s)) != MP_OKAY) + goto CLEANUP; + } + + d /= 2; + + if((res = s_mw_mp_sqr(&x)) != MP_OKAY || + (res = mw_mp_mod(&x, m, &x)) != MP_OKAY) + goto CLEANUP; + } + + s_mw_mp_exch(&s, c); + +CLEANUP: + mw_mp_clear(&x); +X: + mw_mp_clear(&s); + + return res; + +} /* end mw_mp_exptmod_d() */ + +/* }}} */ +#endif /* if MP_MODARITH */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Comparison functions */ + +/* {{{ mw_mp_cmw_mp_z(a) */ + +/* + mw_mp_cmw_mp_z(a) + + Compare a <=> 0. Returns <0 if a<0, 0 if a=0, >0 if a>0. + */ + +int mw_mp_cmw_mp_z(mw_mp_int *a) +{ + if(SIGN(a) == MP_NEG) + return MP_LT; + else if(USED(a) == 1 && DIGIT(a, 0) == 0) + return MP_EQ; + else + return MP_GT; + +} /* end mw_mp_cmw_mp_z() */ + +/* }}} */ + +/* {{{ mw_mp_cmw_mp_d(a, d) */ + +/* + mw_mp_cmw_mp_d(a, d) + + Compare a <=> d. Returns <0 if a<d, 0 if a=d, >0 if a>d + */ + +int mw_mp_cmw_mp_d(mw_mp_int *a, mw_mp_digit d) +{ + ARGCHK(a != NULL, MP_EQ); + + if(SIGN(a) == MP_NEG) + return MP_LT; + + return s_mw_mp_cmw_mp_d(a, d); + +} /* end mw_mp_cmw_mp_d() */ + +/* }}} */ + +/* {{{ mw_mp_cmp(a, b) */ + +int mw_mp_cmp(mw_mp_int *a, mw_mp_int *b) +{ + ARGCHK(a != NULL && b != NULL, MP_EQ); + + if(SIGN(a) == SIGN(b)) { + int mag; + + if((mag = s_mw_mp_cmp(a, b)) == MP_EQ) + return MP_EQ; + + if(SIGN(a) == MP_ZPOS) + return mag; + else + return -mag; + + } else if(SIGN(a) == MP_ZPOS) { + return MP_GT; + } else { + return MP_LT; + } + +} /* end mw_mp_cmp() */ + +/* }}} */ + +/* {{{ mw_mp_cmw_mp_mag(a, b) */ + +/* + mw_mp_cmw_mp_mag(a, b) + + Compares |a| <=> |b|, and returns an appropriate comparison result + */ + +int mw_mp_cmw_mp_mag(mw_mp_int *a, mw_mp_int *b) +{ + ARGCHK(a != NULL && b != NULL, MP_EQ); + + return s_mw_mp_cmp(a, b); + +} /* end mw_mp_cmw_mp_mag() */ + +/* }}} */ + +/* {{{ mw_mp_cmw_mp_int(a, z) */ + +/* + This just converts z to an mw_mp_int, and uses the existing comparison + routines. This is sort of inefficient, but it's not clear to me how + frequently this wil get used anyway. For small positive constants, + you can always use mw_mp_cmw_mp_d(), and for zero, there is mw_mp_cmw_mp_z(). + */ +int mw_mp_cmw_mp_int(mw_mp_int *a, long z) +{ + mw_mp_int tmp; + int out; + + ARGCHK(a != NULL, MP_EQ); + + mw_mp_init(&tmp); mw_mp_set_int(&tmp, z); + out = mw_mp_cmp(a, &tmp); + mw_mp_clear(&tmp); + + return out; + +} /* end mw_mp_cmw_mp_int() */ + +/* }}} */ + +/* {{{ mw_mp_isodd(a) */ + +/* + mw_mp_isodd(a) + + Returns a true (non-zero) value if a is odd, false (zero) otherwise. + */ +int mw_mp_isodd(mw_mp_int *a) +{ + ARGCHK(a != NULL, 0); + + return (DIGIT(a, 0) & 1); + +} /* end mw_mp_isodd() */ + +/* }}} */ + +/* {{{ mw_mp_iseven(a) */ + +int mw_mp_iseven(mw_mp_int *a) +{ + return !mw_mp_isodd(a); + +} /* end mw_mp_iseven() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Number theoretic functions */ + +#if MP_NUMTH +/* {{{ mw_mp_gcd(a, b, c) */ + +/* + Like the old mw_mp_gcd() function, except computes the GCD using the + binary algorithm due to Josef Stein in 1961 (via Knuth). + */ +mw_mp_err mw_mp_gcd(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_err res; + mw_mp_int u, v, t; + mw_mp_size k = 0; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mw_mp_cmw_mp_z(a) == MP_EQ && mw_mp_cmw_mp_z(b) == MP_EQ) + return MP_RANGE; + if(mw_mp_cmw_mp_z(a) == MP_EQ) { + if((res = mw_mp_copy(b, c)) != MP_OKAY) + return res; + SIGN(c) = MP_ZPOS; return MP_OKAY; + } else if(mw_mp_cmw_mp_z(b) == MP_EQ) { + if((res = mw_mp_copy(a, c)) != MP_OKAY) + return res; + SIGN(c) = MP_ZPOS; return MP_OKAY; + } + + if((res = mw_mp_init(&t)) != MP_OKAY) + return res; + if((res = mw_mp_init_copy(&u, a)) != MP_OKAY) + goto U; + if((res = mw_mp_init_copy(&v, b)) != MP_OKAY) + goto V; + + SIGN(&u) = MP_ZPOS; + SIGN(&v) = MP_ZPOS; + + /* Divide out common factors of 2 until at least 1 of a, b is even */ + while(mw_mp_iseven(&u) && mw_mp_iseven(&v)) { + s_mw_mp_div_2(&u); + s_mw_mp_div_2(&v); + ++k; + } + + /* Initialize t */ + if(mw_mp_isodd(&u)) { + if((res = mw_mp_copy(&v, &t)) != MP_OKAY) + goto CLEANUP; + + /* t = -v */ + if(SIGN(&v) == MP_ZPOS) + SIGN(&t) = MP_NEG; + else + SIGN(&t) = MP_ZPOS; + + } else { + if((res = mw_mp_copy(&u, &t)) != MP_OKAY) + goto CLEANUP; + + } + + for(;;) { + while(mw_mp_iseven(&t)) { + s_mw_mp_div_2(&t); + } + + if(mw_mp_cmw_mp_z(&t) == MP_GT) { + if((res = mw_mp_copy(&t, &u)) != MP_OKAY) + goto CLEANUP; + + } else { + if((res = mw_mp_copy(&t, &v)) != MP_OKAY) + goto CLEANUP; + + /* v = -t */ + if(SIGN(&t) == MP_ZPOS) + SIGN(&v) = MP_NEG; + else + SIGN(&v) = MP_ZPOS; + } + + if((res = mw_mp_sub(&u, &v, &t)) != MP_OKAY) + goto CLEANUP; + + if(s_mw_mp_cmw_mp_d(&t, 0) == MP_EQ) + break; + } + + s_mw_mp_2expt(&v, k); /* v = 2^k */ + res = mw_mp_mul(&u, &v, c); /* c = u * v */ + + CLEANUP: + mw_mp_clear(&v); + V: + mw_mp_clear(&u); + U: + mw_mp_clear(&t); + + return res; + +} /* end mw_mp_bgcd() */ + +/* }}} */ + +/* {{{ mw_mp_lcm(a, b, c) */ + +/* We compute the least common multiple using the rule: + + ab = [a, b](a, b) + + ... by computing the product, and dividing out the gcd. + */ + +mw_mp_err mw_mp_lcm(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c) +{ + mw_mp_int gcd, prod; + mw_mp_err res; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + /* Set up temporaries */ + if((res = mw_mp_init(&gcd)) != MP_OKAY) + return res; + if((res = mw_mp_init(&prod)) != MP_OKAY) + goto GCD; + + if((res = mw_mp_mul(a, b, &prod)) != MP_OKAY) + goto CLEANUP; + if((res = mw_mp_gcd(a, b, &gcd)) != MP_OKAY) + goto CLEANUP; + + res = mw_mp_div(&prod, &gcd, c, NULL); + + CLEANUP: + mw_mp_clear(&prod); + GCD: + mw_mp_clear(&gcd); + + return res; + +} /* end mw_mp_lcm() */ + +/* }}} */ + +/* {{{ mw_mp_xgcd(a, b, g, x, y) */ + +/* + mw_mp_xgcd(a, b, g, x, y) + + Compute g = (a, b) and values x and y satisfying Bezout's identity + (that is, ax + by = g). This uses the extended binary GCD algorithm + based on the Stein algorithm used for mw_mp_gcd() + */ + +mw_mp_err mw_mp_xgcd(mw_mp_int *a, mw_mp_int *b, mw_mp_int *g, mw_mp_int *x, mw_mp_int *y) +{ + mw_mp_int gx, xc, yc, u, v, A, B, C, D; + mw_mp_int *clean[9]; + mw_mp_err res; + int last = -1; + + if(mw_mp_cmw_mp_z(b) == 0) + return MP_RANGE; + + /* Initialize all these variables we need */ + if((res = mw_mp_init(&u)) != MP_OKAY) goto CLEANUP; + clean[++last] = &u; + if((res = mw_mp_init(&v)) != MP_OKAY) goto CLEANUP; + clean[++last] = &v; + if((res = mw_mp_init(&gx)) != MP_OKAY) goto CLEANUP; + clean[++last] = &gx; + if((res = mw_mp_init(&A)) != MP_OKAY) goto CLEANUP; + clean[++last] = &A; + if((res = mw_mp_init(&B)) != MP_OKAY) goto CLEANUP; + clean[++last] = &B; + if((res = mw_mp_init(&C)) != MP_OKAY) goto CLEANUP; + clean[++last] = &C; + if((res = mw_mp_init(&D)) != MP_OKAY) goto CLEANUP; + clean[++last] = &D; + if((res = mw_mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP; + clean[++last] = &xc; + mw_mp_abs(&xc, &xc); + if((res = mw_mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP; + clean[++last] = &yc; + mw_mp_abs(&yc, &yc); + + mw_mp_set(&gx, 1); + + /* Divide by two until at least one of them is even */ + while(mw_mp_iseven(&xc) && mw_mp_iseven(&yc)) { + s_mw_mp_div_2(&xc); + s_mw_mp_div_2(&yc); + if((res = s_mw_mp_mul_2(&gx)) != MP_OKAY) + goto CLEANUP; + } + + mw_mp_copy(&xc, &u); + mw_mp_copy(&yc, &v); + mw_mp_set(&A, 1); mw_mp_set(&D, 1); + + /* Loop through binary GCD algorithm */ + for(;;) { + while(mw_mp_iseven(&u)) { + s_mw_mp_div_2(&u); + + if(mw_mp_iseven(&A) && mw_mp_iseven(&B)) { + s_mw_mp_div_2(&A); s_mw_mp_div_2(&B); + } else { + if((res = mw_mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP; + s_mw_mp_div_2(&A); + if((res = mw_mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP; + s_mw_mp_div_2(&B); + } + } + + while(mw_mp_iseven(&v)) { + s_mw_mp_div_2(&v); + + if(mw_mp_iseven(&C) && mw_mp_iseven(&D)) { + s_mw_mp_div_2(&C); s_mw_mp_div_2(&D); + } else { + if((res = mw_mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP; + s_mw_mp_div_2(&C); + if((res = mw_mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP; + s_mw_mp_div_2(&D); + } + } + + if(mw_mp_cmp(&u, &v) >= 0) { + if((res = mw_mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP; + if((res = mw_mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP; + if((res = mw_mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP; + + } else { + if((res = mw_mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP; + if((res = mw_mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP; + if((res = mw_mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP; + + } + + /* If we're done, copy results to output */ + if(mw_mp_cmw_mp_z(&u) == 0) { + if(x) + if((res = mw_mp_copy(&C, x)) != MP_OKAY) goto CLEANUP; + + if(y) + if((res = mw_mp_copy(&D, y)) != MP_OKAY) goto CLEANUP; + + if(g) + if((res = mw_mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP; + + break; + } + } + + CLEANUP: + while(last >= 0) + mw_mp_clear(clean[last--]); + + return res; + +} /* end mw_mp_xgcd() */ + +/* }}} */ + +/* {{{ mw_mp_invmod(a, m, c) */ + +/* + mw_mp_invmod(a, m, c) + + Compute c = a^-1 (mod m), if there is an inverse for a (mod m). + This is equivalent to the question of whether (a, m) = 1. If not, + MP_UNDEF is returned, and there is no inverse. + */ + +mw_mp_err mw_mp_invmod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c) +{ + mw_mp_int g, x; + mw_mp_sign sa; + mw_mp_err res; + + ARGCHK(a && m && c, MP_BADARG); + + if(mw_mp_cmw_mp_z(a) == 0 || mw_mp_cmw_mp_z(m) == 0) + return MP_RANGE; + + sa = SIGN(a); + + if((res = mw_mp_init(&g)) != MP_OKAY) + return res; + if((res = mw_mp_init(&x)) != MP_OKAY) + goto X; + + if((res = mw_mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY) + goto CLEANUP; + + if(mw_mp_cmw_mp_d(&g, 1) != MP_EQ) { + res = MP_UNDEF; + goto CLEANUP; + } + + res = mw_mp_mod(&x, m, c); + SIGN(c) = sa; + +CLEANUP: + mw_mp_clear(&x); +X: + mw_mp_clear(&g); + + return res; + +} /* end mw_mp_invmod() */ + +/* }}} */ +#endif /* if MP_NUMTH */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ mw_mp_print(mp, ofp) */ + +#if MP_IOFUNC +/* + mw_mp_print(mp, ofp) + + Print a textual representation of the given mw_mp_int on the output + stream 'ofp'. Output is generated using the internal radix. + */ + +void mw_mp_print(mw_mp_int *mp, FILE *ofp) +{ + int ix; + + if(mp == NULL || ofp == NULL) + return; + + fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp); + + for(ix = USED(mp) - 1; ix >= 0; ix--) { + fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix)); + } + +} /* end mw_mp_print() */ + +#endif /* if MP_IOFUNC */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ More I/O Functions */ + +/* {{{ mw_mp_read_signed_bin(mp, str, len) */ + +/* + mw_mp_read_signed_bin(mp, str, len) + + Read in a raw value (base 256) into the given mw_mp_int + */ + +mw_mp_err mw_mp_read_signed_bin(mw_mp_int *mp, unsigned char *str, int len) +{ + mw_mp_err res; + + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); + + if((res = mw_mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) { + /* Get sign from first byte */ + if(str[0]) + SIGN(mp) = MP_NEG; + else + SIGN(mp) = MP_ZPOS; + } + + return res; + +} /* end mw_mp_read_signed_bin() */ + +/* }}} */ + +/* {{{ mw_mp_signed_bin_size(mp) */ + +int mw_mp_signed_bin_size(mw_mp_int *mp) +{ + ARGCHK(mp != NULL, 0); + + return mw_mp_unsigned_bin_size(mp) + 1; + +} /* end mw_mp_signed_bin_size() */ + +/* }}} */ + +/* {{{ mw_mp_to_signed_bin(mp, str) */ + +mw_mp_err mw_mp_to_signed_bin(mw_mp_int *mp, unsigned char *str) +{ + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + + /* Caller responsible for allocating enough memory (use mw_mp_raw_size(mp)) */ + str[0] = (char)SIGN(mp); + + return mw_mp_to_unsigned_bin(mp, str + 1); + +} /* end mw_mp_to_signed_bin() */ + +/* }}} */ + +/* {{{ mw_mp_read_unsigned_bin(mp, str, len) */ + +/* + mw_mp_read_unsigned_bin(mp, str, len) + + Read in an unsigned value (base 256) into the given mw_mp_int + */ + +mw_mp_err mw_mp_read_unsigned_bin(mw_mp_int *mp, unsigned char *str, int len) +{ + int ix; + mw_mp_err res; + + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); + + mw_mp_zero(mp); + + for(ix = 0; ix < len; ix++) { + if((res = s_mw_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY) + return res; + + if((res = mw_mp_add_d(mp, str[ix], mp)) != MP_OKAY) + return res; + } + + return MP_OKAY; + +} /* end mw_mp_read_unsigned_bin() */ + +/* }}} */ + +/* {{{ mw_mp_unsigned_bin_size(mp) */ + +int mw_mp_unsigned_bin_size(mw_mp_int *mp) +{ + mw_mp_digit topdig; + int count; + + ARGCHK(mp != NULL, 0); + + /* Special case for the value zero */ + if(USED(mp) == 1 && DIGIT(mp, 0) == 0) + return 1; + + count = (USED(mp) - 1) * sizeof(mw_mp_digit); + topdig = DIGIT(mp, USED(mp) - 1); + + while(topdig != 0) { + ++count; + topdig >>= CHAR_BIT; + } + + return count; + +} /* end mw_mp_unsigned_bin_size() */ + +/* }}} */ + +/* {{{ mw_mp_to_unsigned_bin(mp, str) */ + +mw_mp_err mw_mp_to_unsigned_bin(mw_mp_int *mp, unsigned char *str) +{ + mw_mp_digit *dp, *end, d; + unsigned char *spos; + + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + + dp = DIGITS(mp); + end = dp + USED(mp) - 1; + spos = str; + + /* Special case for zero, quick test */ + if(dp == end && *dp == 0) { + *str = '\0'; + return MP_OKAY; + } + + /* Generate digits in reverse order */ + while(dp < end) { + int ix; + + d = *dp; + for(ix = 0; ix < sizeof(mw_mp_digit); ++ix) { + *spos = d & UCHAR_MAX; + d >>= CHAR_BIT; + ++spos; + } + + ++dp; + } + + /* Now handle last digit specially, high order zeroes are not written */ + d = *end; + while(d != 0) { + *spos = d & UCHAR_MAX; + d >>= CHAR_BIT; + ++spos; + } + + /* Reverse everything to get digits in the correct order */ + while(--spos > str) { + unsigned char t = *str; + *str = *spos; + *spos = t; + + ++str; + } + + return MP_OKAY; + +} /* end mw_mp_to_unsigned_bin() */ + +/* }}} */ + +/* {{{ mw_mp_count_bits(mp) */ + +int mw_mp_count_bits(mw_mp_int *mp) +{ + int len; + mw_mp_digit d; + + ARGCHK(mp != NULL, MP_BADARG); + + len = DIGIT_BIT * (USED(mp) - 1); + d = DIGIT(mp, USED(mp) - 1); + + while(d != 0) { + ++len; + d >>= 1; + } + + return len; + +} /* end mw_mp_count_bits() */ + +/* }}} */ + +/* {{{ mw_mp_read_radix(mp, str, radix) */ + +/* + mw_mp_read_radix(mp, str, radix) + + Read an integer from the given string, and set mp to the resulting + value. The input is presumed to be in base 10. Leading non-digit + characters are ignored, and the function reads until a non-digit + character or the end of the string. + */ + +mw_mp_err mw_mp_read_radix(mw_mp_int *mp, unsigned char *str, int radix) +{ + int ix = 0, val = 0; + mw_mp_err res; + mw_mp_sign sig = MP_ZPOS; + + ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, + MP_BADARG); + + mw_mp_zero(mp); + + /* Skip leading non-digit characters until a digit or '-' or '+' */ + while(str[ix] && + (s_mw_mp_tovalue(str[ix], radix) < 0) && + str[ix] != '-' && + str[ix] != '+') { + ++ix; + } + + if(str[ix] == '-') { + sig = MP_NEG; + ++ix; + } else if(str[ix] == '+') { + sig = MP_ZPOS; /* this is the default anyway... */ + ++ix; + } + + while((val = s_mw_mp_tovalue(str[ix], radix)) >= 0) { + if((res = s_mw_mp_mul_d(mp, radix)) != MP_OKAY) + return res; + if((res = s_mw_mp_add_d(mp, val)) != MP_OKAY) + return res; + ++ix; + } + + if(s_mw_mp_cmw_mp_d(mp, 0) == MP_EQ) + SIGN(mp) = MP_ZPOS; + else + SIGN(mp) = sig; + + return MP_OKAY; + +} /* end mw_mp_read_radix() */ + +/* }}} */ + +/* {{{ mw_mp_radix_size(mp, radix) */ + +int mw_mp_radix_size(mw_mp_int *mp, int radix) +{ + int len; + ARGCHK(mp != NULL, 0); + + len = s_mw_mp_outlen(mw_mp_count_bits(mp), radix) + 1; /* for NUL terminator */ + + if(mw_mp_cmw_mp_z(mp) < 0) + ++len; /* for sign */ + + return len; + +} /* end mw_mp_radix_size() */ + +/* }}} */ + +/* {{{ mw_mp_value_radix_size(num, qty, radix) */ + +/* num = number of digits + qty = number of bits per digit + radix = target base + + Return the number of digits in the specified radix that would be + needed to express 'num' digits of 'qty' bits each. + */ +int mw_mp_value_radix_size(int num, int qty, int radix) +{ + ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0); + + return s_mw_mp_outlen(num * qty, radix); + +} /* end mw_mp_value_radix_size() */ + +/* }}} */ + +/* {{{ mw_mp_toradix(mp, str, radix) */ + +mw_mp_err mw_mp_toradix(mw_mp_int *mp, unsigned char *str, int radix) +{ + int ix, pos = 0; + + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE); + + if(mw_mp_cmw_mp_z(mp) == MP_EQ) { + str[0] = '0'; + str[1] = '\0'; + } else { + mw_mp_err res; + mw_mp_int tmp; + mw_mp_sign sgn; + mw_mp_digit rem, rdx = (mw_mp_digit)radix; + char ch; + + if((res = mw_mp_init_copy(&tmp, mp)) != MP_OKAY) + return res; + + /* Save sign for later, and take absolute value */ + sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS; + + /* Generate output digits in reverse order */ + while(mw_mp_cmw_mp_z(&tmp) != 0) { + if((res = s_mw_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) { + mw_mp_clear(&tmp); + return res; + } + + /* Generate digits, use capital letters */ + ch = s_mw_mp_todigit(rem, radix, 0); + + str[pos++] = ch; + } + + /* Add - sign if original value was negative */ + if(sgn == MP_NEG) + str[pos++] = '-'; + + /* Add trailing NUL to end the string */ + str[pos--] = '\0'; + + /* Reverse the digits and sign indicator */ + ix = 0; + while(ix < pos) { + char tmp = str[ix]; + + str[ix] = str[pos]; + str[pos] = tmp; + ++ix; + --pos; + } + + mw_mp_clear(&tmp); + } + + return MP_OKAY; + +} /* end mw_mp_toradix() */ + +/* }}} */ + +/* {{{ mw_mp_char2value(ch, r) */ + +int mw_mp_char2value(char ch, int r) +{ + return s_mw_mp_tovalue(ch, r); + +} /* end mw_mp_tovalue() */ + +/* }}} */ + +/* }}} */ + +/* {{{ mw_mp_strerror(ec) */ + +/* + mw_mp_strerror(ec) + + Return a string describing the meaning of error code 'ec'. The + string returned is allocated in static memory, so the caller should + not attempt to modify or free the memory associated with this + string. + */ +const char *mw_mp_strerror(mw_mp_err ec) +{ + int aec = (ec < 0) ? -ec : ec; + + /* Code values are negative, so the senses of these comparisons + are accurate */ + if(ec < MP_LAST_CODE || ec > MP_OKAY) { + return mw_mp_err_string[0]; /* unknown error code */ + } else { + return mw_mp_err_string[aec + 1]; + } + +} /* end mw_mp_strerror() */ + +/* }}} */ + +/*========================================================================*/ +/*------------------------------------------------------------------------*/ +/* Static function definitions (internal use only) */ + +/* {{{ Memory management */ + +/* {{{ s_mw_mp_grow(mp, min) */ + +/* Make sure there are at least 'min' digits allocated to mp */ +mw_mp_err s_mw_mp_grow(mw_mp_int *mp, mw_mp_size min) +{ + if(min > ALLOC(mp)) { + mw_mp_digit *tmp; + + /* Set min to next nearest default precision block size */ + min = ((min + (s_mw_mp_defprec - 1)) / s_mw_mp_defprec) * s_mw_mp_defprec; + + if((tmp = s_mw_mp_alloc(min, sizeof(mw_mp_digit))) == NULL) + return MP_MEM; + + s_mw_mp_copy(DIGITS(mp), tmp, USED(mp)); + +#if MP_CRYPTO + s_mw_mp_setz(DIGITS(mp), ALLOC(mp)); +#endif + s_mw_mp_free(DIGITS(mp)); + DIGITS(mp) = tmp; + ALLOC(mp) = min; + } + + return MP_OKAY; + +} /* end s_mw_mp_grow() */ + +/* }}} */ + +/* {{{ s_mw_mp_pad(mp, min) */ + +/* Make sure the used size of mp is at least 'min', growing if needed */ +mw_mp_err s_mw_mp_pad(mw_mp_int *mp, mw_mp_size min) +{ + if(min > USED(mp)) { + mw_mp_err res; + + /* Make sure there is room to increase precision */ + if(min > ALLOC(mp) && (res = s_mw_mp_grow(mp, min)) != MP_OKAY) + return res; + + /* Increase precision; should already be 0-filled */ + USED(mp) = min; + } + + return MP_OKAY; + +} /* end s_mw_mp_pad() */ + +/* }}} */ + +/* {{{ s_mw_mp_setz(dp, count) */ + +#if MP_MACRO == 0 +/* Set 'count' digits pointed to by dp to be zeroes */ +void s_mw_mp_setz(mw_mp_digit *dp, mw_mp_size count) +{ +#if MP_MEMSET == 0 + int ix; + + for(ix = 0; ix < count; ix++) + dp[ix] = 0; +#else + memset(dp, 0, count * sizeof(mw_mp_digit)); +#endif + +} /* end s_mw_mp_setz() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_copy(sp, dp, count) */ + +#if MP_MACRO == 0 +/* Copy 'count' digits from sp to dp */ +void s_mw_mp_copy(mw_mp_digit *sp, mw_mp_digit *dp, mw_mp_size count) +{ +#if MP_MEMCPY == 0 + int ix; + + for(ix = 0; ix < count; ix++) + dp[ix] = sp[ix]; +#else + memcpy(dp, sp, count * sizeof(mw_mp_digit)); +#endif + +} /* end s_mw_mp_copy() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_alloc(nb, ni) */ + +#if MP_MACRO == 0 +/* Allocate ni records of nb bytes each, and return a pointer to that */ +void *s_mw_mp_alloc(size_t nb, size_t ni) +{ + return calloc(nb, ni); + +} /* end s_mw_mp_alloc() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_free(ptr) */ + +#if MP_MACRO == 0 +/* Free the memory pointed to by ptr */ +void s_mw_mp_free(void *ptr) +{ + if(ptr) + free(ptr); + +} /* end s_mw_mp_free() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_clamp(mp) */ + +/* Remove leading zeroes from the given value */ +void s_mw_mp_clamp(mw_mp_int *mp) +{ + mw_mp_size du = USED(mp); + mw_mp_digit *zp = DIGITS(mp) + du - 1; + + while(du > 1 && !*zp--) + --du; + + if(du == 1 && *zp == 0) + SIGN(mp) = MP_ZPOS; + + USED(mp) = du; + +} /* end s_mw_mp_clamp() */ + + +/* }}} */ + +/* {{{ s_mw_mp_exch(a, b) */ + +/* Exchange the data for a and b; (b, a) = (a, b) */ +void s_mw_mp_exch(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_int tmp; + + tmp = *a; + *a = *b; + *b = tmp; + +} /* end s_mw_mp_exch() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Arithmetic helpers */ + +/* {{{ s_mw_mp_lshd(mp, p) */ + +/* + Shift mp leftward by p digits, growing if needed, and zero-filling + the in-shifted digits at the right end. This is a convenient + alternative to multiplication by powers of the radix + */ + +mw_mp_err s_mw_mp_lshd(mw_mp_int *mp, mw_mp_size p) +{ + mw_mp_err res; + mw_mp_size pos; + mw_mp_digit *dp; + int ix; + + if(p == 0) + return MP_OKAY; + + if((res = s_mw_mp_pad(mp, USED(mp) + p)) != MP_OKAY) + return res; + + pos = USED(mp) - 1; + dp = DIGITS(mp); + + /* Shift all the significant figures over as needed */ + /// Miranda NG adaptation start - MSVC + ///for(ix = pos - p; ix >= 0; ix--) + for(ix = (int)(pos - p); ix >= 0; ix--) + /// Miranda NG adaptation end + dp[ix + p] = dp[ix]; + + /* Fill the bottom digits with zeroes */ + /// Miranda NG adaptation start - MSVC + ///for(ix = 0; ix < p; ix++) + for(ix = 0; ix < (int)p; ix++) + /// Miranda NG adaptation end + dp[ix] = 0; + + return MP_OKAY; + +} /* end s_mw_mp_lshd() */ + +/* }}} */ + +/* {{{ s_mw_mp_rshd(mp, p) */ + +/* + Shift mp rightward by p digits. Maintains the invariant that + digits above the precision are all zero. Digits shifted off the + end are lost. Cannot fail. + */ + +void s_mw_mp_rshd(mw_mp_int *mp, mw_mp_size p) +{ + mw_mp_size ix; + mw_mp_digit *dp; + + if(p == 0) + return; + + /* Shortcut when all digits are to be shifted off */ + if(p >= USED(mp)) { + s_mw_mp_setz(DIGITS(mp), ALLOC(mp)); + USED(mp) = 1; + SIGN(mp) = MP_ZPOS; + return; + } + + /* Shift all the significant figures over as needed */ + dp = DIGITS(mp); + for(ix = p; ix < USED(mp); ix++) + dp[ix - p] = dp[ix]; + + /* Fill the top digits with zeroes */ + ix -= p; + while(ix < USED(mp)) + dp[ix++] = 0; + + /* Strip off any leading zeroes */ + s_mw_mp_clamp(mp); + +} /* end s_mw_mp_rshd() */ + +/* }}} */ + +/* {{{ s_mw_mp_div_2(mp) */ + +/* Divide by two -- take advantage of radix properties to do it fast */ +void s_mw_mp_div_2(mw_mp_int *mp) +{ + s_mw_mp_div_2d(mp, 1); + +} /* end s_mw_mp_div_2() */ + +/* }}} */ + +/* {{{ s_mw_mp_mul_2(mp) */ + +mw_mp_err s_mw_mp_mul_2(mw_mp_int *mp) +{ + /// Miranda NG adaptation start - MSVC + //int ix; + mw_mp_size ix; + /// Miranda NG adaptation end + mw_mp_digit kin = 0, kout, *dp = DIGITS(mp); + mw_mp_err res; + + /* Shift digits leftward by 1 bit */ + for(ix = 0; ix < USED(mp); ix++) { + kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1; + dp[ix] = (dp[ix] << 1) | kin; + + kin = kout; + } + + /* Deal with rollover from last digit */ + if(kin) { + if(ix >= ALLOC(mp)) { + if((res = s_mw_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY) + return res; + dp = DIGITS(mp); + } + + dp[ix] = kin; + USED(mp) += 1; + } + + return MP_OKAY; + +} /* end s_mw_mp_mul_2() */ + +/* }}} */ + +/* {{{ s_mw_mp_mod_2d(mp, d) */ + +/* + Remainder the integer by 2^d, where d is a number of bits. This + amounts to a bitwise AND of the value, and does not require the full + division code + */ +void s_mw_mp_mod_2d(mw_mp_int *mp, mw_mp_digit d) +{ + unsigned int ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT); + unsigned int ix; + mw_mp_digit dmask, *dp = DIGITS(mp); + + if(ndig >= USED(mp)) + return; + + /* Flush all the bits above 2^d in its digit */ + dmask = (1 << nbit) - 1; + dp[ndig] &= dmask; + + /* Flush all digits above the one with 2^d in it */ + for(ix = ndig + 1; ix < USED(mp); ix++) + dp[ix] = 0; + + s_mw_mp_clamp(mp); + +} /* end s_mw_mp_mod_2d() */ + +/* }}} */ + +/* {{{ s_mw_mp_mul_2d(mp, d) */ + +/* + Multiply by the integer 2^d, where d is a number of bits. This + amounts to a bitwise shift of the value, and does not require the + full multiplication code. + */ +mw_mp_err s_mw_mp_mul_2d(mw_mp_int *mp, mw_mp_digit d) +{ + mw_mp_err res; + mw_mp_digit save, next, mask, *dp; + mw_mp_size used; + /// Miranda NG adaptation start - MSVC + ///int ix; + mw_mp_size ix; + /// Miranda NG adaptation end + + if((res = s_mw_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY) + return res; + + dp = DIGITS(mp); used = USED(mp); + d %= DIGIT_BIT; + + mask = (1 << d) - 1; + + /* If the shift requires another digit, make sure we've got one to + work with */ + if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) { + if((res = s_mw_mp_grow(mp, used + 1)) != MP_OKAY) + return res; + dp = DIGITS(mp); + } + + /* Do the shifting... */ + save = 0; + for(ix = 0; ix < used; ix++) { + next = (dp[ix] >> (DIGIT_BIT - d)) & mask; + dp[ix] = (dp[ix] << d) | save; + save = next; + } + + /* If, at this point, we have a nonzero carryout into the next + digit, we'll increase the size by one digit, and store it... + */ + if(save) { + dp[used] = save; + USED(mp) += 1; + } + + s_mw_mp_clamp(mp); + return MP_OKAY; + +} /* end s_mw_mp_mul_2d() */ + +/* }}} */ + +/* {{{ s_mw_mp_div_2d(mp, d) */ + +/* + Divide the integer by 2^d, where d is a number of bits. This + amounts to a bitwise shift of the value, and does not require the + full division code (used in Barrett reduction, see below) + */ +void s_mw_mp_div_2d(mw_mp_int *mp, mw_mp_digit d) +{ + int ix; + mw_mp_digit save, next, mask, *dp = DIGITS(mp); + + s_mw_mp_rshd(mp, d / DIGIT_BIT); + d %= DIGIT_BIT; + + mask = (1 << d) - 1; + + save = 0; + for(ix = USED(mp) - 1; ix >= 0; ix--) { + next = dp[ix] & mask; + dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d)); + save = next; + } + + s_mw_mp_clamp(mp); + +} /* end s_mw_mp_div_2d() */ + +/* }}} */ + +/* {{{ s_mw_mp_norm(a, b) */ + +/* + s_mw_mp_norm(a, b) + + Normalize a and b for division, where b is the divisor. In order + that we might make good guesses for quotient digits, we want the + leading digit of b to be at least half the radix, which we + accomplish by multiplying a and b by a constant. This constant is + returned (so that it can be divided back out of the remainder at the + end of the division process). + + We multiply by the smallest power of 2 that gives us a leading digit + at least half the radix. By choosing a power of 2, we simplify the + multiplication and division steps to simple shifts. + */ +mw_mp_digit s_mw_mp_norm(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_digit t, d = 0; + + t = DIGIT(b, USED(b) - 1); + while(t < (RADIX / 2)) { + t <<= 1; + ++d; + } + + if(d != 0) { + s_mw_mp_mul_2d(a, d); + s_mw_mp_mul_2d(b, d); + } + + return d; + +} /* end s_mw_mp_norm() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive digit arithmetic */ + +/* {{{ s_mw_mp_add_d(mp, d) */ + +/* Add d to |mp| in place */ +mw_mp_err s_mw_mp_add_d(mw_mp_int *mp, mw_mp_digit d) /* unsigned digit addition */ +{ + mw_mp_word w, k = 0; + mw_mp_size ix = 1, used = USED(mp); + mw_mp_digit *dp = DIGITS(mp); + + w = dp[0] + d; + dp[0] = ACCUM(w); + k = CARRYOUT(w); + + while(ix < used && k) { + w = dp[ix] + k; + dp[ix] = ACCUM(w); + k = CARRYOUT(w); + ++ix; + } + + if(k != 0) { + mw_mp_err res; + + if((res = s_mw_mp_pad(mp, USED(mp) + 1)) != MP_OKAY) + return res; + + DIGIT(mp, ix) = k; + } + + return MP_OKAY; + +} /* end s_mw_mp_add_d() */ + +/* }}} */ + +/* {{{ s_mw_mp_sub_d(mp, d) */ + +/* Subtract d from |mp| in place, assumes |mp| > d */ +mw_mp_err s_mw_mp_sub_d(mw_mp_int *mp, mw_mp_digit d) /* unsigned digit subtract */ +{ + mw_mp_word w, b = 0; + mw_mp_size ix = 1, used = USED(mp); + mw_mp_digit *dp = DIGITS(mp); + + /* Compute initial subtraction */ + w = (RADIX + dp[0]) - d; + b = CARRYOUT(w) ? 0 : 1; + dp[0] = ACCUM(w); + + /* Propagate borrows leftward */ + while(b && ix < used) { + w = (RADIX + dp[ix]) - b; + b = CARRYOUT(w) ? 0 : 1; + dp[ix] = ACCUM(w); + ++ix; + } + + /* Remove leading zeroes */ + s_mw_mp_clamp(mp); + + /* If we have a borrow out, it's a violation of the input invariant */ + if(b) + return MP_RANGE; + else + return MP_OKAY; + +} /* end s_mw_mp_sub_d() */ + +/* }}} */ + +/* {{{ s_mw_mp_mul_d(a, d) */ + +/* Compute a = a * d, single digit multiplication */ +mw_mp_err s_mw_mp_mul_d(mw_mp_int *a, mw_mp_digit d) +{ + mw_mp_word w, k = 0; + mw_mp_size ix, max; + mw_mp_err res; + mw_mp_digit *dp = DIGITS(a); + + /* + Single-digit multiplication will increase the precision of the + output by at most one digit. However, we can detect when this + will happen -- if the high-order digit of a, times d, gives a + two-digit result, then the precision of the result will increase; + otherwise it won't. We use this fact to avoid calling s_mw_mp_pad() + unless absolutely necessary. + */ + max = USED(a); + w = dp[max - 1] * d; + if(CARRYOUT(w) != 0) { + if((res = s_mw_mp_pad(a, max + 1)) != MP_OKAY) + return res; + dp = DIGITS(a); + } + + for(ix = 0; ix < max; ix++) { + w = (dp[ix] * d) + k; + dp[ix] = ACCUM(w); + k = CARRYOUT(w); + } + + /* If there is a precision increase, take care of it here; the above + test guarantees we have enough storage to do this safely. + */ + if(k) { + dp[max] = k; + USED(a) = max + 1; + } + + s_mw_mp_clamp(a); + + return MP_OKAY; + +} /* end s_mw_mp_mul_d() */ + +/* }}} */ + +/* {{{ s_mw_mp_div_d(mp, d, r) */ + +/* + s_mw_mp_div_d(mp, d, r) + + Compute the quotient mp = mp / d and remainder r = mp mod d, for a + single digit d. If r is null, the remainder will be discarded. + */ + +mw_mp_err s_mw_mp_div_d(mw_mp_int *mp, mw_mp_digit d, mw_mp_digit *r) +{ + mw_mp_word w = 0, t; + mw_mp_int quot; + mw_mp_err res; + mw_mp_digit *dp = DIGITS(mp), *qp; + int ix; + + if(d == 0) + return MP_RANGE; + + /* Make room for the quotient */ + if((res = mw_mp_init_size(", USED(mp))) != MP_OKAY) + return res; + + USED(") = USED(mp); /* so clamping will work below */ + qp = DIGITS("); + + /* Divide without subtraction */ + for(ix = USED(mp) - 1; ix >= 0; ix--) { + w = (w << DIGIT_BIT) | dp[ix]; + + if(w >= d) { + t = w / d; + w = w % d; + } else { + t = 0; + } + + qp[ix] = t; + } + + /* Deliver the remainder, if desired */ + if(r) + *r = w; + + s_mw_mp_clamp("); + mw_mp_exch(", mp); + mw_mp_clear("); + + return MP_OKAY; + +} /* end s_mw_mp_div_d() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive full arithmetic */ + +/* {{{ s_mw_mp_add(a, b) */ + +/* Compute a = |a| + |b| */ +mw_mp_err s_mw_mp_add(mw_mp_int *a, mw_mp_int *b) /* magnitude addition */ +{ + mw_mp_word w = 0; + mw_mp_digit *pa, *pb; + mw_mp_size ix, used = USED(b); + mw_mp_err res; + + /* Make sure a has enough precision for the output value */ + if((used > USED(a)) && (res = s_mw_mp_pad(a, used)) != MP_OKAY) + return res; + + /* + Add up all digits up to the precision of b. If b had initially + the same precision as a, or greater, we took care of it by the + padding step above, so there is no problem. If b had initially + less precision, we'll have to make sure the carry out is duly + propagated upward among the higher-order digits of the sum. + */ + pa = DIGITS(a); + pb = DIGITS(b); + for(ix = 0; ix < used; ++ix) { + w += *pa + *pb++; + *pa++ = ACCUM(w); + w = CARRYOUT(w); + } + + /* If we run out of 'b' digits before we're actually done, make + sure the carries get propagated upward... + */ + used = USED(a); + while(w && ix < used) { + w += *pa; + *pa++ = ACCUM(w); + w = CARRYOUT(w); + ++ix; + } + + /* If there's an overall carry out, increase precision and include + it. We could have done this initially, but why touch the memory + allocator unless we're sure we have to? + */ + if(w) { + if((res = s_mw_mp_pad(a, used + 1)) != MP_OKAY) + return res; + + DIGIT(a, ix) = w; /* pa may not be valid after s_mw_mp_pad() call */ + } + + return MP_OKAY; + +} /* end s_mw_mp_add() */ + +/* }}} */ + +/* {{{ s_mw_mp_sub(a, b) */ + +/* Compute a = |a| - |b|, assumes |a| >= |b| */ +mw_mp_err s_mw_mp_sub(mw_mp_int *a, mw_mp_int *b) /* magnitude subtract */ +{ + mw_mp_word w = 0; + mw_mp_digit *pa, *pb; + mw_mp_size ix, used = USED(b); + + /* + Subtract and propagate borrow. Up to the precision of b, this + accounts for the digits of b; after that, we just make sure the + carries get to the right place. This saves having to pad b out to + the precision of a just to make the loops work right... + */ + pa = DIGITS(a); + pb = DIGITS(b); + + for(ix = 0; ix < used; ++ix) { + w = (RADIX + *pa) - w - *pb++; + *pa++ = ACCUM(w); + w = CARRYOUT(w) ? 0 : 1; + } + + used = USED(a); + while(ix < used) { + w = RADIX + *pa - w; + *pa++ = ACCUM(w); + w = CARRYOUT(w) ? 0 : 1; + ++ix; + } + + /* Clobber any leading zeroes we created */ + s_mw_mp_clamp(a); + + /* + If there was a borrow out, then |b| > |a| in violation + of our input invariant. We've already done the work, + but we'll at least complain about it... + */ + if(w) + return MP_RANGE; + else + return MP_OKAY; + +} /* end s_mw_mp_sub() */ + +/* }}} */ + +/* {{{ s_mw_mp_mul(a, b) */ + +/* Compute a = |a| * |b| */ +mw_mp_err s_mw_mp_mul(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_word w, k = 0; + mw_mp_int tmp; + mw_mp_err res; + mw_mp_size ix, jx, ua = USED(a), ub = USED(b); + mw_mp_digit *pa, *pb, *pt, *pbt; + + if((res = mw_mp_init_size(&tmp, ua + ub)) != MP_OKAY) + return res; + + /* This has the effect of left-padding with zeroes... */ + USED(&tmp) = ua + ub; + + /* We're going to need the base value each iteration */ + pbt = DIGITS(&tmp); + + /* Outer loop: Digits of b */ + + pb = DIGITS(b); + for(ix = 0; ix < ub; ++ix, ++pb) { + if(*pb == 0) + continue; + + /* Inner product: Digits of a */ + pa = DIGITS(a); + for(jx = 0; jx < ua; ++jx, ++pa) { + pt = pbt + ix + jx; + w = *pb * *pa + k + *pt; + *pt = ACCUM(w); + k = CARRYOUT(w); + } + + pbt[ix + jx] = k; + k = 0; + } + + s_mw_mp_clamp(&tmp); + s_mw_mp_exch(&tmp, a); + + mw_mp_clear(&tmp); + + return MP_OKAY; + +} /* end s_mw_mp_mul() */ + +/* }}} */ + +/* {{{ s_mw_mp_kmul(a, b, out, len) */ + +#if 0 +void s_mw_mp_kmul(mw_mp_digit *a, mw_mp_digit *b, mw_mp_digit *out, mw_mp_size len) +{ + mw_mp_word w, k = 0; + mw_mp_size ix, jx; + mw_mp_digit *pa, *pt; + + for(ix = 0; ix < len; ++ix, ++b) { + if(*b == 0) + continue; + + pa = a; + for(jx = 0; jx < len; ++jx, ++pa) { + pt = out + ix + jx; + w = *b * *pa + k + *pt; + *pt = ACCUM(w); + k = CARRYOUT(w); + } + + out[ix + jx] = k; + k = 0; + } + +} /* end s_mw_mp_kmul() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_sqr(a) */ + +/* + Computes the square of a, in place. This can be done more + efficiently than a general multiplication, because many of the + computation steps are redundant when squaring. The inner product + step is a bit more complicated, but we save a fair number of + iterations of the multiplication loop. + */ +#if MP_SQUARE +mw_mp_err s_mw_mp_sqr(mw_mp_int *a) +{ + mw_mp_word w, k = 0; + mw_mp_int tmp; + mw_mp_err res; + mw_mp_size ix, jx, kx, used = USED(a); + mw_mp_digit *pa1, *pa2, *pt, *pbt; + + if((res = mw_mp_init_size(&tmp, 2 * used)) != MP_OKAY) + return res; + + /* Left-pad with zeroes */ + USED(&tmp) = 2 * used; + + /* We need the base value each time through the loop */ + pbt = DIGITS(&tmp); + + pa1 = DIGITS(a); + for(ix = 0; ix < used; ++ix, ++pa1) { + if(*pa1 == 0) + continue; + + w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1); + + pbt[ix + ix] = ACCUM(w); + k = CARRYOUT(w); + + /* + The inner product is computed as: + + (C, S) = t[i,j] + 2 a[i] a[j] + C + + This can overflow what can be represented in an mw_mp_word, and + since C arithmetic does not provide any way to check for + overflow, we have to check explicitly for overflow conditions + before they happen. + */ + for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) { + mw_mp_word u = 0, v; + + /* Store this in a temporary to avoid indirections later */ + pt = pbt + ix + jx; + + /* Compute the multiplicative step */ + w = *pa1 * *pa2; + + /* If w is more than half MP_WORD_MAX, the doubling will + overflow, and we need to record a carry out into the next + word */ + u = (w >> (MP_WORD_BIT - 1)) & 1; + + /* Double what we've got, overflow will be ignored as defined + for C arithmetic (we've already noted if it is to occur) + */ + w *= 2; + + /* Compute the additive step */ + v = *pt + k; + + /* If we do not already have an overflow carry, check to see + if the addition will cause one, and set the carry out if so + */ + u |= ((MP_WORD_MAX - v) < w); + + /* Add in the rest, again ignoring overflow */ + w += v; + + /* Set the i,j digit of the output */ + *pt = ACCUM(w); + + /* Save carry information for the next iteration of the loop. + This is why k must be an mw_mp_word, instead of an mw_mp_digit */ + k = CARRYOUT(w) | (u << DIGIT_BIT); + + } /* for(jx ...) */ + + /* Set the last digit in the cycle and reset the carry */ + k = DIGIT(&tmp, ix + jx) + k; + pbt[ix + jx] = ACCUM(k); + k = CARRYOUT(k); + + /* If we are carrying out, propagate the carry to the next digit + in the output. This may cascade, so we have to be somewhat + circumspect -- but we will have enough precision in the output + that we won't overflow + */ + kx = 1; + while(k) { + k = pbt[ix + jx + kx] + 1; + pbt[ix + jx + kx] = ACCUM(k); + k = CARRYOUT(k); + ++kx; + } + } /* for(ix ...) */ + + s_mw_mp_clamp(&tmp); + s_mw_mp_exch(&tmp, a); + + mw_mp_clear(&tmp); + + return MP_OKAY; + +} /* end s_mw_mp_sqr() */ +#endif + +/* }}} */ + +/* {{{ s_mw_mp_div(a, b) */ + +/* + s_mw_mp_div(a, b) + + Compute a = a / b and b = a mod b. Assumes b > a. + */ + +mw_mp_err s_mw_mp_div(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_int quot, rem, t; + mw_mp_word q; + mw_mp_err res; + mw_mp_digit d; + int ix; + + if(mw_mp_cmw_mp_z(b) == 0) + return MP_RANGE; + + /* Shortcut if b is power of two */ + if((ix = s_mw_mp_ispow2(b)) >= 0) { + mw_mp_copy(a, b); /* need this for remainder */ + s_mw_mp_div_2d(a, (mw_mp_digit)ix); + s_mw_mp_mod_2d(b, (mw_mp_digit)ix); + + return MP_OKAY; + } + + /* Allocate space to store the quotient */ + if((res = mw_mp_init_size(", USED(a))) != MP_OKAY) + return res; + + /* A working temporary for division */ + if((res = mw_mp_init_size(&t, USED(a))) != MP_OKAY) + goto T; + + /* Allocate space for the remainder */ + if((res = mw_mp_init_size(&rem, USED(a))) != MP_OKAY) + goto REM; + + /* Normalize to optimize guessing */ + d = s_mw_mp_norm(a, b); + + /* Perform the division itself...woo! */ + ix = USED(a) - 1; + + while(ix >= 0) { + /* Find a partial substring of a which is at least b */ + while(s_mw_mp_cmp(&rem, b) < 0 && ix >= 0) { + if((res = s_mw_mp_lshd(&rem, 1)) != MP_OKAY) + goto CLEANUP; + + if((res = s_mw_mp_lshd(", 1)) != MP_OKAY) + goto CLEANUP; + + DIGIT(&rem, 0) = DIGIT(a, ix); + s_mw_mp_clamp(&rem); + --ix; + } + + /* If we didn't find one, we're finished dividing */ + if(s_mw_mp_cmp(&rem, b) < 0) + break; + + /* Compute a guess for the next quotient digit */ + q = DIGIT(&rem, USED(&rem) - 1); + if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1) + q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2); + + q /= DIGIT(b, USED(b) - 1); + + /* The guess can be as much as RADIX + 1 */ + if(q >= RADIX) + q = RADIX - 1; + + /* See what that multiplies out to */ + mw_mp_copy(b, &t); + if((res = s_mw_mp_mul_d(&t, q)) != MP_OKAY) + goto CLEANUP; + + /* + If it's too big, back it off. We should not have to do this + more than once, or, in rare cases, twice. Knuth describes a + method by which this could be reduced to a maximum of once, but + I didn't implement that here. + */ + while(s_mw_mp_cmp(&t, &rem) > 0) { + --q; + s_mw_mp_sub(&t, b); + } + + /* At this point, q should be the right next digit */ + if((res = s_mw_mp_sub(&rem, &t)) != MP_OKAY) + goto CLEANUP; + + /* + Include the digit in the quotient. We allocated enough memory + for any quotient we could ever possibly get, so we should not + have to check for failures here + */ + DIGIT(", 0) = q; + } + + /* Denormalize remainder */ + if(d != 0) + s_mw_mp_div_2d(&rem, d); + + s_mw_mp_clamp("); + s_mw_mp_clamp(&rem); + + /* Copy quotient back to output */ + s_mw_mp_exch(", a); + + /* Copy remainder back to output */ + s_mw_mp_exch(&rem, b); + +CLEANUP: + mw_mp_clear(&rem); +REM: + mw_mp_clear(&t); +T: + mw_mp_clear("); + + return res; + +} /* end s_mw_mp_div() */ + +/* }}} */ + +/* {{{ s_mw_mp_2expt(a, k) */ + +mw_mp_err s_mw_mp_2expt(mw_mp_int *a, mw_mp_digit k) +{ + mw_mp_err res; + mw_mp_size dig, bit; + + dig = k / DIGIT_BIT; + bit = k % DIGIT_BIT; + + mw_mp_zero(a); + if((res = s_mw_mp_pad(a, dig + 1)) != MP_OKAY) + return res; + + DIGIT(a, dig) |= (1 << bit); + + return MP_OKAY; + +} /* end s_mw_mp_2expt() */ + +/* }}} */ + +/* {{{ s_mw_mp_reduce(x, m, mu) */ + +/* + Compute Barrett reduction, x (mod m), given a precomputed value for + mu = b^2k / m, where b = RADIX and k = #digits(m). This should be + faster than straight division, when many reductions by the same + value of m are required (such as in modular exponentiation). This + can nearly halve the time required to do modular exponentiation, + as compared to using the full integer divide to reduce. + + This algorithm was derived from the _Handbook of Applied + Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14, + pp. 603-604. + */ + +mw_mp_err s_mw_mp_reduce(mw_mp_int *x, mw_mp_int *m, mw_mp_int *mu) +{ + mw_mp_int q; + mw_mp_err res; + mw_mp_size um = USED(m); + + if((res = mw_mp_init_copy(&q, x)) != MP_OKAY) + return res; + + s_mw_mp_rshd(&q, um - 1); /* q1 = x / b^(k-1) */ + s_mw_mp_mul(&q, mu); /* q2 = q1 * mu */ + s_mw_mp_rshd(&q, um + 1); /* q3 = q2 / b^(k+1) */ + + /* x = x mod b^(k+1), quick (no division) */ + s_mw_mp_mod_2d(x, DIGIT_BIT * (um + 1)); + + /* q = q * m mod b^(k+1), quick (no division) */ + s_mw_mp_mul(&q, m); + s_mw_mp_mod_2d(&q, DIGIT_BIT * (um + 1)); + + /* x = x - q */ + if((res = mw_mp_sub(x, &q, x)) != MP_OKAY) + goto CLEANUP; + + /* If x < 0, add b^(k+1) to it */ + if(mw_mp_cmw_mp_z(x) < 0) { + mw_mp_set(&q, 1); + if((res = s_mw_mp_lshd(&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if((res = mw_mp_add(x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while(mw_mp_cmp(x, m) >= 0) { + if((res = s_mw_mp_sub(x, m)) != MP_OKAY) + break; + } + + CLEANUP: + mw_mp_clear(&q); + + return res; + +} /* end s_mw_mp_reduce() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive comparisons */ + +/* {{{ s_mw_mp_cmp(a, b) */ + +/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b */ +int s_mw_mp_cmp(mw_mp_int *a, mw_mp_int *b) +{ + mw_mp_size ua = USED(a), ub = USED(b); + + if(ua > ub) + return MP_GT; + else if(ua < ub) + return MP_LT; + else { + int ix = ua - 1; + mw_mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix; + + while(ix >= 0) { + if(*ap > *bp) + return MP_GT; + else if(*ap < *bp) + return MP_LT; + + --ap; --bp; --ix; + } + + return MP_EQ; + } + +} /* end s_mw_mp_cmp() */ + +/* }}} */ + +/* {{{ s_mw_mp_cmw_mp_d(a, d) */ + +/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d */ +int s_mw_mp_cmw_mp_d(mw_mp_int *a, mw_mp_digit d) +{ + mw_mp_size ua = USED(a); + mw_mp_digit *ap = DIGITS(a); + + if(ua > 1) + return MP_GT; + + if(*ap < d) + return MP_LT; + else if(*ap > d) + return MP_GT; + else + return MP_EQ; + +} /* end s_mw_mp_cmw_mp_d() */ + +/* }}} */ + +/* {{{ s_mw_mp_ispow2(v) */ + +/* + Returns -1 if the value is not a power of two; otherwise, it returns + k such that v = 2^k, i.e. lg(v). + */ +int s_mw_mp_ispow2(mw_mp_int *v) +{ + mw_mp_digit d, *dp; + mw_mp_size uv = USED(v); + int extra = 0, ix; + + d = DIGIT(v, uv - 1); /* most significant digit of v */ + + while(d && ((d & 1) == 0)) { + d >>= 1; + ++extra; + } + + if(d == 1) { + ix = uv - 2; + dp = DIGITS(v) + ix; + + while(ix >= 0) { + if(*dp) + return -1; /* not a power of two */ + + --dp; --ix; + } + + return ((uv - 1) * DIGIT_BIT) + extra; + } + + return -1; + +} /* end s_mw_mp_ispow2() */ + +/* }}} */ + +/* {{{ s_mw_mp_ispow2d(d) */ + +int s_mw_mp_ispow2d(mw_mp_digit d) +{ + int pow = 0; + + while((d & 1) == 0) { + ++pow; d >>= 1; + } + + if(d == 1) + return pow; + + return -1; + +} /* end s_mw_mp_ispow2d() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive I/O helpers */ + +/* {{{ s_mw_mp_tovalue(ch, r) */ + +/* + Convert the given character to its digit value, in the given radix. + If the given character is not understood in the given radix, -1 is + returned. Otherwise the digit's numeric value is returned. + + The results will be odd if you use a radix < 2 or > 62, you are + expected to know what you're up to. + */ +int s_mw_mp_tovalue(char ch, int r) +{ + int val, xch; + + if(r > 36) + xch = ch; + else + xch = toupper(ch); + + if(isdigit(xch)) + val = xch - '0'; + else if(isupper(xch)) + val = xch - 'A' + 10; + else if(islower(xch)) + val = xch - 'a' + 36; + else if(xch == '+') + val = 62; + else if(xch == '/') + val = 63; + else + return -1; + + if(val < 0 || val >= r) + return -1; + + return val; + +} /* end s_mw_mp_tovalue() */ + +/* }}} */ + +/* {{{ s_mw_mp_todigit(val, r, low) */ + +/* + Convert val to a radix-r digit, if possible. If val is out of range + for r, returns zero. Otherwise, returns an ASCII character denoting + the value in the given radix. + + The results may be odd if you use a radix < 2 or > 64, you are + expected to know what you're doing. + */ + +char s_mw_mp_todigit(int val, int r, int low) +{ + char ch; + + if(val < 0 || val >= r) + return 0; + + ch = s_dmap_1[val]; + + if(r <= 36 && low) + ch = tolower(ch); + + return ch; + +} /* end s_mw_mp_todigit() */ + +/* }}} */ + +/* {{{ s_mw_mp_outlen(bits, radix) */ + +/* + Return an estimate for how long a string is needed to hold a radix + r representation of a number with 'bits' significant bits. + + Does not include space for a sign or a NUL terminator. + */ +int s_mw_mp_outlen(int bits, int r) +{ + return (int)((double)bits * LOG_V_2(r) + 0.5); + +} /* end s_mw_mp_outlen() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* HERE THERE BE DRAGONS */ diff --git a/protocols/Sametime/src/meanwhile/src/mpi/mpi.h b/protocols/Sametime/src/meanwhile/src/mpi/mpi.h new file mode 100644 index 0000000000..0e7cc527a1 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mpi/mpi.h @@ -0,0 +1,221 @@ +/* + mpi.h + + by Michael J. Fromberger <http://www.dartmouth.edu/~sting/> + Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + + Arbitrary precision integer arithmetic library + + modified for use in Meanwhile as a convenience library +*/ + +#ifndef _H_MPI_ +#define _H_MPI_ + +#include "mpi-config.h" + +#if MP_DEBUG +#undef MP_IOFUNC +#define MP_IOFUNC 1 +#endif + +#if MP_IOFUNC +#include <stdio.h> +#include <ctype.h> +#endif + +#include <limits.h> + +#define MP_NEG 1 +#define MP_ZPOS 0 + +/* Included for compatibility... */ +#define NEG MP_NEG +#define ZPOS MP_ZPOS + +#define MP_OKAY 0 /* no error, all is well */ +#define MP_YES 0 /* yes (boolean result) */ +#define MP_NO -1 /* no (boolean result) */ +#define MP_MEM -2 /* out of memory */ +#define MP_RANGE -3 /* argument out of range */ +#define MP_BADARG -4 /* invalid parameter */ +#define MP_UNDEF -5 /* answer is undefined */ +#define MP_LAST_CODE MP_UNDEF + +#include "mpi-types.h" + +/* Included for compatibility... */ +#define DIGIT_BIT MP_DIGIT_BIT +#define DIGIT_MAX MP_DIGIT_MAX + +/* Macros for accessing the mw_mp_int internals */ +#define SIGN(MP) ((MP)->sign) +#define USED(MP) ((MP)->used) +#define ALLOC(MP) ((MP)->alloc) +#define DIGITS(MP) ((MP)->dp) +#define DIGIT(MP,N) (MP)->dp[(N)] + +#if MP_ARGCHK == 1 +#define ARGCHK(X,Y) {if(!(X)){return (Y);}} +#elif MP_ARGCHK == 2 +#include <assert.h> +#define ARGCHK(X,Y) assert(X) +#else +#define ARGCHK(X,Y) /* */ +#endif + +/* This defines the maximum I/O base (minimum is 2) */ +#define MAX_RADIX 64 + +typedef struct { + mw_mp_sign sign; /* sign of this quantity */ + mw_mp_size alloc; /* how many digits allocated */ + mw_mp_size used; /* how many digits used */ + mw_mp_digit *dp; /* the digits themselves */ +} mw_mp_int; + +/*------------------------------------------------------------------------*/ +/* Default precision */ + +unsigned int mw_mp_get_prec(void); +void mw_mp_set_prec(unsigned int prec); + +/*------------------------------------------------------------------------*/ +/* Memory management */ + +mw_mp_err mw_mp_init(mw_mp_int *mp); +mw_mp_err mw_mp_init_array(mw_mp_int mp[], int count); +mw_mp_err mw_mp_init_size(mw_mp_int *mp, mw_mp_size prec); +mw_mp_err mw_mp_init_copy(mw_mp_int *mp, mw_mp_int *from); +mw_mp_err mw_mp_copy(mw_mp_int *from, mw_mp_int *to); +void mw_mp_exch(mw_mp_int *mp1, mw_mp_int *mp2); +void mw_mp_clear(mw_mp_int *mp); +void mw_mp_clear_array(mw_mp_int mp[], int count); +void mw_mp_zero(mw_mp_int *mp); +void mw_mp_set(mw_mp_int *mp, mw_mp_digit d); +mw_mp_err mw_mp_set_int(mw_mp_int *mp, long z); + +/*------------------------------------------------------------------------*/ +/* Single digit arithmetic */ + +mw_mp_err mw_mp_add_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b); +mw_mp_err mw_mp_sub_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b); +mw_mp_err mw_mp_mul_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *b); +mw_mp_err mw_mp_mul_2(mw_mp_int *a, mw_mp_int *c); +mw_mp_err mw_mp_div_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *q, mw_mp_digit *r); +mw_mp_err mw_mp_div_2(mw_mp_int *a, mw_mp_int *c); +mw_mp_err mw_mp_expt_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *c); + +/*------------------------------------------------------------------------*/ +/* Sign manipulations */ + +mw_mp_err mw_mp_abs(mw_mp_int *a, mw_mp_int *b); +mw_mp_err mw_mp_neg(mw_mp_int *a, mw_mp_int *b); + +/*------------------------------------------------------------------------*/ +/* Full arithmetic */ + +mw_mp_err mw_mp_add(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_sub(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_mul(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_mul_2d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *c); +#if MP_SQUARE +mw_mp_err mw_mp_sqr(mw_mp_int *a, mw_mp_int *b); +#else +#define mw_mp_sqr(a, b) mw_mp_mul(a, a, b) +#endif +mw_mp_err mw_mp_div(mw_mp_int *a, mw_mp_int *b, mw_mp_int *q, mw_mp_int *r); +mw_mp_err mw_mp_div_2d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *q, mw_mp_int *r); +mw_mp_err mw_mp_expt(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_2expt(mw_mp_int *a, mw_mp_digit k); +mw_mp_err mw_mp_sqrt(mw_mp_int *a, mw_mp_int *b); + +/*------------------------------------------------------------------------*/ +/* Modular arithmetic */ + +#if MP_MODARITH +mw_mp_err mw_mp_mod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c); +mw_mp_err mw_mp_mod_d(mw_mp_int *a, mw_mp_digit d, mw_mp_digit *c); +mw_mp_err mw_mp_addmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c); +mw_mp_err mw_mp_submod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c); +mw_mp_err mw_mp_mulmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c); +#if MP_SQUARE +mw_mp_err mw_mp_sqrmod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c); +#else +#define mw_mp_sqrmod(a, m, c) mw_mp_mulmod(a, a, m, c) +#endif +mw_mp_err mw_mp_exptmod(mw_mp_int *a, mw_mp_int *b, mw_mp_int *m, mw_mp_int *c); +mw_mp_err mw_mp_exptmod_d(mw_mp_int *a, mw_mp_digit d, mw_mp_int *m, mw_mp_int *c); +#endif /* MP_MODARITH */ + +/*------------------------------------------------------------------------*/ +/* Comparisons */ + +int mw_mp_cmw_mp_z(mw_mp_int *a); +int mw_mp_cmw_mp_d(mw_mp_int *a, mw_mp_digit d); +int mw_mp_cmp(mw_mp_int *a, mw_mp_int *b); +int mw_mp_cmw_mp_mag(mw_mp_int *a, mw_mp_int *b); +int mw_mp_cmw_mp_int(mw_mp_int *a, long z); +int mw_mp_isodd(mw_mp_int *a); +int mw_mp_iseven(mw_mp_int *a); + +/*------------------------------------------------------------------------*/ +/* Number theoretic */ + +#if MP_NUMTH +mw_mp_err mw_mp_gcd(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_lcm(mw_mp_int *a, mw_mp_int *b, mw_mp_int *c); +mw_mp_err mw_mp_xgcd(mw_mp_int *a, mw_mp_int *b, mw_mp_int *g, mw_mp_int *x, mw_mp_int *y); +mw_mp_err mw_mp_invmod(mw_mp_int *a, mw_mp_int *m, mw_mp_int *c); +#endif /* end MP_NUMTH */ + +/*------------------------------------------------------------------------*/ +/* Input and output */ + +#if MP_IOFUNC +void mw_mp_print(mw_mp_int *mp, FILE *ofp); +#endif /* end MP_IOFUNC */ + +/*------------------------------------------------------------------------*/ +/* Base conversion */ + +#define BITS 1 +#define BYTES CHAR_BIT + +mw_mp_err mw_mp_read_signed_bin(mw_mp_int *mp, unsigned char *str, int len); +int mw_mp_signed_bin_size(mw_mp_int *mp); +mw_mp_err mw_mp_to_signed_bin(mw_mp_int *mp, unsigned char *str); + +mw_mp_err mw_mp_read_unsigned_bin(mw_mp_int *mp, unsigned char *str, int len); +int mw_mp_unsigned_bin_size(mw_mp_int *mp); +mw_mp_err mw_mp_to_unsigned_bin(mw_mp_int *mp, unsigned char *str); + +int mw_mp_count_bits(mw_mp_int *mp); + +#if MP_COMPAT_MACROS +#define mw_mp_read_raw(mp, str, len) mw_mp_read_signed_bin((mp), (str), (len)) +#define mw_mp_raw_size(mp) mw_mp_signed_bin_size(mp) +#define mw_mp_toraw(mp, str) mw_mp_to_signed_bin((mp), (str)) +#define mw_mp_read_mag(mp, str, len) mw_mp_read_unsigned_bin((mp), (str), (len)) +#define mw_mp_mag_size(mp) mw_mp_unsigned_bin_size(mp) +#define mw_mp_tomag(mp, str) mw_mp_to_unsigned_bin((mp), (str)) +#endif + +mw_mp_err mw_mp_read_radix(mw_mp_int *mp, unsigned char *str, int radix); +int mw_mp_radix_size(mw_mp_int *mp, int radix); +int mw_mp_value_radix_size(int num, int qty, int radix); +mw_mp_err mw_mp_toradix(mw_mp_int *mp, unsigned char *str, int radix); + +int mw_mp_char2value(char ch, int r); + +#define mw_mp_tobinary(M, S) mw_mp_toradix((M), (S), 2) +#define mw_mp_tooctal(M, S) mw_mp_toradix((M), (S), 8) +#define mw_mp_todecimal(M, S) mw_mp_toradix((M), (S), 10) +#define mw_mp_tohex(M, S) mw_mp_toradix((M), (S), 16) + +/*------------------------------------------------------------------------*/ +/* Error strings */ + +const char *mw_mp_strerror(mw_mp_err ec); + +#endif /* end _H_MPI_ */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_channel.h b/protocols/Sametime/src/meanwhile/src/mw_channel.h new file mode 100644 index 0000000000..7af5e22d86 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_channel.h @@ -0,0 +1,380 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_CHANNEL_H +#define _MW_CHANNEL_H + + +/** @file mw_channel.h + +Life-cycle of an outgoing channel: + +1: mwChannel_new is called. If there is a channel in the outgoing +collection in state NEW, then it is returned. Otherwise, a channel +is allocated, assigned a unique outgoing id, marked as NEW, and +returned. + +2: channel is set to INIT status (effectively earmarking it as in- +use). fields on the channel can then be set as necessary to +prepare it for creation. + +3: mwChannel_create is called. The channel is marked to WAIT status +and a message is sent to the server. The channel is also marked as +inactive as of that moment. + +4: the channel is accepted (step 5) or rejected (step 7) + +5: an accept message is received from the server, and the channel +is marked as OPEN, and the inactive mark is removed. And messages +in the in or out queues for that channel are processed. The channel +is now ready to be used. + +6: data is sent and received over the channel + +7: the channel is closed either by receipt of a close message or by +local action. If by local action, then a close message is sent to +the server. The channel is cleaned up, its queues dumped, and it +is set to NEW status to await re-use. + +Life-cycle of an incoming channel: + +1: a channel create message is received. A channel is allocated and +given an id matching the message. It is placed in status WAIT, and +marked as inactive as of that moment. The service matching that +channel is alerted of the incoming creation request. + +2: the service can either accept (step 3) or reject (step 5) the +channel + +3: mwChannel_accept is called. The channel is marked as OPEN, and +an accept message is sent to the server. And messages in the in or +out queues for that channel are processed. The channel is now ready +to be used. + +4: data is sent and received over the channel + +5: The channel is closed either by receipt of a close message or by +local action. If by local action, then a close message is sent to +the server. The channel is cleaned up, its queues dumped, and it +is deallocated. */ + + +#include <time.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* place-holders */ +struct mwCipherInstance; +struct mwMsgChannelAccept; +struct mwMsgChannelCreate; +struct mwMsgChannelDestroy; +struct mwMsgChannelSend; +struct mwService; +struct mwSession; + + + +/** @struct mwChannel + Represents a channel to a service */ +struct mwChannel; + + +/** @struct mwChannelSet + Collection of channels */ +struct mwChannelSet; + + +/** special ID indicating the master channel */ +#define MW_MASTER_CHANNEL_ID 0x00000000 + + +/** non-zero if a channel id appears to be that of an outgoing channel */ +#define mwChannel_idIsOutgoing(id) \ + (! (0x80000000 & (id))) + +/** non-zero if a channel id appears to be that of an incoming channel */ +#define mwChannel_idIsIncoming(id) \ + (! mwChannel_idIsOutgoing(id)) + +/** non-zero if a channel appears to be an outgoing channel */ +#define mwChannel_isOutgoing(chan) \ + mwChannel_idIsOutgoing(mwChannel_getId(chan)) + +/** non-zero if a channel appears to be an incoming channel */ +#define mwChannel_isIncoming(chan) \ + mwChannel_idIsIncoming(mwChannel_getId(chan)) + + +/** channel status */ +enum mwChannelState { + mwChannel_NEW, /**< channel is newly allocated, in the pool */ + mwChannel_INIT, /**< channel is being prepared, out of the pool */ + mwChannel_WAIT, /**< channel is waiting for accept */ + mwChannel_OPEN, /**< channel is accepted and open */ + mwChannel_DESTROY, /**< channel is being destroyed */ + mwChannel_ERROR, /**< channel is being destroyed due to error */ + mwChannel_UNKNOWN, /**< unknown state, or error determining state */ +}; + + +#define mwChannel_isState(chan, state) \ + (mwChannel_getState(chan) == (state)) + + +/** channel statistic fields. + @see mwChannel_getStatistic */ +enum mwChannelStatField { + mwChannelStat_MSG_SENT, /**< total send-on-chan messages sent */ + mwChannelStat_MSG_RECV, /**< total send-on-chan messages received */ + mwChannelStat_U_BYTES_SENT, /**< total bytes sent, pre-encryption */ + mwChannelStat_U_BYTES_RECV, /**< total bytes received, post-decryption */ + mwChannelStat_OPENED_AT, /**< time when channel was opened */ + mwChannelStat_CLOSED_AT, /**< time when channel was closed */ +}; + + +/** @enum mwEncryptPolicy + + Policy for a channel, dictating what sort of encryption should be + used, if any, and when. +*/ +enum mwEncryptPolicy { + mwEncrypt_NONE = 0x0000, /**< encrypt none */ + mwEncrypt_WHATEVER = 0x0001, /**< encrypt whatever you want */ + mwEncrypt_ALL = 0x0002, /**< encrypt all, any cipher */ + mwEncrypt_RC2_40 = 0x1000, /**< encrypt all, RC2/40 cipher */ + mwEncrypt_RC2_128 = 0x2000, /**< encrypt all, RC2/128 cipher */ +}; + + +/** Allocate and initialize a channel set for a session */ +struct mwChannelSet *mwChannelSet_new(struct mwSession *); + + +/** Clear and deallocate a channel set. Closes, clears, and frees all + contained channels. */ +void mwChannelSet_free(struct mwChannelSet *); + + +/** Create an incoming channel with the given channel id. Channel's state + will be set to WAIT. Primarily for use in mw_session */ +struct mwChannel *mwChannel_newIncoming(struct mwChannelSet *, guint32 id); + + +/** Create an outgoing channel. Its channel ID will be generated by + the owning channel set. Channel's state will be set to INIT */ +struct mwChannel *mwChannel_newOutgoing(struct mwChannelSet *); + + +/** Obtain a reference to a channel by its id. + @returns the channel matching chan, or NULL */ +struct mwChannel *mwChannel_find(struct mwChannelSet *cs, guint32 chan); + + +/** get the ID for a channel. 0x00 indicates an error, as that is not + a permissible value */ +guint32 mwChannel_getId(struct mwChannel *); + + +/** get the session for a channel. */ +struct mwSession *mwChannel_getSession(struct mwChannel *); + + +/** get the ID of the service for a channel. This may be 0x00 for NEW + channels */ +guint32 mwChannel_getServiceId(struct mwChannel *); + + +/** get the service for a channel. This may be NULL for NEW + channels */ +struct mwService *mwChannel_getService(struct mwChannel *); + + +/** associate a channel with an owning service */ +void mwChannel_setService(struct mwChannel *chan, struct mwService *srvc); + + +/** get service-specific data. This is for use by service + implementations to easily associate information with the + channel */ +gpointer mwChannel_getServiceData(struct mwChannel *chan); + + +/** set service-specific data. This is for use by service + implementations to easily associate information with the + channel */ +void mwChannel_setServiceData(struct mwChannel *chan, + gpointer data, GDestroyNotify clean); + + +void mwChannel_removeServiceData(struct mwChannel *chan); + + +guint32 mwChannel_getProtoType(struct mwChannel *chan); + + +void mwChannel_setProtoType(struct mwChannel *chan, guint32 proto_type); + + +guint32 mwChannel_getProtoVer(struct mwChannel *chan); + + +void mwChannel_setProtoVer(struct mwChannel *chan, guint32 proto_ver); + + +/** Channel encryption policy. + + Cannot currently be set, used internally to automatically + negotiate ciphers. Future revisions may allow this to be specified + in a new channel to dictate channel encryption. + + @see enum mwEncryptPolicy +*/ +guint16 mwChannel_getEncryptPolicy(struct mwChannel *chan); + + +guint32 mwChannel_getOptions(struct mwChannel *chan); + + +void mwChannel_setOptions(struct mwChannel *chan, guint32 options); + + +/** User at the other end of the channel. The target user for outgoing + channels, the creator for incoming channels */ +struct mwLoginInfo *mwChannel_getUser(struct mwChannel *chan); + + +/** direct reference to the create addtl information for a channel */ +struct mwOpaque *mwChannel_getAddtlCreate(struct mwChannel *); + + +/** direct reference to the accept addtl information for a channel */ +struct mwOpaque *mwChannel_getAddtlAccept(struct mwChannel *); + + +/** automatically adds instances of all ciphers in the session to the + list of supported ciphers for a channel */ +void mwChannel_populateSupportedCipherInstances(struct mwChannel *chan); + + +/** add a cipher instance to a channel's list of supported + ciphers. Channel must be NEW. */ +void mwChannel_addSupportedCipherInstance(struct mwChannel *chan, + struct mwCipherInstance *ci); + + +/** the list of supported ciphers for a channel. This list will be + empty once a cipher has been selected for the channel */ +GList *mwChannel_getSupportedCipherInstances(struct mwChannel *chan); + + +/** select a cipher instance for a channel. A NULL instance indicates + that no encryption should be used. */ +void mwChannel_selectCipherInstance(struct mwChannel *chan, + struct mwCipherInstance *ci); + + +struct mwCipherInstance * +mwChannel_getCipherInstance(struct mwChannel *chan); + + +/** get the state of a channel */ +enum mwChannelState mwChannel_getState(struct mwChannel *); + + +/** obtain the value for a statistic field as a gpointer */ +gpointer mwChannel_getStatistic(struct mwChannel *chan, + enum mwChannelStatField stat); + + +/** Formally open a channel. + + For outgoing channels: instruct the session to send a channel + create message to the server, and to mark the channel (which must + be in INIT status) as being in WAIT status. + + For incoming channels: configures the channel according to options + in the channel create message. Marks the channel as being in WAIT + status +*/ +int mwChannel_create(struct mwChannel *chan); + + +/** Formally accept an incoming channel. Instructs the session to send + a channel accept message to the server, and to mark the channel as + being OPEN. */ +int mwChannel_accept(struct mwChannel *chan); + + +/** Destroy a channel. Sends a channel-destroy message to the server, + and perform cleanup to remove the channel. + + @param chan the channel to destroy + @param reason the reason code for closing the channel + @param data optional additional information +*/ +int mwChannel_destroy(struct mwChannel *chan, guint32 reason, + struct mwOpaque *data); + + +/** Compose a send-on-channel message, encrypt it as per the channel's + specification, and send it */ +int mwChannel_send(struct mwChannel *chan, guint32 msg_type, + struct mwOpaque *msg); + + +/** Compose a send-on-channel message, and if encrypt is TRUE, encrypt + it as per the channel's specification, and send it */ +int mwChannel_sendEncrypted(struct mwChannel *chan, + guint32 msg_type, struct mwOpaque *msg, + gboolean encrypt); + + +/** pass a create message to a channel for handling */ +void mwChannel_recvCreate(struct mwChannel *chan, + struct mwMsgChannelCreate *msg); + + +/** pass an accept message to a channel for handling */ +void mwChannel_recvAccept(struct mwChannel *chan, + struct mwMsgChannelAccept *msg); + + +/** pass a destroy message to a channel for handling */ +void mwChannel_recvDestroy(struct mwChannel *chan, + struct mwMsgChannelDestroy *msg); + + +/** Feed data into a channel. */ +void mwChannel_recv(struct mwChannel *chan, struct mwMsgChannelSend *msg); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_CHANNEL_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_cipher.h b/protocols/Sametime/src/meanwhile/src/mw_cipher.h new file mode 100644 index 0000000000..a75781397e --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_cipher.h @@ -0,0 +1,297 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_CIPHER_H +#define _MW_CIPHER_H + + +#include <glib.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* place-holders */ +struct mwChannel; +struct mwSession; + + +/** @enum mwCipherType + Common cipher types */ +enum mwCipherType { + mwCipher_RC2_40 = 0x0000, + mwCipher_RC2_128 = 0x0001, +}; + + +struct mwCipher; +struct mwCipherInstance; + + +/** Obtain an instance of a given cipher, which can be used for the + processing of a single channel. */ +typedef struct mwCipherInstance *(*mwCipherInstantiator) + (struct mwCipher *cipher, struct mwChannel *chan); + + +/** Process (encrypt or decrypt, depending) the given data. The passed + buffer may be freed in processing and be replaced with a freshly + allocated buffer. The post-processed buffer must in turn be freed + after use */ +typedef int (*mwCipherProcessor) + (struct mwCipherInstance *ci, struct mwOpaque *data); + + +/** A cipher. Ciphers are primarily used to provide cipher instances + for bi-directional encryption on channels, but some may be used + for other activities. Expand upon this structure to create a + custom encryption provider. + @see mwCipherInstance */ +struct mwCipher { + + /** service this cipher is providing for + @see mwCipher_getSession */ + struct mwSession *session; + + guint16 type; /**< @see mwCipher_getType */ + const char *(*get_name)(); /**< @see mwCipher_getName */ + const char *(*get_desc)(); /**< @see mwCipher_getDesc */ + + /** Generate a new Cipher Instance for use on a channel + @see mwCipher_newInstance */ + mwCipherInstantiator new_instance; + + void (*offered)(struct mwCipherInstance *ci, struct mwEncryptItem *item); + struct mwEncryptItem *(*offer)(struct mwCipherInstance *ci); + void (*accepted)(struct mwCipherInstance *ci, struct mwEncryptItem *item); + struct mwEncryptItem *(*accept)(struct mwCipherInstance *ci); + + mwCipherProcessor encrypt; /**< @see mwCipherInstance_encrypt */ + mwCipherProcessor decrypt; /**< @see mwCipherInstance_decrypt */ + + /** prepare this cipher for being free'd + @see mwCipher_free */ + void (*clear)(struct mwCipher *c); + + /** clean up a cipher instance before being free'd + @see mwCipherInstance_free */ + void (*clear_instance)(struct mwCipherInstance *ci); +}; + + +/** An instance of a cipher. Expand upon this structure to contain + necessary state data + @see mwCipher */ +struct mwCipherInstance { + + /** the parent cipher. + @see mwCipherInstance_getCipher */ + struct mwCipher *cipher; + + /** the channel this instances processes + @see mwCipherInstance_getChannel */ + struct mwChannel *channel; +}; + + +struct mwCipher *mwCipher_new_RC2_40(struct mwSession *s); + + +struct mwCipher *mwCipher_new_RC2_128(struct mwSession *s); + + +struct mwSession *mwCipher_getSession(struct mwCipher *cipher); + + +guint16 mwCipher_getType(struct mwCipher *cipher); + + +const char *mwCipher_getName(struct mwCipher *cipher); + + +const char *mwCipher_getDesc(struct mwCipher *cipher); + + +struct mwCipherInstance *mwCipher_newInstance(struct mwCipher *cipher, + struct mwChannel *channel); + + +/** destroy a cipher */ +void mwCipher_free(struct mwCipher* cipher); + + +/** reference the parent cipher of an instance */ +struct mwCipher *mwCipherInstance_getCipher(struct mwCipherInstance *ci); + + +/** reference the channel a cipher instance is attached to */ +struct mwChannel *mwCipherInstance_getChannel(struct mwCipherInstance *ci); + + +/** Indicates a cipher has been offered to our channel */ +void mwCipherInstance_offered(struct mwCipherInstance *ci, + struct mwEncryptItem *item); + + +/** Offer a cipher */ +struct mwEncryptItem * +mwCipherInstance_offer(struct mwCipherInstance *ci); + + +/** Indicates an offered cipher has been accepted */ +void mwCipherInstance_accepted(struct mwCipherInstance *ci, + struct mwEncryptItem *item); + + +/** Accept a cipher offered to our channel */ +struct mwEncryptItem * +mwCipherInstance_accept(struct mwCipherInstance *ci); + + +/** encrypt data */ +int mwCipherInstance_encrypt(struct mwCipherInstance *ci, + struct mwOpaque *data); + + +/** decrypt data */ +int mwCipherInstance_decrypt(struct mwCipherInstance *ci, + struct mwOpaque *data); + + +/** destroy a cipher instance */ +void mwCipherInstance_free(struct mwCipherInstance *ci); + + +/** + @section General Cipher Functions + + These functions are reused where encryption is necessary outside of + a channel (eg. session authentication) +*/ +/* @{ */ + + +/** generate some pseudo-random bytes + @param keylen count of bytes to write into key + @param key buffer to write keys into +*/ +void mwKeyRandom(guchar *key, gsize keylen); + + +/** Setup an Initialization Vector. IV must be at least 8 bytes */ +void mwIV_init(guchar *iv); + + +/** Expand a variable-length key into a 128-byte key (represented as + an an array of 64 ints) */ +void mwKeyExpand(int *ekey, const guchar *key, gsize keylen); + + +/** Encrypt data using an already-expanded key */ +void mwEncryptExpanded(const int *ekey, guchar *iv, + struct mwOpaque *in, + struct mwOpaque *out); + + +/** Encrypt data using an expanded form of the given key */ +void mwEncrypt(const guchar *key, gsize keylen, guchar *iv, + struct mwOpaque *in, struct mwOpaque *out); + + +/** Decrypt data using an already expanded key */ +void mwDecryptExpanded(const int *ekey, guchar *iv, + struct mwOpaque *in, + struct mwOpaque *out); + + +/** Decrypt data using an expanded form of the given key */ +void mwDecrypt(const guchar *key, gsize keylen, guchar *iv, + struct mwOpaque *in, struct mwOpaque *out); + + +/* @} */ + + +/** + @section Diffie-Hellman Functions + + These functions are reused where DH Key negotiation is necessary + outside of a channel (eg. session authentication). These are + wrapping a full multiple-precision integer math library, but most of + the functionality there-of is not exposed. Currently, the math is + provided by a copy of the public domain libmpi. + + for more information on the used MPI Library, visit + http://www.cs.dartmouth.edu/~sting/mpi/ +*/ +/* @{ */ + + +/** @struct mwMpi */ +struct mwMpi; + + +/** prepare a new mpi value */ +struct mwMpi *mwMpi_new(); + + +/** destroy an mpi value */ +void mwMpi_free(struct mwMpi *i); + + +/** Import a value from an opaque */ +void mwMpi_import(struct mwMpi *i, struct mwOpaque *o); + + +/** Export a value into an opaque */ +void mwMpi_export(struct mwMpi *i, struct mwOpaque *o); + + +/** set a big integer to the Sametime Prime value */ +void mwMpi_setDHPrime(struct mwMpi *i); + + +/** set a big integer to the Sametime Base value */ +void mwMpi_setDHBase(struct mwMpi *i); + + +/** sets private to a randomly generated value, and calculates public + using the Sametime Prime and Base */ +void mwMpi_randDHKeypair(struct mwMpi *private_key, struct mwMpi *public_key); + + +/** sets the shared key value based on the remote and private keys, + using the Sametime Prime and Base */ +void mwMpi_calculateDHShared(struct mwMpi *shared_key, struct mwMpi *remote_key, + struct mwMpi *private_key); + + +/* @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_CIPHER_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_common.h b/protocols/Sametime/src/meanwhile/src/mw_common.h new file mode 100644 index 0000000000..1294da4959 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_common.h @@ -0,0 +1,437 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_COMMON_H +#define _MW_COMMON_H + + +/** @file mw_common.h + + Common data types and functions for handling those types. + + Functions in this file all fit into similar naming conventions of + <code>TYPE_ACTION</code> as per the activity they perform. The + following actions are available: + + <code>void TYPE_put(struct mwPutBuffer *b, TYPE *val)</code> + - marshalls val onto the buffer b. The buffer will grow as necessary + to fit all the data put into it. For guint16, guint32, and + gboolean, <code>TYPE val</code> is used instead of <code>TYPE + \*val</code>. + + <code>void TYPE_get(struct mwGetBuffer *b, TYPE *val)</code> + - unmarshals val from the buffer b. Failure (due to lack of + insufficient remaining buffer) is indicated in the buffer's error + field. A call to a _get function with a buffer in an error state + has to effect. + + <code>void TYPE_clear(TYPE *val)</code> + - zeros and frees internal members of val, but does not free val + itself. Needs to be called before free-ing any complex types which + have been unmarshalled from a TYPE_get or populated from a + TYPE_clone call to prevent memory leaks. + + <code>void TYPE_clone(TYPE *to, TYPE *from)</code> + - copies/clones members of from into to. May result in memory + allocation for some types. Note that to is not cleared + before-hand, it must already be in a pristine condition. + + <code>gboolean TYPE_equal(TYPE *y, TYPE *z)</code> + - simple equality test. +*/ + + +#include <glib.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @struct mwPutBuffer + buffer to be written to */ +struct mwPutBuffer; + +/** @struct mwGetBuffer + buffer to be read from */ +struct mwGetBuffer; + + +/** A length of binary data, not null-terminated. */ +struct mwOpaque { + gsize len; /**< length of data. */ + guchar *data; /**< data, normally with no NULL termination */ +}; + + +/* 8.3.6 Login Types */ + +/** The type of login. Normally meaning the type of client code being + used to login with. + + If you know of any additional client identifiers, please add them + below or submit an RFE to the meanwhile tracker. +*/ +enum mwLoginType { + mwLogin_LIB = 0x1000, /**< official Lotus binary library */ + mwLogin_JAVA_WEB = 0x1001, /**< official Lotus Java applet */ + mwLogin_BINARY = 0x1002, /**< official Lotus binary application */ + mwLogin_JAVA_APP = 0x1003, /**< official Lotus Java application */ + mwLogin_LINKS = 0x100a, /**< official Sametime Links toolkit */ + + /* now we're getting crazy */ + mwLogin_NOTES_6_5 = 0x1200, + mwLogin_NOTES_6_5_3 = 0x1203, + mwLogin_NOTES_7_0_beta = 0x1210, + mwLogin_NOTES_7_0 = 0x1214, + mwLogin_ICT = 0x1300, + mwLogin_ICT_1_7_8_2 = 0x1302, + mwLogin_ICT_SIP = 0x1303, + mwLogin_NOTESBUDDY_4_14 = 0x1400, /**< 0xff00 mask? */ + mwLogin_NOTESBUDDY_4_15 = 0x1405, + mwLogin_NOTESBUDDY_4_16 = 0x1406, + mwLogin_SANITY = 0x1600, + mwLogin_ST_PERL = 0x1625, + mwLogin_PMR_ALERT = 0x1650, + mwLogin_TRILLIAN = 0x16aa, /**< http://sf.net/st-plugin/ */ + mwLogin_TRILLIAN_IBM = 0x16bb, + mwLogin_MEANWHILE = 0x1700, /**< Meanwhile library */ +}; + + +/* 8.2 Common Structures */ +/* 8.2.1 Login Info block */ + +struct mwLoginInfo { + char *login_id; /**< community-unique ID of the login */ + guint16 type; /**< @see mwLoginType */ + char *user_id; /**< community-unique ID of the user */ + char *user_name; /**< name of user (nick name, full name, etc) */ + char *community; /**< community name (usually domain name) */ + gboolean full; /**< if FALSE, following fields non-existant */ + char *desc; /**< implementation defined description */ + guint32 ip_addr; /**< ip addr of the login */ + char *server_id; /**< unique ID of login's server */ +}; + + +/* 8.2.2 Private Info Block */ + +struct mwUserItem { + gboolean full; /**< if FALSE, don't include name */ + char *id; /**< user id */ + char *community; /**< community */ + char *name; /**< user name */ +}; + + +struct mwPrivacyInfo { + gboolean deny; /**< deny (true) or allow (false) users */ + guint32 count; /**< count of users */ + struct mwUserItem *users; /**< the users list */ +}; + + +/* 8.3.5 User Status Types */ + +enum mwStatusType { + mwStatus_ACTIVE = 0x0020, + mwStatus_IDLE = 0x0040, + mwStatus_AWAY = 0x0060, + mwStatus_BUSY = 0x0080, +}; + + +/* 8.2.3 User Status Block */ + +struct mwUserStatus { + guint16 status; /**< @see mwStatusType */ + guint32 time; /**< last status change time in seconds */ + char *desc; /**< status description */ +}; + + +/* 8.2.4 ID Block */ + +struct mwIdBlock { + char *user; /**< user id (login id or empty for some services) */ + char *community; /**< community id (NULL for same community) */ +}; + + +/* 8.3.8.2 Awareness Presence Types */ + +/* @todo move mwAwareType, mwAwareIdBlock and mwAwareSnapshot into the + aware service and out of common */ + +/** type codes for mwAwareIdBlock */ +enum mwAwareType { + mwAware_USER = 0x0002, /**< a single user */ + mwAware_GROUP = 0x0003, /**< a group */ + mwAware_SERVER = 0x0008, /**< a server */ +}; + + +/* 8.4.2 Awareness Messages */ +/* 8.4.2.1 Awareness ID Block */ + +struct mwAwareIdBlock { + guint16 type; /**< @see mwAwareType */ + char *user; /**< user id */ + char *community; /**< community id (NULL for same community) */ +}; + + +/* 8.4.2.4 Snapshot */ + +struct mwAwareSnapshot { + struct mwAwareIdBlock id; + char *group; /**< group this id belongs to */ + gboolean online; /**< is this user online? */ + char *alt_id; /**< alternate ID, often same as id.user */ + struct mwUserStatus status; /**< status of this user */ + char *name; /**< Formatted version of ID */ +}; + + +/** encryption blocks */ +struct mwEncryptItem { + guint16 id; /**< cipher identifier */ + struct mwOpaque info; /**< cipher information */ +}; + + +/** @name buffer utility functions */ +/*@{*/ + + +/** allocate a new empty buffer */ +struct mwPutBuffer *mwPutBuffer_new(); + + +/** write raw data to the put buffer */ +void mwPutBuffer_write(struct mwPutBuffer *b, gpointer data, gsize len); + + +/** destroy the buffer */ +void mwPutBuffer_free(struct mwPutBuffer *b); + + +/** move the buffer's data into an opaque, destroy the buffer */ +void mwPutBuffer_finalize(struct mwOpaque *to, struct mwPutBuffer *from); + + +/** allocate a new buffer with a copy of the given data */ +struct mwGetBuffer *mwGetBuffer_new(struct mwOpaque *data); + + +/** read len bytes of raw data from the get buffer into mem. If len is + greater than the count of bytes remaining in the buffer, the + buffer's error flag will NOT be set. + + @returns count of bytes successfully copied to mem */ +gsize mwGetBuffer_read(struct mwGetBuffer *b, gpointer mem, gsize len); + + +/** skip len bytes in the get buffer. If len is greater than the count + of bytes remaining in the buffer, the buffer's error flag will NOT + be set. + + @returns count of bytes successfully skipped */ +gsize mwGetBuffer_advance(struct mwGetBuffer *b, gsize len); + + +/** allocate a new buffer backed by the given data. Calling + mwGetBuffer_free will not result in the underlying data being + freed */ +struct mwGetBuffer *mwGetBuffer_wrap(const struct mwOpaque *data); + + +/** destroy the buffer */ +void mwGetBuffer_free(struct mwGetBuffer *b); + + +/** reset the buffer to the very beginning. Also clears the buffer's + error flag. */ +void mwGetBuffer_reset(struct mwGetBuffer *b); + + +/** count of remaining available bytes */ +gsize mwGetBuffer_remaining(struct mwGetBuffer *b); + + +/** TRUE if an error occurred while reading a basic type from this + buffer */ +gboolean mwGetBuffer_error(struct mwGetBuffer *b); + + +/*@}*/ + + +/** @name Basic Data Types + The basic types are combined to construct the compound types. + */ +/*@{*/ + + +void guint16_put(struct mwPutBuffer *b, guint16 val); + +void guint16_get(struct mwGetBuffer *b, guint16 *val); + +guint16 guint16_peek(struct mwGetBuffer *b); + + +void guint32_put(struct mwPutBuffer *b, guint32 val); + +void guint32_get(struct mwGetBuffer *b, guint32 *val); + +guint32 guint32_peek(struct mwGetBuffer *b); + + +void gboolean_put(struct mwPutBuffer *b, gboolean val); + +void gboolean_get(struct mwGetBuffer *b, gboolean *val); + +gboolean gboolean_peek(struct mwGetBuffer *b); + + +void mwString_put(struct mwPutBuffer *b, const char *str); + +void mwString_get(struct mwGetBuffer *b, char **str); + + +void mwOpaque_put(struct mwPutBuffer *b, const struct mwOpaque *o); + +void mwOpaque_get(struct mwGetBuffer *b, struct mwOpaque *o); + +void mwOpaque_clear(struct mwOpaque *o); + +void mwOpaque_free(struct mwOpaque *o); + +void mwOpaque_clone(struct mwOpaque *to, const struct mwOpaque *from); + + +/*@}*/ + + +/** @name Compound Data Types */ +/*@{*/ + + +void mwLoginInfo_put(struct mwPutBuffer *b, const struct mwLoginInfo *info); + +void mwLoginInfo_get(struct mwGetBuffer *b, struct mwLoginInfo *info); + +void mwLoginInfo_clear(struct mwLoginInfo *info); + +void mwLoginInfo_clone(struct mwLoginInfo *to, const struct mwLoginInfo *from); + + +void mwUserItem_put(struct mwPutBuffer *b, const struct mwUserItem *user); + +void mwUserItem_get(struct mwGetBuffer *b, struct mwUserItem *user); + +void mwUserItem_clear(struct mwUserItem *user); + +void mwUserItem_clone(struct mwUserItem *to, const struct mwUserItem *from); + + +void mwPrivacyInfo_put(struct mwPutBuffer *b, + const struct mwPrivacyInfo *info); + +void mwPrivacyInfo_get(struct mwGetBuffer *b, struct mwPrivacyInfo *info); + +void mwPrivacyInfo_clear(struct mwPrivacyInfo *info); + +void mwPrivacyInfo_clone(struct mwPrivacyInfo *to, + const struct mwPrivacyInfo *from); + + +void mwUserStatus_put(struct mwPutBuffer *b, + const struct mwUserStatus *stat); + +void mwUserStatus_get(struct mwGetBuffer *b, struct mwUserStatus *stat); + +void mwUserStatus_clear(struct mwUserStatus *stat); + +void mwUserStatus_clone(struct mwUserStatus *to, + const struct mwUserStatus *from); + + +void mwIdBlock_put(struct mwPutBuffer *b, const struct mwIdBlock *id); + +void mwIdBlock_get(struct mwGetBuffer *b, struct mwIdBlock *id); + +void mwIdBlock_clear(struct mwIdBlock *id); + +void mwIdBlock_clone(struct mwIdBlock *to, + const struct mwIdBlock *from); + +guint mwIdBlock_hash(const struct mwIdBlock *idb); + +gboolean mwIdBlock_equal(const struct mwIdBlock *a, + const struct mwIdBlock *b); + + +void mwAwareIdBlock_put(struct mwPutBuffer *b, + const struct mwAwareIdBlock *idb); + +void mwAwareIdBlock_get(struct mwGetBuffer *b, struct mwAwareIdBlock *idb); + +void mwAwareIdBlock_clear(struct mwAwareIdBlock *idb); + +void mwAwareIdBlock_clone(struct mwAwareIdBlock *to, + const struct mwAwareIdBlock *from); + +guint mwAwareIdBlock_hash(const struct mwAwareIdBlock *a); + +gboolean mwAwareIdBlock_equal(const struct mwAwareIdBlock *a, + const struct mwAwareIdBlock *b); + + +void mwAwareSnapshot_get(struct mwGetBuffer *b, + struct mwAwareSnapshot *idb); + +void mwAwareSnapshot_clear(struct mwAwareSnapshot *idb); + +void mwAwareSnapshot_clone(struct mwAwareSnapshot *to, + const struct mwAwareSnapshot *from); + + +void mwEncryptItem_put(struct mwPutBuffer *b, + const struct mwEncryptItem *item); + +void mwEncryptItem_get(struct mwGetBuffer *b, struct mwEncryptItem *item); + +void mwEncryptItem_clear(struct mwEncryptItem *item); + +void mwEncryptItem_free(struct mwEncryptItem *item); + + +/*@}*/ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_COMMON_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_debug.c b/protocols/Sametime/src/meanwhile/src/mw_debug.c new file mode 100644 index 0000000000..cf47a38e38 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_debug.c @@ -0,0 +1,184 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <glib/gstring.h> + +#include "mw_debug.h" + + + +#define FRMT1 "%02x" +#define FRMT2 FRMT1 FRMT1 " " +#define FRMT4 FRMT2 FRMT2 +#define FRMT8 FRMT4 FRMT4 +#define FRMT16 FRMT8 FRMT8 + +#define ADVANCE(b, n, c) {b += c; n -= c;} + + + +/** writes hex pairs of buf to str */ +static void pretty_print(GString *str, const guchar *buf, gsize len) { + while(len >= 16) { + /* write a complete line */ + g_string_append_printf(str, FRMT16, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15]); + ADVANCE(buf, len, 16); + + /* append \n to each line but the last */ + if(len) g_string_append(str, "\n"); + } + + /* write an incomplete line */ + if(len >= 8) { + g_string_append_printf(str, FRMT8, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + ADVANCE(buf, len, 8); + } + + if(len >= 4) { + g_string_append_printf(str, FRMT4, + buf[0], buf[1], buf[2], buf[3]); + ADVANCE(buf, len, 4); + } + + if(len >= 2) { + g_string_append_printf(str, FRMT2, buf[0], buf[1]); + ADVANCE(buf, len, 2); + } + + if(len >= 1) { + g_string_append_printf(str, FRMT1, buf[0]); + ADVANCE(buf, len, 1); + } +} + + + +void mw_debug_datav(const guchar *buf, gsize len, + const char *msg, va_list args) { + GString *str; + + g_return_if_fail(buf != NULL || len == 0); + + str = g_string_new(NULL); + + if(msg) { + char *txt = g_strdup_vprintf(msg, args); + g_string_append_printf(str, "%s\n", txt); + g_free(txt); + } + pretty_print(str, buf, len); + + g_debug(str->str); + g_string_free(str, TRUE); +} + + + +void mw_debug_data(const guchar *buf, gsize len, + const char *msg, ...) { + va_list args; + + g_return_if_fail(buf != NULL || len == 0); + + va_start(args, msg); + mw_debug_datav(buf, len, msg, args); + va_end(args); +} + + + +void mw_debug_opaquev(struct mwOpaque *o, const char *txt, va_list args) { + g_return_if_fail(o != NULL); + mw_debug_datav(o->data, o->len, txt, args); +} + + + +void mw_debug_opaque(struct mwOpaque *o, const char *txt, ...) { + va_list args; + + g_return_if_fail(o != NULL); + + va_start(args, txt); + mw_debug_opaquev(o, txt, args); + va_end(args); +} + + +void mw_mailme_datav(const guchar *buf, gsize len, + const char *info, va_list args) { + +#if MW_MAILME + GString *str; + char *txt; + + str = g_string_new(MW_MAILME_MESSAGE "\n" + " Please send mail to: " MW_MAILME_ADDRESS "\n" + MW_MAILME_CUT_START "\n"); + str = g_string_new(NULL); + + txt = g_strdup_vprintf(info, args); + g_string_append_printf(str, "%s\n", txt); + g_free(txt); + + if(buf && len) pretty_print(str, buf, len); + + g_string_append(str, MW_MAILME_CUT_STOP); + + g_debug(str->str); + g_string_free(str, TRUE); + +#else + mw_debug_datav(buf, len, info, args); + +#endif +} + + + +void mw_mailme_data(const guchar *buf, gsize len, + const char *info, ...) { + va_list args; + va_start(args, info); + mw_mailme_datav(buf, len, info, args); + va_end(args); +} + + + +void mw_mailme_opaquev(struct mwOpaque *o, const char *info, va_list args) { + mw_mailme_datav(o->data, o->len, info, args); +} + + + +void mw_mailme_opaque(struct mwOpaque *o, const char *info, ...) { + va_list args; + va_start(args, info); + mw_mailme_opaquev(o, info, args); + va_end(args); +} diff --git a/protocols/Sametime/src/meanwhile/src/mw_debug.h b/protocols/Sametime/src/meanwhile/src/mw_debug.h new file mode 100644 index 0000000000..acd7455eec --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_debug.h @@ -0,0 +1,130 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_DEBUG_H +#define _MW_DEBUG_H + + +#include <stdarg.h> +#include <glib.h> + +#include "mw_common.h" + + +/** replaces NULL strings with "(null)". useful for printf where + you're unsure that the %s will be non-NULL. Note that while the + linux printf will do this automatically, not all will. The others + will instead segfault */ +#define NSTR(str) ((str)? (str): "(null)") + + +// Miranda NG adaptation, MSVC +// #ifndef g_debug +// #define g_debug(format...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) +// #endif + + +// Miranda NG adaptation, MSVC +// #ifndef g_info +// #define g_info(format...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) +// #endif + + +#ifndef MW_MAILME_ADDRESS +/** email address used in mw_debug_mailme. */ +#define MW_MAILME_ADDRESS "meanwhile-devel@lists.sourceforge.net" +#endif + + +#ifndef MW_MAILME_CUT_START +#define MW_MAILME_CUT_START "-------- begin copy --------" +#endif + + +#ifndef MW_MAILME_CUT_STOP +#define MW_MAILME_CUT_STOP "--------- end copy ---------" +#endif + + +#ifndef MW_MAILME_MESSAGE +/** message used in mw_debug_mailme instructing user on what to do + with the debugging output produced from that function */ +#define MW_MAILME_MESSAGE "\n" \ + " Greetings! It seems that you've run across protocol data that the\n" \ + "Meanwhile library does not yet know about. As such, there may be\n" \ + "some unexpected behaviour in this session. If you'd like to help\n" \ + "resolve this issue, please copy and paste the following block into\n" \ + "an email to the address listed below with a brief explanation of\n" \ + "what you were doing at the time of this message. Thanks a lot!" +#endif + + +void mw_debug_datav(const guchar *buf, gsize len, + const char *info, va_list args); + + +void mw_debug_data(const guchar *buf, gsize len, + const char *info, ...); + + +void mw_debug_opaquev(struct mwOpaque *o, const char *info, va_list args); + + +void mw_debug_opaque(struct mwOpaque *o, const char *info, ...); + + +void mw_mailme_datav(const guchar *buf, gsize len, + const char *info, va_list args); + +void mw_mailme_data(const guchar *buf, gsize len, + const char *info, ...); + + +/** Outputs a hex dump of a mwOpaque with debugging info and a + pre-defined message. Identical to mw_mailme_opaque, but taking a + va_list argument */ +void mw_mailme_opaquev(struct mwOpaque *o, const char *info, va_list args); + + + +/** Outputs a hex dump of a mwOpaque with debugging info and a + pre-defined message. + + if MW_MAILME is undefined or false, this function acts the same as + mw_mailme_opaque. + + @arg block data to be printed in a hex block + @arg info a printf-style format string + + The resulting message is in the following format: + @code + MW_MAILME_MESSAGE + " Please send mail to: " MW_MAILME_ADDRESS + MW_MAILME_CUT_START + info + block + MW_MAILME_CUT_STOP + @endcode + */ +void mw_mailme_opaque(struct mwOpaque *o, const char *info, ...); + + +#endif + diff --git a/protocols/Sametime/src/meanwhile/src/mw_error.h b/protocols/Sametime/src/meanwhile/src/mw_error.h new file mode 100644 index 0000000000..6345358561 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_error.h @@ -0,0 +1,174 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_ERROR_H +#define _MW_ERROR_H + + +/** @file mw_error.h + + Common error code constants used by Meanwhile. + + Not all of these error codes (or even many, really) will ever + actually appear from Meanwhile. These are taken directly from the + houri draft, along with the minimal explanation for each. +*/ + + +#include <glib.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** reference to a new string appropriate for the given error code.*/ +char* mwError(guint32 code); + + +/* 8.3 Constants */ +/* 8.3.1 Error Codes */ +/* 8.3.1.1 General error/success codes */ + +/** @enum ERR_GENERAL + general error codes */ +enum ERR_GENERAL { + ERR_SUCCESS = 0x00000000, + ERR_FAILURE = 0x80000000, + ERR_REQUEST_DELAY = 0x00000001, + ERR_REQUEST_INVALID = 0x80000001, + ERR_NOT_LOGGED_IN = 0x80000002, + ERR_NOT_AUTHORIZED = 0x80000003, + ERR_ABORT = 0x80000004, + ERR_NO_ELEMENT = 0x80000005, + ERR_NO_USER = 0x80000006, + ERR_BAD_DATA = 0x80000007, + ERR_NOT_IMPLEMENTED = 0x80000008, + ERR_UNKNOWN_ERROR = 0x80000009, /* what is this? */ + ERR_STARVING = 0x8000000a, + ERR_CHANNEL_NO_SUPPORT = 0x8000000b, + ERR_CHANNEL_EXISTS = 0x8000000c, + ERR_SERVICE_NO_SUPPORT = 0x8000000d, + ERR_PROTOCOL_NO_SUPPORT = 0x8000000e, + ERR_PROTOCOL_NO_SUPPORT2 = 0x8000000f, /* duplicate? */ + ERR_VERSION_NO_SUPPORT = 0x80000010, + ERR_USER_SKETCHY = 0x80000011, + ERR_ALREADY_INITIALIZED = 0x80000013, + ERR_NOT_OWNER = 0x80000014, + ERR_TOKEN_INVALID = 0x80000015, + ERR_TOKEN_EXPIRED = 0x80000016, + ERR_TOKEN_IP_MISMATCH = 0x80000017, + ERR_PORT_IN_USE = 0x80000018, + ERR_NETWORK_DEAD = 0x80000019, + ERR_NO_MASTER_CHANNEL = 0x8000001a, + ERR_ALREADY_SUBSCRIBED = 0x8000001b, + ERR_NOT_SUBSCRIBED = 0x8000001c, + ERR_ENCRYPT_NO_SUPPORT = 0x8000001d, + ERR_ENCRYPT_UNINITIALIZED = 0x8000001e, + ERR_ENCRYPT_UNACCEPTABLE = 0x8000001f, + ERR_ENCRYPT_INVALID = 0x80000020, + ERR_NO_COMMON_ENCRYPT = 0x80000021, + ERR_CHANNEL_DESTROYED = 0x80000022, + ERR_CHANNEL_REDIRECTED = 0x80000023 +}; + + +/* 8.3.1.2 Connection/disconnection errors */ + +#define VERSION_MISMATCH 0x80000200 +#define INSUF_BUFFER 0x80000201 +#define NOT_IN_USE 0x80000202 +#define INSUF_SOCKET 0x80000203 +#define HARDWARE_ERROR 0x80000204 +#define NETWORK_DOWN 0x80000205 +#define HOST_DOWN 0x80000206 +#define HOST_UNREACHABLE 0x80000207 +#define TCPIP_ERROR 0x80000208 +#define FAT_MESSAGE 0x80000209 +#define PROXY_ERROR 0x8000020A +#define SERVER_FULL 0x8000020B +#define SERVER_NORESPOND 0x8000020C +#define CANT_CONNECT 0x8000020D +#define USER_REMOVED 0x8000020E +#define PROTOCOL_ERROR 0x8000020F +#define USER_RESTRICTED 0x80000210 +#define INCORRECT_LOGIN 0x80000211 +#define ENCRYPT_MISMATCH 0x80000212 +#define USER_UNREGISTERED 0x80000213 +#define VERIFICATION_DOWN 0x80000214 +#define USER_TOO_IDLE 0x80000216 +#define GUEST_IN_USE 0x80000217 +#define USER_EXISTS 0x80000218 +#define USER_RE_LOGIN 0x80000219 +#define BAD_NAME 0x8000021A +#define REG_MODE_NS 0x8000021B +#define WRONG_USER_PRIV 0x8000021C +#define NEED_EMAIL 0x8000021D +#define DNS_ERROR 0x8000021E +#define DNS_FATAL_ERROR 0x8000021F +#define DNS_NOT_FOUND 0x80000220 +#define CONNECTION_BROKEN 0x80000221 +#define CONNECTION_ABORTED 0x80000222 +#define CONNECTION_REFUSED 0x80000223 +#define CONNECTION_RESET 0x80000224 +#define CONNECTION_TIMED 0x80000225 +#define CONNECTION_CLOSED 0x80000226 +#define MULTI_SERVER_LOGIN 0x80000227 +#define MULTI_SERVER_LOGIN2 0x80000228 +#define MULTI_LOGIN_COMP 0x80000229 +#define MUTLI_LOGIN_ALREADY 0x8000022A +#define SERVER_BROKEN 0x8000022B +#define SERVER_PATH_OLD 0x8000022C +#define APPLET_LOGOUT 0x8000022D + + +/* 8.3.1.3 Client error codes */ + +/** @enum ERR_CLIENT + Client error codes */ +enum ERR_CLIENT { + ERR_CLIENT_USER_GONE = 0x80002000, /* user isn't here */ + ERR_CLIENT_USER_DND = 0x80002001, /* user is DND */ + ERR_CLIENT_USER_ELSEWHERE = 0x80002002, /* already logged in elsewhere */ +}; + + +/* 8.3.1.4 IM error codes */ + +/** @enum ERR_IM + IM error codes */ +enum ERR_IM { + ERR_IM_COULDNT_REGISTER = 0x80002003, + ERR_IM_ALREADY_REGISTERED = 0x80002004, + + /** apparently, this is used to mean that the requested feature (per + the channel create addtl data) is not supported by the client on + the other end of the IM channel */ + ERR_IM_NOT_REGISTERED = 0x80002005, +}; + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_ERROR_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_message.h b/protocols/Sametime/src/meanwhile/src/mw_message.h new file mode 100644 index 0000000000..8402b8b7ee --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_message.h @@ -0,0 +1,305 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_MESSAGE_H +#define _MW_MESSAGE_H + + +#include <glib/glist.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Cast a pointer to a message subtype (eg, mwMsgHandshake, + mwMsgAdmin) into a pointer to a mwMessage */ +#define MW_MESSAGE(msg) (&msg->head) + + +/** Indicates the type of a message. */ +enum mwMessageType { + mwMessage_HANDSHAKE = 0x0000, /**< mwMsgHandshake */ + mwMessage_HANDSHAKE_ACK = 0x8000, /**< mwMsgHandshakeAck */ + mwMessage_LOGIN = 0x0001, /**< mwMsgLogin */ + mwMessage_LOGIN_ACK = 0x8001, /**< mwMsgLoginAck */ + mwMessage_LOGIN_REDIRECT = 0x0018, /**< mwMsgLoginRedirect */ + mwMessage_LOGIN_CONTINUE = 0x0016, /**< mwMsgLoginContinue */ + + mwMessage_CHANNEL_CREATE = 0x0002, /**< mwMsgChannelCreate */ + mwMessage_CHANNEL_DESTROY = 0x0003, /**< mwMsgChannelDestroy */ + mwMessage_CHANNEL_SEND = 0x0004, /**< mwMsgChannelSend */ + mwMessage_CHANNEL_ACCEPT = 0x0006, /**< mwMsgChannelAccept */ + + mwMessage_SET_USER_STATUS = 0x0009, /**< mwMsgSetUserStatus */ + mwMessage_SET_PRIVACY_LIST = 0x000b, /**< mwMsgSetPrivacyList */ + mwMessage_SENSE_SERVICE = 0x0011, /**< mwMsgSenseService */ + mwMessage_ADMIN = 0x0019, /**< mwMsgAdmin */ + mwMessage_ANNOUNCE = 0x0022, /**< mwMsgAnnounce */ +}; + + +enum mwMessageOption { + mwMessageOption_ENCRYPT = 0x4000, /**< message data is encrypted */ + mwMessageOption_HAS_ATTRIBS = 0x8000, /**< message has attributes */ +}; + + +/** @see mwMessageOption */ +#define MW_MESSAGE_HAS_OPTION(msg, opt) \ + ((msg)->options & (opt)) + + +struct mwMessage { + guint16 type; /**< @see mwMessageType */ + guint16 options; /**< @see mwMessageOption */ + guint32 channel; /**< ID of channel message is intended for */ + struct mwOpaque attribs; /**< optional message attributes */ +}; + + + +/** Allocate and initialize a new message of the specified type */ +struct mwMessage *mwMessage_new(enum mwMessageType type); + + +/** build a message from its representation */ +struct mwMessage *mwMessage_get(struct mwGetBuffer *b); + + +void mwMessage_put(struct mwPutBuffer *b, struct mwMessage *msg); + + +void mwMessage_free(struct mwMessage *msg); + + +/* 8.4 Messages */ +/* 8.4.1 Basic Community Messages */ +/* 8.4.1.1 Handshake */ + +struct mwMsgHandshake { + struct mwMessage head; + guint16 major; /**< client's major version number */ + guint16 minor; /**< client's minor version number */ + guint32 srvrcalc_addr; /**< 0.0.0.0 */ + guint16 login_type; /**< @see mwLoginType */ + guint32 loclcalc_addr; /**< local public IP */ + guint16 unknown_a; /**< normally 0x0100 */ + guint32 unknown_b; /**< normally 0x00000000 */ + char *local_host; /**< name of client host */ +}; + + +/* 8.4.1.2 HandshakeAck */ + +struct mwMsgHandshakeAck { + struct mwMessage head; + guint16 major; /**< server's major version number */ + guint16 minor; /**< server's minor version number */ + guint32 srvrcalc_addr; /**< server-calculated address */ + guint32 magic; /**< four bytes of something */ + struct mwOpaque data; /**< server's DH public key for auth */ +}; + + +/* 8.3.7 Authentication Types */ + +enum mwAuthType { + mwAuthType_PLAIN = 0x0000, + mwAuthType_TOKEN = 0x0001, + mwAuthType_ENCRYPT = 0x0002, /**< @todo remove for 1.0 */ + mwAuthType_RC2_40 = 0x0002, + mwAuthType_RC2_128 = 0x0004, +}; + + +/* 8.4.1.3 Login */ + +struct mwMsgLogin { + struct mwMessage head; + guint16 login_type; /**< @see mwLoginType */ + char *name; /**< user identification */ + guint16 auth_type; /**< @see mwAuthType */ + struct mwOpaque auth_data; /**< authentication data */ +}; + + +/* 8.4.1.4 LoginAck */ + +struct mwMsgLoginAck { + struct mwMessage head; + struct mwLoginInfo login; + struct mwPrivacyInfo privacy; + struct mwUserStatus status; +}; + + +/* 8.4.1.5 LoginCont */ + +struct mwMsgLoginContinue { + struct mwMessage head; +}; + + +/* 8.4.1.6 AuthPassed */ + +struct mwMsgLoginRedirect { + struct mwMessage head; + char *host; + char *server_id; +}; + + +/* 8.4.1.7 CreateCnl */ + +/** an offer of encryption items */ +struct mwEncryptOffer { + guint16 mode; /**< encryption mode */ + GList *items; /**< list of mwEncryptItem offered */ + guint16 extra; /**< encryption mode again? */ + gboolean flag; /**< unknown flag */ +}; + + +struct mwMsgChannelCreate { + struct mwMessage head; + guint32 reserved; /**< unknown reserved data */ + guint32 channel; /**< intended ID for new channel */ + struct mwIdBlock target; /**< User ID. for service use */ + guint32 service; /**< ID for the target service */ + guint32 proto_type; /**< protocol type for the service */ + guint32 proto_ver; /**< protocol version for the service */ + guint32 options; /**< options */ + struct mwOpaque addtl; /**< service-specific additional data */ + gboolean creator_flag; /**< indicate presence of creator information */ + struct mwLoginInfo creator; + struct mwEncryptOffer encrypt; +}; + + +/* 8.4.1.8 AcceptCnl */ + +/** a selected encryption item from those offered */ +struct mwEncryptAccept { + guint16 mode; /**< encryption mode */ + struct mwEncryptItem *item; /**< chosen mwEncryptItem (optional) */ + guint16 extra; /**< encryption mode again? */ + gboolean flag; /**< unknown flag */ +}; + + +struct mwMsgChannelAccept { + struct mwMessage head; + guint32 service; /**< ID for the channel's service */ + guint32 proto_type; /**< protocol type for the service */ + guint32 proto_ver; /**< protocol version for the service */ + struct mwOpaque addtl; /**< service-specific additional data */ + gboolean acceptor_flag; /**< indicate presence of acceptor information */ + struct mwLoginInfo acceptor; + struct mwEncryptAccept encrypt; +}; + + +/* 8.4.1.9 SendOnCnl */ + +struct mwMsgChannelSend { + struct mwMessage head; + + /** message type. each service defines its own send types. Type IDs + are only necessarily unique within a given service. */ + guint16 type; + + /** protocol data to be interpreted by the handling service */ + struct mwOpaque data; +}; + + +/* 8.4.1.10 DestroyCnl */ + +struct mwMsgChannelDestroy { + struct mwMessage head; + guint32 reason; /**< reason for closing the channel. */ + struct mwOpaque data; /**< additional information */ +}; + + +/* 8.4.1.11 SetUserStatus */ + +struct mwMsgSetUserStatus { + struct mwMessage head; + struct mwUserStatus status; +}; + + +/* 8.4.1.12 SetPrivacyList */ + +struct mwMsgSetPrivacyList { + struct mwMessage head; + struct mwPrivacyInfo privacy; +}; + + +/* Sense Service */ + +/** Sent to the server to request the presense of a service by its + ID. Sent to the client to indicate the presense of such a + service */ +struct mwMsgSenseService { + struct mwMessage head; + guint32 service; +}; + + +/* Admin */ + +/** An administrative broadcast message */ +struct mwMsgAdmin { + struct mwMessage head; + char *text; +}; + + +/* Announce */ + +/** An announcement between users */ +struct mwMsgAnnounce { + struct mwMessage head; + gboolean sender_present; /**< indicates presence of sender data */ + struct mwLoginInfo sender; /**< who sent the announcement */ + guint16 unknown_a; /**< unknown A. Usually 0x00 */ + gboolean may_reply; /**< replies allowed */ + char *text; /**< text of message */ + + /** list of (char *) indicating recipients. Recipient users are in + the format "@U username" and recipient NAB groups are in the + format "@G groupname" */ + GList *recipients; +}; + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_MESSAGE_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_service.h b/protocols/Sametime/src/meanwhile/src/mw_service.h new file mode 100644 index 0000000000..9bcd6509db --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_service.h @@ -0,0 +1,370 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SERVICE_H +#define _MW_SERVICE_H + + +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* place-holders */ +struct mwChannel; +struct mwService; +struct mwSession; +struct mwMsgChannelCreate; +struct mwMsgChannelAccept; +struct mwMsgChannelDestroy; + + +/** State-tracking for a service */ +enum mwServiceState { + mwServiceState_STOPPED, /**< the service is not active */ + mwServiceState_STOPPING, /**< the service is shutting down */ + mwServiceState_STARTED, /**< the service is active */ + mwServiceState_STARTING, /**< the service is starting up */ + mwServiceState_ERROR, /**< error in service, shutting down */ + mwServiceState_UNKNOWN, /**< error determining state */ +}; + + +/** Casts a concrete service (such as mwServiceAware) into a mwService */ +#define MW_SERVICE(srv) ((struct mwService *) srv) + + +#define MW_SERVICE_IS_STATE(srvc, state) \ + (mwService_getState(MW_SERVICE(srvc)) == (state)) + +#define MW_SERVICE_IS_STOPPED(srvc) \ + MW_SERVICE_IS_STATE(srvc, mwServiceState_STOPPED) + +#define MW_SERVICE_IS_STOPPING(srvc) \ + MW_SERVICE_IS_STATE(srvc, mwServiceState_STOPPING) + +#define MW_SERVICE_IS_STARTED(srvc) \ + MW_SERVICE_IS_STATE(srvc, mwServiceState_STARTED) + +#define MW_SERVICE_IS_STARTING(srvc) \ + MW_SERVICE_IS_STATE(srvc, mwServiceState_STARTING) + + +/** If a service is STARTING or STARTED, it's considered LIVE */ +#define MW_SERVICE_IS_LIVE(srvc) \ + (MW_SERVICE_IS_STARTING(srvc) || MW_SERVICE_IS_STARTED(srvc)) + +/** If a service is STOPPING or STOPPED, it's considered DEAD */ +#define MW_SERVICE_IS_DEAD(srvc) \ + (MW_SERVICE_IS_STOPPING(srvc) || MW_SERVICE_IS_STOPPED(srvc)) + + +typedef void (*mwService_funcStart)(struct mwService *service); + +typedef void (*mwService_funcStop)(struct mwService *service); + +typedef void (*mwService_funcClear)(struct mwService *service); + +typedef const char *(*mwService_funcGetName)(struct mwService *service); + +typedef const char *(*mwService_funcGetDesc)(struct mwService *service); + +/** @todo remove msg and replace with appropriate additional parameters */ +typedef void (*mwService_funcRecvCreate) + (struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelCreate *msg); + +/** @todo remove msg and replace with appropriate additional parameters */ +typedef void (*mwService_funcRecvAccept) + (struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelAccept *msg); + +/** @todo remove msg and replace with appropriate additional parameters */ +typedef void (*mwService_funcRecvDestroy) + (struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelDestroy *msg); + +typedef void (*mwService_funcRecv) + (struct mwService *service, + struct mwChannel *channel, + guint16 msg_type, + struct mwOpaque *data); + + +/** A service is the recipient of sendOnCnl messages sent over + channels marked with the corresponding service id. Services + provide functionality such as IM relaying, Awareness tracking and + notification, and Conference handling. It is a service's + responsibility to accept or destroy channels, and to process data + sent over those channels */ +struct mwService { + + /** the unique identifier by which this service is registered. The + type value also relates to those channels which will be directed + to this service */ + guint32 type; + + /** the state of this service. Determines whether or not the session + should call the start function upon receipt of a service + available message. Should not be set or checked by hand. + + @relates mwService_getState */ + enum mwServiceState state; + + /** session this service is attached to. + @relates mwService_getSession */ + struct mwSession *session; + + /** @return string short name of the service + @relates mwService_getName */ + mwService_funcGetName get_name; + + /** @return string short description of the service + @relates mwService_getDesc */ + mwService_funcGetDesc get_desc; + + /** The service's channel create handler. Called when the session + receives a channel create message with a service matching this + service's type. + + @relates mwService_recvCreate */ + mwService_funcRecvCreate recv_create; + + /** The service's channel accept handler. Called when the session + receives a channel accept message for a channel with a service + matching this service's type. + + @relates mwService_recvAccept */ + mwService_funcRecvAccept recv_accept; + + /** The service's channel destroy handler. Called when the session + receives a channel destroy message for a channel with a service + matching this service's type. + + @relates mwService_recvDestroy */ + mwService_funcRecvDestroy recv_destroy; + + /** The service's input handler. Called when the session receives + data on a channel belonging to this service + + @relates mwService_recv */ + mwService_funcRecv recv; + + /** The service's start handler. Called upon the receipt of a + service available message. + + @relates mwService_start */ + mwService_funcStart start; + + /** The service's stop handler. Called when the session is shutting + down, or when the service is free'd. + + @relates mwService_stop */ + mwService_funcStop stop; + + /** The service's cleanup handler. Service implementations should + presume that mwService::stop will be called first. The clear + handler is not for shutting down channels or generating + non-cleanup side-effects, it is only for handling tear-down of + the service, and will only be called once for any instance. + + @relates mwService_free */ + mwService_funcClear clear; + + /** Optional client data, not for use by service implementations + + @relates mwService_getClientData + @relates mwService_setClientData */ + gpointer client_data; + + /** Optional client data cleanup function. Called with client_data + from mwService_free + + @relates mwService_getClientData + @relates mwService_setClientData */ + GDestroyNotify client_cleanup; +}; + + +/** @name Service Extension API + + These functions are for use by service implementations */ +/*@{*/ + + +/** Prepares a newly allocated service for use. + + Intended for use by service implementations, rather than by code + utilizing a service. + + The service state will be initialized to STOPPED. + + @param service the service to initialize + @param session the service's owning session + @param service_type the service ID number */ +void mwService_init(struct mwService *service, + struct mwSession *session, + guint32 service_type); + + +/** Indicate that a service is started. To be used by service + implementations when the service is fully started. */ +void mwService_started(struct mwService *service); + + +/** Indicate that a service is stopped. To be used by service + implementations when the service is fully stopped. */ +void mwService_stopped(struct mwService *service); + + +/*@}*/ + + +/** @name General Services API + + These functions provide unified access to the general functions of + a client service, with some simple sanity-checking. */ +/*@{*/ + + +/** Triggers the recv_create handler on the service. + + @param service the service to handle the message + @param channel the channel being created + @param msg the channel create message */ +void mwService_recvCreate(struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelCreate *msg); + + +/** Triggers the recv_accept handler on the service. + + @param service the service to handle the message + @param channel the channel being accepted + @param msg the channel accept message */ +void mwService_recvAccept(struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelAccept *msg); + + +/** Triggers the recv_destroy handler on the service. + + @param service the service to handle the message + @param channel the channel being destroyed + @param msg the channel destroy message */ +void mwService_recvDestroy(struct mwService *service, + struct mwChannel *channel, + struct mwMsgChannelDestroy *msg); + + +/** Triggers the input handler on the service + + @param service the service to receive the input + @param channel the channel the input was received from + @param msg_type the service-dependant message type + @param data the message data */ +void mwService_recv(struct mwService *service, + struct mwChannel *channel, + guint16 msg_type, + struct mwOpaque *data); + + +/** @return the appropriate type id for the service */ +guint32 mwService_getType(struct mwService *); + + +/** @return string short name of the service */ +const char *mwService_getName(struct mwService *); + + +/** @return string short description of the service */ +const char *mwService_getDesc(struct mwService *); + + +/** @return the service's session */ +struct mwSession *mwService_getSession(struct mwService *service); + + +/** @returns the service's state +*/ +enum mwServiceState mwService_getState(struct mwService *service); + + +/** Triggers the start handler for the service. Normally called from + the session upon receipt of a service available message. Service + implementations should use this handler to open any necessary + channels, etc. Checks that the service is STOPPED, or returns. + + @param service The service to start +*/ +void mwService_start(struct mwService *service); + + +/** Triggers the stop handler for the service. Normally called from + the session before closing down the connection. Checks that the + service is STARTED or STARTING, or returns + + @param service The service to stop +*/ +void mwService_stop(struct mwService *service); + + +/** Frees memory used by a service. Will trigger the stop handler if + the service is STARTED or STARTING. Triggers clear handler to allow + cleanup. + + @param service The service to clear and free +*/ +void mwService_free(struct mwService *service); + + +/** Associates client data with service. If there is existing data, it + will not have its cleanup function called. Client data is not for + use by service implementations. Rather, it is for use by client + code which may later make use of those service implementations. */ +void mwService_setClientData(struct mwService *service, + gpointer data, GDestroyNotify cleanup); + + +/** Reference associated client data */ +gpointer mwService_getClientData(struct mwService *service); + + +/** Removes client data from service. If there is a cleanup function, + it will be called. */ +void mwService_removeClientData(struct mwService *service); + + +/*@}*/ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SERVICE_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_session.h b/protocols/Sametime/src/meanwhile/src/mw_session.h new file mode 100644 index 0000000000..e606e0ca98 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_session.h @@ -0,0 +1,397 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SESSION_H +#define _MW_SESSION_H + + +/** @file mw_session.h + + A client session with a Sametime server is encapsulated in the + mwSession structure. The session controls channels, provides + encryption ciphers, and manages services using messages over the + Master channel. + + A session does not directly communicate with a socket or stream, + instead the session is initialized from client code with an + instance of a mwSessionHandler structure. This session handler + provides functions as call-backs for common session events, and + provides functions for writing-to and closing the connection to + the server. + + A session does not perform reads on a socket directly. Instead, it + must be fed from an outside source via the mwSession_recv + function. The session will buffer and merge data passed to this + function to build complete protocol messages, and will act upon + each complete message accordingly. +*/ + + +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct mwChannelSet; +struct mwCipher; +struct mwMessage; +struct mwService; + + +/** default protocol major version */ +#define MW_PROTOCOL_VERSION_MAJOR 0x001e + + +/** default protocol minor version */ +#define MW_PROTOCOL_VERSION_MINOR 0x001d + + +/** @section Session Properties + for use with mwSession_setProperty, et al. +*/ +/*@{*/ + +/** char *, session user ID */ +#define mwSession_AUTH_USER_ID "session.auth.user" + +/** char *, plaintext password */ +#define mwSession_AUTH_PASSWORD "session.auth.password" + +/** struct mwOpaque *, authentication token */ +#define mwSession_AUTH_TOKEN "session.auth.token" + +/** char *, hostname of client */ +#define mwSession_CLIENT_HOST "client.host" + +/** guint32, local IP of client */ +#define mwSession_CLIENT_IP "client.ip" + +/** guint16, major version of client protocol */ +#define mwSession_CLIENT_VER_MAJOR "client.version.major" + +/** guint16, minor version of client protocol */ +#define mwSession_CLIENT_VER_MINOR "client.version.minor" + +/** guint16, client type identifier */ +#define mwSession_CLIENT_TYPE_ID "client.id" + +/** guint16, major version of server protocol */ +#define mwSession_SERVER_VER_MAJOR "server.version.major" + +/** guint16, minor version of server protocol */ +#define mwSession_SERVER_VER_MINOR "server.version.minor" + +/*@}*/ + + +enum mwSessionState { + mwSession_STARTING, /**< session is starting */ + mwSession_HANDSHAKE, /**< session has sent handshake */ + mwSession_HANDSHAKE_ACK, /**< session has received handshake ack */ + mwSession_LOGIN, /**< session has sent login */ + mwSession_LOGIN_REDIR, /**< session has been redirected */ + mwSession_LOGIN_ACK, /**< session has received login ack */ + mwSession_STARTED, /**< session is active */ + mwSession_STOPPING, /**< session is shutting down */ + mwSession_STOPPED, /**< session is stopped */ + mwSession_UNKNOWN, /**< indicates an error determining state */ + mwSession_LOGIN_CONT, /**< session has sent a login continue */ +}; + + +#define mwSession_isState(session, state) \ + (mwSession_getState((session)) == (state)) + +#define mwSession_isStarting(s) \ + (mwSession_isState((s), mwSession_STARTING) || \ + mwSession_isState((s), mwSession_HANDSHAKE) || \ + mwSession_isState((s), mwSession_HANDSHAKE_ACK) || \ + mwSession_isState((s), mwSession_LOGIN) || \ + mwSession_isState((s), mwSession_LOGIN_ACK) || \ + mwSession_isState((s), mwSession_LOGIN_REDIR) || \ + mwSession_isState((s), mwSession_LOGIN_CONT)) + +#define mwSession_isStarted(s) \ + (mwSession_isState((s), mwSession_STARTED)) + +#define mwSession_isStopping(s) \ + (mwSession_isState((s), mwSession_STOPPING)) + +#define mwSession_isStopped(s) \ + (mwSession_isState((s), mwSession_STOPPED)) + + +/** @struct mwSession + + Represents a Sametime client session */ +struct mwSession; + + +/** @struct mwSessionHandler + + session handler. Structure which interfaces a session with client + code to provide I/O and event handling */ +struct mwSessionHandler { + + /** write data to the server connection. Required. Should return + zero for success, non-zero for error */ + int (*io_write)(struct mwSession *, const guchar *buf, gsize len); + + /** close the server connection. Required */ + void (*io_close)(struct mwSession *); + + /** triggered by mwSession_free. Optional. Put cleanup code here */ + void (*clear)(struct mwSession *); + + /** Called when the session has changed status. + + @see mwSession_getStateInfo for uses of info field + + @param s the session + @param state the session's state + @param info additional state information */ + void (*on_stateChange)(struct mwSession *s, + enum mwSessionState state, gpointer info); + + /** called when privacy information has been sent or received + + @see mwSession_getPrivacyInfo + */ + void (*on_setPrivacyInfo)(struct mwSession *); + + /** called when user status has changed + + @see mwSession_getUserStatus */ + void (*on_setUserStatus)(struct mwSession *); + + /** called when an admin messages has been received */ + void (*on_admin)(struct mwSession *, const char *text); + + /** called when an announcement arrives */ + void (*on_announce)(struct mwSession *, struct mwLoginInfo *from, + gboolean may_reply, const char *text); + +}; + + +/** allocate a new session */ +struct mwSession *mwSession_new(struct mwSessionHandler *); + + +/** stop, clear, free a session. Does not free contained ciphers or + services, these must be taken care of explicitly. */ +void mwSession_free(struct mwSession *); + + +/** obtain a reference to the session's handler */ +struct mwSessionHandler *mwSession_getHandler(struct mwSession *); + + +/** instruct the session to begin. This will result in the initial + handshake message being sent. */ +void mwSession_start(struct mwSession *); + + +/** instruct the session to shut down with the following reason + code. */ +void mwSession_stop(struct mwSession *, guint32 reason); + + +/** Data is buffered, unpacked, and parsed into a message, then + processed accordingly. */ +void mwSession_recv(struct mwSession *, const guchar *, gsize); + + +/** primarily used by services to have messages serialized and sent + @param s session to send message over + @param msg message to serialize and send + @returns 0 for success */ +int mwSession_send(struct mwSession *s, struct mwMessage *msg); + + +/** sends the keepalive byte */ +int mwSession_sendKeepalive(struct mwSession *s); + + +/** respond to a login redirect message by forcing the login sequence + to continue through the immediate server. */ +int mwSession_forceLogin(struct mwSession *s); + + +/** send an announcement to a list of users/groups. Targets of + announcement must be in the same community as the session. + + @param s session to send announcement from + @param may_reply permit clients to reply. Not all clients honor this. + @param text text of announcement + @param recipients list of recipients. Each recipient is specified + by a single string, prefix with "@U " for users + and "@G " for Notes Address Book groups. +*/ +int mwSession_sendAnnounce(struct mwSession *s, gboolean may_reply, + const char *text, const GList *recipients); + + +/** set the internal privacy information, and inform the server as + necessary. Triggers the on_setPrivacyInfo call-back. */ +int mwSession_setPrivacyInfo(struct mwSession *, struct mwPrivacyInfo *); + + +/** direct reference to the session's internal privacy structure */ +struct mwPrivacyInfo *mwSession_getPrivacyInfo(struct mwSession *); + + +/** reference the login information for the session */ +struct mwLoginInfo *mwSession_getLoginInfo(struct mwSession *); + + +/** set the internal user status state, and inform the server as + necessary. Triggers the on_setUserStatus call-back */ +int mwSession_setUserStatus(struct mwSession *, struct mwUserStatus *); + + +struct mwUserStatus *mwSession_getUserStatus(struct mwSession *); + + +/** current status of the session */ +enum mwSessionState mwSession_getState(struct mwSession *); + + +/** additional status-specific information. Depending on the state of + the session, this value has different meaning. + + @li @c mwSession_STOPPING guint32 error code causing + the session to shut down + + @li @c mwSession_STOPPED guint32 error code causing + the session to shut down + + @li @c mwSession_LOGIN_REDIR (char *) host to redirect + to +*/ +gpointer mwSession_getStateInfo(struct mwSession *); + + +struct mwChannelSet *mwSession_getChannels(struct mwSession *); + + +/** adds a service to the session. If the session is started (or when + the session is successfully started) and the service has a start + function, the session will request service availability from the + server. On receipt of the service availability notification, the + session will call the service's start function. + + @return TRUE if the session was added correctly */ +gboolean mwSession_addService(struct mwSession *, struct mwService *); + + +/** find a service by its type identifier */ +struct mwService *mwSession_getService(struct mwSession *, guint32 type); + + +/** removes a service from the session. If the session is started and + the service has a stop function, it will be called. Returns the + removed service */ +struct mwService *mwSession_removeService(struct mwSession *, guint32 type); + + +/** a GList of services in this session. The GList needs to be freed + after use */ +GList *mwSession_getServices(struct mwSession *); + + +/** instruct a STARTED session to check the server for the presense of + a given service. The service will be automatically started upon + receipt of an affirmative reply from the server. This function is + automatically called upon all services in a session when the + session is fully STARTED. + + Services which terminate due to an error may call this on + themselves to re-initialize when their server-side counterpart is + made available again. + + @param s owning session + @param type service type ID */ +void mwSession_senseService(struct mwSession *s, guint32 type); + + +/** adds a cipher to the session. */ +gboolean mwSession_addCipher(struct mwSession *, struct mwCipher *); + + +/** find a cipher by its type identifier */ +struct mwCipher *mwSession_getCipher(struct mwSession *, guint16 type); + + +/** remove a cipher from the session */ +struct mwCipher *mwSession_removeCipher(struct mwSession *, guint16 type); + + +/** a GList of ciphers in this session. The GList needs to be freed + after use */ +GList *mwSession_getCiphers(struct mwSession *); + + +/** associate a key:value pair with the session. If an existing value is + associated with the same key, it will have its clear function called + and will be replaced with the new value */ +void mwSession_setProperty(struct mwSession *, const char *key, + gpointer val, GDestroyNotify clear); + + +/** obtain the value of a previously set property, or NULL */ +gpointer mwSession_getProperty(struct mwSession *, const char *key); + + +/** remove a property, calling the optional GDestroyNotify function + indicated in mwSession_setProperty if applicable */ +void mwSession_removeProperty(struct mwSession *, const char *key); + + +/** associate arbitrary data with the session for use by the client + code. Only client applications should use this, never services. + + @param session the session to associate the data with + @param data arbitrary client data + @param clear optional cleanup function called on data from + mwSession_removeClientData and mwSession_free +*/ +void mwSession_setClientData(struct mwSession *session, + gpointer data, GDestroyNotify clear); + + +gpointer mwSession_getClientData(struct mwSession *session); + + +/** remove client data, calling the optional GDestroyNotify function + indicated in mwSession_setClientData if applicable */ +void mwSession_removeClientData(struct mwSession *session); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SESSION_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_aware.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_aware.h new file mode 100644 index 0000000000..0d5090d258 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_aware.h @@ -0,0 +1,289 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_AWARE_H +#define _MW_SRVC_AWARE_H + + +/** @file mw_srvc_aware.h + + The aware service... + + @todo remove the whole idea of an instantiated mwAwareList and + instead use arbitrary pointers (including NULL) as keys to + internally stored lists. This removes the problem of the service + free'ing its lists and invalidating mwAwareList references from + client code. +*/ + + +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Type identifier for the aware service */ +#define mwService_AWARE 0x00000011 + + +/** @struct mwServiceAware + + Instance of an Aware Service. The members of this structure are + not made available. Accessing the parts of an aware service should + be performed through the appropriate functions. Note that + instances of this structure can be safely cast to a mwService. +*/ +struct mwServiceAware; + + +/** @struct mwAwareList + + Instance of an Aware List. The members of this structure are not + made available. Access to the parts of an aware list should be + handled through the appropriate functions. + + Any references to an aware list are rendered invalid when the + parent service is free'd +*/ +struct mwAwareList; + + +/** @struct mwAwareAttribute + + Key/Opaque pair indicating an identity's attribute. + */ +struct mwAwareAttribute; + + +/** Predefined keys appropriate for a mwAwareAttribute + */ +enum mwAwareAttributeKeys { + mwAttribute_AV_PREFS_SET = 0x01, /**< A/V prefs specified, gboolean */ + mwAttribute_MICROPHONE = 0x02, /**< has a microphone, gboolean */ + mwAttribute_SPEAKERS = 0x03, /**< has speakers, gboolean */ + mwAttribute_VIDEO_CAMERA = 0x04, /**< has a video camera, gboolean */ + mwAttribute_FILE_TRANSFER = 0x06, /**< supports file transfers, gboolean */ +}; + + +typedef void (*mwAwareAttributeHandler) + (struct mwServiceAware *srvc, + struct mwAwareAttribute *attrib); + + +struct mwAwareHandler { + mwAwareAttributeHandler on_attrib; + void (*clear)(struct mwServiceAware *srvc); +}; + + +/** Appropriate function type for the on-aware signal + + @param list mwAwareList emiting the signal + @param id awareness status information + @param data user-specified data +*/ +typedef void (*mwAwareSnapshotHandler) + (struct mwAwareList *list, + struct mwAwareSnapshot *id); + + +/** Appropriate function type for the on-option signal. The option's + value may need to be explicitly loaded in some instances, + resulting in this handler being triggered again. + + @param list mwAwareList emiting the signal + @param id awareness the attribute belongs to + @param attrib attribute +*/ +typedef void (*mwAwareIdAttributeHandler) + (struct mwAwareList *list, + struct mwAwareIdBlock *id, + struct mwAwareAttribute *attrib); + + +struct mwAwareListHandler { + /** handle aware updates */ + mwAwareSnapshotHandler on_aware; + + /** handle attribute updates */ + mwAwareIdAttributeHandler on_attrib; + + /** optional. Called from mwAwareList_free */ + void (*clear)(struct mwAwareList *list); +}; + + +struct mwServiceAware * +mwServiceAware_new(struct mwSession *session, + struct mwAwareHandler *handler); + + +/** Set an attribute value for this session */ +int mwServiceAware_setAttribute(struct mwServiceAware *srvc, + guint32 key, struct mwOpaque *opaque); + + +int mwServiceAware_setAttributeBoolean(struct mwServiceAware *srvc, + guint32 key, gboolean val); + + +int mwServiceAware_setAttributeInteger(struct mwServiceAware *srvc, + guint32 key, guint32 val); + + +int mwServiceAware_setAttributeString(struct mwServiceAware *srvc, + guint32 key, const char *str); + + +/** Unset an attribute for this session */ +int mwServiceAware_unsetAttribute(struct mwServiceAware *srvc, + guint32 key); + + +guint32 mwAwareAttribute_getKey(const struct mwAwareAttribute *attrib); + + +gboolean mwAwareAttribute_asBoolean(const struct mwAwareAttribute *attrib); + + +guint32 mwAwareAttribute_asInteger(const struct mwAwareAttribute *attrib); + + +/** Copy of attribute string, must be g_free'd. If the attribute's + content cannot be loaded as a string, returns NULL */ +char *mwAwareAttribute_asString(const struct mwAwareAttribute *attrib); + + +/** Direct access to an attribute's underlying opaque */ +const struct mwOpaque * +mwAwareAttribute_asOpaque(const struct mwAwareAttribute *attrib); + + +/** Allocate and initialize an aware list */ +struct mwAwareList * +mwAwareList_new(struct mwServiceAware *srvc, + struct mwAwareListHandler *handler); + + +/** Clean and free an aware list */ +void mwAwareList_free(struct mwAwareList *list); + + +struct mwAwareListHandler *mwAwareList_getHandler(struct mwAwareList *list); + + +/// Miranda NG adaptation start - new method +struct mwServiceAware *mwAwareList_getServiceAware(struct mwAwareList *list); +/// Miranda NG adaptation end + + +/** Add a collection of user IDs to an aware list. + @param list mwAwareList to add user ID to + @param id_list mwAwareIdBlock list of user IDs to add + @return 0 for success, non-zero to indicate an error. +*/ +int mwAwareList_addAware(struct mwAwareList *list, GList *id_list); + + +/** Remove a collection of user IDs from an aware list. + @param list mwAwareList to remove user ID from + @param id_list mwAwareIdBlock list of user IDs to remove + @return 0 for success, non-zero to indicate an error. +*/ +int mwAwareList_removeAware(struct mwAwareList *list, GList *id_list); + + +int mwAwareList_removeAllAware(struct mwAwareList *list); + + +/** watch an NULL terminated array of keys */ +int mwAwareList_watchAttributeArray(struct mwAwareList *list, + guint32 *keys); + + +/** watch a NULL terminated list of keys */ +int mwAwareList_watchAttributes(struct mwAwareList *list, + guint32 key, ...); + + +/** stop watching a NULL terminated array of keys */ +int mwAwareList_unwatchAttributeArray(struct mwAwareList *list, + guint32 *keys); + + +/** stop watching a NULL terminated list of keys */ +int mwAwareList_unwatchAttributes(struct mwAwareList *list, + guint32 key, ...); + + +/** remove all watched attributes */ +int mwAwareList_unwatchAllAttributes(struct mwAwareList *list); + + +guint32 *mwAwareList_getWatchedAttributes(struct mwAwareList *list); + + +void mwAwareList_setClientData(struct mwAwareList *list, + gpointer data, GDestroyNotify cleanup); + + +void mwAwareList_removeClientData(struct mwAwareList *list); + + +gpointer mwAwareList_getClientData(struct mwAwareList *list); + + +/** trigger a got_aware event constructed from the passed user and + status information. Useful for adding false users and having the + getText function work for them */ +void mwServiceAware_setStatus(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user, + struct mwUserStatus *stat); + + +/** look up the status description for a user */ +const char *mwServiceAware_getText(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user); + + +/** look up the last known copy of an attribute for a user by the + attribute's key */ +const struct mwAwareAttribute * +mwServiceAware_getAttribute(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user, + guint32 key); + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceAware_getService(struct mwServiceAware *srvc); +/// Miranda NG adaptation end + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_AWARE_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_conf.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_conf.h new file mode 100644 index 0000000000..1447fd3830 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_conf.h @@ -0,0 +1,216 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_CONF_H +#define _MW_SRVC_CONF_H + + +#include <glib/glist.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Type identifier for the conference service */ +#define mwService_CONFERENCE 0x80000010 + + +enum mwConferenceState { + mwConference_NEW, /**< new outgoing conference */ + mwConference_PENDING, /**< outgoing conference pending creation */ + mwConference_INVITED, /**< invited to incoming conference */ + mwConference_OPEN, /**< conference open and active */ + mwConference_CLOSING, /**< conference is closing */ + mwConference_ERROR, /**< conference is closing due to error */ + mwConference_UNKNOWN, /**< unable to determine conference state */ +}; + + +/** @struct mwServiceConference + Instance of the multi-user conference service */ +struct mwServiceConference; + + +/** @struct mwConference + A multi-user chat */ +struct mwConference; + + +/** Handler structure used to provide callbacks for an instance of the + conferencing service */ +struct mwConferenceHandler { + + /** triggered when we receive a conference invitation. Call + mwConference_accept to accept the invitation and join the + conference, or mwConference_close to reject the invitation. + + @param conf the newly created conference + @param inviter the indentity of the user who sent the invitation + @param invite the invitation text + */ + void (*on_invited)(struct mwConference *conf, + struct mwLoginInfo *inviter, const char *invite); + + /** triggered when we enter the conference. Provides the initial + conference membership list as a GList of mwLoginInfo structures + + @param conf the conference just joined + @param members mwLoginInfo list of existing conference members + */ + void (*conf_opened)(struct mwConference *conf, GList *members); + + /** triggered when a conference is closed. This is typically when + we've left it */ + void (*conf_closed)(struct mwConference *, guint32 reason); + + /** triggered when someone joins the conference */ + void (*on_peer_joined)(struct mwConference *, struct mwLoginInfo *); + + /** triggered when someone leaves the conference */ + void (*on_peer_parted)(struct mwConference *, struct mwLoginInfo *); + + /** triggered when someone says something */ + void (*on_text)(struct mwConference *conf, + struct mwLoginInfo *who, const char *what); + + /** typing notification */ + void (*on_typing)(struct mwConference *conf, + struct mwLoginInfo *who, gboolean typing); + + /** optional. called from mwService_free */ + void (*clear)(struct mwServiceConference *srvc); +}; + + +/** Allocate a new conferencing service, attaching the given handler + @param sess owning session + @param handler handler providing call-back functions for the service + */ +struct mwServiceConference * +mwServiceConference_new(struct mwSession *sess, + struct mwConferenceHandler *handler); + + +/** @returns the conference handler for the service */ +struct mwConferenceHandler * +mwServiceConference_getHandler(struct mwServiceConference *srvc); + + +/** a mwConference list of the conferences in this service. The GList + will need to be destroyed with g_list_free after use */ +GList *mwServiceConference_getConferences(struct mwServiceConference *srvc); + + +/** Allocate a new conference, in state NEW with the given title. + @see mwConference_create */ +struct mwConference *mwConference_new(struct mwServiceConference *srvc, + const char *title); + + +/** @returns the owning service of a conference */ +/// Miranda NG adaptation start - renamed method +struct mwServiceConference *mwConference_getServiceConference(struct mwConference *conf); +/// Miranda NG adaptation end + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceConference_getService(struct mwServiceConference *srvc); +/// Miranda NG adaptation end + + +/** @returns unique conference name */ +const char *mwConference_getName(struct mwConference *conf); + + +/** @returns conference title */ +const char *mwConference_getTitle(struct mwConference *conf); + + +/** a mwIdBlock list of the members of the conference. The GList will + need to be free'd after use */ +GList *mwConference_getMembers(struct mwConference *conf); + + +/** Initiate a conference. Conference must be in state NEW. If no name + or title for the conference has been set, they will be + generated. Conference will be placed into state PENDING. */ +int mwConference_open(struct mwConference *conf); + + +/** Leave and close an existing conference, or reject an invitation. + Triggers mwServiceConfHandler::conf_closed and free's the + conference. + */ +int mwConference_destroy(struct mwConference *conf, + guint32 reason, const char *text); + + +#define mwConference_reject(c,r,t) \ + mwConference_destroy((c),(r),(t)) + + +/** accept a conference invitation. Conference must be in the state + INVITED. */ +int mwConference_accept(struct mwConference *conf); + + +/** invite another user to an ACTIVE conference + @param conf conference + @param who user to invite + @param text invitation message + */ +int mwConference_invite(struct mwConference *conf, + struct mwIdBlock *who, const char *text); + + +/** send a text message over an open conference */ +int mwConference_sendText(struct mwConference *conf, const char *text); + + +/** send typing notification over an open conference */ +int mwConference_sendTyping(struct mwConference *conf, gboolean typing); + + +/** associate arbitrary client data and an optional cleanup function + with a conference. If there is already client data with a clear + function, it will not be called. */ +void mwConference_setClientData(struct mwConference *conf, + gpointer data, GDestroyNotify clear); + + +/** reference associated client data */ +gpointer mwConference_getClientData(struct mwConference *conf); + + +/** remove associated client data if any, and call the cleanup + function on the data as necessary */ +void mwConference_removeClientData(struct mwConference *conf); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_CONF_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_dir.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_dir.h new file mode 100644 index 0000000000..b9230bbf08 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_dir.h @@ -0,0 +1,212 @@ +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_DIR_H +#define _MW_SERV_DIR_H + + +#include <glib.h> +#include <glib/glist.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct mwSession; + + +#define SERVICE_DIRECTORY 0x0000001a + + +/** @struct mwServiceDirectory + + the directory service. */ +struct mwServiceDirectory; + + +/** @struct mwAddressBook + + server-side collection of users and groups. Open a directory + based on an address book to search or list its contents */ +struct mwAddressBook; + + +/** @struct mwDirectory + + searchable directory, based off of an address book */ +struct mwDirectory; + + +enum mwDirectoryState { + mwDirectory_NEW, /**< directory is created, but not open */ + mwDirectory_PENDING, /**< directory has in the process of opening */ + mwDirectory_OPEN, /**< directory is open */ + mwDirectory_ERROR, /**< error opening or using directory */ + mwDirectory_UNKNOWN, /**< error determining directory state */ +}; + + +/** return value of directory searches that fail */ +#define DIR_SEARCH_ERROR 0x00000000 + + +#define MW_DIRECTORY_IS_STATE(dir, state) \ + (mwDirectory_getState(dir) == (state)) + +#define MW_DIRECTORY_IS_NEW(dir) \ + MW_DIRECTORY_IS_STATE((dir), mwDirectory_NEW) + +#define MW_DIRECTORY_IS_PENDING(dir) \ + MW_DIRECTORY_IS_STATE((dir), mwDirectory_PENDING) + +#define MW_DIRECTORY_IS_OPEN(dir) \ + MW_DIRECTORY_IS_STATE((dir), mwDirectory_OPEN) + + +enum mwDirectoryMemberType { + mwDirectoryMember_USER = 0x0000, + mwDirectoryMember_GROUP = 0x0001, +}; + + +struct mwDirectoryMember { + guint16 type; /**< @see mwDirectoryMemberType */ + char *id; /**< proper ID for member */ + char *long_name; /**< full name of member (USER type only) */ + char *short_name; /**< short name of member */ + guint16 foo; /**< unknown */ +}; + + +/** Appropriate function signature for handling directory search results */ +typedef void (*mwSearchHandler) + (struct mwDirectory *dir, + guint32 code, guint32 offset, GList *members); + + +/** handles asynchronous events for a directory service instance */ +struct mwDirectoryHandler { + + /** handle receipt of the address book list from the service. + Initially triggered by mwServiceDirectory_refreshAddressBooks + and at service startup */ + void (*on_book_list)(struct mwServiceDirectory *srvc, GList *books); + + /** triggered when a directory has been successfully opened */ + void (*dir_opened)(struct mwDirectory *dir); + + /** triggered when a directory has been closed */ + void (*dir_closed)(struct mwDirectory *dir, guint32 reason); + + /** optional. called from mwService_free */ + void (*clear)(struct mwServiceDirectory *srvc); +}; + + +/** Allocate a new directory service instance for use with session */ +struct mwServiceDirectory * +mwServiceDirectory_new(struct mwSession *session, + struct mwDirectoryHandler *handler); + + +/** the handler associated with the service at its creation */ +struct mwDirectoryHandler * +mwServiceDirectory_getHandler(struct mwServiceDirectory *srvc); + + +/** most recent list of address books available in service */ +GList *mwServiceDirectory_getAddressBooks(struct mwServiceDirectory *srvc); + + +/** submit a request to obtain an updated list of address books from + service */ +int mwServiceDirectory_refreshAddressBooks(struct mwServiceDirectory *srvc); + + +/** list of directories in the service */ +GList *mwServiceDirectory_getDirectories(struct mwServiceDirectory *srvc); + + +/** list of directories associated with address book. Note that the + returned GList will need to be free'd after use */ +GList *mwAddressBook_getDirectories(struct mwAddressBook *book); + + +/** the name of the address book */ +const char *mwAddressBook_getName(struct mwAddressBook *book); + + +/** allocate a new directory based off the given address book */ +struct mwDirectory *mwDirectory_new(struct mwAddressBook *book); + + +enum mwDirectoryState mwDirectory_getState(struct mwDirectory *dir); + + +/** set client data. If there is an existing clear function, it will + not be called */ +void mwDirectory_setClientData(struct mwDirectory *dir, + gpointer data, GDestroyNotify clear); + + +/** reference associated client data */ +gpointer mwDirectory_getClientData(struct mwDirectory *dir); + + +/** remove and cleanup user data */ +void mwDirectory_removeClientData(struct mwDirectory *dir); + + +/** reference owning service */ +struct mwServiceDirectory *mwDirectory_getService(struct mwDirectory *dir); + + +/** reference owning address book */ +struct mwAddressBook *mwDirectory_getAddressBook(struct mwDirectory *dir); + + +/** initialize a directory. */ +int mwDirectory_open(struct mwDirectory *dir, mwSearchHandler cb); + + +/** continue a search into its next results */ +int mwDirectory_next(struct mwDirectory *dir); + + +/** continue a search into its previous results */ +int mwDirectory_previous(struct mwDirectory *dir); + + +/** initiate a search on an open directory */ +int mwDirectory_search(struct mwDirectory *dir, const char *query); + + +/** close and free the directory, and unassociate it with its owning + address book and service */ +int mwDirectory_destroy(struct mwDirectory *dir); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_DIR_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_ft.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_ft.h new file mode 100644 index 0000000000..aef7de886a --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_ft.h @@ -0,0 +1,255 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _MW_SRVC_FT_H +#define _MW_SRVC_FT_H + + +/** @file mw_srvc_ft.h + + A file transfer is a simple way to get large chunks of binary data + from one client to another. +*/ + + +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @struct mwServiceFileTransfer + File transfer service +*/ +struct mwServiceFileTransfer; + + +/** @struct mwFileTransfer + A single file trasfer session + */ +struct mwFileTransfer; + + +#define mwService_FILE_TRANSFER 0x00000038 + + +enum mwFileTransferState { + mwFileTransfer_NEW, /**< file transfer is not open */ + mwFileTransfer_PENDING, /**< file transfer is opening */ + mwFileTransfer_OPEN, /**< file transfer is open */ + mwFileTransfer_CANCEL_LOCAL, + mwFileTransfer_CANCEL_REMOTE, + mwFileTransfer_DONE, + mwFileTransfer_ERROR, /**< error in file transfer */ + mwFileTransfer_UNKNOWN, /**< unknown state */ +}; + + +#define mwFileTransfer_isState(ft, state) \ + (mwFileTransfer_getState(ft) == (state)) + +#define mwFileTransfer_isNew(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_NEW) + +#define mwFileTransfer_isPending(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_PENDING) + +#define mwFileTransfer_isOpen(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_OPEN) + +#define mwFileTransfer_isDone(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_DONE) + +#define mwFileTransfer_isCancelLocal(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_CANCEL_LOCAL) + +#define mwFileTransfer_isCancelRemote(ft) \ + mwFileTransfer_isState((ft), mwFileTransfer_CANCEL_REMOTE) + + +enum mwFileTranferCode { + mwFileTransfer_SUCCESS = 0x00000000, + mwFileTransfer_REJECTED = 0x08000606, +}; + + +struct mwFileTransferHandler { + + /** an incoming file transfer has been offered */ + void (*ft_offered)(struct mwFileTransfer *ft); + + /** a file transfer has been fully initiated */ + void (*ft_opened)(struct mwFileTransfer *ft); + + /** a file transfer has been closed. Check the status of the file + transfer to determine if the transfer was complete or if it had + been interrupted */ + void (*ft_closed)(struct mwFileTransfer *ft, guint32 code); + + /** receive a chunk of a file from an inbound file transfer. */ + void (*ft_recv)(struct mwFileTransfer *ft, struct mwOpaque *data); + + /** received an ack for a sent chunk on an outbound file transfer. + this indicates that a previous call to mwFileTransfer_send has + reached the target and that the target has responded. */ + void (*ft_ack)(struct mwFileTransfer *ft); + + /** optional. called from mwService_free */ + void (*clear)(struct mwServiceFileTransfer *srvc); +}; + + +struct mwServiceFileTransfer * +mwServiceFileTransfer_new(struct mwSession *session, + struct mwFileTransferHandler *handler); + + +struct mwFileTransferHandler * +mwServiceFileTransfer_getHandler(struct mwServiceFileTransfer *srvc); + + +const GList * +mwServiceFileTransfer_getTransfers(struct mwServiceFileTransfer *srvc); + + +/// Miranda NG adaptation start - new method +struct mwService * +mwServiceFileTransfer_getService(struct mwServiceFileTransfer *srvc); +/// Miranda NG adaptation end + + +struct mwFileTransfer * +mwFileTransfer_new(struct mwServiceFileTransfer *srvc, + const struct mwIdBlock *who, const char *msg, + const char *filename, guint32 filesize); + + +/** deallocate a file transfer. will call mwFileTransfer_close if + necessary */ +void +mwFileTransfer_free(struct mwFileTransfer *ft); + + +/** the status of this file transfer */ +enum mwFileTransferState +mwFileTransfer_getState(struct mwFileTransfer *ft); + + +struct mwServiceFileTransfer * +mwFileTransfer_getService(struct mwFileTransfer *ft); + + +/** the user on the other end of the file transfer */ +const struct mwIdBlock * +mwFileTransfer_getUser(struct mwFileTransfer *ft); + + +/** the message sent along with an offered file transfer */ +const char * +mwFileTransfer_getMessage(struct mwFileTransfer *ft); + + +/** the publicized file name. Not necessarily related to any actual + file on either system */ +const char * +mwFileTransfer_getFileName(struct mwFileTransfer *ft); + + +/** total bytes intended to be sent/received */ +guint32 mwFileTransfer_getFileSize(struct mwFileTransfer *ft); + + +/** bytes remaining to be received/send */ +guint32 mwFileTransfer_getRemaining(struct mwFileTransfer *ft); + + +/** count of bytes sent/received over this file transfer so far */ +#define mwFileTransfer_getSent(ft) \ + (mwFileTransfer_getFileSize(ft) - mwFileTransfer_getRemaining(ft)) + + +/** initiate an outgoing file transfer */ +int mwFileTransfer_offer(struct mwFileTransfer *ft); + + +/** accept an incoming file transfer */ +int mwFileTransfer_accept(struct mwFileTransfer *ft); + + +/** reject an incoming file transfer */ +#define mwFileTransfer_reject(ft) \ + mwFileTransfer_close((ft), mwFileTransfer_REJECTED) + + +/** cancel an open file transfer */ +#define mwFileTransfer_cancel(ft) \ + mwFileTransfer_close((ft), mwFileTransfer_SUCCESS); + + +/** Close a file transfer. This will trigger the ft_close function of the + session's handler. + + @see mwFileTransfer_reject + @see mwFileTransfer_cancel +*/ +int mwFileTransfer_close(struct mwFileTransfer *ft, guint32 code); + + +/** send a chunk of data over an outbound file transfer. The client at + the other end of the transfer should respond with an acknowledgement + message, which can be caught in the service's handler. + + @see mwFileTransferHandler::ft_ack +*/ +int mwFileTransfer_send(struct mwFileTransfer *ft, + struct mwOpaque *data); + + +/** acknowledge the receipt of a chunk of data from an inbound file + transfer. This should be done after every received chunk, or the + transfer will stall. However, not all clients will wait for an ack + after sending a chunk before sending the next chunk, so it is + possible to have the handler's ft_recv function triggered again + even if no ack was sent. + + @see mwFileTransferHandler::ft_recv +*/ +int mwFileTransfer_ack(struct mwFileTransfer *ft); + + +void mwFileTransfer_setClientData(struct mwFileTransfer *ft, + gpointer data, GDestroyNotify clean); + + +gpointer mwFileTransfer_getClientData(struct mwFileTransfer *ft); + + +void mwFileTransfer_removeClientData(struct mwFileTransfer *ft); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_FT_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_im.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_im.h new file mode 100644 index 0000000000..adb710e32c --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_im.h @@ -0,0 +1,281 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_IM_H +#define _MW_SRVC_IM_H + + +/** @file mw_srvc_im.h + + The IM service provides one-on-one communication between + users. Messages sent over conversations may relay different types + of information, in a variety of formats. The basic feature-set + provides plain-text chat with typing notification. More complex + features may be negotiated transparently by setting the IM Client + Type for a conversation, or for the service as a whole. +*/ + + +#include <glib.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* identifier for the IM service */ +#define mwService_IM 0x00001000 + + +/** @struct mwServiceIm + + An instance of the IM service. This service provides simple + instant messaging functionality */ +struct mwServiceIm; + + +/** @struct mwConversation + + A conversation between the local service and a single other user */ +struct mwConversation; + + +enum mwImClientType { + mwImClient_PLAIN = 0x00000001, /**< text, typing */ + mwImClient_NOTESBUDDY = 0x00033453, /**< adds html, subject, mime */ + mwImClient_PRECONF = 0x00000019, /**< pre-conference, legacy */ + mwImClient_UNKNOWN = 0xffffffff, /**< trouble determining type */ +}; + + +/** + Types of supported messages. When a conversation is created, the + least common denominator of features between either side of the + conversation (based on what features are available in the IM + service itself) becomes the set of supported features for that + conversation. At any point, the feature set for the service may + change, without affecting any existing conversations. + + @see mwServiceIm_supports + @see mwServiceIm_setSupported + @see mwConversation_supports + @see mwConversation_send + @see mwServiceImHandler::conversation_recv + */ +enum mwImSendType { + mwImSend_PLAIN, /**< char *, plain-text message */ + mwImSend_TYPING, /**< gboolean, typing status */ + mwImSend_HTML, /**< char *, HTML formatted message (NOTESBUDDY) */ + mwImSend_SUBJECT, /**< char *, conversation subject (NOTESBUDDY) */ + mwImSend_MIME, /**< char *, MIME-encoded message (NOTESBUDDY) */ + mwImSend_TIMESTAMP, /**< char *, YYYY:MM:DD:HH:mm:SS format (NOTESBUDDY) */ +}; + + + +/** @see mwConversation_getState */ +enum mwConversationState { + mwConversation_CLOSED, /**< conversation is not open */ + mwConversation_PENDING, /**< conversation is opening */ + mwConversation_OPEN, /**< conversation is open */ + mwConversation_UNKNOWN, /**< unknown state */ +}; + + +#define mwConversation_isState(conv, state) \ + (mwConversation_getState(conv) == (state)) + +#define mwConversation_isClosed(conv) \ + mwConversation_isState((conv), mwConversation_CLOSED) + +#define mwConversation_isPending(conv) \ + mwConversation_isState((conv), mwConversation_PENDING) + +#define mwConversation_isOpen(conv) \ + mwConversation_isState((conv), mwConversation_OPEN) + + + +/** IM Service Handler. Provides functions for events triggered from an + IM service instance. */ +struct mwImHandler { + + /** A conversation has been successfully opened */ + void (*conversation_opened)(struct mwConversation *conv); + + /** A conversation has been closed */ + void (*conversation_closed)(struct mwConversation *conv, guint32 err); + + /** A message has been received on a conversation */ + void (*conversation_recv)(struct mwConversation *conv, + enum mwImSendType type, gconstpointer msg); + + /** Handle a Place invitation. Set this to NULL and we should end up + receiving a conference invitation instead. */ + void (*place_invite)(struct mwConversation *conv, + const char *message, + const char *title, const char *name); + + /** optional. called from mwService_free */ + void (*clear)(struct mwServiceIm *srvc); +}; + + +struct mwServiceIm *mwServiceIm_new(struct mwSession *session, + struct mwImHandler *handler); + + +struct mwImHandler *mwServiceIm_getHandler(struct mwServiceIm *srvc); + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceIm_getService(struct mwServiceIm *srvc); +/// Miranda NG adaptation end + + +/** reference an existing conversation to target, or create a new + conversation to target if one does not already exist */ +struct mwConversation *mwServiceIm_getConversation(struct mwServiceIm *srvc, + struct mwIdBlock *target); + + +/** reference an existing conversation to target */ +struct mwConversation *mwServiceIm_findConversation(struct mwServiceIm *srvc, + struct mwIdBlock *target); + + +/** determine if the conversations created from this service will + support a given send type */ +gboolean mwServiceIm_supports(struct mwServiceIm *srvc, + enum mwImSendType type); + + +/** Set the default client type for the service. Newly created + conversations will attempt to meet this level of functionality + first. + + @param srvc the IM service + @param type the send type to enable/disable +*/ +void mwServiceIm_setClientType(struct mwServiceIm *srvc, + enum mwImClientType type); + + +enum mwImClientType mwServiceIm_getClientType(struct mwServiceIm *srvc); + + +/** attempt to open a conversation. If the conversation was not + already open and it is accepted, + mwServiceImHandler::conversation_opened will be triggered. Upon + failure, mwServiceImHandler::conversation_closed will be + triggered */ +void mwConversation_open(struct mwConversation *conv); + + +/** close a conversation. If the conversation was not already closed, + mwServiceImHandler::conversation_closed will be triggered */ +void mwConversation_close(struct mwConversation *conv, guint32 err); + + +/** determine whether a conversation supports the given message type */ +gboolean mwConversation_supports(struct mwConversation *conv, + enum mwImSendType type); + + +enum mwImClientType mwConversation_getClientType(struct mwConversation *conv); + + +/** get the state of a conversation + + @see mwConversation_isOpen + @see mwConversation_isClosed + @see mwConversation_isPending +*/ +enum mwConversationState mwConversation_getState(struct mwConversation *conv); + + +/** send a message over an open conversation */ +int mwConversation_send(struct mwConversation *conv, + enum mwImSendType type, gconstpointer send); + + +/** @returns owning service for a conversation */ +struct mwServiceIm *mwConversation_getService(struct mwConversation *conv); + + +/** login information for conversation partner. returns NULL if conversation + is not OPEN */ +struct mwLoginInfo *mwConversation_getTargetInfo(struct mwConversation *conv); + + +/** ID for conversation partner */ +struct mwIdBlock *mwConversation_getTarget(struct mwConversation *conv); + + +/** set whether outgoing messages should be encrypted using the + negotiated cipher, if any */ +void mwConversation_setEncrypted(struct mwConversation *conv, + gboolean useCipher); + + +/** determine whether outgoing messages are being encrypted */ +gboolean mwConversation_isEncrypted(struct mwConversation *conv); + + +/** Associates client data with a conversation. If there is existing data, + it will not have its cleanup function called. + + @see mwConversation_getClientData + @see mwConversation_removeClientData +*/ +void mwConversation_setClientData(struct mwConversation *conv, + gpointer data, GDestroyNotify clean); + + +/** Reference associated client data + + @see mwConversation_setClientData + @see mwConversation_removeClientData + */ +gpointer mwConversation_getClientData(struct mwConversation *conv); + + +/** Remove any associated client data, calling the optional cleanup + function if one was provided + + @see mwConversation_setClientData + @see mwConversation_getClientData +*/ +void mwConversation_removeClientData(struct mwConversation *conv); + + +/** close and destroy the conversation and its backing channel, and + call the optional client data cleanup function */ +void mwConversation_free(struct mwConversation *conv); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_IM_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_place.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_place.h new file mode 100644 index 0000000000..e17aa711c5 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_place.h @@ -0,0 +1,148 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_PLACE_H +#define _MW_SRVC_PLACE_H + + +#include <glib/glist.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Type identifier for the place service */ +#define mwService_PLACE 0x80000022 + + +/** @struct mwServicePlace */ +struct mwServicePlace; + + +/** @struct mwPlace */ +struct mwPlace; + + +struct mwPlaceHandler { + void (*opened)(struct mwPlace *place); + void (*closed)(struct mwPlace *place, guint32 code); + + void (*peerJoined)(struct mwPlace *place, + const struct mwIdBlock *peer); + + void (*peerParted)(struct mwPlace *place, + const struct mwIdBlock *peer); + + void (*peerSetAttribute)(struct mwPlace *place, + const struct mwIdBlock *peer, + guint32 attr, struct mwOpaque *o); + + void (*peerUnsetAttribute)(struct mwPlace *place, + const struct mwIdBlock *peer, + guint32 attr); + + void (*message)(struct mwPlace *place, + const struct mwIdBlock *who, + const char *msg); + + void (*clear)(struct mwServicePlace *srvc); +}; + + +enum mwPlacePeerAttribute { + mwPlacePeer_TYPING = 0x00000008, +}; + + +struct mwServicePlace * +mwServicePlace_new(struct mwSession *session, + struct mwPlaceHandler *handler); + + +struct mwPlaceHandler * +mwServicePlace_getHandler(struct mwServicePlace *srvc); + + +const GList *mwServicePlace_getPlaces(struct mwServicePlace *srvc); + + +struct mwPlace *mwPlace_new(struct mwServicePlace *srvc, + const char *name, const char *title); + + +struct mwServicePlace *mwPlace_getService(struct mwPlace *place); + + +const char *mwPlace_getName(struct mwPlace *place); + + +const char *mwPlace_getTitle(struct mwPlace *place); + + +int mwPlace_open(struct mwPlace *place); + + +int mwPlace_destroy(struct mwPlace *place, guint32 code); + + +/** returns a GList* of struct mwIdBlock*. The GList will need to be + freed after use, the mwIdBlock structures should not be modified + or freed */ +GList *mwPlace_getMembers(struct mwPlace *place); + + +int mwPlace_sendText(struct mwPlace *place, const char *msg); + + +/** send a legacy invitation for this place to a user. The user will + receive an apparent invitation from a Conference (rather than a + Place) */ +int mwPlace_legacyInvite(struct mwPlace *place, + struct mwIdBlock *idb, + const char *message); + + +int mwPlace_setAttribute(struct mwPlace *place, guint32 attrib, + struct mwOpaque *data); + + +int mwPlace_unsetAttribute(struct mwPlace *place, guint32 attrib); + + +void mwPlace_setClientData(struct mwPlace *place, + gpointer data, GDestroyNotify clean); + + +gpointer mwPlace_getClientData(struct mwPlace *place); + + +void mwPlace_removeClientData(struct mwPlace *place); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_PLACE_H */ + diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_resolve.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_resolve.h new file mode 100644 index 0000000000..436b20a5d5 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_resolve.h @@ -0,0 +1,155 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_RESOLVE_H +#define _MW_SRVC_RESOLVE_H + + +#include <glib.h> +#include <glib/glist.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Type identifier for the conference service */ +#define mwService_RESOLVE 0x00000015 + + +/** Return value of mwServiceResolve_search indicating an error */ +#define SEARCH_ERROR 0x00 + + +/** @struct mwServiceResolve + User lookup service */ +struct mwServiceResolve; + + +enum mwResolveFlag { + /** return unique results or none at all */ + mwResolveFlag_UNIQUE = 0x00000001, + + /** return only the first result */ + mwResolveFlag_FIRST = 0x00000002, + + /** search all directories, not just the first with a match */ + mwResolveFlag_ALL_DIRS = 0x00000004, + + /** search for users */ + mwResolveFlag_USERS = 0x00000008, + + /** search for groups */ + mwResolveFlag_GROUPS = 0x00000010, +}; + + +/** @see mwResolveResult */ +enum mwResolveCode { + /** successful search */ + mwResolveCode_SUCCESS = 0x00000000, + + /** only some of the nested searches were successful */ + mwResolveCode_PARTIAL = 0x00010000, + + /** more than one result (occurs when mwResolveFlag_UNIQUE is used + and more than one result would have been otherwise returned) */ + mwResolveCode_MULTIPLE = 0x80020000, + + /** the name is not resolvable due to its format */ + mwResolveCode_BAD_FORMAT = 0x80030000, +}; + + +enum mwResolveMatchType { + mwResolveMatch_USER = 0x00000001, + mwResolveMatch_GROUP = 0x00000002, +}; + + +struct mwResolveMatch { + char *id; /**< user id */ + char *name; /**< user name */ + char *desc; /**< description */ + guint32 type; /**< @see mwResolveMatchType */ +}; + + +struct mwResolveResult { + guint32 code; /**< @see mwResolveCode */ + char *name; /**< name of the result */ + GList *matches; /**< list of mwResolveMatch */ +}; + + +/** Handle the results of a resolve request. If there was a cleanup + function specified to mwServiceResolve_search, it will be called + upon the user data after this callback returns. + + @param srvc the resolve service + @param id the resolve request ID + @param code return code + @param results list of mwResolveResult + @param data optional user data attached to the request +*/ +typedef void (*mwResolveHandler) + (struct mwServiceResolve *srvc, + guint32 id, guint32 code, GList *results, + gpointer data); + + +/** Allocate a new resolve service */ +struct mwServiceResolve *mwServiceResolve_new(struct mwSession *); + + +/** Inisitate a resolve request. + + @param srvc the resolve service + @param queries list query strings + @param flags search flags + @param handler result handling function + @param data optional user data attached to the request + @param cleanup optional function to clean up user data + @return generated ID for the search request, or SEARCH_ERROR +*/ +guint32 mwServiceResolve_resolve(struct mwServiceResolve *srvc, + GList *queries, enum mwResolveFlag flags, + mwResolveHandler handler, + gpointer data, GDestroyNotify cleanup); + + +/** Cancel a resolve request by its generated ID. The handler function + will not be called, and the optional cleanup function will be + called upon the optional user data for the request */ +void mwServiceResolve_cancelResolve(struct mwServiceResolve *, guint32); + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceResolve_getService(struct mwServiceResolve *srvc); +/// Miranda NG adaptation end + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_RESOLVE_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_srvc_store.h b/protocols/Sametime/src/meanwhile/src/mw_srvc_store.h new file mode 100644 index 0000000000..b55ddf21fe --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_srvc_store.h @@ -0,0 +1,201 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_SRVC_STORE_H +#define _MW_SRVC_STORE_H + + +#include <glib.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Type identifier for the storage service */ +#define mwService_STORAGE 0x00000018 + + +/** @struct mwServiceStorage + @see mwServiceStorage_new + + Instance of the storage service */ +struct mwServiceStorage; + + +/** @struct mwStorage + + Unit Represents information intended for loading from or saving to + the storage service */ +struct mwStorageUnit; + + +/** The upper limit of reserved Lotus keys */ +#define LOTUS_RESERVED_LIMIT 0x186a0 + + +/** Check if a key is in the range of Lotus reserved keys */ +#define KEY_IS_LOTUS_RESERVED(key) \ + (((guint32) key) <= (LOTUS_RESERVED_LIMIT)) + + +/** Some common keys storage keys. Anything in the range 0x00 to + 0x186a0 (100000) is reserved for use by the Lotus + clients. */ +enum mwStorageKey { + + /** The buddy list, in the Sametime .dat file format. String */ + mwStore_AWARE_LIST = 0x00000000, + + /** Default text for chat invitations. String */ + mwStore_INVITE_CHAT = 0x00000006, + + /** Default text for meeting invitations. String */ + mwStore_INVITE_MEETING = 0x0000000e, + + /** Last five Away messages, separated by semicolon. String */ + mwStore_AWAY_MESSAGES = 0x00000050, + + /** Last five Busy (DND) messages, separated by semicolon. String */ + mwStore_BUSY_MESSAGES = 0x0000005a, + + /** Last five Active messages, separated by semicolon. String */ + mwStore_ACTIVE_MESSAGES = 0x00000064, +}; + + +/** Appropriate function type for load and store callbacks. + @param srvc the storage service + @param result the result value of the load or store call + @param item the storage unit loaded or saved + @param data optional user data +*/ +typedef void (*mwStorageCallback) + (struct mwServiceStorage *srvc, + guint32 result, struct mwStorageUnit *item, + gpointer data); + + +/** Allocates and initializes a storage service instance for use on + the passed session. */ +struct mwServiceStorage *mwServiceStorage_new(struct mwSession *); + + +/** create an empty storage unit */ +struct mwStorageUnit *mwStorageUnit_new(guint32 key); + + +/** creates a storage unit with the passed key, and a copy of data. */ +struct mwStorageUnit *mwStorageUnit_newOpaque(guint32 key, + struct mwOpaque *data); + + +/** creates a storage unit with the passed key, and an encapsulated + boolean value */ +struct mwStorageUnit *mwStorageUnit_newBoolean(guint32 key, + gboolean val); + + +struct mwStorageUnit *mwStorageUnit_newInteger(guint32 key, + guint32 val); + + +/** creates a storage unit with the passed key, and an encapsulated + string value. */ +struct mwStorageUnit *mwStorageUnit_newString(guint32 key, + const char *str); + + +/** get the key for the given storage unit */ +guint32 mwStorageUnit_getKey(struct mwStorageUnit *); + + +/** attempts to obtain a boolean value from a storage unit. If the + unit is empty, or does not contain the type in a recongnizable + format, val is returned instead */ +gboolean mwStorageUnit_asBoolean(struct mwStorageUnit *, gboolean val); + + +/** attempts to obtain a guint32 value from a storage unit. If the + unit is empty, or does not contain the type in a recognizable + format, val is returned instead */ +guint32 mwStorageUnit_asInteger(struct mwStorageUnit *, guint32 val); + + +/** attempts to obtain a string value from a storage unit. If the unit + is empty, or does not contain the type in a recognizable format, + NULL is returned instead. Note that the string returned is a copy, + and will need to be deallocated at some point. */ +char *mwStorageUnit_asString(struct mwStorageUnit *); + + +/** direct access to the opaque data backing the storage unit */ +struct mwOpaque *mwStorageUnit_asOpaque(struct mwStorageUnit *); + + +/** clears and frees a storage unit */ +void mwStorageUnit_free(struct mwStorageUnit *); + + +/** Initiates a load call to the storage service. If the service is + not currently available, the call will be cached and processed + when the service is started. + + @param srvc the storage service + @param item storage unit to load + @param cb callback function when the load call completes + @param data user data for callback + @param data_free optional cleanup function for user data +*/ +void mwServiceStorage_load(struct mwServiceStorage *srvc, + struct mwStorageUnit *item, + mwStorageCallback cb, + gpointer data, GDestroyNotify data_free); + + +/** Initiates a store call to the storage service. If the service is + not currently available, the call will be cached and processed + when the service is started. + + @param srvc the storage service + @param item storage unit to save + @param cb callback function when the load call completes + @param data optional user data for callback + @param data_free optional cleanup function for user data + */ +void mwServiceStorage_save(struct mwServiceStorage *srvc, + struct mwStorageUnit *item, + mwStorageCallback cb, + gpointer data, GDestroyNotify data_free); + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceStorage_getService(struct mwServiceStorage *srvc); +/// Miranda NG adaptation end + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_SRVC_STORE_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_st_list.h b/protocols/Sametime/src/meanwhile/src/mw_st_list.h new file mode 100644 index 0000000000..39e1cbf84b --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_st_list.h @@ -0,0 +1,218 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_ST_LIST_H +#define _MW_ST_LIST_H + + +/** @file mw_st_list.h + + Parse and compose buddy lists in the format commonly used by Sametime + Connect clients. +*/ + + +#include <glib.h> +#include <glib/glist.h> +#include "mw_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ST_LIST_MAJOR 3 +#define ST_LIST_MINOR 1 +#define ST_LIST_MICRO 3 + + +enum mwSametimeGroupType { + mwSametimeGroup_NORMAL = 1, /**< a normal group of users */ + mwSametimeGroup_DYNAMIC = 2, /**< a server-side group */ + mwSametimeGroup_UNKNOWN = 0, /**< error determining group type */ +}; + + +enum mwSametimeUserType { + mwSametimeUser_NORMAL = 1, /**< user on same community */ + mwSametimeUser_EXTERNAL = 2, /**< external user */ + mwSametimeUser_UNKNOWN = 0, /**< error determining user type */ +}; + + +/** @struct mwSametimeList + + Represents a group-based buddy list. */ +struct mwSametimeList; + + +/** @struct mwSametimeGroup + + Represents a group in a buddy list */ +struct mwSametimeGroup; + + +/** @struct mwSametimeUser + + Represents a user in a group in a buddy list */ +struct mwSametimeUser; + + +/** Create a new list */ +struct mwSametimeList *mwSametimeList_new(); + + +/** Free the list, all of its groups, and all of the groups' members */ +void mwSametimeList_free(struct mwSametimeList *l); + + +/** Load a sametime list from a buffer. The list must be encapsulated + as a string (eg, the first two bytes in the buffer should be the + length of the string) */ +void mwSametimeList_get(struct mwGetBuffer *b, struct mwSametimeList *l); + + +/** Write a sametime list onto a buffer. The list will be encapsulated + in a string (the first two bytes written will be the length of the + rest of the written list data) */ +void mwSametimeList_put(struct mwPutBuffer *b, struct mwSametimeList *l); + + +/** convert a plain string into a sametime list */ +struct mwSametimeList *mwSametimeList_load(const char *str); + + +/** convert a sametime list into a string */ +char *mwSametimeList_store(struct mwSametimeList *l); + + +void mwSametimeList_setMajor(struct mwSametimeList *l, guint v); + + +guint mwSametimeList_getMajor(struct mwSametimeList *l); + + +void mwSametimeList_setMinor(struct mwSametimeList *l, guint v); + + +guint mwSametimeList_getMinor(struct mwSametimeList *l); + + +void mwSametimeList_setMicro(struct mwSametimeList *l, guint v); + + +guint mwSametimeList_getMicro(struct mwSametimeList *l); + + +/** Get a GList snapshot of the groups in a list */ +GList *mwSametimeList_getGroups(struct mwSametimeList *l); + + +struct mwSametimeGroup * +mwSametimeList_findGroup(struct mwSametimeList *l, + const char *name); + + +/** Create a new group in a list */ +struct mwSametimeGroup * +mwSametimeGroup_new(struct mwSametimeList *l, + enum mwSametimeGroupType type, + const char *name); + + +/** Remove a group from its list, and free it. Also frees all users + contained in the group */ +void mwSametimeGroup_free(struct mwSametimeGroup *g); + + +enum mwSametimeGroupType mwSametimeGroup_getType(struct mwSametimeGroup *g); + + +const char *mwSametimeGroup_getName(struct mwSametimeGroup *g); + + +void mwSametimeGroup_setAlias(struct mwSametimeGroup *g, + const char *alias); + + +const char *mwSametimeGroup_getAlias(struct mwSametimeGroup *g); + + +void mwSametimeGroup_setOpen(struct mwSametimeGroup *g, gboolean open); + + +gboolean mwSametimeGroup_isOpen(struct mwSametimeGroup *g); + + +struct mwSametimeList *mwSametimeGroup_getList(struct mwSametimeGroup *g); + + +/** Get a GList snapshot of the users in a list */ +GList *mwSametimeGroup_getUsers(struct mwSametimeGroup *g); + + +struct mwSametimeUser * +mwSametimeGroup_findUser(struct mwSametimeGroup *g, + struct mwIdBlock *user); + + +/** Create a user in a group */ +struct mwSametimeUser * +mwSametimeUser_new(struct mwSametimeGroup *g, + enum mwSametimeUserType type, + struct mwIdBlock *user); + + +/** Remove user from its group, and free it */ +void mwSametimeUser_free(struct mwSametimeUser *u); + + +struct mwSametimeGroup *mwSametimeUser_getGroup(struct mwSametimeUser *u); + + +enum mwSametimeUserType mwSametimeUser_getType(struct mwSametimeUser *u); + + +const char *mwSametimeUser_getUser(struct mwSametimeUser *u); + + +const char *mwSametimeUser_getCommunity(struct mwSametimeUser *u); + + +void mwSametimeUser_setShortName(struct mwSametimeUser *u, const char *name); + + +const char *mwSametimeUser_getShortName(struct mwSametimeUser *u); + + +void mwSametimeUser_setAlias(struct mwSametimeUser *u, const char *alias); + + +const char *mwSametimeUser_getAlias(struct mwSametimeUser *u); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MW_ST_LIST_H */ diff --git a/protocols/Sametime/src/meanwhile/src/mw_util.c b/protocols/Sametime/src/meanwhile/src/mw_util.c new file mode 100644 index 0000000000..57c1845b38 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_util.c @@ -0,0 +1,80 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mw_util.h" + + +static void collect_keys(gpointer key, gpointer val, gpointer data) { + GList **list = data; + *list = g_list_append(*list, key); +} + + +GList *map_collect_keys(GHashTable *ht) { + GList *ret = NULL; + g_hash_table_foreach(ht, collect_keys, &ret); + return ret; +} + + +static void collect_values(gpointer key, gpointer val, gpointer data) { + GList **list = data; + *list = g_list_append(*list, val); +} + + +GList *map_collect_values(GHashTable *ht) { + GList *ret = NULL; + g_hash_table_foreach(ht, collect_values, &ret); + return ret; +} + + +struct mw_datum *mw_datum_new(gpointer data, GDestroyNotify clear) { + struct mw_datum *d = g_new(struct mw_datum, 1); + mw_datum_set(d, data, clear); + return d; +} + + +void mw_datum_set(struct mw_datum *d, gpointer data, GDestroyNotify clear) { + d->data = data; + d->clear = clear; +} + + +gpointer mw_datum_get(struct mw_datum *d) { + return d->data; +} + + +void mw_datum_clear(struct mw_datum *d) { + if(d->clear) { + d->clear(d->data); + d->clear = NULL; + } + d->data = NULL; +} + + +void mw_datum_free(struct mw_datum *d) { + mw_datum_clear(d); + g_free(d); +} diff --git a/protocols/Sametime/src/meanwhile/src/mw_util.h b/protocols/Sametime/src/meanwhile/src/mw_util.h new file mode 100644 index 0000000000..b8e0b7e968 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/mw_util.h @@ -0,0 +1,85 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MW_UTIL_H +#define _MW_UTIL_H + + +#include <glib.h> +#include <glib/ghash.h> +#include <glib/glist.h> + + +#define map_guint_new() \ + g_hash_table_new(g_direct_hash, g_direct_equal) + + +#define map_guint_new_full(valfree) \ + g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (valfree)) + + +#define map_guint_insert(ht, key, val) \ + g_hash_table_insert((ht), GUINT_TO_POINTER((guint)(key)), (val)) + + +#define map_guint_replace(ht, key, val) \ + g_hash_table_replace((ht), GUINT_TO_POINTER((guint)(key)), (val)) + + +#define map_guint_lookup(ht, key) \ + g_hash_table_lookup((ht), GUINT_TO_POINTER((guint)(key))) + + +#define map_guint_remove(ht, key) \ + g_hash_table_remove((ht), GUINT_TO_POINTER((guint)(key))) + + +#define map_guint_steal(ht, key) \ + g_hash_table_steal((ht), GUINT_TO_POINTER((guint)(key))) + + +GList *map_collect_keys(GHashTable *ht); + + +GList *map_collect_values(GHashTable *ht); + + +struct mw_datum { + gpointer data; + GDestroyNotify clear; +}; + + +struct mw_datum *mw_datum_new(gpointer data, GDestroyNotify clear); + + +void mw_datum_set(struct mw_datum *d, gpointer data, GDestroyNotify clear); + + +gpointer mw_datum_get(struct mw_datum *d); + + +void mw_datum_clear(struct mw_datum *d); + + +void mw_datum_free(struct mw_datum *d); + + +#endif diff --git a/protocols/Sametime/src/meanwhile/src/service.c b/protocols/Sametime/src/meanwhile/src/service.c new file mode 100644 index 0000000000..9ff8d8639f --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/service.c @@ -0,0 +1,267 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mw_channel.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" + + +/* I tried to be explicit with the g_return_* calls, to make the debug + logging a bit more sensible. Hence all the explicit "foo != NULL" + checks. */ + + +void mwService_recvCreate(struct mwService *s, struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + /* ensure none are null, ensure that the service and channel belong + to the same session, and ensure that the message belongs on the + channel */ + g_return_if_fail(s != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(s->session == mwChannel_getSession(chan)); + g_return_if_fail(mwChannel_getId(chan) == msg->channel); + + if(s->recv_create) { + s->recv_create(s, chan, msg); + } else { + mwChannel_destroy(chan, ERR_FAILURE, NULL); + } +} + + +void mwService_recvAccept(struct mwService *s, struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + /* ensure none are null, ensure that the service and channel belong + to the same session, and ensure that the message belongs on the + channel */ + g_return_if_fail(s != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(s->session == mwChannel_getSession(chan)); + g_return_if_fail(mwChannel_getId(chan) == msg->head.channel); + + if(s->recv_accept) + s->recv_accept(s, chan, msg); +} + + +void mwService_recvDestroy(struct mwService *s, struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + /* ensure none are null, ensure that the service and channel belong + to the same session, and ensure that the message belongs on the + channel */ + g_return_if_fail(s != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(s->session == mwChannel_getSession(chan)); + g_return_if_fail(mwChannel_getId(chan) == msg->head.channel); + + if(s->recv_destroy) + s->recv_destroy(s, chan, msg); +} + + +void mwService_recv(struct mwService *s, struct mwChannel *chan, + guint16 msg_type, struct mwOpaque *data) { + + /* ensure that none are null. zero-length messages are acceptable */ + g_return_if_fail(s != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(data != NULL); + g_return_if_fail(s->session == mwChannel_getSession(chan)); + + /* + g_message("mwService_recv: session = %p, service = %p, b = %p, n = %u", + mwService_getSession(s), s, data->data, data->len); + */ + + if(s->recv) + s->recv(s, chan, msg_type, data); +} + + +guint32 mwService_getType(struct mwService *s) { + g_return_val_if_fail(s != NULL, 0x00); + return s->type; +} + + +const char *mwService_getName(struct mwService *s) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->get_name != NULL, NULL); + + return s->get_name(s); +} + + +const char *mwService_getDesc(struct mwService *s) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->get_desc != NULL, NULL); + + return s->get_desc(s); +} + + +struct mwSession *mwService_getSession(struct mwService *s) { + g_return_val_if_fail(s != NULL, NULL); + return s->session; +} + + +void mwService_init(struct mwService *srvc, struct mwSession *sess, + guint32 type) { + + /* ensure nothing is null, and there's no such thing as a zero + service type */ + g_return_if_fail(srvc != NULL); + g_return_if_fail(sess != NULL); + g_return_if_fail(type != 0x00); + + srvc->session = sess; + srvc->type = type; + srvc->state = mwServiceState_STOPPED; +} + + +enum mwServiceState mwService_getState(struct mwService *srvc) { + g_return_val_if_fail(srvc != NULL, mwServiceState_STOPPED); + return srvc->state; +} + + +void mwService_start(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + if(! MW_SERVICE_IS_STOPPED(srvc)) + return; + + srvc->state = mwServiceState_STARTING; + g_message("starting service %s", NSTR(mwService_getName(srvc))); + + if(srvc->start) { + srvc->start(srvc); + } else { + mwService_started(srvc); + } +} + + +void mwService_started(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + srvc->state = mwServiceState_STARTED; + g_message("started service %s", NSTR(mwService_getName(srvc))); +} + + +void mwService_error(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + if(MW_SERVICE_IS_DEAD(srvc)) + return; + + srvc->state = mwServiceState_ERROR; + g_message("error in service %s", NSTR(mwService_getName(srvc))); + + if(srvc->stop) { + srvc->stop(srvc); + } else { + mwService_stopped(srvc); + } +} + + +void mwService_stop(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + if(MW_SERVICE_IS_DEAD(srvc)) + return; + + srvc->state = mwServiceState_STOPPING; + g_message("stopping service %s", NSTR(mwService_getName(srvc))); + + if(srvc->stop) { + srvc->stop(srvc); + } else { + mwService_stopped(srvc); + } +} + + +void mwService_stopped(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + if(srvc->state != mwServiceState_STOPPED) { + srvc->state = mwServiceState_STOPPED; + g_message("stopped service %s", NSTR(mwService_getName(srvc))); + } +} + + +void mwService_free(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + mwService_stop(srvc); + + if(srvc->clear) + srvc->clear(srvc); + + if(srvc->client_cleanup) + srvc->client_cleanup(srvc->client_data); + + g_free(srvc); +} + + +/** @todo switch the following to using mw_datum */ + +void mwService_setClientData(struct mwService *srvc, + gpointer data, GDestroyNotify cleanup) { + + g_return_if_fail(srvc != NULL); + + srvc->client_data = data; + srvc->client_cleanup = cleanup; +} + + +gpointer mwService_getClientData(struct mwService *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->client_data; +} + + +void mwService_removeClientData(struct mwService *srvc) { + g_return_if_fail(srvc != NULL); + + if(srvc->client_cleanup) { + srvc->client_cleanup(srvc->client_data); + srvc->client_cleanup = NULL; + } + + srvc->client_data = NULL; +} + diff --git a/protocols/Sametime/src/meanwhile/src/session.c b/protocols/Sametime/src/meanwhile/src/session.c new file mode 100644 index 0000000000..6c116b7a58 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/session.c @@ -0,0 +1,1220 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <string.h> + +#include "mw_channel.h" +#include "mw_cipher.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_util.h" + + +/** the hash table key for a service, for mwSession::services */ +#define SERVICE_KEY(srvc) mwService_getType(srvc) + +/** the hash table key for a cipher, for mwSession::ciphers */ +#define CIPHER_KEY(ciph) mwCipher_getType(ciph) + + +#define GPOINTER(val) (GUINT_TO_POINTER((guint) (val))) +#define GUINT(val) (GPOINTER_TO_UINT((val))) + + +struct mwSession { + + /** provides I/O and callback functions */ + struct mwSessionHandler *handler; + + enum mwSessionState state; /**< session state */ + gpointer state_info; /**< additional state info */ + + /* input buffering for an incoming message */ + guchar *buf; /**< buffer for incoming message data */ + gsize buf_len; /**< length of buf */ + gsize buf_used; /**< offset to last-used byte of buf */ + + struct mwLoginInfo login; /**< login information */ + struct mwUserStatus status; /**< user status */ + struct mwPrivacyInfo privacy; /**< privacy list */ + + /** the collection of channels */ + struct mwChannelSet *channels; + + /** the collection of services, keyed to guint32 service id */ + GHashTable *services; + + /** the collection of ciphers, keyed to guint16 cipher type */ + GHashTable *ciphers; + + /** arbitrary key:value pairs */ + GHashTable *attributes; + + /** optional user data */ + struct mw_datum client_data; +}; + + +static void property_set(struct mwSession *s, const char *key, + gpointer val, GDestroyNotify clean) { + + g_hash_table_insert(s->attributes, g_strdup(key), + mw_datum_new(val, clean)); +} + + +static gpointer property_get(struct mwSession *s, const char *key) { + struct mw_datum *p = g_hash_table_lookup(s->attributes, key); + return p? p->data: NULL; +} + + +static void property_del(struct mwSession *s, const char *key) { + g_hash_table_remove(s->attributes, key); +} + + +/** + set up the default properties for a newly created session +*/ +static void session_defaults(struct mwSession *s) { + property_set(s, mwSession_CLIENT_VER_MAJOR, + GPOINTER(MW_PROTOCOL_VERSION_MAJOR), NULL); + + property_set(s, mwSession_CLIENT_VER_MINOR, + GPOINTER(MW_PROTOCOL_VERSION_MINOR), NULL); + + property_set(s, mwSession_CLIENT_TYPE_ID, + GPOINTER(mwLogin_MEANWHILE), NULL); +} + + +struct mwSession *mwSession_new(struct mwSessionHandler *handler) { + struct mwSession *s; + + g_return_val_if_fail(handler != NULL, NULL); + + /* consider io_write and io_close to be absolute necessities */ + g_return_val_if_fail(handler->io_write != NULL, NULL); + g_return_val_if_fail(handler->io_close != NULL, NULL); + + s = g_new0(struct mwSession, 1); + + s->state = mwSession_STOPPED; + + s->handler = handler; + + s->channels = mwChannelSet_new(s); + s->services = map_guint_new(); + s->ciphers = map_guint_new(); + + s->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify) mw_datum_free); + + session_defaults(s); + + return s; +} + + +/** free and reset the session buffer */ +static void session_buf_free(struct mwSession *s) { + g_return_if_fail(s != NULL); + + g_free(s->buf); + s->buf = NULL; + s->buf_len = 0; + s->buf_used = 0; +} + + +/** a polite string version of the session state enum */ +static const char *state_str(enum mwSessionState state) { + switch(state) { + case mwSession_STARTING: return "starting"; + case mwSession_HANDSHAKE: return "handshake sent"; + case mwSession_HANDSHAKE_ACK: return "handshake acknowledged"; + case mwSession_LOGIN: return "login sent"; + case mwSession_LOGIN_REDIR: return "login redirected"; + case mwSession_LOGIN_CONT: return "forcing login"; + case mwSession_LOGIN_ACK: return "login acknowledged"; + case mwSession_STARTED: return "started"; + case mwSession_STOPPING: return "stopping"; + case mwSession_STOPPED: return "stopped"; + + case mwSession_UNKNOWN: /* fall-through */ + default: return "UNKNOWN"; + } +} + + +void mwSession_free(struct mwSession *s) { + struct mwSessionHandler *h; + + g_return_if_fail(s != NULL); + + if(! mwSession_isStopped(s)) { + g_debug("session is not stopped (state: %s), proceeding with free", + state_str(s->state)); + } + + h = s->handler; + if(h && h->clear) h->clear(s); + s->handler = NULL; + + session_buf_free(s); + + mwChannelSet_free(s->channels); + g_hash_table_destroy(s->services); + g_hash_table_destroy(s->ciphers); + g_hash_table_destroy(s->attributes); + + mwLoginInfo_clear(&s->login); + mwUserStatus_clear(&s->status); + mwPrivacyInfo_clear(&s->privacy); + + g_free(s); +} + + +/** write data to the session handler */ +static int io_write(struct mwSession *s, const guchar *buf, gsize len) { + g_return_val_if_fail(s != NULL, -1); + g_return_val_if_fail(s->handler != NULL, -1); + g_return_val_if_fail(s->handler->io_write != NULL, -1); + + return s->handler->io_write(s, buf, len); +} + + +/** close the session handler */ +static void io_close(struct mwSession *s) { + g_return_if_fail(s != NULL); + g_return_if_fail(s->handler != NULL); + g_return_if_fail(s->handler->io_close != NULL); + + s->handler->io_close(s); +} + + +static void state(struct mwSession *s, enum mwSessionState state, + gpointer info) { + + struct mwSessionHandler *sh; + + g_return_if_fail(s != NULL); + g_return_if_fail(s->handler != NULL); + + if(mwSession_isState(s, state)) return; + + s->state = state; + s->state_info = info; + + switch(state) { + case mwSession_STOPPING: + case mwSession_STOPPED: + g_message("session state: %s (0x%08x)", state_str(state), + GPOINTER_TO_UINT(info)); + break; + + case mwSession_LOGIN_REDIR: + /// Miranda NG adaptation - start - https://developer.pidgin.im/ticket/7563#comment:4 + //g_message("session state: %s (%s)", state_str(state), (char *)info); + g_message("session state: %s (%s)", state_str(state), NSTR((char *)info)); + /// Miranda NG adaptation - end + break; + + default: + g_message("session state: %s", state_str(state)); + } + + sh = s->handler; + if(sh && sh->on_stateChange) + sh->on_stateChange(s, state, info); +} + + +void mwSession_start(struct mwSession *s) { + struct mwMsgHandshake *msg; + int ret; + + g_return_if_fail(s != NULL); + g_return_if_fail(mwSession_isStopped(s)); + + if(mwSession_isStarted(s) || mwSession_isStarting(s)) { + g_debug("attempted to start session that is already started/starting"); + return; + } + + state(s, mwSession_STARTING, 0); + + msg = (struct mwMsgHandshake *) mwMessage_new(mwMessage_HANDSHAKE); + msg->major = GUINT(property_get(s, mwSession_CLIENT_VER_MAJOR)); + msg->minor = GUINT(property_get(s, mwSession_CLIENT_VER_MINOR)); + msg->login_type = GUINT(property_get(s, mwSession_CLIENT_TYPE_ID)); + + msg->loclcalc_addr = GUINT(property_get(s, mwSession_CLIENT_IP)); + + if(msg->major >= 0x001e && msg->minor >= 0x001d) { + msg->unknown_a = 0x0100; + msg->local_host = property_get(s, mwSession_CLIENT_HOST); + } + + ret = mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + if(ret) { + mwSession_stop(s, CONNECTION_BROKEN); + } else { + state(s, mwSession_HANDSHAKE, 0); + } +} + + +void mwSession_stop(struct mwSession *s, guint32 reason) { + GList *list, *l = NULL; + struct mwMsgChannelDestroy *msg; + + g_return_if_fail(s != NULL); + + if(mwSession_isStopped(s) || mwSession_isStopping(s)) { + g_debug("attempted to stop session that is already stopped/stopping"); + return; + } + + state(s, mwSession_STOPPING, GUINT_TO_POINTER(reason)); + + for(list = l = mwSession_getServices(s); l; l = l->next) + mwService_stop(MW_SERVICE(l->data)); + g_list_free(list); + + msg = (struct mwMsgChannelDestroy *) + mwMessage_new(mwMessage_CHANNEL_DESTROY); + + msg->head.channel = MW_MASTER_CHANNEL_ID; + msg->reason = reason; + + /* don't care if this fails, we're closing the connection anyway */ + mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + session_buf_free(s); + + /* close the connection */ + io_close(s); + + state(s, mwSession_STOPPED, GUINT_TO_POINTER(reason)); +} + + +/** compose authentication information into an opaque based on the + password, encrypted via RC2/40 */ +static void compose_auth_rc2_40(struct mwOpaque *auth, const char *pass) { + guchar iv[8], key[5]; + struct mwOpaque a, b, z; + struct mwPutBuffer *p; + + /* get an IV and a random five-byte key */ + mwIV_init(iv); + mwKeyRandom(key, 5); + + /* the opaque with the key */ + a.len = 5; + a.data = key; + + /* the opaque to receive the encrypted pass */ + b.len = 0; + b.data = NULL; + + /* the plain-text pass dressed up as an opaque */ + z.len = strlen(pass); + z.data = (guchar *) pass; + + /* the opaque with the encrypted pass */ + mwEncrypt(a.data, a.len, iv, &z, &b); + + /* an opaque containing the other two opaques */ + p = mwPutBuffer_new(); + mwOpaque_put(p, &a); + mwOpaque_put(p, &b); + mwPutBuffer_finalize(auth, p); + + /* this is the only one to clear, as the other uses a static buffer */ + mwOpaque_clear(&b); +} + + +static void compose_auth_rc2_128(struct mwOpaque *auth, const char *pass, + guint32 magic, struct mwOpaque *rkey) { + + guchar iv[8]; + struct mwOpaque a, b, c; + struct mwPutBuffer *p; + + struct mwMpi *private, *public; + struct mwMpi *remote; + struct mwMpi *shared; + + private = mwMpi_new(); + public = mwMpi_new(); + remote = mwMpi_new(); + shared = mwMpi_new(); + + mwIV_init(iv); + + mwMpi_randDHKeypair(private, public); + mwMpi_import(remote, rkey); + mwMpi_calculateDHShared(shared, remote, private); + + /* put the password in opaque a */ + p = mwPutBuffer_new(); + guint32_put(p, magic); + mwString_put(p, pass); + mwPutBuffer_finalize(&a, p); + + /* put the shared key in opaque b */ + mwMpi_export(shared, &b); + + /* encrypt the password (a) using the shared key (b), put the result + in opaque c */ + mwEncrypt(b.data+(b.len-16), 16, iv, &a, &c); + + /* don't need the shared key anymore, re-use opaque (b) as the + export of the public key */ + mwOpaque_clear(&b); + mwMpi_export(public, &b); + + p = mwPutBuffer_new(); + guint16_put(p, 0x0001); /* XXX: unknown */ + mwOpaque_put(p, &b); + mwOpaque_put(p, &c); + mwPutBuffer_finalize(auth, p); + + mwOpaque_clear(&a); + mwOpaque_clear(&b); + mwOpaque_clear(&c); + + mwMpi_free(private); + mwMpi_free(public); + mwMpi_free(remote); + mwMpi_free(shared); +} + + +/** handle the receipt of a handshake_ack message by sending the login + message */ +static void HANDSHAKE_ACK_recv(struct mwSession *s, + struct mwMsgHandshakeAck *msg) { + struct mwMsgLogin *log; + int ret; + + g_return_if_fail(s != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(mwSession_isState(s, mwSession_HANDSHAKE) || + mwSession_isState(s, mwSession_LOGIN_CONT)); + + if(mwSession_isState(s, mwSession_LOGIN_CONT)) { + /* this is a login continuation, don't re-send the login. We + should receive a login ack in a moment */ + + state(s, mwSession_HANDSHAKE_ACK, 0); + state(s, mwSession_LOGIN, 0); + return; + + } else { + state(s, mwSession_HANDSHAKE_ACK, 0); + } + + /* record the major/minor versions from the server */ + property_set(s, mwSession_SERVER_VER_MAJOR, GPOINTER(msg->major), NULL); + property_set(s, mwSession_SERVER_VER_MINOR, GPOINTER(msg->minor), NULL); + + /* compose the login message */ + log = (struct mwMsgLogin *) mwMessage_new(mwMessage_LOGIN); + log->login_type = GUINT(property_get(s, mwSession_CLIENT_TYPE_ID)); + log->name = g_strdup(property_get(s, mwSession_AUTH_USER_ID)); + + /** @todo default to password for now. later use token optionally */ + { + const char *pw; + pw = property_get(s, mwSession_AUTH_PASSWORD); + + if(msg->data.len >= 64) { + /* good login encryption */ + log->auth_type = mwAuthType_RC2_128; + compose_auth_rc2_128(&log->auth_data, pw, msg->magic, &msg->data); + + } else { + /* BAD login encryption */ + log->auth_type = mwAuthType_RC2_40; + compose_auth_rc2_40(&log->auth_data, pw); + } + } + + /* send the login message */ + ret = mwSession_send(s, MW_MESSAGE(log)); + mwMessage_free(MW_MESSAGE(log)); + + if(! ret) { + /* sent login OK, set state appropriately */ + state(s, mwSession_LOGIN, 0); + } +} + + +/** handle the receipt of a login_ack message. This completes the + startup sequence for the session */ +static void LOGIN_ACK_recv(struct mwSession *s, + struct mwMsgLoginAck *msg) { + GList *ll, *l; + + g_return_if_fail(s != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(mwSession_isState(s, mwSession_LOGIN)); + + /* store the login information in the session */ + mwLoginInfo_clear(&s->login); + mwLoginInfo_clone(&s->login, &msg->login); + + state(s, mwSession_LOGIN_ACK, 0); + + /* start up our services */ + for(ll = l = mwSession_getServices(s); l; l = l->next) { + mwService_start(l->data); + } + g_list_free(ll); + + /* @todo any further startup stuff? */ + + state(s, mwSession_STARTED, 0); +} + + +static void CHANNEL_CREATE_recv(struct mwSession *s, + struct mwMsgChannelCreate *msg) { + struct mwChannel *chan; + chan = mwChannel_newIncoming(s->channels, msg->channel); + + /* hand off to channel */ + mwChannel_recvCreate(chan, msg); +} + + +static void CHANNEL_ACCEPT_recv(struct mwSession *s, + struct mwMsgChannelAccept *msg) { + struct mwChannel *chan; + chan = mwChannel_find(s->channels, msg->head.channel); + + g_return_if_fail(chan != NULL); + + /* hand off to channel */ + mwChannel_recvAccept(chan, msg); +} + + +static void CHANNEL_DESTROY_recv(struct mwSession *s, + struct mwMsgChannelDestroy *msg) { + + /* the server can indicate that we should close the session by + destroying the zero channel */ + if(msg->head.channel == MW_MASTER_CHANNEL_ID) { + mwSession_stop(s, msg->reason); + + } else { + struct mwChannel *chan; + chan = mwChannel_find(s->channels, msg->head.channel); + + /* we don't have any such channel... so I guess we destroyed it. + This is to remove a warning from timing errors when two clients + both try to close a channel at about the same time. */ + if(! chan) return; + + /* hand off to channel */ + mwChannel_recvDestroy(chan, msg); + } +} + + +static void CHANNEL_SEND_recv(struct mwSession *s, + struct mwMsgChannelSend *msg) { + struct mwChannel *chan; + chan = mwChannel_find(s->channels, msg->head.channel); + + /* if we don't have any such channel, we're certainly not going to + accept data from it */ + if(! chan) return; + + /* hand off to channel */ + mwChannel_recv(chan, msg); +} + + +static void SET_PRIVACY_LIST_recv(struct mwSession *s, + struct mwMsgSetPrivacyList *msg) { + struct mwSessionHandler *sh = s->handler; + + /// Miranda NG adaptation start - MSVC + ///g_info("SET_PRIVACY_LIST"); + g_message("SET_PRIVACY_LIST"); + /// Miranda NG adaptation end + + mwPrivacyInfo_clear(&s->privacy); + mwPrivacyInfo_clone(&s->privacy, &msg->privacy); + + if(sh && sh->on_setPrivacyInfo) + sh->on_setPrivacyInfo(s); +} + + +static void SET_USER_STATUS_recv(struct mwSession *s, + struct mwMsgSetUserStatus *msg) { + struct mwSessionHandler *sh = s->handler; + + mwUserStatus_clear(&s->status); + mwUserStatus_clone(&s->status, &msg->status); + + if(sh && sh->on_setUserStatus) + sh->on_setUserStatus(s); +} + + +static void SENSE_SERVICE_recv(struct mwSession *s, + struct mwMsgSenseService *msg) { + struct mwService *srvc; + + srvc = mwSession_getService(s, msg->service); + if(srvc) mwService_start(srvc); +} + + +static void ADMIN_recv(struct mwSession *s, struct mwMsgAdmin *msg) { + struct mwSessionHandler *sh = s->handler; + + if(sh && sh->on_admin) + sh->on_admin(s, msg->text); +} + + +static void ANNOUNCE_recv(struct mwSession *s, struct mwMsgAnnounce *msg) { + struct mwSessionHandler *sh = s->handler; + + if(sh && sh->on_announce) + sh->on_announce(s, &msg->sender, msg->may_reply, msg->text); +} + + +static void LOGIN_REDIRECT_recv(struct mwSession *s, + struct mwMsgLoginRedirect *msg) { + + state(s, mwSession_LOGIN_REDIR, msg->host); +} + + +#define CASE(var, type) \ +case mwMessage_ ## var: \ + var ## _recv(s, (struct type *) msg); \ + break; + + +static void session_process(struct mwSession *s, + const guchar *buf, gsize len) { + + /// Miranda NG adaptation start - MSVC + /// struct mwOpaque o = { .len = len, .data = (guchar *) buf }; + struct mwOpaque o; + /// Miranda NG adaptation end + + struct mwGetBuffer *b; + struct mwMessage *msg; + + /// Miranda NG adaptation start - MSVC + o.len = len; + o.data = (guchar*) buf; + /// Miranda NG adaptation end + + g_return_if_fail(s != NULL); + g_return_if_fail(buf != NULL); + + /* ignore zero-length messages */ + if(len == 0) return; + + /* wrap up buf */ + b = mwGetBuffer_wrap(&o); + + /* attempt to parse the message. */ + msg = mwMessage_get(b); + + if(mwGetBuffer_error(b)) { + mw_mailme_opaque(&o, "parsing of message failed"); + } + + mwGetBuffer_free(b); + + g_return_if_fail(msg != NULL); + + /* handle each of the appropriate incoming types of mwMessage */ + switch(msg->type) { + CASE(HANDSHAKE_ACK, mwMsgHandshakeAck); + CASE(LOGIN_REDIRECT, mwMsgLoginRedirect); + CASE(LOGIN_ACK, mwMsgLoginAck); + CASE(CHANNEL_CREATE, mwMsgChannelCreate); + CASE(CHANNEL_DESTROY, mwMsgChannelDestroy); + CASE(CHANNEL_SEND, mwMsgChannelSend); + CASE(CHANNEL_ACCEPT, mwMsgChannelAccept); + CASE(SET_PRIVACY_LIST, mwMsgSetPrivacyList); + CASE(SET_USER_STATUS, mwMsgSetUserStatus); + CASE(SENSE_SERVICE, mwMsgSenseService); + CASE(ADMIN, mwMsgAdmin); + CASE(ANNOUNCE, mwMsgAnnounce); + + default: + g_warning("unknown message type 0x%04x, no handler", msg->type); + } + + mwMessage_free(msg); +} + + +#undef CASE + + +#define ADVANCE(b, n, count) { b += count; n -= count; } + + +/* handle input to complete an existing buffer */ +static gsize session_recv_cont(struct mwSession *s, + const guchar *b, gsize n) { + + /* determine how many bytes still required */ + gsize x = s->buf_len - s->buf_used; + + /* g_message(" session_recv_cont: session = %p, b = %p, n = %u", + s, b, n); */ + + if(n < x) { + /* not quite enough; still need some more */ + memcpy(s->buf+s->buf_used, b, n); + s->buf_used += n; + return 0; + + } else { + /* enough to finish the buffer, at least */ + memcpy(s->buf+s->buf_used, b, x); + ADVANCE(b, n, x); + + if(s->buf_len == 4) { + /* if only the length bytes were being buffered, we'll now try + to complete an actual message */ + + struct mwOpaque o = { 4, s->buf }; + struct mwGetBuffer *gb = mwGetBuffer_wrap(&o); + x = guint32_peek(gb); + mwGetBuffer_free(gb); + + if(n < x) { + /* there isn't enough to meet the demands of the length, so + we'll buffer it for next time */ + + guchar *t; + x += 4; + t = (guchar *) g_malloc(x); + memcpy(t, s->buf, 4); + memcpy(t+4, b, n); + + session_buf_free(s); + + s->buf = t; + s->buf_len = x; + s->buf_used = n + 4; + return 0; + + } else { + /* there's enough (maybe more) for a full message. don't need + the old session buffer (which recall, was only the length + bytes) any more */ + + session_buf_free(s); + session_process(s, b, x); + ADVANCE(b, n, x); + } + + } else { + /* process the now-complete buffer. remember to skip the first + four bytes, since they're just the size count */ + session_process(s, s->buf+4, s->buf_len-4); + session_buf_free(s); + } + } + + return n; +} + + +/* handle input when there's nothing previously buffered */ +static gsize session_recv_empty(struct mwSession *s, + const guchar *b, gsize n) { + + struct mwOpaque o = { n, (guchar *) b }; + struct mwGetBuffer *gb; + gsize x; + + if(n < 4) { + /* uh oh. less than four bytes means we've got an incomplete + length indicator. Have to buffer to get the rest of it. */ + s->buf = (guchar *) g_malloc0(4); + memcpy(s->buf, b, n); + s->buf_len = 4; + s->buf_used = n; + return 0; + } + + /* peek at the length indicator. if it's a zero length message, + don't process, just skip it */ + gb = mwGetBuffer_wrap(&o); + x = guint32_peek(gb); + mwGetBuffer_free(gb); + if(! x) return n - 4; + + if(n < (x + 4)) { + /* if the total amount of data isn't enough to cover the length + bytes and the length indicated by those bytes, then we'll need + to buffer. This is where the DOS mentioned below in + session_recv takes place */ + + x += 4; + s->buf = (guchar *) g_malloc(x); + memcpy(s->buf, b, n); + s->buf_len = x; + s->buf_used = n; + return 0; + + } else { + /* advance past length bytes */ + ADVANCE(b, n, 4); + + /* process and advance */ + session_process(s, b, x); + ADVANCE(b, n, x); + + /* return left-over count */ + return n; + } +} + + +static gsize session_recv(struct mwSession *s, + const guchar *b, gsize n) { + + /* This is messy and kind of confusing. I'd like to simplify it at + some point, but the constraints are as follows: + + - buffer up to a single full message on the session buffer + - buffer must contain the four length bytes + - the four length bytes indicate how much we'll need to buffer + - the four length bytes might not arrive all at once, so it's + possible that we'll need to buffer to get them. + - since our buffering includes the length bytes, we know we + still have an incomplete length if the buffer length is only + four. */ + + /** @todo we should allow a compiled-in upper limit to message + sizes, and just drop messages over that size. However, to do that + we'd need to keep track of the size of a message and keep + dropping bytes until we'd fulfilled the entire length. eg: if we + receive a message size of 10MB, we need to pass up exactly 10MB + before it's safe to start processing the rest as a new + message. As it stands, a malicious packet from the server can run + us out of memory by indicating it's going to send us some + obscenely long message (even if it never actually sends it) */ + + /* g_message(" session_recv: session = %p, b = %p, n = %u", + s, b, n); */ + + if(s->buf_len == 0) { + while(n && (*b & 0x80)) { + /* keep-alive and series bytes are ignored */ + ADVANCE(b, n, 1); + } + } + + if(n == 0) { + return 0; + + } else if(s->buf_len > 0) { + return session_recv_cont(s, b, n); + + } else { + return session_recv_empty(s, b, n); + } +} + + +#undef ADVANCE + + +void mwSession_recv(struct mwSession *s, const guchar *buf, gsize n) { + guchar *b = (guchar *) buf; + gsize remain = 0; + + g_return_if_fail(s != NULL); + + while(n > 0) { + remain = session_recv(s, b, n); + b += (n - remain); + n = remain; + } +} + + +int mwSession_send(struct mwSession *s, struct mwMessage *msg) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret = 0; + + g_return_val_if_fail(s != NULL, -1); + + /* writing nothing is easy */ + if(! msg) return 0; + + /* first we render the message into an opaque */ + b = mwPutBuffer_new(); + mwMessage_put(b, msg); + mwPutBuffer_finalize(&o, b); + + /* then we render the opaque into... another opaque! */ + b = mwPutBuffer_new(); + mwOpaque_put(b, &o); + mwOpaque_clear(&o); + mwPutBuffer_finalize(&o, b); + + /* then we use that opaque's data and length to write to the socket */ + ret = io_write(s, o.data, o.len); + mwOpaque_clear(&o); + + /* ensure we could actually write the message */ + if(! ret) { + + /* special case, as the server doesn't always respond to user + status messages. Thus, we trigger the event when we send the + messages as well as when we receive them */ + if(msg->type == mwMessage_SET_USER_STATUS) { + SET_USER_STATUS_recv(s, (struct mwMsgSetUserStatus *) msg); + } + } + + return ret; +} + + +int mwSession_sendKeepalive(struct mwSession *s) { + const guchar b = 0x80; + + g_return_val_if_fail(s != NULL, -1); + return io_write(s, &b, 1); +} + + +int mwSession_forceLogin(struct mwSession *s) { + struct mwMsgLoginContinue *msg; + int ret; + + g_return_val_if_fail(s != NULL, -1); + g_return_val_if_fail(mwSession_isState(s, mwSession_LOGIN_REDIR), -1); + + state(s, mwSession_LOGIN_CONT, 0x00); + + msg = (struct mwMsgLoginContinue *) + mwMessage_new(mwMessage_LOGIN_CONTINUE); + + ret = mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + return ret; +} + + +int mwSession_sendAnnounce(struct mwSession *s, gboolean may_reply, + const char *text, const GList *recipients) { + + struct mwMsgAnnounce *msg; + int ret; + + g_return_val_if_fail(s != NULL, -1); + g_return_val_if_fail(mwSession_isStarted(s), -1); + + msg = (struct mwMsgAnnounce *) mwMessage_new(mwMessage_ANNOUNCE); + + msg->recipients = (GList *) recipients; + msg->may_reply = may_reply; + msg->text = g_strdup(text); + + ret = mwSession_send(s, MW_MESSAGE(msg)); + + msg->recipients = NULL; /* don't kill our recipients param */ + mwMessage_free(MW_MESSAGE(msg)); + + return ret; +} + + +struct mwSessionHandler *mwSession_getHandler(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + return s->handler; +} + + +struct mwLoginInfo *mwSession_getLoginInfo(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + return &s->login; +} + + +int mwSession_setPrivacyInfo(struct mwSession *s, + struct mwPrivacyInfo *privacy) { + + struct mwMsgSetPrivacyList *msg; + int ret; + + g_return_val_if_fail(s != NULL, -1); + g_return_val_if_fail(privacy != NULL, -1); + + msg = (struct mwMsgSetPrivacyList *) + mwMessage_new(mwMessage_SET_PRIVACY_LIST); + + mwPrivacyInfo_clone(&msg->privacy, privacy); + + ret = mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + return ret; +} + + +struct mwPrivacyInfo *mwSession_getPrivacyInfo(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + return &s->privacy; +} + + +int mwSession_setUserStatus(struct mwSession *s, + struct mwUserStatus *stat) { + + struct mwMsgSetUserStatus *msg; + int ret; + + g_return_val_if_fail(s != NULL, -1); + g_return_val_if_fail(stat != NULL, -1); + + msg = (struct mwMsgSetUserStatus *) + mwMessage_new(mwMessage_SET_USER_STATUS); + + mwUserStatus_clone(&msg->status, stat); + + ret = mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); + + return ret; +} + + +struct mwUserStatus *mwSession_getUserStatus(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + return &s->status; +} + + +enum mwSessionState mwSession_getState(struct mwSession *s) { + g_return_val_if_fail(s != NULL, mwSession_UNKNOWN); + return s->state; +} + + +gpointer mwSession_getStateInfo(struct mwSession *s) { + g_return_val_if_fail(s != NULL, 0); + return s->state_info; +} + + +struct mwChannelSet *mwSession_getChannels(struct mwSession *session) { + g_return_val_if_fail(session != NULL, NULL); + return session->channels; +} + + +gboolean mwSession_addService(struct mwSession *s, struct mwService *srv) { + g_return_val_if_fail(s != NULL, FALSE); + g_return_val_if_fail(srv != NULL, FALSE); + g_return_val_if_fail(s->services != NULL, FALSE); + + if(map_guint_lookup(s->services, SERVICE_KEY(srv))) { + return FALSE; + + } else { + map_guint_insert(s->services, SERVICE_KEY(srv), srv); + if(mwSession_isState(s, mwSession_STARTED)) + mwSession_senseService(s, mwService_getType(srv)); + return TRUE; + } +} + + +struct mwService *mwSession_getService(struct mwSession *s, guint32 srv) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->services != NULL, NULL); + + return map_guint_lookup(s->services, srv); +} + + +struct mwService *mwSession_removeService(struct mwSession *s, guint32 srv) { + struct mwService *svc; + + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->services != NULL, NULL); + + svc = map_guint_lookup(s->services, srv); + if(svc) map_guint_remove(s->services, srv); + return svc; +} + + +GList *mwSession_getServices(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->services != NULL, NULL); + + return map_collect_values(s->services); +} + + +void mwSession_senseService(struct mwSession *s, guint32 srvc) { + struct mwMsgSenseService *msg; + + g_return_if_fail(s != NULL); + g_return_if_fail(srvc != 0x00); + g_return_if_fail(mwSession_isStarted(s)); + + msg = (struct mwMsgSenseService *) + mwMessage_new(mwMessage_SENSE_SERVICE); + msg->service = srvc; + + mwSession_send(s, MW_MESSAGE(msg)); + mwMessage_free(MW_MESSAGE(msg)); +} + + +gboolean mwSession_addCipher(struct mwSession *s, struct mwCipher *c) { + g_return_val_if_fail(s != NULL, FALSE); + g_return_val_if_fail(c != NULL, FALSE); + g_return_val_if_fail(s->ciphers != NULL, FALSE); + + if(map_guint_lookup(s->ciphers, mwCipher_getType(c))) { + g_message("cipher %s is already added, apparently", + NSTR(mwCipher_getName(c))); + return FALSE; + + } else { + g_message("adding cipher %s", NSTR(mwCipher_getName(c))); + map_guint_insert(s->ciphers, mwCipher_getType(c), c); + return TRUE; + } +} + + +struct mwCipher *mwSession_getCipher(struct mwSession *s, guint16 c) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->ciphers != NULL, NULL); + + return map_guint_lookup(s->ciphers, c); +} + + +struct mwCipher *mwSession_removeCipher(struct mwSession *s, guint16 c) { + struct mwCipher *ciph; + + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->ciphers != NULL, NULL); + + ciph = map_guint_lookup(s->ciphers, c); + if(ciph) map_guint_remove(s->ciphers, c); + return ciph; +} + + +GList *mwSession_getCiphers(struct mwSession *s) { + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->ciphers != NULL, NULL); + + return map_collect_values(s->ciphers); +} + + +void mwSession_setProperty(struct mwSession *s, const char *key, + gpointer val, GDestroyNotify clean) { + + g_return_if_fail(s != NULL); + g_return_if_fail(s->attributes != NULL); + g_return_if_fail(key != NULL); + + property_set(s, key, val, clean); +} + + +gpointer mwSession_getProperty(struct mwSession *s, const char *key) { + + g_return_val_if_fail(s != NULL, NULL); + g_return_val_if_fail(s->attributes != NULL, NULL); + g_return_val_if_fail(key != NULL, NULL); + + return property_get(s, key); +} + + +void mwSession_removeProperty(struct mwSession *s, const char *key) { + g_return_if_fail(s != NULL); + g_return_if_fail(s->attributes != NULL); + g_return_if_fail(key != NULL); + + property_del(s, key); +} + + +void mwSession_setClientData(struct mwSession *session, + gpointer data, GDestroyNotify clear) { + + g_return_if_fail(session != NULL); + mw_datum_set(&session->client_data, data, clear); +} + + +gpointer mwSession_getClientData(struct mwSession *session) { + g_return_val_if_fail(session != NULL, NULL); + return mw_datum_get(&session->client_data); +} + + +void mwSession_removeClientData(struct mwSession *session) { + g_return_if_fail(session != NULL); + mw_datum_clear(&session->client_data); +} + diff --git a/protocols/Sametime/src/meanwhile/src/srvc_aware.c b/protocols/Sametime/src/meanwhile/src/srvc_aware.c new file mode 100644 index 0000000000..8c11be229f --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_aware.c @@ -0,0 +1,1341 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <glib/ghash.h> +#include <glib/glist.h> +#include <string.h> + +#include "mw_channel.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_aware.h" +#include "mw_util.h" + + +struct mwServiceAware { + struct mwService service; + + struct mwAwareHandler *handler; + + /** map of ENTRY_KEY(aware_entry):aware_entry */ + GHashTable *entries; + + /** set of guint32:attrib_watch_entry attribute keys */ + GHashTable *attribs; + + /** collection of lists of awareness for this service. Each item is + a mwAwareList */ + GList *lists; + + /** the buddy list channel */ + struct mwChannel *channel; +}; + + +struct mwAwareList { + + /** the owning service */ + struct mwServiceAware *service; + + /** map of ENTRY_KEY(aware_entry):aware_entry */ + GHashTable *entries; + + /** set of guint32:attrib_watch_entry attribute keys */ + GHashTable *attribs; + + struct mwAwareListHandler *handler; + struct mw_datum client_data; +}; + + +struct mwAwareAttribute { + guint32 key; + struct mwOpaque data; +}; + + +struct attrib_entry { + guint32 key; + GList *membership; +}; + + +/** an actual awareness entry, belonging to any number of aware lists */ +struct aware_entry { + struct mwAwareSnapshot aware; + + /** list of mwAwareList containing this entry */ + GList *membership; + + /** collection of attribute values for this entry. + map of ATTRIB_KEY(mwAwareAttribute):mwAwareAttribute */ + GHashTable *attribs; +}; + + +#define ENTRY_KEY(entry) &entry->aware.id + + +/** the channel send types used by this service */ +enum msg_types { + msg_AWARE_ADD = 0x0068, /**< remove an aware */ + msg_AWARE_REMOVE = 0x0069, /**< add an aware */ + + msg_OPT_DO_SET = 0x00c9, /**< set an attribute */ + msg_OPT_DO_UNSET = 0x00ca, /**< unset an attribute */ + msg_OPT_WATCH = 0x00cb, /**< set the attribute watch list */ + + msg_AWARE_SNAPSHOT = 0x01f4, /**< recv aware snapshot */ + msg_AWARE_UPDATE = 0x01f5, /**< recv aware update */ + msg_AWARE_GROUP = 0x01f6, /**< recv group aware */ + + msg_OPT_GOT_SET = 0x0259, /**< recv attribute set update */ + msg_OPT_GOT_UNSET = 0x025a, /**< recv attribute unset update */ + + msg_OPT_GOT_UNKNOWN = 0x025b, /**< UNKNOWN */ + + msg_OPT_DID_SET = 0x025d, /**< attribute set response */ + msg_OPT_DID_UNSET = 0x025e, /**< attribute unset response */ + msg_OPT_DID_ERROR = 0x025f, /**< attribute set/unset error */ +}; + + +static void aware_entry_free(struct aware_entry *ae) { + mwAwareSnapshot_clear(&ae->aware); + g_list_free(ae->membership); + g_hash_table_destroy(ae->attribs); + g_free(ae); +} + + +static void attrib_entry_free(struct attrib_entry *ae) { + g_list_free(ae->membership); + g_free(ae); +} + + +static void attrib_free(struct mwAwareAttribute *attrib) { + mwOpaque_clear(&attrib->data); + g_free(attrib); +} + + +static struct aware_entry *aware_find(struct mwServiceAware *srvc, + struct mwAwareIdBlock *srch) { + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(srvc->entries != NULL, NULL); + g_return_val_if_fail(srch != NULL, NULL); + + return g_hash_table_lookup(srvc->entries, srch); +} + + +static struct aware_entry *list_aware_find(struct mwAwareList *list, + struct mwAwareIdBlock *srch) { + g_return_val_if_fail(list != NULL, NULL); + g_return_val_if_fail(list->entries != NULL, NULL); + g_return_val_if_fail(srch != NULL, NULL); + + return g_hash_table_lookup(list->entries, srch); +} + + +static void compose_list(struct mwPutBuffer *b, GList *id_list) { + guint32_put(b, g_list_length(id_list)); + for(; id_list; id_list = id_list->next) + mwAwareIdBlock_put(b, id_list->data); +} + + +static int send_add(struct mwChannel *chan, GList *id_list) { + struct mwPutBuffer *b = mwPutBuffer_new(); + struct mwOpaque o; + int ret; + + g_return_val_if_fail(chan != NULL, 0); + + compose_list(b, id_list); + + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(chan, msg_AWARE_ADD, &o); + mwOpaque_clear(&o); + + return ret; +} + + +static int send_rem(struct mwChannel *chan, GList *id_list) { + struct mwPutBuffer *b = mwPutBuffer_new(); + struct mwOpaque o; + int ret; + + g_return_val_if_fail(chan != NULL, 0); + + compose_list(b, id_list); + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(chan, msg_AWARE_REMOVE, &o); + mwOpaque_clear(&o); + + return ret; +} + + +static gboolean collect_dead(gpointer key, gpointer val, gpointer data) { + struct aware_entry *aware = val; + GList **dead = data; + + if(aware->membership == NULL) { + // Miranda NG adaptation + //g_info(" removing %s, %s", + // NSTR(aware->aware.id.user), NSTR(aware->aware.id.community)); + g_message(" removing %s, %s", NSTR(aware->aware.id.user), NSTR(aware->aware.id.community)); + *dead = g_list_append(*dead, aware); + return TRUE; + + } else { + return FALSE; + } +} + + +static int remove_unused(struct mwServiceAware *srvc) { + /* - create a GList of all the unused aware entries + - remove each unused aware from the service + - if the service is alive, send a removal message for the collected + unused. + */ + + int ret = 0; + GList *dead = NULL, *l; + + if(srvc->entries) { + // Miranda NG adaptation + //g_info("bring out your dead *clang*"); + g_message("bring out your dead *clang*"); + g_hash_table_foreach_steal(srvc->entries, collect_dead, &dead); + } + + if(dead) { + if(MW_SERVICE_IS_LIVE(srvc)) + ret = send_rem(srvc->channel, dead) || ret; + + for(l = dead; l; l = l->next) + aware_entry_free(l->data); + + g_list_free(dead); + } + + return ret; +} + + +static int send_attrib_list(struct mwServiceAware *srvc) { + struct mwPutBuffer *b; + struct mwOpaque o; + + int tmp; + GList *l; + + g_return_val_if_fail(srvc != NULL, -1); + g_return_val_if_fail(srvc->channel != NULL, 0); + + l = map_collect_keys(srvc->attribs); + tmp = g_list_length(l); + + b = mwPutBuffer_new(); + guint32_put(b, 0x00); + guint32_put(b, tmp); + + for(; l; l = g_list_delete_link(l, l)) { + guint32_put(b, GPOINTER_TO_UINT(l->data)); + } + + mwPutBuffer_finalize(&o, b); + tmp = mwChannel_send(srvc->channel, msg_OPT_WATCH, &o); + mwOpaque_clear(&o); + + return tmp; +} + + +static gboolean collect_attrib_dead(gpointer key, gpointer val, + gpointer data) { + + struct attrib_entry *attrib = val; + GList **dead = data; + + if(attrib->membership == NULL) { + // Miranda NG adaptation + //g_info(" removing 0x%08x", GPOINTER_TO_UINT(key)); + g_message(" removing 0x%08x", GPOINTER_TO_UINT(key)); + *dead = g_list_append(*dead, attrib); + return TRUE; + + } else { + return FALSE; + } +} + + +static int remove_unused_attrib(struct mwServiceAware *srvc) { + GList *dead = NULL; + + if(srvc->attribs) { + // Miranda NG adaptation + //g_info("collecting dead attributes"); + g_message("collecting dead attributes"); + g_hash_table_foreach_steal(srvc->attribs, collect_attrib_dead, &dead); + } + + /* since we stole them, we'll have to clean 'em up manually */ + for(; dead; dead = g_list_delete_link(dead, dead)) { + attrib_entry_free(dead->data); + } + + return MW_SERVICE_IS_LIVE(srvc)? send_attrib_list(srvc): 0; +} + + +static void recv_accept(struct mwServiceAware *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + g_return_if_fail(srvc->channel != NULL); + g_return_if_fail(srvc->channel == chan); + + if(MW_SERVICE_IS_STARTING(MW_SERVICE(srvc))) { + GList *list = NULL; + + list = map_collect_values(srvc->entries); + send_add(chan, list); + g_list_free(list); + + send_attrib_list(srvc); + + mwService_started(MW_SERVICE(srvc)); + + } else { + mwChannel_destroy(chan, ERR_FAILURE, NULL); + } +} + + +static void recv_destroy(struct mwServiceAware *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + srvc->channel = NULL; + mwService_stop(MW_SERVICE(srvc)); + + /** @todo session sense service and mwService_start */ +} + + +/** called from SNAPSHOT_recv, UPDATE_recv, and + mwServiceAware_setStatus */ +static void status_recv(struct mwServiceAware *srvc, + struct mwAwareSnapshot *idb) { + + struct aware_entry *aware; + GList *l; + + aware = aware_find(srvc, &idb->id); + + if(! aware) { + /* we don't deal with receiving status for something we're not + monitoring, but it will happen sometimes, eg from manually set + status */ + return; + } + + /* clear the existing status, then clone in the new status */ + mwAwareSnapshot_clear(&aware->aware); + mwAwareSnapshot_clone(&aware->aware, idb); + + /* trigger each of the entry's lists */ + for(l = aware->membership; l; l = l->next) { + struct mwAwareList *alist = l->data; + struct mwAwareListHandler *handler = alist->handler; + + if(handler && handler->on_aware) + handler->on_aware(alist, idb); + } +} + + +static void attrib_recv(struct mwServiceAware *srvc, + struct mwAwareIdBlock *idb, + struct mwAwareAttribute *attrib) { + + struct aware_entry *aware; + struct mwAwareAttribute *old_attrib = NULL; + GList *l; + guint32 key; + gpointer k; + + aware = aware_find(srvc, idb); + g_return_if_fail(aware != NULL); + + key = attrib->key; + k = GUINT_TO_POINTER(key); + + if(aware->attribs) + old_attrib = g_hash_table_lookup(aware->attribs, k); + + if(! old_attrib) { + old_attrib = g_new0(struct mwAwareAttribute, 1); + old_attrib->key = key; + g_hash_table_insert(aware->attribs, k, old_attrib); + } + + mwOpaque_clear(&old_attrib->data); + mwOpaque_clone(&old_attrib->data, &attrib->data); + + for(l = aware->membership; l; l = l->next) { + struct mwAwareList *list = l->data; + struct mwAwareListHandler *h = list->handler; + + if(h && h->on_attrib && + list->attribs && g_hash_table_lookup(list->attribs, k)) + + h->on_attrib(list, idb, old_attrib); + } +} + + +static gboolean list_add(struct mwAwareList *list, + struct mwAwareIdBlock *id) { + + struct mwServiceAware *srvc = list->service; + struct aware_entry *aware; + + g_return_val_if_fail(id->user != NULL, FALSE); + g_return_val_if_fail(strlen(id->user) > 0, FALSE); + + if(! list->entries) + list->entries = g_hash_table_new((GHashFunc) mwAwareIdBlock_hash, + (GEqualFunc) mwAwareIdBlock_equal); + + aware = list_aware_find(list, id); + if(aware) return FALSE; + + aware = aware_find(srvc, id); + if(! aware) { + aware = g_new0(struct aware_entry, 1); + aware->attribs = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) attrib_free); + mwAwareIdBlock_clone(ENTRY_KEY(aware), id); + + g_hash_table_insert(srvc->entries, ENTRY_KEY(aware), aware); + } + + aware->membership = g_list_append(aware->membership, list); + + g_hash_table_insert(list->entries, ENTRY_KEY(aware), aware); + + return TRUE; +} + + +static void group_member_recv(struct mwServiceAware *srvc, + struct mwAwareSnapshot *idb) { + /* @todo + - look up group by id + - find each list group belongs to + - add user to lists + */ + + struct mwAwareIdBlock gsrch = { mwAware_GROUP, idb->group, NULL }; + struct aware_entry *grp; + GList *l, *m; + + grp = aware_find(srvc, &gsrch); + g_return_if_fail(grp != NULL); /* this could happen, with timing. */ + + l = g_list_prepend(NULL, &idb->id); + + for(m = grp->membership; m; m = m->next) { + + /* if we just list_add, we won't receive updates for attributes, + so annoyingly we have to turn around and send out an add aware + message for each incoming group member */ + + /* list_add(m->data, &idb->id); */ + mwAwareList_addAware(m->data, l); + } + + g_list_free(l); +} + + +static void recv_SNAPSHOT(struct mwServiceAware *srvc, + struct mwGetBuffer *b) { + + guint32 count; + + struct mwAwareSnapshot *snap; + snap = g_new0(struct mwAwareSnapshot, 1); + + guint32_get(b, &count); + + while(count--) { + mwAwareSnapshot_get(b, snap); + + if(mwGetBuffer_error(b)) { + mwAwareSnapshot_clear(snap); + break; + } + + if(snap->group) + group_member_recv(srvc, snap); + + status_recv(srvc, snap); + mwAwareSnapshot_clear(snap); + } + + g_free(snap); +} + + +static void recv_UPDATE(struct mwServiceAware *srvc, + struct mwGetBuffer *b) { + + struct mwAwareSnapshot *snap; + + snap = g_new0(struct mwAwareSnapshot, 1); + mwAwareSnapshot_get(b, snap); + + if(snap->group) + group_member_recv(srvc, snap); + + if(! mwGetBuffer_error(b)) + status_recv(srvc, snap); + + mwAwareSnapshot_clear(snap); + g_free(snap); +} + + +static void recv_GROUP(struct mwServiceAware *srvc, + struct mwGetBuffer *b) { + + struct mwAwareIdBlock idb = { 0, 0, 0 }; + + /* really nothing to be done with this. The group should have + already been added to the list and service, and is now simply + awaiting a snapshot/update with users listed as belonging in said + group. */ + + mwAwareIdBlock_get(b, &idb); + mwAwareIdBlock_clear(&idb); +} + + +static void recv_OPT_GOT_SET(struct mwServiceAware *srvc, + struct mwGetBuffer *b) { + + struct mwAwareAttribute attrib; + struct mwAwareIdBlock idb; + guint32 junk, check; + + guint32_get(b, &junk); + mwAwareIdBlock_get(b, &idb); + guint32_get(b, &junk); + guint32_get(b, &check); + guint32_get(b, &junk); + guint32_get(b, &attrib.key); + + if(check) { + mwOpaque_get(b, &attrib.data); + } else { + attrib.data.len = 0; + attrib.data.data = NULL; + } + + attrib_recv(srvc, &idb, &attrib); + + mwAwareIdBlock_clear(&idb); + mwOpaque_clear(&attrib.data); +} + + +static void recv_OPT_GOT_UNSET(struct mwServiceAware *srvc, + struct mwGetBuffer *b) { + + struct mwAwareAttribute attrib; + struct mwAwareIdBlock idb; + guint32 junk; + + attrib.key = 0; + attrib.data.len = 0; + attrib.data.data = NULL; + + guint32_get(b, &junk); + mwAwareIdBlock_get(b, &idb); + guint32_get(b, &attrib.key); + + attrib_recv(srvc, &idb, &attrib); + + mwAwareIdBlock_clear(&idb); +} + + +static void recv(struct mwService *srvc, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + struct mwServiceAware *srvc_aware = (struct mwServiceAware *) srvc; + struct mwGetBuffer *b; + + g_return_if_fail(srvc_aware->channel == chan); + g_return_if_fail(srvc->session == mwChannel_getSession(chan)); + g_return_if_fail(data != NULL); + + b = mwGetBuffer_wrap(data); + + switch(type) { + case msg_AWARE_SNAPSHOT: + recv_SNAPSHOT(srvc_aware, b); + break; + + case msg_AWARE_UPDATE: + recv_UPDATE(srvc_aware, b); + break; + + case msg_AWARE_GROUP: + recv_GROUP(srvc_aware, b); + break; + + case msg_OPT_GOT_SET: + recv_OPT_GOT_SET(srvc_aware, b); + break; + + case msg_OPT_GOT_UNSET: + recv_OPT_GOT_UNSET(srvc_aware, b); + break; + + case msg_OPT_GOT_UNKNOWN: + case msg_OPT_DID_SET: + case msg_OPT_DID_UNSET: + case msg_OPT_DID_ERROR: + break; + + default: + mw_mailme_opaque(data, "unknown message in aware service: 0x%04x", type); + } + + mwGetBuffer_free(b); +} + + +static void clear(struct mwService *srvc) { + struct mwServiceAware *srvc_aware = (struct mwServiceAware *) srvc; + + g_return_if_fail(srvc != NULL); + + while(srvc_aware->lists) + mwAwareList_free( (struct mwAwareList *) srvc_aware->lists->data ); + + g_hash_table_destroy(srvc_aware->entries); + srvc_aware->entries = NULL; + + g_hash_table_destroy(srvc_aware->attribs); + srvc_aware->attribs = NULL; +} + + +static const char *name(struct mwService *srvc) { + return "Presence Awareness"; +} + + +static const char *desc(struct mwService *srvc) { + return "Buddy list service with support for server-side groups"; +} + + +static struct mwChannel *make_blist(struct mwServiceAware *srvc, + struct mwChannelSet *cs) { + + struct mwChannel *chan = mwChannel_newOutgoing(cs); + + mwChannel_setService(chan, MW_SERVICE(srvc)); + mwChannel_setProtoType(chan, 0x00000011); + mwChannel_setProtoVer(chan, 0x00030005); + + return mwChannel_create(chan)? NULL: chan; +} + + +static void start(struct mwService *srvc) { + struct mwServiceAware *srvc_aware; + struct mwChannel *chan = NULL; + + srvc_aware = (struct mwServiceAware *) srvc; + chan = make_blist(srvc_aware, mwSession_getChannels(srvc->session)); + + if(chan != NULL) { + srvc_aware->channel = chan; + } else { + mwService_stopped(srvc); + } +} + + +static void stop(struct mwService *srvc) { + struct mwServiceAware *srvc_aware; + + srvc_aware = (struct mwServiceAware *) srvc; + + if(srvc_aware->channel) { + mwChannel_destroy(srvc_aware->channel, ERR_SUCCESS, NULL); + srvc_aware->channel = NULL; + } + + mwService_stopped(srvc); +} + + +struct mwServiceAware * +mwServiceAware_new(struct mwSession *session, + struct mwAwareHandler *handler) { + + struct mwService *service; + struct mwServiceAware *srvc; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + srvc = g_new0(struct mwServiceAware, 1); + srvc->handler = handler; + srvc->entries = g_hash_table_new_full((GHashFunc) mwAwareIdBlock_hash, + (GEqualFunc) mwAwareIdBlock_equal, + NULL, + (GDestroyNotify) aware_entry_free); + + srvc->attribs = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) attrib_entry_free); + + service = MW_SERVICE(srvc); + mwService_init(service, session, mwService_AWARE); + + service->recv_accept = (mwService_funcRecvAccept) recv_accept; + service->recv_destroy = (mwService_funcRecvDestroy) recv_destroy; + service->recv = recv; + service->start = start; + service->stop = stop; + service->clear = clear; + service->get_name = name; + service->get_desc = desc; + + return srvc; +} + + +int mwServiceAware_setAttribute(struct mwServiceAware *srvc, + guint32 key, struct mwOpaque *data) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + b = mwPutBuffer_new(); + + guint32_put(b, 0x00); + guint32_put(b, data->len); + guint32_put(b, 0x00); + guint32_put(b, key); + mwOpaque_put(b, data); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(srvc->channel, msg_OPT_DO_SET, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwServiceAware_setAttributeBoolean(struct mwServiceAware *srvc, + guint32 key, gboolean val) { + int ret; + struct mwPutBuffer *b; + struct mwOpaque o; + + b = mwPutBuffer_new(); + + gboolean_put(b, FALSE); + gboolean_put(b, val); + + mwPutBuffer_finalize(&o, b); + + ret = mwServiceAware_setAttribute(srvc, key, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwServiceAware_setAttributeInteger(struct mwServiceAware *srvc, + guint32 key, guint32 val) { + int ret; + struct mwPutBuffer *b; + struct mwOpaque o; + + b = mwPutBuffer_new(); + guint32_put(b, val); + + mwPutBuffer_finalize(&o, b); + + ret = mwServiceAware_setAttribute(srvc, key, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwServiceAware_setAttributeString(struct mwServiceAware *srvc, + guint32 key, const char *str) { + int ret; + struct mwPutBuffer *b; + struct mwOpaque o; + + b = mwPutBuffer_new(); + mwString_put(b, str); + + mwPutBuffer_finalize(&o, b); + + ret = mwServiceAware_setAttribute(srvc, key, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwServiceAware_unsetAttribute(struct mwServiceAware *srvc, + guint32 key) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + b = mwPutBuffer_new(); + + guint32_put(b, 0x00); + guint32_put(b, key); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(srvc->channel, msg_OPT_DO_UNSET, &o); + mwOpaque_clear(&o); + + return ret; +} + + +guint32 mwAwareAttribute_getKey(const struct mwAwareAttribute *attrib) { + g_return_val_if_fail(attrib != NULL, 0x00); + return attrib->key; +} + + +gboolean mwAwareAttribute_asBoolean(const struct mwAwareAttribute *attrib) { + struct mwGetBuffer *b; + gboolean ret; + + if(! attrib) return FALSE; + + b = mwGetBuffer_wrap(&attrib->data); + if(attrib->data.len >= 4) { + guint32 r32 = 0x00; + guint32_get(b, &r32); + ret = !! r32; + + } else if(attrib->data.len >= 2) { + guint16 r16 = 0x00; + guint16_get(b, &r16); + ret = !! r16; + + } else if(attrib->data.len) { + gboolean_get(b, &ret); + } + + mwGetBuffer_free(b); + + return ret; +} + + +guint32 mwAwareAttribute_asInteger(const struct mwAwareAttribute *attrib) { + struct mwGetBuffer *b; + guint32 r32 = 0x00; + + if(! attrib) return 0x00; + + b = mwGetBuffer_wrap(&attrib->data); + if(attrib->data.len >= 4) { + guint32_get(b, &r32); + + } else if(attrib->data.len == 3) { + gboolean rb = FALSE; + guint16 r16 = 0x00; + gboolean_get(b, &rb); + guint16_get(b, &r16); + r32 = (guint32) r16; + + } else if(attrib->data.len == 2) { + guint16 r16 = 0x00; + guint16_get(b, &r16); + r32 = (guint32) r16; + + } else if(attrib->data.len) { + gboolean rb = FALSE; + gboolean_get(b, &rb); + r32 = (guint32) rb; + } + + mwGetBuffer_free(b); + + return r32; +} + + +char *mwAwareAttribute_asString(const struct mwAwareAttribute *attrib) { + struct mwGetBuffer *b; + char *ret = NULL; + + if(! attrib) return NULL; + + b = mwGetBuffer_wrap(&attrib->data); + mwString_get(b, &ret); + mwGetBuffer_free(b); + + return ret; +} + + +const struct mwOpaque * +mwAwareAttribute_asOpaque(const struct mwAwareAttribute *attrib) { + g_return_val_if_fail(attrib != NULL, NULL); + return &attrib->data; +} + + +struct mwAwareList * +mwAwareList_new(struct mwServiceAware *srvc, + struct mwAwareListHandler *handler) { + + struct mwAwareList *al; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + al = g_new0(struct mwAwareList, 1); + al->service = srvc; + al->handler = handler; + + srvc->lists = g_list_prepend(srvc->lists, al); + + return al; +} + + +void mwAwareList_free(struct mwAwareList *list) { + struct mwServiceAware *srvc; + struct mwAwareListHandler *handler; + + g_return_if_fail(list != NULL); + g_return_if_fail(list->service != NULL); + + srvc = list->service; + srvc->lists = g_list_remove_all(srvc->lists, list); + + handler = list->handler; + if(handler && handler->clear) { + handler->clear(list); + list->handler = NULL; + } + + mw_datum_clear(&list->client_data); + + mwAwareList_unwatchAllAttributes(list); + mwAwareList_removeAllAware(list); + + list->service = NULL; + + g_free(list); +} + + +struct mwAwareListHandler *mwAwareList_getHandler(struct mwAwareList *list) { + g_return_val_if_fail(list != NULL, NULL); + return list->handler; +} + + +/// Miranda NG adaptation start - new method +struct mwServiceAware *mwAwareList_getServiceAware(struct mwAwareList *list) { + g_return_val_if_fail(list != NULL, NULL); + return list->service; +} +/// Miranda NG adaptation end + + +static void watch_add(struct mwAwareList *list, guint32 key) { + struct mwServiceAware *srvc; + struct attrib_entry *watch; + gpointer k = GUINT_TO_POINTER(key); + + if(! list->attribs) + list->attribs = g_hash_table_new(g_direct_hash, g_direct_equal); + + if(g_hash_table_lookup(list->attribs, k)) + return; + + srvc = list->service; + + watch = g_hash_table_lookup(srvc->attribs, k); + if(! watch) { + watch = g_new0(struct attrib_entry, 1); + watch->key = key; + g_hash_table_insert(srvc->attribs, k, watch); + } + + g_hash_table_insert(list->attribs, k, watch); + + watch->membership = g_list_prepend(watch->membership, list); +} + + +static void watch_remove(struct mwAwareList *list, guint32 key) { + struct attrib_entry *watch = NULL; + gpointer k = GUINT_TO_POINTER(key); + + if(list->attribs) + watch = g_hash_table_lookup(list->attribs, k); + + g_return_if_fail(watch != NULL); + + g_hash_table_remove(list->attribs, k); + watch->membership = g_list_remove(watch->membership, list); +} + + +int mwAwareList_watchAttributeArray(struct mwAwareList *list, + guint32 *keys) { + guint32 k; + + g_return_val_if_fail(list != NULL, -1); + g_return_val_if_fail(list->service != NULL, -1); + + if(! keys) return 0; + + for(k = *keys; k; keys++) + watch_add(list, k); + + return send_attrib_list(list->service); +} + + +int mwAwareList_watchAttributes(struct mwAwareList *list, + guint32 key, ...) { + guint32 k; + va_list args; + + g_return_val_if_fail(list != NULL, -1); + g_return_val_if_fail(list->service != NULL, -1); + + va_start(args, key); + for(k = key; k; k = va_arg(args, guint32)) + watch_add(list, k); + va_end(args); + + return send_attrib_list(list->service); +} + + +int mwAwareList_unwatchAttributeArray(struct mwAwareList *list, + guint32 *keys) { + guint32 k; + + g_return_val_if_fail(list != NULL, -1); + g_return_val_if_fail(list->service != NULL, -1); + + if(! keys) return 0; + + for(k = *keys; k; keys++) + watch_add(list, k); + + return remove_unused_attrib(list->service); +} + + +int mwAwareList_unwatchAttributes(struct mwAwareList *list, + guint32 key, ...) { + guint32 k; + va_list args; + + g_return_val_if_fail(list != NULL, -1); + g_return_val_if_fail(list->service != NULL, -1); + + va_start(args, key); + for(k = key; k; k = va_arg(args, guint32)) + watch_remove(list, k); + va_end(args); + + return remove_unused_attrib(list->service); +} + + +static void dismember_attrib(gpointer k, struct attrib_entry *watch, + struct mwAwareList *list) { + + watch->membership = g_list_remove(watch->membership, list); +} + + +int mwAwareList_unwatchAllAttributes(struct mwAwareList *list) { + + struct mwServiceAware *srvc; + + g_return_val_if_fail(list != NULL, -1); + srvc = list->service; + + if(list->attribs) { + g_hash_table_foreach(list->attribs, (GHFunc) dismember_attrib, list); + g_hash_table_destroy(list->attribs); + } + + return remove_unused_attrib(srvc); +} + + +static void collect_attrib_keys(gpointer key, struct attrib_entry *attrib, + guint32 **ck) { + guint32 *keys = (*ck)++; + *keys = GPOINTER_TO_UINT(key); +} + + +guint32 *mwAwareList_getWatchedAttributes(struct mwAwareList *list) { + guint32 *keys, **ck; + guint count; + + g_return_val_if_fail(list != NULL, NULL); + g_return_val_if_fail(list->attribs != NULL, NULL); + + count = g_hash_table_size(list->attribs); + keys = g_new0(guint32, count + 1); + + ck = &keys; + g_hash_table_foreach(list->attribs, (GHFunc) collect_attrib_keys, ck); + + return keys; +} + + +int mwAwareList_addAware(struct mwAwareList *list, GList *id_list) { + + /* for each awareness id: + - if it's already in the list, continue + - if it's not in the service list: + - create an awareness + - add it to the service list + - add this list to the membership + - add to the list + */ + + struct mwServiceAware *srvc; + GList *additions = NULL; + int ret = 0; + + g_return_val_if_fail(list != NULL, -1); + + srvc = list->service; + g_return_val_if_fail(srvc != NULL, -1); + + for(; id_list; id_list = id_list->next) { + if(list_add(list, id_list->data)) + additions = g_list_prepend(additions, id_list->data); + } + + /* if the service is alive-- or getting there-- we'll need to send + these additions upstream */ + if(MW_SERVICE_IS_LIVE(srvc) && additions) + ret = send_add(srvc->channel, additions); + + g_list_free(additions); + return ret; +} + + +int mwAwareList_removeAware(struct mwAwareList *list, GList *id_list) { + + /* for each awareness id: + - if it's not in the list, forget it + - remove from the list + - remove list from the membership + + - call remove round + */ + + struct mwServiceAware *srvc; + struct mwAwareIdBlock *id; + struct aware_entry *aware; + + g_return_val_if_fail(list != NULL, -1); + + srvc = list->service; + g_return_val_if_fail(srvc != NULL, -1); + + for(; id_list; id_list = id_list->next) { + id = id_list->data; + aware = list_aware_find(list, id); + + if(! aware) { + g_warning("buddy %s, %s not in list", + NSTR(id->user), + NSTR(id->community)); + continue; + } + + aware->membership = g_list_remove(aware->membership, list); + g_hash_table_remove(list->entries, id); + } + + return remove_unused(srvc); +} + + +static void dismember_aware(gpointer k, struct aware_entry *aware, + struct mwAwareList *list) { + + aware->membership = g_list_remove(aware->membership, list); +} + + +int mwAwareList_removeAllAware(struct mwAwareList *list) { + struct mwServiceAware *srvc; + + g_return_val_if_fail(list != NULL, -1); + srvc = list->service; + + g_return_val_if_fail(srvc != NULL, -1); + + /* for each entry, remove the aware list from the service entry's + membership collection */ + if(list->entries) { + g_hash_table_foreach(list->entries, (GHFunc) dismember_aware, list); + g_hash_table_destroy(list->entries); + } + + return remove_unused(srvc); +} + + +void mwAwareList_setClientData(struct mwAwareList *list, + gpointer data, GDestroyNotify clear) { + + g_return_if_fail(list != NULL); + mw_datum_set(&list->client_data, data, clear); +} + + +gpointer mwAwareList_getClientData(struct mwAwareList *list) { + g_return_val_if_fail(list != NULL, NULL); + return mw_datum_get(&list->client_data); +} + + +void mwAwareList_removeClientData(struct mwAwareList *list) { + g_return_if_fail(list != NULL); + mw_datum_clear(&list->client_data); +} + + +void mwServiceAware_setStatus(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user, + struct mwUserStatus *stat) { + + struct mwAwareSnapshot idb; + + g_return_if_fail(srvc != NULL); + g_return_if_fail(user != NULL); + g_return_if_fail(stat != NULL); + + /* just reference the strings. then we don't need to free them */ + idb.id.type = user->type; + idb.id.user = user->user; + idb.id.community = user->community; + + idb.group = NULL; + idb.online = TRUE; + idb.alt_id = NULL; + + idb.status.status = stat->status; + idb.status.time = stat->time; + idb.status.desc = stat->desc; + + idb.name = NULL; + + status_recv(srvc, &idb); +} + + +const struct mwAwareAttribute * +mwServiceAware_getAttribute(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user, + guint32 key) { + + struct aware_entry *aware; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(user != NULL, NULL); + g_return_val_if_fail(key != 0x00, NULL); + + aware = aware_find(srvc, user); + g_return_val_if_fail(aware != NULL, NULL); + + return g_hash_table_lookup(aware->attribs, GUINT_TO_POINTER(key)); +} + + +const char *mwServiceAware_getText(struct mwServiceAware *srvc, + struct mwAwareIdBlock *user) { + + struct aware_entry *aware; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(user != NULL, NULL); + + aware = aware_find(srvc, user); + if(! aware) return NULL; + + return aware->aware.status.desc; +} + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceAware_getService(struct mwServiceAware *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end diff --git a/protocols/Sametime/src/meanwhile/src/srvc_conf.c b/protocols/Sametime/src/meanwhile/src/srvc_conf.c new file mode 100644 index 0000000000..f302a706f8 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_conf.c @@ -0,0 +1,884 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <glib/ghash.h> +#include <glib/glist.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "mw_channel.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_conf.h" +#include "mw_util.h" + + +/* This thing needs a re-write. More than anything else, I need to + re-examine the conferencing service protocol from more modern + clients */ + + +#define PROTOCOL_TYPE 0x00000010 +#define PROTOCOL_VER 0x00000002 + + +/** @see mwMsgChannelSend::type + @see recv */ +enum msg_type { + msg_WELCOME = 0x0000, /**< welcome message */ + msg_INVITE = 0x0001, /**< outgoing invitation */ + msg_JOIN = 0x0002, /**< someone joined */ + msg_PART = 0x0003, /**< someone left */ + msg_MESSAGE = 0x0004, /**< conference message */ +}; + + +/** the conferencing service */ +struct mwServiceConference { + struct mwService service; + + /** call-back handler for this service */ + struct mwConferenceHandler *handler; + + /** collection of conferences in this service */ + GList *confs; +}; + + +/** a conference and its members */ +struct mwConference { + enum mwConferenceState state; /**< state of the conference */ + struct mwServiceConference *service; /**< owning service */ + struct mwChannel *channel; /**< conference's channel */ + + char *name; /**< server identifier for the conference */ + char *title; /**< topic for the conference */ + + struct mwLoginInfo owner; /**< person who created this conference */ + GHashTable *members; /**< mapping guint16:mwLoginInfo */ + struct mw_datum client_data; +}; + + +#define MEMBER_FIND(conf, id) \ + g_hash_table_lookup(conf->members, GUINT_TO_POINTER((guint) id)) + + +#define MEMBER_ADD(conf, id, member) \ + g_hash_table_insert(conf->members, GUINT_TO_POINTER((guint) id), member) + + +#define MEMBER_REM(conf, id) \ + g_hash_table_remove(conf->members, GUINT_TO_POINTER((guint) id)); + + +/** clear and free a login info block */ +static void login_free(struct mwLoginInfo *li) { + mwLoginInfo_clear(li); + g_free(li); +} + + +/** generates a random conference name built around a user name */ +static char *conf_generate_name(const char *user) { + /// Miranda NG adaptation start - MSVC + ///guint a, b; + guint a; + guint64 b; + /// Miranda NG adaptation end + char *ret; + + user = user? user: ""; + + srand(clock() + rand()); + a = ((rand() & 0xff) << 8) | (rand() & 0xff); + b = time(NULL); + + /// Miranda NG adaptation start - MSVC + ///ret = g_strdup_printf("%s(%08x,%04x)", user, b, a); + ret = g_strdup_printf("%s(%I64u,%04x)", user, b, a); + /// Miranda NG adaptation end + g_debug("generated random conference name: '%s'", ret); + return ret; +} + + + + + +static struct mwConference *conf_new(struct mwServiceConference *srvc) { + + struct mwConference *conf; + struct mwSession *session; + const char *user; + + conf = g_new0(struct mwConference, 1); + conf->state = mwConference_NEW; + conf->service = srvc; + conf->members = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) login_free); + + session = mwService_getSession(MW_SERVICE(srvc)); + user = mwSession_getProperty(session, mwSession_AUTH_USER_ID); + + srvc->confs = g_list_prepend(srvc->confs, conf); + + return conf; +} + + +/** clean and free a conference structure */ +static void conf_free(struct mwConference *conf) { + struct mwServiceConference *srvc; + + /* this shouldn't ever happen, but just to be sure */ + g_return_if_fail(conf != NULL); + + srvc = conf->service; + + if(conf->members) + g_hash_table_destroy(conf->members); + + g_list_remove_all(srvc->confs, conf); + + mw_datum_clear(&conf->client_data); + + g_free(conf->name); + g_free(conf->title); + g_free(conf); +} + + +static struct mwConference *conf_find(struct mwServiceConference *srvc, + struct mwChannel *chan) { + GList *l; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(chan != NULL, NULL); + + for(l = srvc->confs; l; l = l->next) { + struct mwConference *conf = l->data; + if(conf->channel == chan) return conf; + } + + return NULL; +} + + +static const char *conf_state_str(enum mwConferenceState state) { + switch(state) { + case mwConference_NEW: return "new"; + case mwConference_PENDING: return "pending"; + case mwConference_INVITED: return "invited"; + case mwConference_OPEN: return "open"; + case mwConference_CLOSING: return "closing"; + case mwConference_ERROR: return "error"; + + case mwConference_UNKNOWN: /* fall through */ + default: return "UNKNOWN"; + } +} + + +static void conf_state(struct mwConference *conf, + enum mwConferenceState state) { + g_return_if_fail(conf != NULL); + + if(conf->state == state) return; + + conf->state = state; + g_message("conference %s state: %s", + NSTR(conf->name), conf_state_str(state)); +} + + +static void recv_channelCreate(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + /* - this is how we really receive invitations + - create a conference and associate it with the channel + - obtain the invite data from the msg addtl info + - mark the conference as INVITED + - trigger the got_invite event + */ + + struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc; + struct mwConference *conf; + + struct mwGetBuffer *b; + + char *invite = NULL; + guint tmp; + + conf = conf_new(srvc_conf); + conf->channel = chan; + + b = mwGetBuffer_wrap(&msg->addtl); + + guint32_get(b, &tmp); + mwString_get(b, &conf->name); + mwString_get(b, &conf->title); + guint32_get(b, &tmp); + mwLoginInfo_get(b, &conf->owner); + guint32_get(b, &tmp); + mwString_get(b, &invite); + + if(mwGetBuffer_error(b)) { + g_warning("failure parsing addtl for conference invite"); + mwConference_destroy(conf, ERR_FAILURE, NULL); + + } else { + struct mwConferenceHandler *h = srvc_conf->handler; + conf_state(conf, mwConference_INVITED); + if(h->on_invited) + h->on_invited(conf, &conf->owner, invite); + } + + mwGetBuffer_free(b); + g_free(invite); +} + + +static void recv_channelAccept(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + ; +} + + +static void recv_channelDestroy(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + /* - find conference from channel + - trigger got_closed + - remove conference, dealloc + */ + + struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc; + struct mwConference *conf = conf_find(srvc_conf, chan); + struct mwConferenceHandler *h = srvc_conf->handler; + + /* if there's no such conference, then I guess there's nothing to worry + about. Except of course for the fact that we should never receive a + channel destroy for a conference that doesn't exist. */ + if(! conf) return; + + conf->channel = NULL; + + conf_state(conf, msg->reason? mwConference_ERROR: mwConference_CLOSING); + + if(h->conf_closed) + h->conf_closed(conf, msg->reason); + + mwConference_destroy(conf, ERR_SUCCESS, NULL); +} + + +static void WELCOME_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwGetBuffer *b) { + + struct mwConferenceHandler *h; + guint16 tmp16; + guint32 tmp32; + guint32 count; + GList *l = NULL; + + /* re-read name and title */ + g_free(conf->name); + g_free(conf->title); + conf->name = NULL; + conf->title = NULL; + mwString_get(b, &conf->name); + mwString_get(b, &conf->title); + + /* some numbers we don't care about, then a count of members */ + guint16_get(b, &tmp16); + guint32_get(b, &tmp32); + guint32_get(b, &count); + + if(mwGetBuffer_error(b)) { + g_warning("error parsing welcome message for conference"); + mwConference_destroy(conf, ERR_FAILURE, NULL); + return; + } + + while(count--) { + guint16 member_id; + struct mwLoginInfo *member = g_new0(struct mwLoginInfo, 1); + + guint16_get(b, &member_id); + mwLoginInfo_get(b, member); + + if(mwGetBuffer_error(b)) { + login_free(member); + break; + } + + MEMBER_ADD(conf, member_id, member); + l = g_list_append(l, member); + } + + conf_state(conf, mwConference_OPEN); + + h = srvc->handler; + if(h->conf_opened) + h->conf_opened(conf, l); + + /* get rid of the GList, but not its contents */ + g_list_free(l); +} + + +static void JOIN_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwGetBuffer *b) { + + struct mwConferenceHandler *h; + guint16 m_id; + struct mwLoginInfo *m; + + /* for some inane reason, conferences we create will send a join + message for ourselves before the welcome message. Since the + welcome message will list our ID among those in the channel, + we're going to just pretend that these join messages don't + exist */ + if(conf->state == mwConference_PENDING) + return; + + m = g_new0(struct mwLoginInfo, 1); + + guint16_get(b, &m_id); + mwLoginInfo_get(b, m); + + if(mwGetBuffer_error(b)) { + g_warning("failed parsing JOIN message in conference"); + login_free(m); + return; + } + + MEMBER_ADD(conf, m_id, m); + + h = srvc->handler; + if(h->on_peer_joined) + h->on_peer_joined(conf, m); +} + + +static void PART_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwGetBuffer *b) { + + /* - parse who left + - look up their membership + - remove them from the members list + - trigger the event + */ + + struct mwConferenceHandler *h; + guint16 id = 0; + struct mwLoginInfo *m; + + guint16_get(b, &id); + + if(mwGetBuffer_error(b)) return; + + m = MEMBER_FIND(conf, id); + if(! m) return; + + h = srvc->handler; + if(h->on_peer_parted) + h->on_peer_parted(conf, m); + + MEMBER_REM(conf, id); +} + + +static void text_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwLoginInfo *m, + struct mwGetBuffer *b) { + + /* this function acts a lot like receiving an IM Text message. The text + message contains only a string */ + + char *text = NULL; + struct mwConferenceHandler *h; + + mwString_get(b, &text); + + if(mwGetBuffer_error(b)) { + g_warning("failed to parse text message in conference"); + g_free(text); + return; + } + + h = srvc->handler; + if(text && h->on_text) { + h->on_text(conf, m, text); + } + + g_free(text); +} + + +static void data_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwLoginInfo *m, + struct mwGetBuffer *b) { + + /* this function acts a lot like receiving an IM Data message. The + data message has a type, a subtype, and an opaque. We only + support typing notification though. */ + + /** @todo it's possible that some clients send text in a data + message, as we've seen rarely in the IM service. Have to add + support for that here */ + + guint32 type, subtype; + struct mwConferenceHandler *h; + + guint32_get(b, &type); + guint32_get(b, &subtype); + + if(mwGetBuffer_error(b)) return; + + /* don't know how to deal with any others yet */ + if(type != 0x01) { + g_message("unknown data message type (0x%08x, 0x%08x)", type, subtype); + return; + } + + h = srvc->handler; + if(h->on_typing) { + h->on_typing(conf, m, !subtype); + } +} + + +static void MESSAGE_recv(struct mwServiceConference *srvc, + struct mwConference *conf, + struct mwGetBuffer *b) { + + /* - look up who send the message by their id + - trigger the event + */ + + guint16 id; + guint32 type; + struct mwLoginInfo *m; + + /* an empty buffer isn't an error, just ignored */ + if(! mwGetBuffer_remaining(b)) return; + + guint16_get(b, &id); + guint32_get(b, &type); /* reuse type variable */ + guint32_get(b, &type); + + if(mwGetBuffer_error(b)) return; + + m = MEMBER_FIND(conf, id); + if(! m) { + g_warning("received message type 0x%04x from" + " unknown conference member %u", type, id); + return; + } + + switch(type) { + case 0x01: /* type is text */ + text_recv(srvc, conf, m, b); + break; + + case 0x02: /* type is data */ + data_recv(srvc, conf, m, b); + break; + + default: + g_warning("unknown message type 0x%4x received in conference", type); + } +} + + +static void recv(struct mwService *srvc, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + struct mwServiceConference *srvc_conf = (struct mwServiceConference *) srvc; + struct mwConference *conf = conf_find(srvc_conf, chan); + struct mwGetBuffer *b; + + g_return_if_fail(conf != NULL); + + b = mwGetBuffer_wrap(data); + + switch(type) { + case msg_WELCOME: + WELCOME_recv(srvc_conf, conf, b); + break; + + case msg_JOIN: + JOIN_recv(srvc_conf, conf, b); + break; + + case msg_PART: + PART_recv(srvc_conf, conf, b); + break; + + case msg_MESSAGE: + MESSAGE_recv(srvc_conf, conf, b); + break; + + default: + ; /* hrm. should log this. TODO */ + } +} + + +static void clear(struct mwServiceConference *srvc) { + struct mwConferenceHandler *h; + + while(srvc->confs) + conf_free(srvc->confs->data); + + h = srvc->handler; + if(h && h->clear) + h->clear(srvc); + srvc->handler = NULL; +} + + +static const char *name(struct mwService *srvc) { + return "Basic Conferencing"; +} + + +static const char *desc(struct mwService *srvc) { + return "Multi-user plain-text conferencing"; +} + + +static void start(struct mwService *srvc) { + mwService_started(srvc); +} + + +static void stop(struct mwServiceConference *srvc) { + while(srvc->confs) + mwConference_destroy(srvc->confs->data, ERR_SUCCESS, NULL); + + mwService_stopped(MW_SERVICE(srvc)); +} + + +struct mwServiceConference * +mwServiceConference_new(struct mwSession *session, + struct mwConferenceHandler *handler) { + + struct mwServiceConference *srvc_conf; + struct mwService *srvc; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + srvc_conf = g_new0(struct mwServiceConference, 1); + srvc = &srvc_conf->service; + + mwService_init(srvc, session, mwService_CONFERENCE); + srvc->start = start; + srvc->stop = (mwService_funcStop) stop; + srvc->recv_create = recv_channelCreate; + srvc->recv_accept = recv_channelAccept; + srvc->recv_destroy = recv_channelDestroy; + srvc->recv = recv; + srvc->clear = (mwService_funcClear) clear; + srvc->get_name = name; + srvc->get_desc = desc; + + srvc_conf->handler = handler; + + return srvc_conf; +} + + +struct mwConference *mwConference_new(struct mwServiceConference *srvc, + const char *title) { + struct mwConference *conf; + + g_return_val_if_fail(srvc != NULL, NULL); + + conf = conf_new(srvc); + conf->title = g_strdup(title); + + return conf; +} + + +/// Miranda NG adaptation start - renamed method +struct mwServiceConference * +mwConference_getServiceConference(struct mwConference *conf) { + g_return_val_if_fail(conf != NULL, NULL); + return conf->service; +} +/// Miranda NG adaptation end + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceConference_getService(struct mwServiceConference *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end + + +const char *mwConference_getName(struct mwConference *conf) { + g_return_val_if_fail(conf != NULL, NULL); + return conf->name; +} + + +const char *mwConference_getTitle(struct mwConference *conf) { + g_return_val_if_fail(conf != NULL, NULL); + return conf->title; +} + + +GList *mwConference_getMembers(struct mwConference *conf) { + g_return_val_if_fail(conf != NULL, NULL); + g_return_val_if_fail(conf->members != NULL, NULL); + + return map_collect_values(conf->members); +} + + +int mwConference_open(struct mwConference *conf) { + struct mwSession *session; + struct mwChannel *chan; + struct mwPutBuffer *b; + int ret; + + g_return_val_if_fail(conf != NULL, -1); + g_return_val_if_fail(conf->service != NULL, -1); + g_return_val_if_fail(conf->state == mwConference_NEW, -1); + g_return_val_if_fail(conf->channel == NULL, -1); + + session = mwService_getSession(MW_SERVICE(conf->service)); + g_return_val_if_fail(session != NULL, -1); + + if(! conf->name) { + char *user = mwSession_getProperty(session, mwSession_AUTH_USER_ID); + conf->name = conf_generate_name(user? user: "meanwhile"); + } + + chan = mwChannel_newOutgoing(mwSession_getChannels(session)); + mwChannel_setService(chan, MW_SERVICE(conf->service)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + +#if 0 + /* offer all known ciphers */ + mwChannel_populateSupportedCipherInstances(chan); +#endif + + b = mwPutBuffer_new(); + mwString_put(b, conf->name); + mwString_put(b, conf->title); + guint32_put(b, 0x00); + mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b); + + ret = mwChannel_create(chan); + if(ret) { + conf_state(conf, mwConference_ERROR); + } else { + conf_state(conf, mwConference_PENDING); + conf->channel = chan; + } + + return ret; +} + + +int mwConference_destroy(struct mwConference *conf, + guint32 reason, const char *text) { + + struct mwServiceConference *srvc; + struct mwOpaque info = { 0, 0 }; + int ret = 0; + + g_return_val_if_fail(conf != NULL, -1); + + srvc = conf->service; + g_return_val_if_fail(srvc != NULL, -1); + + /* remove conference from the service */ + srvc->confs = g_list_remove_all(srvc->confs, conf); + + /* close the channel if applicable */ + if(conf->channel) { + if(text && *text) { + info.len = strlen(text); + info.data = (guchar *) text; + } + + ret = mwChannel_destroy(conf->channel, reason, &info); + } + + /* free the conference */ + conf_free(conf); + + return ret; +} + + +int mwConference_accept(struct mwConference *conf) { + /* - if conference is not INVITED, return -1 + - accept the conference channel + - send an empty JOIN message + */ + + struct mwChannel *chan; + int ret; + + g_return_val_if_fail(conf != NULL, -1); + g_return_val_if_fail(conf->state == mwConference_INVITED, -1); + + chan = conf->channel; + ret = mwChannel_accept(chan); + + if(! ret) + ret = mwChannel_sendEncrypted(chan, msg_JOIN, NULL, FALSE); + + return ret; +} + + +int mwConference_invite(struct mwConference *conf, + struct mwIdBlock *who, + const char *text) { + + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(conf != NULL, -1); + g_return_val_if_fail(conf->channel != NULL, -1); + g_return_val_if_fail(who != NULL, -1); + + b = mwPutBuffer_new(); + + mwIdBlock_put(b, who); + guint16_put(b, 0x00); + guint32_put(b, 0x00); + mwString_put(b, text); + mwString_put(b, who->user); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_sendEncrypted(conf->channel, msg_INVITE, &o, FALSE); + mwOpaque_clear(&o); + + return ret; +} + + +int mwConference_sendText(struct mwConference *conf, const char *text) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(conf != NULL, -1); + g_return_val_if_fail(conf->channel != NULL, -1); + + b = mwPutBuffer_new(); + + guint32_put(b, 0x01); + mwString_put(b, text); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_sendEncrypted(conf->channel, msg_MESSAGE, &o, FALSE); + mwOpaque_clear(&o); + + return ret; +} + + +int mwConference_sendTyping(struct mwConference *conf, gboolean typing) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(conf != NULL, -1); + g_return_val_if_fail(conf->channel != NULL, -1); + g_return_val_if_fail(conf->state == mwConference_OPEN, -1); + + b = mwPutBuffer_new(); + + guint32_put(b, 0x02); + guint32_put(b, 0x01); + guint32_put(b, !typing); + mwOpaque_put(b, NULL); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_sendEncrypted(conf->channel, msg_MESSAGE, &o, FALSE); + mwOpaque_clear(&o); + + return ret; +} + + +void mwConference_setClientData(struct mwConference *conference, + gpointer data, GDestroyNotify clear) { + + g_return_if_fail(conference != NULL); + mw_datum_set(&conference->client_data, data, clear); +} + + +gpointer mwConference_getClientData(struct mwConference *conference) { + g_return_val_if_fail(conference != NULL, NULL); + return mw_datum_get(&conference->client_data); +} + + +void mwConference_removeClientData(struct mwConference *conference) { + g_return_if_fail(conference != NULL); + mw_datum_clear(&conference->client_data); +} + + +struct mwConferenceHandler * +mwServiceConference_getHandler(struct mwServiceConference *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->handler; +} + + +GList *mwServiceConference_getConferences(struct mwServiceConference *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return g_list_copy(srvc->confs); +} + diff --git a/protocols/Sametime/src/meanwhile/src/srvc_dir.c b/protocols/Sametime/src/meanwhile/src/srvc_dir.c new file mode 100644 index 0000000000..1505f69c53 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_dir.c @@ -0,0 +1,664 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib/ghash.h> + +#include "mw_channel.h" +#include "mw_common.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_dir.h" +#include "mw_util.h" + + +#define PROTOCOL_TYPE 0x0000001c +#define PROTOCOL_VER 0x00000005 + + +enum dir_action { + action_list = 0x0000, /**< list address books */ + action_open = 0x0001, /**< open an addressbook as a directory */ + action_close = 0x0002, /**< close a directory */ + action_search = 0x0003, /**< search an open directory */ +}; + + +struct mwServiceDirectory { + struct mwService service; + + struct mwDirectoryHandler *handler; + + struct mwChannel *channel; + + guint32 counter; /**< counter of request IDs */ + GHashTable *requests; /**< map of request ID:directory */ + GHashTable *books; /**< book->name:mwAddressBook */ +}; + + +struct mwAddressBook { + struct mwServiceDirectory *service; + + guint32 id; /**< id or type or something */ + char *name; /**< name of address book */ + GHashTable *dirs; /**< dir->id:mwDirectory */ +}; + + +struct mwDirectory { + struct mwServiceDirectory *service; + struct mwAddressBook *book; + + enum mwDirectoryState state; + + guint32 id; /**< id of directory, assigned by server */ + guint32 search_id; /**< id of current search, from srvc->counter++ */ + + mwSearchHandler handler; + struct mw_datum client_data; +}; + + +#define next_request_id(srvc) ( ++((srvc)->counter) ) + + +static guint32 map_request(struct mwDirectory *dir) { + struct mwServiceDirectory *srvc = dir->service; + guint32 id = next_request_id(srvc); + + dir->search_id = id; + map_guint_insert(srvc->requests, id, dir); + + return id; +} + + +/** called when directory is removed from the service directory map */ +static void dir_free(struct mwDirectory *dir) { + map_guint_remove(dir->service->requests, dir->search_id); + g_free(dir); +} + + +/** remove the directory from the service list and its owning address + book, then frees the directory */ +static void dir_remove(struct mwDirectory *dir) { + struct mwAddressBook *book = dir->book; + map_guint_remove(book->dirs, dir->id); +} + + +/// __attribute__((used)) ///Miranda NG adaptation, MSVC +static struct mwDirectory *dir_new(struct mwAddressBook *book, guint32 id) { + struct mwDirectory *dir = g_new0(struct mwDirectory, 1); + dir->service = book->service; + dir->book = book; + dir->id = id; + map_guint_insert(book->dirs, id, dir); + return dir; +} + + +/** called when book is removed from the service book map. Removed all + directories as well */ +static void book_free(struct mwAddressBook *book) { + g_hash_table_destroy(book->dirs); + g_free(book->name); +} + + +/// __attribute__((used)) ///Miranda NG adaptation, MSVC +static void book_remove(struct mwAddressBook *book) { + struct mwServiceDirectory *srvc = book->service; + g_hash_table_remove(srvc->books, book->name); +} + + +static struct mwAddressBook *book_new(struct mwServiceDirectory *srvc, + const char *name, guint32 id) { + struct mwAddressBook *book = g_new0(struct mwAddressBook, 1); + book->service = srvc; + book->id = id; + book->name = g_strdup(name); + book->dirs = map_guint_new_full((GDestroyNotify) dir_free); + g_hash_table_insert(srvc->books, book->name, book); + return book; +} + + +static const char *getName(struct mwService *srvc) { + return "Address Book and Directory"; +} + + +static const char *getDesc(struct mwService *srvc) { + return "Address book directory service for user and group lookups"; +} + + +static struct mwChannel *make_channel(struct mwServiceDirectory *srvc) { + struct mwSession *session; + struct mwChannelSet *cs; + struct mwChannel *chan; + + session = mwService_getSession(MW_SERVICE(srvc)); + cs = mwSession_getChannels(session); + chan = mwChannel_newOutgoing(cs); + + mwChannel_setService(chan, MW_SERVICE(srvc)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + return mwChannel_create(chan)? NULL: chan; +} + + +static void start(struct mwServiceDirectory *srvc) { + struct mwChannel *chan; + + chan = make_channel(srvc); + if(chan) { + srvc->channel = chan; + } else { + mwService_stopped(MW_SERVICE(srvc)); + return; + } +} + + +static void stop(struct mwServiceDirectory *srvc) { + /* XXX */ + + if(srvc->channel) { + mwChannel_destroy(srvc->channel, ERR_SUCCESS, NULL); + srvc->channel = NULL; + } +} + + +static void clear(struct mwServiceDirectory *srvc) { + struct mwDirectoryHandler *handler; + + if(srvc->books) { + g_hash_table_destroy(srvc->books); + srvc->books = NULL; + } + + /* clear the handler */ + handler = srvc->handler; + if(handler && handler->clear) + handler->clear(srvc); + srvc->handler = NULL; +} + + +static void recv_create(struct mwServiceDirectory *srvc, + struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + /* no way man, we call the shots around here */ + mwChannel_destroy(chan, ERR_FAILURE, NULL); +} + + +static void recv_accept(struct mwServiceDirectory *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + g_return_if_fail(srvc->channel != NULL); + g_return_if_fail(srvc->channel == chan); + + if(MW_SERVICE_IS_STARTING(srvc)) { + mwService_started(MW_SERVICE(srvc)); + + } else { + mwChannel_destroy(chan, ERR_FAILURE, NULL); + } +} + + +static void recv_destroy(struct mwServiceDirectory *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + srvc->channel = NULL; + mwService_stop(MW_SERVICE(srvc)); + /** @todo session sense service */ +} + + +static void recv_list(struct mwServiceDirectory *srvc, + struct mwOpaque *data) { + + struct mwGetBuffer *b; + guint32 request, code, count; + gboolean foo_1; + guint16 foo_2; + + b = mwGetBuffer_wrap(data); + + guint32_get(b, &request); + guint32_get(b, &code); + guint32_get(b, &count); + + gboolean_get(b, &foo_1); + guint16_get(b, &foo_2); + + if(foo_1 || foo_2) { + mw_mailme_opaque(data, "received strange address book list"); + mwGetBuffer_free(b); + return; + } + + while(!mwGetBuffer_error(b) && count--) { + guint32 id; + char *name = NULL; + + guint32_get(b, &id); + mwString_get(b, &name); + + book_new(srvc, name, id); + g_free(name); + } +} + + +static void recv_open(struct mwServiceDirectory *srvc, + struct mwOpaque *data) { + + /* look up the directory associated with this request id, + mark it as open, and trigger the event */ +} + + +static void recv_search(struct mwServiceDirectory *srvc, + struct mwOpaque *data) { + + /* look up the directory associated with this request id, + trigger the event */ +} + + +static void recv(struct mwServiceDirectory *srvc, + struct mwChannel *chan, + guint16 msg_type, struct mwOpaque *data) { + + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc->channel); + g_return_if_fail(data != NULL); + + switch(msg_type) { + case action_list: + recv_list(srvc, data); + break; + + case action_open: + recv_open(srvc, data); + break; + + case action_close: + ; /* I don't think we should receive these */ + break; + + case action_search: + recv_search(srvc, data); + break; + + default: + mw_mailme_opaque(data, "msg type 0x%04x in directory service", msg_type); + } +} + + +struct mwServiceDirectory * +mwServiceDirectory_new(struct mwSession *session, + struct mwDirectoryHandler *handler) { + + struct mwServiceDirectory *srvc; + struct mwService *service; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + srvc = g_new0(struct mwServiceDirectory, 1); + service = MW_SERVICE(srvc); + + mwService_init(service, session, SERVICE_DIRECTORY); + service->get_name = getName; + service->get_desc = getDesc; + service->start = (mwService_funcStart) start; + service->stop = (mwService_funcStop) stop; + service->clear = (mwService_funcClear) clear; + service->recv_create = (mwService_funcRecvCreate) recv_create; + service->recv_accept = (mwService_funcRecvAccept) recv_accept; + service->recv_destroy = (mwService_funcRecvDestroy) recv_destroy; + service->recv = (mwService_funcRecv) recv; + + srvc->handler = handler; + srvc->requests = map_guint_new(); + srvc->books = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify) book_free); + return srvc; +} + + +struct mwDirectoryHandler * +mwServiceDirectory_getHandler(struct mwServiceDirectory *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->handler; +} + + +int mwServiceDirectory_refreshAddressBooks(struct mwServiceDirectory *srvc) { + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, next_request_id(srvc)); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_list, &o); + mwOpaque_clear(&o); + + return ret; +} + + +GList *mwServiceDirectory_getAddressBooks(struct mwServiceDirectory *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(srvc->books != NULL, NULL); + + return map_collect_values(srvc->books); +} + + +GList *mwServiceDirectory_getDirectories(struct mwServiceDirectory *srvc) { + GList *bl, *ret = NULL; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(srvc->books != NULL, NULL); + + bl = map_collect_values(srvc->books); + for( ; bl; bl = g_list_delete_link(bl, bl)) { + struct mwAddressBook *book = bl->data; + ret = g_list_concat(ret, map_collect_values(book->dirs)); + } + + return ret; +} + + +GList *mwAddressBook_getDirectories(struct mwAddressBook *book) { + g_return_val_if_fail(book != NULL, NULL); + g_return_val_if_fail(book->dirs != NULL, NULL); + + return map_collect_values(book->dirs); +} + + +const char *mwAddressBook_getName(struct mwAddressBook *book) { + g_return_val_if_fail(book != NULL, NULL); + return book->name; +} + + +struct mwDirectory *mwDirectory_new(struct mwAddressBook *book) { + struct mwDirectory *dir; + + g_return_val_if_fail(book != NULL, NULL); + g_return_val_if_fail(book->service != NULL, NULL); + + dir = g_new0(struct mwDirectory, 1); + dir->service = book->service; + dir->book = book; + dir->state = mwDirectory_NEW; + + return dir; +} + + +enum mwDirectoryState mwDirectory_getState(struct mwDirectory *dir) { + g_return_val_if_fail(dir != NULL, mwDirectory_UNKNOWN); + return dir->state; +} + + +void mwDirectory_setClientData(struct mwDirectory *dir, + gpointer data, GDestroyNotify clear) { + + g_return_if_fail(dir != NULL); + mw_datum_set(&dir->client_data, data, clear); +} + + +gpointer mwDirectory_getClientData(struct mwDirectory *dir) { + g_return_val_if_fail(dir != NULL, NULL); + return mw_datum_get(&dir->client_data); +} + + +void mwDirectory_removeClientData(struct mwDirectory *dir) { + g_return_if_fail(dir != NULL); + mw_datum_clear(&dir->client_data); +} + + +struct mwServiceDirectory *mwDirectory_getService(struct mwDirectory *dir) { + g_return_val_if_fail(dir != NULL, NULL); + g_return_val_if_fail(dir->book != NULL, NULL); + return dir->book->service; +} + + +struct mwAddressBook *mwDirectory_getAddressBook(struct mwDirectory *dir) { + g_return_val_if_fail(dir != NULL, NULL); + return dir->book; +} + + +static int dir_open(struct mwDirectory *dir) { + struct mwServiceDirectory *srvc; + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(dir != NULL, -1); + + srvc = dir->service; + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, map_request(dir)); + + /* unsure about these three bytes */ + gboolean_put(b, FALSE); + guint16_put(b, 0x0000); + + guint32_put(b, dir->book->id); + mwString_put(b, dir->book->name); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_open, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwDirectory_open(struct mwDirectory *dir, mwSearchHandler cb) { + g_return_val_if_fail(dir != NULL, -1); + g_return_val_if_fail(cb != NULL, -1); + g_return_val_if_fail(MW_DIRECTORY_IS_NEW(dir), -1); + + dir->state = mwDirectory_PENDING; + dir->handler = cb; + + return dir_open(dir); +} + + +int mwDirectory_next(struct mwDirectory *dir) { + struct mwServiceDirectory *srvc; + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(dir != NULL, -1); + g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1); + + srvc = dir->service; + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, map_request(dir)); + guint32_put(b, dir->id); + guint16_put(b, 0xffff); /* some magic? */ + guint32_put(b, 0x00000000); /* next results */ + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_search, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwDirectory_previous(struct mwDirectory *dir) { + struct mwServiceDirectory *srvc; + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(dir != NULL, -1); + g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1); + + srvc = dir->service; + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, map_request(dir)); + guint32_put(b, dir->id); + guint16_put(b, 0x0061); /* some magic? */ + guint32_put(b, 0x00000001); /* prev results */ + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_search, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwDirectory_search(struct mwDirectory *dir, const char *query) { + struct mwServiceDirectory *srvc; + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(dir != NULL, -1); + g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1); + g_return_val_if_fail(query != NULL, -1); + g_return_val_if_fail(*query != '\0', -1); + + srvc = dir->service; + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, map_request(dir)); + guint32_put(b, dir->id); + guint16_put(b, 0x0061); /* some magic? */ + guint32_put(b, 0x00000008); /* seek results */ + mwString_put(b, query); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_search, &o); + mwOpaque_clear(&o); + + return ret; +} + + +static int dir_close(struct mwDirectory *dir) { + struct mwServiceDirectory *srvc; + struct mwChannel *chan; + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + g_return_val_if_fail(dir != NULL, -1); + + srvc = dir->service; + g_return_val_if_fail(srvc != NULL, -1); + + chan = srvc->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + guint32_put(b, next_request_id(dir->service)); + guint32_put(b, dir->id); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, action_close, &o); + mwOpaque_clear(&o); + + return ret; +} + + +int mwDirectory_destroy(struct mwDirectory *dir) { + int ret = 0; + + g_return_val_if_fail(dir != NULL, -1); + + if(MW_DIRECTORY_IS_OPEN(dir) || MW_DIRECTORY_IS_PENDING(dir)) { + ret = dir_close(dir); + } + dir_remove(dir); + + return ret; +} + diff --git a/protocols/Sametime/src/meanwhile/src/srvc_ft.c b/protocols/Sametime/src/meanwhile/src/srvc_ft.c new file mode 100644 index 0000000000..38479e3452 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_ft.c @@ -0,0 +1,667 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <glib/glist.h> + +#include "mw_channel.h" +#include "mw_common.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_ft.h" +#include "mw_util.h" + + +#define PROTOCOL_TYPE 0x00000000 +#define PROTOCOL_VER 0x00000001 + + +/** send-on-channel type: FT transfer data */ +#define msg_TRANSFER 0x0001 + + +/** ack received transfer data */ +#define msg_RECEIVED 0x0002 + + +struct mwServiceFileTransfer { + struct mwService service; + + struct mwFileTransferHandler *handler; + GList *transfers; +}; + + +struct mwFileTransfer { + struct mwServiceFileTransfer *service; + + struct mwChannel *channel; + struct mwIdBlock who; + + enum mwFileTransferState state; + + char *filename; + char *message; + + guint32 size; + guint32 remaining; + + struct mw_datum client_data; +}; + + +/** momentarily places a mwLoginInfo into a mwIdBlock */ +static void login_into_id(struct mwIdBlock *to, struct mwLoginInfo *from) { + to->user = from->user_id; + to->community = from->community; +} + + +static const char *ft_state_str(enum mwFileTransferState state) { + switch(state) { + case mwFileTransfer_NEW: + return "new"; + + case mwFileTransfer_PENDING: + return "pending"; + + case mwFileTransfer_OPEN: + return "open"; + + case mwFileTransfer_CANCEL_LOCAL: + return "cancelled locally"; + + case mwFileTransfer_CANCEL_REMOTE: + return "cancelled remotely"; + + case mwFileTransfer_DONE: + return "done"; + + case mwFileTransfer_ERROR: + return "error"; + + case mwFileTransfer_UNKNOWN: + default: + return "UNKNOWN"; + } +} + + +static void ft_state(struct mwFileTransfer *ft, + enum mwFileTransferState state) { + + g_return_if_fail(ft != NULL); + + if(ft->state == state) return; + + // Miranda NG adaptation + //g_info("setting ft (%s, %s) state: %s", + // NSTR(ft->who.user), NSTR(ft->who.community), + // ft_state_str(state)); + g_message("setting ft (%s, %s) state: %s", NSTR(ft->who.user), NSTR(ft->who.community), ft_state_str(state)); + + ft->state = state; +} + + +static void recv_channelCreate(struct mwServiceFileTransfer *srvc, + struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + struct mwFileTransferHandler *handler; + struct mwGetBuffer *b; + + char *fnm, *txt; + guint32 size, junk; + gboolean b_err; + + g_return_if_fail(srvc->handler != NULL); + handler = srvc->handler; + + b = mwGetBuffer_wrap(&msg->addtl); + + guint32_get(b, &junk); /* unknown */ + mwString_get(b, &fnm); /* offered filename */ + mwString_get(b, &txt); /* offering message */ + guint32_get(b, &size); /* size of offered file */ + /// Miranda NG adaptation - start - http://www.lilotux.net/~mikael/pub/meanwhile/ft_fix.diff + /* guint32_get(b, &junk); */ /* unknown */ + /// Miranda NG adaptation - end + /* and we just skip an unknown guint16 at the end */ + + b_err = mwGetBuffer_error(b); + mwGetBuffer_free(b); + + if(b_err) { + g_warning("bad/malformed addtl in File Transfer service"); + mwChannel_destroy(chan, ERR_FAILURE, NULL); + + } else { + struct mwIdBlock idb; + struct mwFileTransfer *ft; + + login_into_id(&idb, mwChannel_getUser(chan)); + ft = mwFileTransfer_new(srvc, &idb, txt, fnm, size); + ft->channel = chan; + ft_state(ft, mwFileTransfer_PENDING); + + mwChannel_setServiceData(chan, ft, NULL); + + if(handler->ft_offered) + handler->ft_offered(ft); + } + + g_free(fnm); + g_free(txt); +} + + +static void recv_channelAccept(struct mwServiceFileTransfer *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + struct mwFileTransferHandler *handler; + struct mwFileTransfer *ft; + + g_return_if_fail(srvc->handler != NULL); + handler = srvc->handler; + + ft = mwChannel_getServiceData(chan); + g_return_if_fail(ft != NULL); + + ft_state(ft, mwFileTransfer_OPEN); + + if(handler->ft_opened) + handler->ft_opened(ft); +} + + +static void recv_channelDestroy(struct mwServiceFileTransfer *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + struct mwFileTransferHandler *handler; + struct mwFileTransfer *ft; + guint32 code; + + code = msg->reason; + + g_return_if_fail(srvc->handler != NULL); + handler = srvc->handler; + + ft = mwChannel_getServiceData(chan); + g_return_if_fail(ft != NULL); + + ft->channel = NULL; + + if(! mwFileTransfer_isDone(ft)) + ft_state(ft, mwFileTransfer_CANCEL_REMOTE); + + mwFileTransfer_close(ft, code); +} + + +static void recv_TRANSFER(struct mwFileTransfer *ft, + struct mwOpaque *data) { + + struct mwServiceFileTransfer *srvc; + struct mwFileTransferHandler *handler; + + srvc = ft->service; + handler = srvc->handler; + + g_return_if_fail(mwFileTransfer_isOpen(ft)); + + if(data->len > ft->remaining) { + /* @todo handle error */ + + } else { + ft->remaining -= data->len; + + if(! ft->remaining) + ft_state(ft, mwFileTransfer_DONE); + + if(handler->ft_recv) + handler->ft_recv(ft, data); + } +} + + +static void recv_RECEIVED(struct mwFileTransfer *ft, + struct mwOpaque *data) { + + struct mwServiceFileTransfer *srvc; + struct mwFileTransferHandler *handler; + + srvc = ft->service; + handler = srvc->handler; + + if(! ft->remaining) + ft_state(ft, mwFileTransfer_DONE); + + if(handler->ft_ack) + handler->ft_ack(ft); + + if(! ft->remaining) + mwFileTransfer_close(ft, mwFileTransfer_SUCCESS); +} + + +static void recv(struct mwService *srvc, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + struct mwFileTransfer *ft; + + ft = mwChannel_getServiceData(chan); + g_return_if_fail(ft != NULL); + + switch(type) { + case msg_TRANSFER: + recv_TRANSFER(ft, data); + break; + + case msg_RECEIVED: + recv_RECEIVED(ft, data); + break; + + default: + mw_mailme_opaque(data, "unknown message in ft service: 0x%04x", type); + } +} + + +static void clear(struct mwServiceFileTransfer *srvc) { + struct mwFileTransferHandler *h; + + h = srvc->handler; + if(h && h->clear) + h->clear(srvc); + srvc->handler = NULL; +} + + +static const char *name(struct mwService *srvc) { + return "File Transfer"; +} + + +static const char *desc(struct mwService *srvc) { + return "Provides file transfer capabilities through the community server"; +} + + +static void start(struct mwService *srvc) { + mwService_started(srvc); +} + + +static void stop(struct mwServiceFileTransfer *srvc) { + while(srvc->transfers) { + mwFileTransfer_free(srvc->transfers->data); + } + + mwService_stopped(MW_SERVICE(srvc)); +} + + +struct mwServiceFileTransfer * +mwServiceFileTransfer_new(struct mwSession *session, + struct mwFileTransferHandler *handler) { + + struct mwServiceFileTransfer *srvc_ft; + struct mwService *srvc; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + srvc_ft = g_new0(struct mwServiceFileTransfer, 1); + srvc = MW_SERVICE(srvc_ft); + + mwService_init(srvc, session, mwService_FILE_TRANSFER); + srvc->recv_create = (mwService_funcRecvCreate) recv_channelCreate; + srvc->recv_accept = (mwService_funcRecvAccept) recv_channelAccept; + srvc->recv_destroy = (mwService_funcRecvDestroy) recv_channelDestroy; + srvc->recv = recv; + srvc->clear = (mwService_funcClear) clear; + srvc->get_name = name; + srvc->get_desc = desc; + srvc->start = start; + srvc->stop = (mwService_funcStop) stop; + + srvc_ft->handler = handler; + + return srvc_ft; +} + + +struct mwFileTransferHandler * +mwServiceFileTransfer_getHandler(struct mwServiceFileTransfer *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->handler; +} + + +const GList * +mwServiceFileTransfer_getTransfers(struct mwServiceFileTransfer *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->transfers; +} + + +/// Miranda NG adaptation start - new method +struct mwService * +mwServiceFileTransfer_getService(struct mwServiceFileTransfer *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end + + +struct mwFileTransfer * +mwFileTransfer_new(struct mwServiceFileTransfer *srvc, + const struct mwIdBlock *who, const char *msg, + const char *filename, guint32 filesize) { + + struct mwFileTransfer *ft; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(who != NULL, NULL); + + ft = g_new0(struct mwFileTransfer, 1); + ft->service = srvc; + mwIdBlock_clone(&ft->who, who); + ft->filename = g_strdup(filename); + ft->message = g_strdup(msg); + ft->size = ft->remaining = filesize; + + ft_state(ft, mwFileTransfer_NEW); + + /* stick a reference in the service */ + srvc->transfers = g_list_prepend(srvc->transfers, ft); + + return ft; +} + + +struct mwServiceFileTransfer * +mwFileTransfer_getService(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, NULL); + return ft->service; +} + + +enum mwFileTransferState +mwFileTransfer_getState(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, mwFileTransfer_UNKNOWN); + return ft->state; +} + + +const struct mwIdBlock * +mwFileTransfer_getUser(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, NULL); + return &ft->who; +} + + +const char * +mwFileTransfer_getMessage(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, NULL); + return ft->message; +} + + +const char * +mwFileTransfer_getFileName(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, NULL); + return ft->filename; +} + + +guint32 mwFileTransfer_getFileSize(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, 0); + return ft->size; +} + + +guint32 mwFileTransfer_getRemaining(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, 0); + return ft->remaining; +} + + +int mwFileTransfer_accept(struct mwFileTransfer *ft) { + struct mwServiceFileTransfer *srvc; + struct mwFileTransferHandler *handler; + int ret; + + g_return_val_if_fail(ft != NULL, -1); + g_return_val_if_fail(ft->channel != NULL, -1); + g_return_val_if_fail(mwFileTransfer_isPending(ft), -1); + g_return_val_if_fail(mwChannel_isIncoming(ft->channel), -1); + g_return_val_if_fail(mwChannel_isState(ft->channel, mwChannel_WAIT), -1); + + g_return_val_if_fail(ft->service != NULL, -1); + srvc = ft->service; + + g_return_val_if_fail(srvc->handler != NULL, -1); + handler = srvc->handler; + + ret = mwChannel_accept(ft->channel); + + if(ret) { + mwFileTransfer_close(ft, ERR_FAILURE); + + } else { + ft_state(ft, mwFileTransfer_OPEN); + if(handler->ft_opened) + handler->ft_opened(ft); + } + + return ret; +} + + +static void ft_create_chan(struct mwFileTransfer *ft) { + struct mwSession *s; + struct mwChannelSet *cs; + struct mwChannel *chan; + struct mwLoginInfo *login; + struct mwPutBuffer *b; + + /* we only should be calling this if there isn't a channel already + associated with the conversation */ + g_return_if_fail(ft != NULL); + g_return_if_fail(mwFileTransfer_isNew(ft)); + g_return_if_fail(ft->channel == NULL); + + s = mwService_getSession(MW_SERVICE(ft->service)); + cs = mwSession_getChannels(s); + + chan = mwChannel_newOutgoing(cs); + mwChannel_setService(chan, MW_SERVICE(ft->service)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + /* offer all known ciphers */ + mwChannel_populateSupportedCipherInstances(chan); + + /* set the target */ + login = mwChannel_getUser(chan); + login->user_id = g_strdup(ft->who.user); + login->community = g_strdup(ft->who.community); + + /* compose the addtl create */ + b = mwPutBuffer_new(); + guint32_put(b, 0x00); + mwString_put(b, ft->filename); + mwString_put(b, ft->message); + guint32_put(b, ft->size); + guint32_put(b, 0x00); + guint16_put(b, 0x00); + + mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b); + + ft->channel = mwChannel_create(chan)? NULL: chan; + if(ft->channel) { + mwChannel_setServiceData(ft->channel, ft, NULL); + } +} + + +int mwFileTransfer_offer(struct mwFileTransfer *ft) { + struct mwServiceFileTransfer *srvc; + struct mwFileTransferHandler *handler; + + g_return_val_if_fail(ft != NULL, -1); + g_return_val_if_fail(ft->channel == NULL, -1); + g_return_val_if_fail(mwFileTransfer_isNew(ft), -1); + + g_return_val_if_fail(ft->service != NULL, -1); + srvc = ft->service; + + g_return_val_if_fail(srvc->handler != NULL, -1); + handler = srvc->handler; + + ft_create_chan(ft); + if(ft->channel) { + ft_state(ft, mwFileTransfer_PENDING); + } else { + ft_state(ft, mwFileTransfer_ERROR); + mwFileTransfer_close(ft, ERR_FAILURE); + } + + return 0; +} + + +int mwFileTransfer_close(struct mwFileTransfer *ft, guint32 code) { + struct mwServiceFileTransfer *srvc; + struct mwFileTransferHandler *handler; + int ret = 0; + + g_return_val_if_fail(ft != NULL, -1); + + if(mwFileTransfer_isOpen(ft)) + ft_state(ft, mwFileTransfer_CANCEL_LOCAL); + + if(ft->channel) { + ret = mwChannel_destroy(ft->channel, code, NULL); + ft->channel = NULL; + } + + srvc = ft->service; + g_return_val_if_fail(srvc != NULL, ret); + + handler = srvc->handler; + g_return_val_if_fail(handler != NULL, ret); + + if(handler->ft_closed) + handler->ft_closed(ft, code); + + return ret; +} + + +void mwFileTransfer_free(struct mwFileTransfer *ft) { + struct mwServiceFileTransfer *srvc; + + if(! ft) return; + + srvc = ft->service; + if(srvc) + srvc->transfers = g_list_remove(srvc->transfers, ft); + + if(ft->channel) { + mwChannel_destroy(ft->channel, mwFileTransfer_SUCCESS, NULL); + ft->channel = NULL; + } + + mwFileTransfer_removeClientData(ft); + + mwIdBlock_clear(&ft->who); + g_free(ft->filename); + g_free(ft->message); + g_free(ft); +} + + +int mwFileTransfer_send(struct mwFileTransfer *ft, + struct mwOpaque *data) { + + struct mwChannel *chan; + int ret; + + g_return_val_if_fail(ft != NULL, -1); + g_return_val_if_fail(mwFileTransfer_isOpen(ft), -1); + g_return_val_if_fail(ft->channel != NULL, -1); + chan = ft->channel; + + g_return_val_if_fail(mwChannel_isOutgoing(chan), -1); + + if(data->len > ft->remaining) { + /* @todo handle error */ + return -1; + } + + ret = mwChannel_send(chan, msg_TRANSFER, data); + if(! ret) ft->remaining -= data->len; + + /* we're not done until we receive an ACK for the last piece of + outgoing data */ + + return ret; +} + + +int mwFileTransfer_ack(struct mwFileTransfer *ft) { + struct mwChannel *chan; + + g_return_val_if_fail(ft != NULL, -1); + + chan = ft->channel; + g_return_val_if_fail(chan != NULL, -1); + g_return_val_if_fail(mwChannel_isIncoming(chan), -1); + + return mwChannel_sendEncrypted(chan, msg_RECEIVED, NULL, FALSE); +} + + +void mwFileTransfer_setClientData(struct mwFileTransfer *ft, + gpointer data, GDestroyNotify clean) { + g_return_if_fail(ft != NULL); + mw_datum_set(&ft->client_data, data, clean); +} + + +gpointer mwFileTransfer_getClientData(struct mwFileTransfer *ft) { + g_return_val_if_fail(ft != NULL, NULL); + return mw_datum_get(&ft->client_data); +} + + +void mwFileTransfer_removeClientData(struct mwFileTransfer *ft) { + g_return_if_fail(ft != NULL); + mw_datum_clear(&ft->client_data); +} + diff --git a/protocols/Sametime/src/meanwhile/src/srvc_im.c b/protocols/Sametime/src/meanwhile/src/srvc_im.c new file mode 100644 index 0000000000..b03991d3b9 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_im.c @@ -0,0 +1,1095 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <glib/glist.h> +#include <string.h> + +#include "mw_channel.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_im.h" +#include "mw_util.h" + + +#define PROTOCOL_TYPE 0x00001000 +#define PROTOCOL_VER 0x00000003 + + +/* data for the addtl blocks of channel creation */ +#define mwImAddtlA_NORMAL 0x00000001 + +#define mwImAddtlB_NORMAL 0x00000001 /**< standard */ +#define mwImAddtlB_PRECONF 0x00000019 /**< pre-conference chat */ +#define mwImAddtlB_NOTESBUDDY 0x00033453 /**< notesbuddy */ + +#define mwImAddtlC_NORMAL 0x00000002 + + +/* send-on-channel message type */ +#define msg_MESSAGE 0x0064 /**< IM message */ + + +#define BREAKUP 2048 + + +/* which type of im? */ +enum mwImType { + mwIm_TEXT = 0x00000001, /**< text message */ + mwIm_DATA = 0x00000002, /**< status message (usually) */ +}; + + +/* which type of data im? */ +enum mwImDataType { + mwImData_TYPING = 0x00000001, /**< common use typing indicator */ + mwImData_SUBJECT = 0x00000003, /**< notesbuddy IM topic */ + mwImData_HTML = 0x00000004, /**< notesbuddy HTML message */ + mwImData_MIME = 0x00000005, /**< notesbuddy MIME message, w/image */ + mwImData_TIMESTAMP = 0x00000006, /**< notesbuddy timestamp */ + + mwImData_INVITE = 0x0000000a, /**< Places invitation */ + + mwImData_MULTI_START = 0x00001388, + mwImData_MULTI_STOP = 0x00001389, +}; + + +/** @todo might be appropriate to make a couple of hashtables to + reference conversations by channel and target */ +struct mwServiceIm { + struct mwService service; + + enum mwImClientType features; + + struct mwImHandler *handler; + GList *convs; /**< list of struct im_convo */ +}; + + +struct mwConversation { + struct mwServiceIm *service; /**< owning service */ + struct mwChannel *channel; /**< channel */ + struct mwIdBlock target; /**< conversation target */ + + gboolean ext_id; /**< special treatment, external ID */ + + /** state of the conversation, based loosely on the state of its + underlying channel */ + enum mwConversationState state; + + enum mwImClientType features; + + GString *multi; /**< buffer for multi-chunk message */ + enum mwImSendType multi_type; /**< type of incoming multi-chunk message */ + + struct mw_datum client_data; +}; + + +/** momentarily places a mwLoginInfo into a mwIdBlock */ +static void login_into_id(struct mwIdBlock *to, struct mwLoginInfo *from) { + to->user = from->user_id; + to->community = from->community; +} + + +static struct mwConversation *convo_find_by_user(struct mwServiceIm *srvc, + struct mwIdBlock *to) { + GList *l; + + for(l = srvc->convs; l; l = l->next) { + struct mwConversation *c = l->data; + if(mwIdBlock_equal(&c->target, to)) + return c; + } + + return NULL; +} + + +static const char *conv_state_str(enum mwConversationState state) { + switch(state) { + case mwConversation_CLOSED: + return "closed"; + + case mwConversation_OPEN: + return "open"; + + case mwConversation_PENDING: + return "pending"; + + case mwConversation_UNKNOWN: + default: + return "UNKNOWN"; + } +} + + +static void convo_set_state(struct mwConversation *conv, + enum mwConversationState state) { + + g_return_if_fail(conv != NULL); + + if(conv->state != state) { + // Miranda NG adaptation + //g_info("setting conversation (%s, %s) state: %s", + // NSTR(conv->target.user), NSTR(conv->target.community), + // conv_state_str(state)); + g_message("setting conversation (%s, %s) state: %s", NSTR(conv->target.user), NSTR(conv->target.community), conv_state_str(state)); + conv->state = state; + } +} + + +struct mwConversation *mwServiceIm_findConversation(struct mwServiceIm *srvc, + struct mwIdBlock *to) { + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + + return convo_find_by_user(srvc, to); +} + + +struct mwConversation *mwServiceIm_getConversation(struct mwServiceIm *srvc, + struct mwIdBlock *to) { + struct mwConversation *c; + + g_return_val_if_fail(srvc != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + + c = convo_find_by_user(srvc, to); + if(! c) { + c = g_new0(struct mwConversation, 1); + c->service = srvc; + mwIdBlock_clone(&c->target, to); + c->state = mwConversation_CLOSED; + c->features = srvc->features; + + /* mark external users */ + /* c->ext_id = g_str_has_prefix(to->user, "@E "); */ + + srvc->convs = g_list_prepend(srvc->convs, c); + } + + return c; +} + + +static void convo_create_chan(struct mwConversation *c) { + struct mwSession *s; + struct mwChannelSet *cs; + struct mwChannel *chan; + struct mwLoginInfo *login; + struct mwPutBuffer *b; + + /* we only should be calling this if there isn't a channel already + associated with the conversation */ + g_return_if_fail(c != NULL); + g_return_if_fail(mwConversation_isPending(c)); + g_return_if_fail(c->channel == NULL); + + s = mwService_getSession(MW_SERVICE(c->service)); + cs = mwSession_getChannels(s); + + chan = mwChannel_newOutgoing(cs); + mwChannel_setService(chan, MW_SERVICE(c->service)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + /* offer all known ciphers */ + mwChannel_populateSupportedCipherInstances(chan); + + /* set the target */ + login = mwChannel_getUser(chan); + login->user_id = g_strdup(c->target.user); + login->community = g_strdup(c->target.community); + + /* compose the addtl create, with optional FANCY HTML! */ + b = mwPutBuffer_new(); + guint32_put(b, mwImAddtlA_NORMAL); + guint32_put(b, c->features); + mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b); + + c->channel = mwChannel_create(chan)? NULL: chan; + if(c->channel) { + mwChannel_setServiceData(c->channel, c, NULL); + } +} + + +void mwConversation_open(struct mwConversation *conv) { + g_return_if_fail(conv != NULL); + g_return_if_fail(mwConversation_isClosed(conv)); + + convo_set_state(conv, mwConversation_PENDING); + convo_create_chan(conv); +} + + +static void convo_opened(struct mwConversation *conv) { + struct mwImHandler *h = NULL; + + g_return_if_fail(conv != NULL); + g_return_if_fail(conv->service != NULL); + + convo_set_state(conv, mwConversation_OPEN); + h = conv->service->handler; + + g_return_if_fail(h != NULL); + + if(h->conversation_opened) + h->conversation_opened(conv); +} + + +static void convo_free(struct mwConversation *conv) { + struct mwServiceIm *srvc; + + mwConversation_removeClientData(conv); + + srvc = conv->service; + srvc->convs = g_list_remove_all(srvc->convs, conv); + + mwIdBlock_clear(&conv->target); + g_free(conv); +} + + +static int send_accept(struct mwConversation *c) { + + struct mwChannel *chan = c->channel; + struct mwSession *s = mwChannel_getSession(chan); + struct mwUserStatus *stat = mwSession_getUserStatus(s); + + struct mwPutBuffer *b; + struct mwOpaque *o; + + b = mwPutBuffer_new(); + guint32_put(b, mwImAddtlA_NORMAL); + guint32_put(b, c->features); + guint32_put(b, mwImAddtlC_NORMAL); + mwUserStatus_put(b, stat); + + o = mwChannel_getAddtlAccept(chan); + mwOpaque_clear(o); + mwPutBuffer_finalize(o, b); + + return mwChannel_accept(chan); +} + + +static void recv_channelCreate(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + /* - ensure it's the right service,proto,and proto ver + - check the opaque for the right opaque junk + - if not, close channel + - compose & send a channel accept + */ + + struct mwServiceIm *srvc_im = (struct mwServiceIm *) srvc; + struct mwImHandler *handler; + struct mwSession *s; + struct mwUserStatus *stat; + guint32 x, y, z; + struct mwGetBuffer *b; + struct mwConversation *c = NULL; + struct mwIdBlock idb; + + handler = srvc_im->handler; + s = mwChannel_getSession(chan); + stat = mwSession_getUserStatus(s); + + /* ensure the appropriate service/proto/ver */ + x = mwChannel_getServiceId(chan); + y = mwChannel_getProtoType(chan); + z = mwChannel_getProtoVer(chan); + + if( (x != mwService_IM) || (y != PROTOCOL_TYPE) || (z != PROTOCOL_VER) ) { + g_warning("unacceptable service, proto, ver:" + " 0x%08x, 0x%08x, 0x%08x", x, y, z); + mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL); + return; + } + + /* act upon the values in the addtl block */ + b = mwGetBuffer_wrap(&msg->addtl); + guint32_get(b, &x); + guint32_get(b, &y); + z = (guint) mwGetBuffer_error(b); + mwGetBuffer_free(b); + + if(z /* buffer error, BOOM! */ ) { + g_warning("bad/malformed addtl in IM service"); + mwChannel_destroy(chan, ERR_FAILURE, NULL); + return; + + } else if(x != mwImAddtlA_NORMAL) { + g_message("unknown params: 0x%08x, 0x%08x", x, y); + mwChannel_destroy(chan, ERR_IM_NOT_REGISTERED, NULL); + return; + + } else if(y == mwImAddtlB_PRECONF) { + if(! handler->place_invite) { + // Miranda NG adaptation + //g_info("rejecting place-invite channel"); + g_message("rejecting place-invite channel"); + mwChannel_destroy(chan, ERR_IM_NOT_REGISTERED, NULL); + return; + + } else { + // Miranda NG adaptation + //g_info("accepting place-invite channel"); + g_message("accepting place-invite channel"); + } + + } else if(y != mwImClient_PLAIN && y != srvc_im->features) { + /** reject what we do not understand */ + mwChannel_destroy(chan, ERR_IM_NOT_REGISTERED, NULL); + return; + + } else if(stat->status == mwStatus_BUSY) { + // Miranda NG adaptation + //g_info("rejecting IM channel due to DND status"); + g_message("rejecting IM channel due to DND status"); + mwChannel_destroy(chan, ERR_CLIENT_USER_DND, NULL); + return; + } + + login_into_id(&idb, mwChannel_getUser(chan)); + +#if 0 + c = convo_find_by_user(srvc_im, &idb); +#endif + + if(! c) { + c = g_new0(struct mwConversation, 1); + c->service = srvc_im; + srvc_im->convs = g_list_prepend(srvc_im->convs, c); + } + +#if 0 + /* we're going to re-associate any existing conversations with this + new channel. That means closing any existing ones */ + if(c->channel) { + // Miranda NG adaptation + //g_info("closing existing IM channel 0x%08x", mwChannel_getId(c->channel)); + g_message("closing existing IM channel 0x%08x", mwChannel_getId(c->channel)); + mwConversation_close(c, ERR_SUCCESS); + } +#endif + + /* set up the conversation with this channel, target, and be fancy + if the other side requested it */ + c->channel = chan; + mwIdBlock_clone(&c->target, &idb); + c->features = y; + convo_set_state(c, mwConversation_PENDING); + mwChannel_setServiceData(c->channel, c, NULL); + + if(send_accept(c)) { + g_warning("sending IM channel accept failed"); + mwConversation_free(c); + + } else { + convo_opened(c); + } +} + + +static void recv_channelAccept(struct mwService *srvc, struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + struct mwConversation *conv; + + conv = mwChannel_getServiceData(chan); + if(! conv) { + g_warning("received channel accept for non-existant conversation"); + mwChannel_destroy(chan, ERR_FAILURE, NULL); + return; + } + + convo_opened(conv); +} + + +static void recv_channelDestroy(struct mwService *srvc, struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + struct mwConversation *c; + + c = mwChannel_getServiceData(chan); + g_return_if_fail(c != NULL); + + c->channel = NULL; + + if(mwChannel_isState(chan, mwChannel_ERROR)) { + + /* checking for failure on the receiving end to accept html + messages. Fail-over to a non-html format on a new channel for + the convo */ + if(c->features != mwImClient_PLAIN + && (msg->reason == ERR_IM_NOT_REGISTERED || + msg->reason == ERR_SERVICE_NO_SUPPORT)) { + + g_debug("falling back on a plaintext conversation"); + c->features = mwImClient_PLAIN; + convo_create_chan(c); + return; + } + } + + mwConversation_close(c, msg->reason); +} + + +static void convo_recv(struct mwConversation *conv, enum mwImSendType type, + gconstpointer msg) { + + struct mwServiceIm *srvc; + struct mwImHandler *handler; + + g_return_if_fail(conv != NULL); + + srvc = conv->service; + g_return_if_fail(srvc != NULL); + + handler = srvc->handler; + if(handler && handler->conversation_recv) + handler->conversation_recv(conv, type, msg); +} + + +static void convo_multi_start(struct mwConversation *conv) { + g_return_if_fail(conv->multi == NULL); + conv->multi = g_string_new(NULL); +} + + +static void convo_multi_stop(struct mwConversation *conv) { + + g_return_if_fail(conv->multi != NULL); + + /* actually send it */ + convo_recv(conv, conv->multi_type, conv->multi->str); + + /* clear up the multi buffer */ + g_string_free(conv->multi, TRUE); + conv->multi = NULL; +} + + +static void recv_text(struct mwServiceIm *srvc, struct mwChannel *chan, + struct mwGetBuffer *b) { + + struct mwConversation *c; + char *text = NULL; + + mwString_get(b, &text); + + if(! text) return; + + c = mwChannel_getServiceData(chan); + if(c) { + if(c->multi) { + g_string_append(c->multi, text); + + } else { + convo_recv(c, mwImSend_PLAIN, text); + } + } + + g_free(text); +} + + +static void convo_invite(struct mwConversation *conv, + struct mwOpaque *o) { + + struct mwServiceIm *srvc; + struct mwImHandler *handler; + + struct mwGetBuffer *b; + char *title, *name, *msg; + char *unkn, *host; + guint16 with_who; + + // Miranda NG adaptation + //g_info("convo_invite"); + g_message("convo_invite"); + + srvc = conv->service; + handler = srvc->handler; + + g_return_if_fail(handler != NULL); + g_return_if_fail(handler->place_invite != NULL); + + b = mwGetBuffer_wrap(o); + mwGetBuffer_advance(b, 4); + mwString_get(b, &title); + mwString_get(b, &msg); + mwGetBuffer_advance(b, 19); + mwString_get(b, &name); + + /* todo: add a mwString_skip */ + mwString_get(b, &unkn); + mwString_get(b, &host); + g_free(unkn); + g_free(host); + + /* hack. Sometimes incoming convo invitation channels won't have the + owner id block filled in */ + guint16_get(b, &with_who); + if(with_who && !conv->target.user) { + char *login; + mwString_get(b, &conv->target.user); + mwString_get(b, &login); g_free(login); + mwString_get(b, &conv->target.community); + } + + if(mwGetBuffer_error(b)) { + mw_mailme_opaque(o, "problem with place invite over IM service"); + } else { + handler->place_invite(conv, msg, title, name); + } + + mwGetBuffer_free(b); + g_free(msg); + g_free(title); + g_free(name); +} + + +static void recv_data(struct mwServiceIm *srvc, struct mwChannel *chan, + struct mwGetBuffer *b) { + + struct mwConversation *conv; + guint32 type, subtype; + struct mwOpaque o = { 0, 0 }; + char *x; + + guint32_get(b, &type); + guint32_get(b, &subtype); + mwOpaque_get(b, &o); + + if(mwGetBuffer_error(b)) { + mwOpaque_clear(&o); + return; + } + + conv = mwChannel_getServiceData(chan); + if(! conv) return; + + switch(type) { + case mwImData_TYPING: + convo_recv(conv, mwImSend_TYPING, GINT_TO_POINTER(! subtype)); + break; + + case mwImData_HTML: + if(o.len) { + if(conv->multi) { + g_string_append_len(conv->multi, (char *) o.data, o.len); + conv->multi_type = mwImSend_HTML; + + } else { + x = g_strndup((char *) o.data, o.len); + convo_recv(conv, mwImSend_HTML, x); + g_free(x); + } + } + break; + + case mwImData_SUBJECT: + x = g_strndup((char *) o.data, o.len); + convo_recv(conv, mwImSend_SUBJECT, x); + g_free(x); + break; + + case mwImData_MIME: + if(conv->multi) { + g_string_append_len(conv->multi, (char *) o.data, o.len); + conv->multi_type = mwImSend_MIME; + + } else { + x = g_strndup((char *) o.data, o.len); + convo_recv(conv, mwImSend_MIME, x); + g_free(x); + } + break; + + case mwImData_TIMESTAMP: + /* todo */ + break; + + case mwImData_INVITE: + convo_invite(conv, &o); + break; + + case mwImData_MULTI_START: + convo_multi_start(conv); + break; + + case mwImData_MULTI_STOP: + convo_multi_stop(conv); + break; + + default: + + mw_mailme_opaque(&o, "unknown data message type in IM service:" + " (0x%08x, 0x%08x)", type, subtype); + } + + mwOpaque_clear(&o); +} + + +static void recv(struct mwService *srvc, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + /* - ensure message type is something we want + - parse message type into either mwIMText or mwIMData + - handle + */ + + struct mwGetBuffer *b; + guint32 mt; + + g_return_if_fail(type == msg_MESSAGE); + + b = mwGetBuffer_wrap(data); + guint32_get(b, &mt); + + if(mwGetBuffer_error(b)) { + g_warning("failed to parse message for IM service"); + mwGetBuffer_free(b); + return; + } + + switch(mt) { + case mwIm_TEXT: + recv_text((struct mwServiceIm *) srvc, chan, b); + break; + + case mwIm_DATA: + recv_data((struct mwServiceIm *) srvc, chan, b); + break; + + default: + g_warning("unknown message type 0x%08x for IM service", mt); + } + + if(mwGetBuffer_error(b)) + g_warning("failed to parse message type 0x%08x for IM service", mt); + + mwGetBuffer_free(b); +} + + +static void clear(struct mwServiceIm *srvc) { + struct mwImHandler *h; + + while(srvc->convs) + convo_free(srvc->convs->data); + + h = srvc->handler; + if(h && h->clear) + h->clear(srvc); + srvc->handler = NULL; +} + + +static const char *name(struct mwService *srvc) { + return "Instant Messaging"; +} + + +static const char *desc(struct mwService *srvc) { + return "IM service with Standard and NotesBuddy features"; +} + + +static void start(struct mwService *srvc) { + mwService_started(srvc); +} + + +static void stop(struct mwServiceIm *srvc) { + + while(srvc->convs) + mwConversation_free(srvc->convs->data); + + mwService_stopped(MW_SERVICE(srvc)); +} + + +struct mwServiceIm *mwServiceIm_new(struct mwSession *session, + struct mwImHandler *hndl) { + + struct mwServiceIm *srvc_im; + struct mwService *srvc; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(hndl != NULL, NULL); + + srvc_im = g_new0(struct mwServiceIm, 1); + srvc = MW_SERVICE(srvc_im); + + mwService_init(srvc, session, mwService_IM); + srvc->recv_create = recv_channelCreate; + srvc->recv_accept = recv_channelAccept; + srvc->recv_destroy = recv_channelDestroy; + srvc->recv = recv; + srvc->clear = (mwService_funcClear) clear; + srvc->get_name = name; + srvc->get_desc = desc; + srvc->start = start; + srvc->stop = (mwService_funcStop) stop; + + srvc_im->features = mwImClient_PLAIN; + srvc_im->handler = hndl; + + return srvc_im; +} + + +struct mwImHandler *mwServiceIm_getHandler(struct mwServiceIm *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->handler; +} + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceIm_getService(struct mwServiceIm *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end + + +gboolean mwServiceIm_supports(struct mwServiceIm *srvc, + enum mwImSendType type) { + + g_return_val_if_fail(srvc != NULL, FALSE); + + switch(type) { + case mwImSend_PLAIN: + case mwImSend_TYPING: + return TRUE; + + case mwImSend_SUBJECT: + case mwImSend_HTML: + case mwImSend_MIME: + case mwImSend_TIMESTAMP: + return srvc->features == mwImClient_NOTESBUDDY; + + default: + return FALSE; + } +} + + +void mwServiceIm_setClientType(struct mwServiceIm *srvc, + enum mwImClientType type) { + + g_return_if_fail(srvc != NULL); + srvc->features = type; +} + + +enum mwImClientType mwServiceIm_getClientType(struct mwServiceIm *srvc) { + g_return_val_if_fail(srvc != NULL, mwImClient_UNKNOWN); + return srvc->features; +} + + +static int convo_send_data(struct mwConversation *conv, + guint32 type, guint32 subtype, + struct mwOpaque *data) { + struct mwPutBuffer *b; + struct mwOpaque o; + struct mwChannel *chan; + int ret; + + chan = conv->channel; + g_return_val_if_fail(chan != NULL, -1); + + b = mwPutBuffer_new(); + + guint32_put(b, mwIm_DATA); + guint32_put(b, type); + guint32_put(b, subtype); + mwOpaque_put(b, data); + + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_sendEncrypted(chan, msg_MESSAGE, &o, !conv->ext_id); + mwOpaque_clear(&o); + + return ret; +} + + +static int convo_send_multi_start(struct mwConversation *conv) { + return convo_send_data(conv, mwImData_MULTI_START, 0x00, NULL); +} + + +static int convo_send_multi_stop(struct mwConversation *conv) { + return convo_send_data(conv, mwImData_MULTI_STOP, 0x00, NULL); +} + + +/* breaks up a large message into segments, sends a start_segment + message, then sends each segment in turn, then sends a stop_segment + message */ +static int +convo_sendSegmented(struct mwConversation *conv, const char *message, + int (*send)(struct mwConversation *conv, + const char *msg)) { + char *buf = (char *) message; + gsize len; + int ret = 0; + + len = strlen(buf); + ret = convo_send_multi_start(conv); + + while(len && !ret) { + char tail; + gsize seg; + + seg = BREAKUP; + if(len < BREAKUP) + seg = len; + + /* temporarily NUL-terminate this segment */ + tail = buf[seg]; + buf[seg] = 0x00; + + ret = send(conv, buf); + + /* restore this segment */ + buf[seg] = tail; + + buf += seg; + len -= seg; + } + + if(! ret) + ret = convo_send_multi_stop(conv); + + return ret; +} + + +static int convo_sendText(struct mwConversation *conv, const char *text) { + struct mwPutBuffer *b; + struct mwOpaque o; + int ret; + + b = mwPutBuffer_new(); + + guint32_put(b, mwIm_TEXT); + mwString_put(b, text); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_sendEncrypted(conv->channel, msg_MESSAGE, &o, !conv->ext_id); + mwOpaque_clear(&o); + + return ret; +} + + +static int convo_sendTyping(struct mwConversation *conv, gboolean typing) { + return convo_send_data(conv, mwImData_TYPING, !typing, NULL); +} + + +static int convo_sendSubject(struct mwConversation *conv, + const char *subject) { + struct mwOpaque o; + + o.len = strlen(subject); + o.data = (guchar *) subject; + + return convo_send_data(conv, mwImData_SUBJECT, 0x00, &o); +} + + +static int convo_sendHtml(struct mwConversation *conv, const char *html) { + struct mwOpaque o; + + o.len = strlen(html); + o.data = (guchar *) html; + + if(o.len > BREAKUP) { + return convo_sendSegmented(conv, html, convo_sendHtml); + } else { + return convo_send_data(conv, mwImData_HTML, 0x00, &o); + } +} + + +static int convo_sendMime(struct mwConversation *conv, const char *mime) { + struct mwOpaque o; + + o.len = strlen(mime); + o.data = (guchar *) mime; + + if(o.len > BREAKUP) { + return convo_sendSegmented(conv, mime, convo_sendMime); + } else { + return convo_send_data(conv, mwImData_MIME, 0x00, &o); + } +} + + +int mwConversation_send(struct mwConversation *conv, enum mwImSendType type, + gconstpointer msg) { + + g_return_val_if_fail(conv != NULL, -1); + g_return_val_if_fail(mwConversation_isOpen(conv), -1); + g_return_val_if_fail(conv->channel != NULL, -1); + + switch(type) { + case mwImSend_PLAIN: + return convo_sendText(conv, msg); + case mwImSend_TYPING: + return convo_sendTyping(conv, GPOINTER_TO_INT(msg)); + case mwImSend_SUBJECT: + return convo_sendSubject(conv, msg); + case mwImSend_HTML: + return convo_sendHtml(conv, msg); + case mwImSend_MIME: + return convo_sendMime(conv, msg); + + default: + g_warning("unsupported IM Send Type, 0x%x", type); + return -1; + } +} + + +enum mwConversationState mwConversation_getState(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, mwConversation_UNKNOWN); + return conv->state; +} + + +struct mwServiceIm *mwConversation_getService(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, NULL); + return conv->service; +} + + +gboolean mwConversation_supports(struct mwConversation *conv, + enum mwImSendType type) { + g_return_val_if_fail(conv != NULL, FALSE); + + switch(type) { + case mwImSend_PLAIN: + case mwImSend_TYPING: + return TRUE; + + case mwImSend_SUBJECT: + case mwImSend_HTML: + case mwImSend_MIME: + return conv->features == mwImClient_NOTESBUDDY; + + default: + return FALSE; + } +} + + +enum mwImClientType +mwConversation_getClientType(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, mwImClient_UNKNOWN); + return conv->features; +} + + +struct mwIdBlock *mwConversation_getTarget(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, NULL); + return &conv->target; +} + + +struct mwLoginInfo *mwConversation_getTargetInfo(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, NULL); + g_return_val_if_fail(conv->channel != NULL, NULL); + return mwChannel_getUser(conv->channel); +} + + +void mwConversation_setClientData(struct mwConversation *conv, + gpointer data, GDestroyNotify clean) { + g_return_if_fail(conv != NULL); + mw_datum_set(&conv->client_data, data, clean); +} + + +gpointer mwConversation_getClientData(struct mwConversation *conv) { + g_return_val_if_fail(conv != NULL, NULL); + return mw_datum_get(&conv->client_data); +} + + +void mwConversation_removeClientData(struct mwConversation *conv) { + g_return_if_fail(conv != NULL); + mw_datum_clear(&conv->client_data); +} + + +void mwConversation_close(struct mwConversation *conv, guint32 reason) { + struct mwServiceIm *srvc; + struct mwImHandler *h; + + g_return_if_fail(conv != NULL); + + convo_set_state(conv, mwConversation_CLOSED); + + srvc = conv->service; + g_return_if_fail(srvc != NULL); + + h = srvc->handler; + if(h && h->conversation_closed) + h->conversation_closed(conv, reason); + + if(conv->channel) { + mwChannel_destroy(conv->channel, reason, NULL); + conv->channel = NULL; + } +} + + +void mwConversation_free(struct mwConversation *conv) { + g_return_if_fail(conv != NULL); + + if(! mwConversation_isClosed(conv)) + mwConversation_close(conv, ERR_SUCCESS); + + convo_free(conv); +} + diff --git a/protocols/Sametime/src/meanwhile/src/srvc_place.c b/protocols/Sametime/src/meanwhile/src/srvc_place.c new file mode 100644 index 0000000000..5029dffbb8 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_place.c @@ -0,0 +1,1089 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> +#include <glib/ghash.h> +#include <glib/glist.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "mw_channel.h" +#include "mw_common.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_place.h" +#include "mw_util.h" + + +#define PROTOCOL_TYPE 0x00 +#define PROTOCOL_VER 0x05 + + +enum incoming_msg { + msg_in_JOIN_RESPONSE = 0x0000, /* ? */ + msg_in_INFO = 0x0002, + msg_in_MESSAGE = 0x0004, + msg_in_SECTION = 0x0014, /* see in_section_subtype */ + msg_in_UNKNOWNa = 0x0015, +}; + + +enum in_section_subtype { + msg_in_SECTION_LIST = 0x0000, /* list of section members */ + msg_in_SECTION_PEER = 0x0001, /* see in_section_peer_subtye */ + msg_in_SECTION_PART = 0x0003, +}; + + +enum in_section_peer_subtype { + msg_in_SECTION_PEER_JOIN = 0x0000, + msg_in_SECTION_PEER_PART = 0x0001, /* after msg_in_SECTION_PART */ + msg_in_SECTION_PEER_CLEAR_ATTR = 0x0003, + msg_in_SECTION_PEER_SET_ATTR = 0x0004, +}; + + +enum outgoing_msg { + msg_out_JOIN_PLACE = 0x0000, /* ? */ + msg_out_PEER_INFO = 0x0002, /* ? */ + msg_out_MESSAGE = 0x0003, + msg_out_OLD_INVITE = 0x0005, /* old-style conf. invitation */ + msg_out_SET_ATTR = 0x000a, + msg_out_CLEAR_ATTR = 0x000b, + msg_out_SECTION = 0x0014, /* see out_section_subtype */ + msg_out_UNKNOWNb = 0x001e, /* ? maybe enter stage ? */ +}; + + +enum out_section_subtype { + msg_out_SECTION_LIST = 0x0002, /* req list of members */ + msg_out_SECTION_PART = 0x0003, +}; + + +/* + : allocate section + : state = NEW + + : create channel + : state = PENDING + + : channel accepted + : msg_out_JOIN_PLACE (maybe create?) + : state = JOINING + + : msg_in_JOIN_RESPONSE (contains our place member ID and section ID) + : msg_in_INFO (for place, not peer) + : state = JOINED + + : msg_out_SECTION_LIST (asking for all sections) (optional) + : msg_in_SECTION_LIST (listing all sections, as requested above) + + : msg_out_PEER_INFO (with our place member ID) (optional) + : msg_in_INFO (peer info as requested above) + + : msg_out_SECTION_LIST (with our section ID) (sorta optional) + : msg_in_SECTION_LIST (section listing as requested above) + + : msg_out_UNKNOWNb + : msg_in_SECTION_PEER_JOINED (empty, with our place member ID) + : state = OPEN + + : stuff... (invites, joins, parts, messages, attr) + + : state = CLOSING + : msg_out_SECTION_PART + : destroy channel + : deallocate section +*/ + + +struct mwServicePlace { + struct mwService service; + struct mwPlaceHandler *handler; + GList *places; +}; + + +enum mwPlaceState { + mwPlace_NEW, + mwPlace_PENDING, + mwPlace_JOINING, + mwPlace_JOINED, + mwPlace_OPEN, + mwPlace_CLOSING, + mwPlace_ERROR, + mwPlace_UNKNOWN, +}; + + +struct mwPlace { + struct mwServicePlace *service; + + enum mwPlaceState state; + struct mwChannel *channel; + + char *name; + char *title; + GHashTable *members; /* mapping of member ID: place_member */ + guint32 our_id; /* our member ID */ + guint32 section; /* the section we're using */ + + guint32 requests; /* counter for requests */ + + struct mw_datum client_data; +}; + + +struct place_member { + guint32 place_id; + guint16 member_type; + struct mwIdBlock idb; + char *login_id; + char *name; + guint16 login_type; + guint32 unknown_a; + guint32 unknown_b; +}; + + +#define GET_MEMBER(place, id) \ + (g_hash_table_lookup(place->members, GUINT_TO_POINTER(id))) + + +#define PUT_MEMBER(place, member) \ + (g_hash_table_insert(place->members, \ + GUINT_TO_POINTER(member->place_id), member)) + + +#define REMOVE_MEMBER_ID(place, id) \ + (g_hash_table_remove(place->members, GUINT_TO_POINTER(id))) + + +#define REMOVE_MEMBER(place, member) \ + REMOVE_MEMBER_ID(place, member->place_id) + + +static void member_free(struct place_member *p) { + mwIdBlock_clear(&p->idb); + g_free(p->login_id); + g_free(p->name); + g_free(p); +} + +/// Miranda NG adaptation start - MSVC +/// __attribute__((used)) +/// Miranda NG adaptation end +static const struct mwLoginInfo * +member_as_login_info(struct place_member *p) { + static struct mwLoginInfo li; + + li.login_id = p->login_id; + li.type = p->login_type; + li.user_id = p->idb.user; + li.user_name = p->name; + li.community = p->idb.community; + li.full = FALSE; + + return &li; +} + + +static const char *place_state_str(enum mwPlaceState s) { + switch(s) { + case mwPlace_NEW: return "new"; + case mwPlace_PENDING: return "pending"; + case mwPlace_JOINING: return "joining"; + case mwPlace_JOINED: return "joined"; + case mwPlace_OPEN: return "open"; + case mwPlace_CLOSING: return "closing"; + case mwPlace_ERROR: return "error"; + + case mwPlace_UNKNOWN: /* fall-through */ + default: return "UNKNOWN"; + } +} + + +static void place_state(struct mwPlace *place, enum mwPlaceState s) { + g_return_if_fail(place != NULL); + + if(place->state == s) return; + + place->state = s; + g_message("place %s state: %s", NSTR(place->name), place_state_str(s)); +} + + +static void place_free(struct mwPlace *place) { + struct mwServicePlace *srvc; + + if(! place) return; + + srvc = place->service; + g_return_if_fail(srvc != NULL); + + srvc->places = g_list_remove_all(srvc->places, place); + + mw_datum_clear(&place->client_data); + + g_hash_table_destroy(place->members); + + g_free(place->name); + g_free(place->title); + g_free(place); +} + + +static int recv_JOIN_RESPONSE(struct mwPlace *place, + struct mwGetBuffer *b) { + + int ret = 0; + guint32 our_id, section; + + guint32_get(b, &our_id); + guint32_get(b, §ion); + + place->our_id = our_id; + place->section = section; + + return ret; +} + + +static int send_SECTION_LIST(struct mwPlace *place, guint32 section) { + int ret = 0; + struct mwOpaque o = {0, 0}; + struct mwPutBuffer *b; + + b = mwPutBuffer_new(); + guint16_put(b, msg_out_SECTION_LIST); + guint32_put(b, section); + gboolean_put(b, FALSE); + guint32_put(b, ++place->requests); + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(place->channel, msg_out_SECTION, &o); + mwOpaque_clear(&o); + + return ret; +} + + +static int recv_INFO(struct mwPlace *place, + struct mwGetBuffer *b) { + + int ret = 0; + guint32 skip = 0; + guint32 section = 0; + + guint32_get(b, &skip); + guint32_get(b, §ion); + mwGetBuffer_advance(b, skip); + + if(! section) { + /* this is a place info rather than member info */ + if(place->title) g_free(place->title); + mwGetBuffer_advance(b, 2); + mwString_get(b, &place->title); + + place_state(place, mwPlace_JOINED); + ret = send_SECTION_LIST(place, place->section); + } + + return ret; +} + + +static int recv_MESSAGE(struct mwPlace *place, + struct mwGetBuffer *b) { + + struct mwServicePlace *srvc; + guint32 pm_id; + guint32 unkn_a, unkn_b, ign; + struct place_member *pm; + char *msg = NULL; + int ret = 0; + + srvc = place->service; + + /* no messages before becoming fully open, please */ + g_return_val_if_fail(place->state == mwPlace_OPEN, -1); + + /* regarding unkn_a and unkn_b: + + they're probably a section indicator and a message count, I'm + just not sure which is which. Until this implementation supports + place sections in the API, it really doesn't matter. */ + + guint32_get(b, &pm_id); + pm = GET_MEMBER(place, pm_id); + g_return_val_if_fail(pm != NULL, -1); + + guint32_get(b, &unkn_a); + guint32_get(b, &ign); /* actually an opaque length */ + + if(! ign) return ret; + + guint32_get(b, &unkn_b); + mwString_get(b, &msg); + + if(srvc->handler && srvc->handler->message) + srvc->handler->message(place, &pm->idb, msg); + + g_free(msg); + + return ret; +} + + +static void place_opened(struct mwPlace *place) { + struct mwServicePlace *srvc; + + place_state(place, mwPlace_OPEN); + + srvc = place->service; + if(srvc->handler && srvc->handler->opened) + srvc->handler->opened(place); +} + + +static int recv_SECTION_PEER_JOIN(struct mwPlace *place, + struct mwGetBuffer *b) { + struct mwServicePlace *srvc; + struct place_member *pm; + guint32 section; + int ret = 0; + + srvc = place->service; + + guint32_get(b, §ion); + if(! section) { + /// Miranda NG adaptation start - MSVC + ///g_info("SECTION_PEER_JOIN with section 0x00"); + g_message("SECTION_PEER_JOIN with section 0x00"); + /// Miranda NG adaptation end + return 0; + } + + mwGetBuffer_advance(b, 4); + + pm = g_new0(struct place_member, 1); + guint32_get(b, &pm->place_id); + guint16_get(b, &pm->member_type); + mwIdBlock_get(b, &pm->idb); + mwString_get(b, &pm->login_id); + mwString_get(b, &pm->name); + guint16_get(b, &pm->login_type); + guint32_get(b, &pm->unknown_a); + guint32_get(b, &pm->unknown_b); + + PUT_MEMBER(place, pm); + if(srvc->handler && srvc->handler->peerJoined) + srvc->handler->peerJoined(place, &pm->idb); + + if(pm->place_id == place->our_id) + place_opened(place); + + return ret; +} + + +static int recv_SECTION_PEER_PART(struct mwPlace *place, + struct mwGetBuffer *b) { + struct mwServicePlace *srvc; + int ret = 0; + guint32 section, id; + struct place_member *pm; + + srvc = place->service; + + guint32_get(b, §ion); + g_return_val_if_fail(section == place->section, 0); + + guint32_get(b, &id); + pm = GET_MEMBER(place, id); + + /* SECTION_PART may have been called already */ + if(! pm) return 0; + + if(srvc->handler && srvc->handler->peerParted) + srvc->handler->peerParted(place, &pm->idb); + + REMOVE_MEMBER(place, pm); + + return ret; +} + + +static int recv_SECTION_PEER_CLEAR_ATTR(struct mwPlace *place, + struct mwGetBuffer *b) { + struct mwServicePlace *srvc; + int ret = 0; + guint32 id, attr; + struct place_member *pm; + + srvc = place->service; + + guint32_get(b, &id); + guint32_get(b, &attr); + + pm = GET_MEMBER(place, id); + g_return_val_if_fail(pm != NULL, -1); + + if(srvc->handler && srvc->handler->peerUnsetAttribute) + srvc->handler->peerUnsetAttribute(place, &pm->idb, attr); + + return ret; +} + + +static int recv_SECTION_PEER_SET_ATTR(struct mwPlace *place, + struct mwGetBuffer *b) { + struct mwServicePlace *srvc; + int ret = 0; + guint32 id, attr; + struct mwOpaque o = {0,0}; + struct place_member *pm; + + srvc = place->service; + + guint32_get(b, &id); + mwGetBuffer_advance(b, 4); + mwOpaque_get(b, &o); + mwGetBuffer_advance(b, 4); + guint32_get(b, &attr); + + pm = GET_MEMBER(place, id); + g_return_val_if_fail(pm != NULL, -1); + + if(srvc->handler && srvc->handler->peerSetAttribute) + srvc->handler->peerSetAttribute(place, &pm->idb, attr, &o); + + mwOpaque_clear(&o); + + return ret; +} + + +static int recv_SECTION_PEER(struct mwPlace *place, + struct mwGetBuffer *b) { + guint16 subtype; + int res; + + guint16_get(b, &subtype); + + g_return_val_if_fail(! mwGetBuffer_error(b), -1); + + switch(subtype) { + case msg_in_SECTION_PEER_JOIN: + res = recv_SECTION_PEER_JOIN(place, b); + break; + + case msg_in_SECTION_PEER_PART: + res = recv_SECTION_PEER_PART(place, b); + break; + + case msg_in_SECTION_PEER_CLEAR_ATTR: + res = recv_SECTION_PEER_CLEAR_ATTR(place, b); + break; + + case msg_in_SECTION_PEER_SET_ATTR: + res = recv_SECTION_PEER_SET_ATTR(place, b); + break; + + default: + res = -1; + } + + return res; +} + + +static int recv_SECTION_LIST(struct mwPlace *place, + struct mwGetBuffer *b) { + int ret = 0; + guint32 sec, count; + + mwGetBuffer_advance(b, 4); + guint32_get(b, &sec); + + g_return_val_if_fail(sec == place->section, -1); + + mwGetBuffer_advance(b, 8); + guint32_get(b, &count); + mwGetBuffer_advance(b, 8); + + while(count--) { + struct place_member *m; + + m = g_new0(struct place_member, 1); + mwGetBuffer_advance(b, 4); + guint32_get(b, &m->place_id); + guint16_get(b, &m->member_type); + mwIdBlock_get(b, &m->idb); + mwString_get(b, &m->login_id); + mwString_get(b, &m->name); + guint16_get(b, &m->login_type); + guint32_get(b, &m->unknown_a); + guint32_get(b, &m->unknown_b); + + PUT_MEMBER(place, m); + } + + if(place->state != mwPlace_OPEN) + place_opened(place); + + return ret; +} + + +static int recv_SECTION_PART(struct mwPlace *place, + struct mwGetBuffer *b) { + /* look up user in place + remove user from place + trigger event */ + + struct mwServicePlace *srvc; + guint32 pm_id; + struct place_member *pm; + + srvc = place->service; + + guint32_get(b, &pm_id); + pm = GET_MEMBER(place, pm_id); + + /* SECTION_PEER_PART may have been called already */ + if(! pm) return 0; + + if(srvc->handler && srvc->handler->peerParted) + srvc->handler->peerParted(place, &pm->idb); + + REMOVE_MEMBER(place, pm); + + return 0; +} + + +static int recv_SECTION(struct mwPlace *place, struct mwGetBuffer *b) { + guint16 subtype; + int res; + + guint16_get(b, &subtype); + + g_return_val_if_fail(! mwGetBuffer_error(b), -1); + + switch(subtype) { + case msg_in_SECTION_LIST: + res = recv_SECTION_LIST(place, b); + break; + + case msg_in_SECTION_PEER: + res = recv_SECTION_PEER(place, b); + break; + + case msg_in_SECTION_PART: + res = recv_SECTION_PART(place, b); + break; + + default: + res = -1; + } + + return res; +} + + +static int recv_UNKNOWNa(struct mwPlace *place, struct mwGetBuffer *b) { + int res = 0; + + if(place->state == mwPlace_JOINING) { + ; + /* place_state(place, mwPlace_JOINED); + res = send_SECTION_LIST(place, place->section); */ + + } else if(place->state == mwPlace_JOINED) { + ; + /* if(GET_MEMBER(place, place->our_id)) + place_opened(place); */ + } + + return res; +} + + +static void recv(struct mwService *service, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + struct mwPlace *place; + struct mwGetBuffer *b; + int res = 0; + + place = mwChannel_getServiceData(chan); + g_return_if_fail(place != NULL); + + b = mwGetBuffer_wrap(data); + switch(type) { + case msg_in_JOIN_RESPONSE: + res = recv_JOIN_RESPONSE(place, b); + break; + + case msg_in_INFO: + res = recv_INFO(place, b); + break; + + case msg_in_MESSAGE: + res = recv_MESSAGE(place, b); + break; + + case msg_in_SECTION: + res = recv_SECTION(place, b); + break; + + case msg_in_UNKNOWNa: + res = recv_UNKNOWNa(place, b); + break; + + default: + mw_mailme_opaque(data, "Received unknown message type 0x%x on place %s", + type, NSTR(place->name)); + } + + if(res) { + mw_mailme_opaque(data, "Troubling parsing message type 0x0%x on place %s", + type, NSTR(place->name)); + } + + mwGetBuffer_free(b); +} + + +static void stop(struct mwServicePlace *srvc) { + while(srvc->places) + mwPlace_destroy(srvc->places->data, ERR_SUCCESS); + + mwService_stopped(MW_SERVICE(srvc)); +} + + +static int send_JOIN_PLACE(struct mwPlace *place) { + struct mwOpaque o = {0, 0}; + struct mwPutBuffer *b; + int ret; + + b = mwPutBuffer_new(); + gboolean_put(b, FALSE); + guint16_put(b, 0x01); + guint16_put(b, 0x02); /* 0x01 */ + guint16_put(b, 0x01); /* 0x00 */ + + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(place->channel, msg_out_JOIN_PLACE, &o); + + mwOpaque_clear(&o); + + if(ret) { + place_state(place, mwPlace_ERROR); + } else { + place_state(place, mwPlace_JOINING); + } + + return ret; +} + + +static void recv_channelAccept(struct mwService *service, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + struct mwServicePlace *srvc; + struct mwPlace *place; + int res; + + srvc = (struct mwServicePlace *) service; + g_return_if_fail(srvc != NULL); + + place = mwChannel_getServiceData(chan); + g_return_if_fail(place != NULL); + + res = send_JOIN_PLACE(place); +} + + +static void recv_channelDestroy(struct mwService *service, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + struct mwServicePlace *srvc; + struct mwPlace *place; + + srvc = (struct mwServicePlace *) service; + g_return_if_fail(srvc != NULL); + + place = mwChannel_getServiceData(chan); + g_return_if_fail(place != NULL); + + place_state(place, mwPlace_ERROR); + + place->channel = NULL; + + if(srvc->handler && srvc->handler->closed) + srvc->handler->closed(place, msg->reason); + + mwPlace_destroy(place, msg->reason); +} + + +static void clear(struct mwServicePlace *srvc) { + + if(srvc->handler && srvc->handler->clear) + srvc->handler->clear(srvc); + + while(srvc->places) + place_free(srvc->places->data); +} + + +static const char *get_name(struct mwService *srvc) { + return "Places Conferencing"; +} + + +static const char *get_desc(struct mwService *srvc) { + return "Barebones conferencing via Places"; +} + + +struct mwServicePlace * +mwServicePlace_new(struct mwSession *session, + struct mwPlaceHandler *handler) { + + struct mwServicePlace *srvc_place; + struct mwService *srvc; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(handler != NULL, NULL); + + srvc_place = g_new0(struct mwServicePlace, 1); + srvc_place->handler = handler; + + srvc = MW_SERVICE(srvc_place); + mwService_init(srvc, session, mwService_PLACE); + srvc->start = NULL; + srvc->stop = (mwService_funcStop) stop; + srvc->recv_create = NULL; + srvc->recv_accept = recv_channelAccept; + srvc->recv_destroy = recv_channelDestroy; + srvc->recv = recv; + srvc->clear = (mwService_funcClear) clear; + srvc->get_name = get_name; + srvc->get_desc = get_desc; + + return srvc_place; +} + + +struct mwPlaceHandler * +mwServicePlace_getHandler(struct mwServicePlace *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->handler; +} + + +const GList *mwServicePlace_getPlaces(struct mwServicePlace *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return srvc->places; +} + + +struct mwPlace *mwPlace_new(struct mwServicePlace *srvc, + const char *name, const char *title) { + struct mwPlace *place; + + g_return_val_if_fail(srvc != NULL, NULL); + + place = g_new0(struct mwPlace, 1); + place->service = srvc; + place->name = g_strdup(name); + place->title = g_strdup(title); + place->state = mwPlace_NEW; + + place->members = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) member_free); + + srvc->places = g_list_prepend(srvc->places, place); + + return place; +} + + +struct mwServicePlace *mwPlace_getService(struct mwPlace *place) { + g_return_val_if_fail(place != NULL, NULL); + return place->service; +} + + +static char *place_generate_name(const char *user) { + /// Miranda NG adaptation start - MSVC + ///guint a, b; + guint a; + guint64 b; + /// Miranda NG adaptation end + char *ret; + + user = user? user: "meanwhile"; + + srand(clock() + rand()); + a = ((rand() & 0xff) << 8) | (rand() & 0xff); + b = time(NULL); + + /// Miranda NG adaptation start - MSVC + ///ret = g_strdup_printf("%s(%08x,%04x)", user, b, a); + ret = g_strdup_printf("%s(%I64u,%04x)", user, b, a); + /// Miranda NG adaptation end + g_debug("generated random conference name: '%s'", ret); + return ret; +} + + +const char *mwPlace_getName(struct mwPlace *place) { + g_return_val_if_fail(place != NULL, NULL); + + if(! place->name) { + struct mwSession *session; + struct mwLoginInfo *li; + + session = mwService_getSession(MW_SERVICE(place->service)); + li = mwSession_getLoginInfo(session); + + place->name = place_generate_name(li? li->user_id: NULL); + } + + return place->name; +} + + +static char *place_generate_title(const char *user) { + char *ret; + + user = user? user: "Meanwhile"; + ret = g_strdup_printf("%s's Conference", user); + g_debug("generated conference title: %s", ret); + + return ret; +} + + +const char *mwPlace_getTitle(struct mwPlace *place) { + g_return_val_if_fail(place != NULL, NULL); + + if(! place->title) { + struct mwSession *session; + struct mwLoginInfo *li; + + session = mwService_getSession(MW_SERVICE(place->service)); + li = mwSession_getLoginInfo(session); + + place->title = place_generate_title(li? li->user_name: NULL); + } + + return place->title; +} + + +int mwPlace_open(struct mwPlace *p) { + struct mwSession *session; + struct mwChannelSet *cs; + struct mwChannel *chan; + struct mwPutBuffer *b; + int ret; + + g_return_val_if_fail(p != NULL, -1); + g_return_val_if_fail(p->service != NULL, -1); + + session = mwService_getSession(MW_SERVICE(p->service)); + g_return_val_if_fail(session != NULL, -1); + + cs = mwSession_getChannels(session); + g_return_val_if_fail(cs != NULL, -1); + + chan = mwChannel_newOutgoing(cs); + mwChannel_setService(chan, MW_SERVICE(p->service)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + mwChannel_populateSupportedCipherInstances(chan); + + b = mwPutBuffer_new(); + mwString_put(b, mwPlace_getName(p)); + mwString_put(b, mwPlace_getTitle(p)); + guint32_put(b, 0x00); /* ? */ + + mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b); + + ret = mwChannel_create(chan); + if(ret) { + place_state(p, mwPlace_ERROR); + } else { + place_state(p, mwPlace_PENDING); + p->channel = chan; + mwChannel_setServiceData(chan, p, NULL); + } + + return ret; +} + + +int mwPlace_destroy(struct mwPlace *p, guint32 code) { + int ret = 0; + + place_state(p, mwPlace_CLOSING); + + if(p->channel) { + ret = mwChannel_destroy(p->channel, code, NULL); + p->channel = NULL; + } + + place_free(p); + + return ret; +} + + +GList *mwPlace_getMembers(struct mwPlace *place) { + GList *l, *ll; + + g_return_val_if_fail(place != NULL, NULL); + g_return_val_if_fail(place->members != NULL, NULL); + + ll = map_collect_values(place->members); + for(l = ll; l; l = l->next) { + struct place_member *pm = l->data; + l->data = &pm->idb; + /// Miranda NG adaptation start - MSVC + //g_info("collected member %u: %s, %s", pm->place_id, + // NSTR(pm->idb.user), NSTR(pm->idb.community)); + g_message("collected member %u: %s, %s", pm->place_id, NSTR(pm->idb.user), NSTR(pm->idb.community)); + /// Miranda NG adaptation end + } + + return ll; +} + + +int mwPlace_sendText(struct mwPlace *place, const char *msg) { + struct mwOpaque o = {0,0}; + struct mwPutBuffer *b; + int ret; + + b = mwPutBuffer_new(); + guint32_put(b, 0x01); /* probably a message type */ + mwString_put(b, msg); + mwPutBuffer_finalize(&o, b); + + b = mwPutBuffer_new(); + guint32_put(b, place->section); + mwOpaque_put(b, &o); + mwOpaque_clear(&o); + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(place->channel, msg_out_MESSAGE, &o); + mwOpaque_clear(&o); + return ret; +} + + +int mwPlace_legacyInvite(struct mwPlace *place, + struct mwIdBlock *idb, + const char *message) { + + struct mwOpaque o = {0,0}; + struct mwPutBuffer *b; + int ret; + + b = mwPutBuffer_new(); + mwIdBlock_put(b, idb); + mwString_put(b, idb->user); + mwString_put(b, idb->user); + mwString_put(b, message); + gboolean_put(b, FALSE); + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(place->channel, msg_out_OLD_INVITE, &o); + mwOpaque_clear(&o); + return ret; +} + + +int mwPlace_setAttribute(struct mwPlace *place, guint32 attrib, + struct mwOpaque *data) { + + struct mwOpaque o = {0,0}; + struct mwPutBuffer *b; + int ret; + + b = mwPutBuffer_new(); + guint32_put(b, place->our_id); + guint32_put(b, 0x00); + guint32_put(b, attrib); + mwOpaque_put(b, data); + + ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o); + mwOpaque_clear(&o); + return ret; +} + + +int mwPlace_unsetAttribute(struct mwPlace *place, guint32 attrib) { + struct mwOpaque o = {0,0}; + struct mwPutBuffer *b; + int ret; + + b = mwPutBuffer_new(); + guint32_put(b, place->our_id); + guint32_put(b, attrib); + + ret = mwChannel_send(place->channel, msg_out_SET_ATTR, &o); + mwOpaque_clear(&o); + return ret; +} + + +void mwPlace_setClientData(struct mwPlace *place, + gpointer data, GDestroyNotify clear) { + + g_return_if_fail(place != NULL); + mw_datum_set(&place->client_data, data, clear); +} + + +gpointer mwPlace_getClientData(struct mwPlace *place) { + g_return_val_if_fail(place != NULL, NULL); + return mw_datum_get(&place->client_data); +} + + +void mwPlace_removeClientData(struct mwPlace *place) { + g_return_if_fail(place != NULL); + mw_datum_clear(&place->client_data); +} diff --git a/protocols/Sametime/src/meanwhile/src/srvc_resolve.c b/protocols/Sametime/src/meanwhile/src/srvc_resolve.c new file mode 100644 index 0000000000..bb4c536be8 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_resolve.c @@ -0,0 +1,396 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib/ghash.h> + +#include "mw_channel.h" +#include "mw_common.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_resolve.h" + + +#define PROTOCOL_TYPE 0x00000015 +#define PROTOCOL_VER 0x00000000 + + +/** oddly, there is only one message type in this service */ +#define RESOLVE_ACTION 0x02 + + +struct mwServiceResolve { + struct mwService service; + + struct mwChannel *channel; /**< channel for this service */ + GHashTable *searches; /**< guint32:struct mw_search */ + guint32 counter; /**< incremented to provide searche IDs */ +}; + + +/** structure representing an active search. keeps track of the ID, + the handler, and the optional user data and cleanup */ +struct mw_search { + struct mwServiceResolve *service; + guint32 id; + mwResolveHandler handler; + gpointer data; + GDestroyNotify cleanup; +}; + + +static struct mw_search *search_new(struct mwServiceResolve *srvc, + mwResolveHandler handler, + gpointer data, GDestroyNotify cleanup) { + + struct mw_search *search = g_new0(struct mw_search, 1); + + search->service = srvc; + search->handler = handler; + + /* we want search IDs that aren't SEARCH_ERROR */ + do { + search->id = srvc->counter++; + } while(search->id == SEARCH_ERROR); + + search->data = data; + search->cleanup = cleanup; + + return search; +} + + +/** called whenever a mw_search is removed from the searches table of + the service */ +static void search_free(struct mw_search *search) { + g_return_if_fail(search != NULL); + + if(search->cleanup) + search->cleanup(search->data); + + g_free(search); +} + + +static const char *get_name(struct mwService *srvc) { + return "Identity Resolution"; +} + + +static const char *get_desc(struct mwService *srvc) { + return "Resolves short IDs to full IDs"; +} + + +static struct mwChannel *make_channel(struct mwServiceResolve *srvc) { + struct mwSession *session; + struct mwChannelSet *cs; + struct mwChannel *chan; + + session = mwService_getSession(MW_SERVICE(srvc)); + cs = mwSession_getChannels(session); + chan = mwChannel_newOutgoing(cs); + + mwChannel_setService(chan, MW_SERVICE(srvc)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + return mwChannel_create(chan)? NULL: chan; +} + + +static void start(struct mwServiceResolve *srvc) { + struct mwChannel *chan; + + g_return_if_fail(srvc != NULL); + + chan = make_channel(srvc); + if(chan) { + srvc->channel = chan; + } else { + mwService_stopped(MW_SERVICE(srvc)); + return; + } + + /* semi-lazily create the searches table */ + srvc->searches = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) search_free); +} + + +static void stop(struct mwServiceResolve *srvc) { + g_return_if_fail(srvc != NULL); + + if(srvc->channel) { + mwChannel_destroy(srvc->channel, ERR_SUCCESS, NULL); + srvc->channel = NULL; + } + + /* destroy all the pending requests. */ + g_hash_table_destroy(srvc->searches); + srvc->searches = NULL; + + mwService_stopped(MW_SERVICE(srvc)); +} + + +static void clear(struct mwServiceResolve *srvc) { + if(srvc->searches) { + g_hash_table_destroy(srvc->searches); + srvc->searches = NULL; + } +} + + +static void recv_create(struct mwServiceResolve *srvc, + struct mwChannel *chan, + struct mwMsgChannelCreate *msg) { + + /* you serve me, not the other way around */ + mwChannel_destroy(chan, ERR_FAILURE, NULL); +} + + +static void recv_accept(struct mwServiceResolve *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc->channel); + + mwService_started(MW_SERVICE(srvc)); +} + + +static void recv_destroy(struct mwServiceResolve *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + struct mwSession *session; + + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc->channel); + + srvc->channel = NULL; + mwService_stop(MW_SERVICE(srvc)); + + session = mwService_getSession(MW_SERVICE(srvc)); + g_return_if_fail(session != NULL); + + mwSession_senseService(session, mwService_getType(MW_SERVICE(srvc))); +} + + +static GList *load_matches(struct mwGetBuffer *b, guint32 count) { + GList *matches = NULL; + + while(count--) { + struct mwResolveMatch *m = g_new0(struct mwResolveMatch, 1); + + mwString_get(b, &m->id); + mwString_get(b, &m->name); + mwString_get(b, &m->desc); + guint32_get(b, &m->type); + + matches = g_list_append(matches, m); + } + + return matches; +} + + +static GList *load_results(struct mwGetBuffer *b, guint32 count) { + GList *results = NULL; + + while(count--) { + struct mwResolveResult *r = g_new0(struct mwResolveResult, 1); + guint32 junk, matches; + + guint32_get(b, &junk); + guint32_get(b, &r->code); + mwString_get(b, &r->name); + + guint32_get(b, &matches); + r->matches = load_matches(b, matches); + + results = g_list_append(results, r); + } + + return results; +} + + +static void free_matches(GList *matches) { + for(; matches; matches = g_list_delete_link(matches, matches)) { + struct mwResolveMatch *m = matches->data; + g_free(m->id); + g_free(m->name); + g_free(m->desc); + g_free(m); + } +} + + +static void free_results(GList *results) { + for(; results; results = g_list_delete_link(results, results)) { + struct mwResolveResult *r = results->data; + g_free(r->name); + free_matches(r->matches); + g_free(r); + } +} + + +static void recv(struct mwServiceResolve *srvc, + struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + struct mwGetBuffer *b; + guint32 junk, id, code, count; + struct mw_search *search; + + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc->channel); + g_return_if_fail(data != NULL); + + if(type != RESOLVE_ACTION) { + mw_mailme_opaque(data, "unknown message in resolve service: 0x%04x", type); + return; + } + + b = mwGetBuffer_wrap(data); + guint32_get(b, &junk); + guint32_get(b, &id); + guint32_get(b, &code); + guint32_get(b, &count); + + if(mwGetBuffer_error(b)) { + g_warning("error parsing search result"); + mwGetBuffer_free(b); + return; + } + + search = g_hash_table_lookup(srvc->searches, GUINT_TO_POINTER(id)); + + if(search) { + GList *results = load_results(b, count); + if(mwGetBuffer_error(b)) { + g_warning("error parsing search results"); + } else { + g_debug("triggering handler"); + search->handler(srvc, id, code, results, search->data); + } + free_results(results); + g_hash_table_remove(srvc->searches, GUINT_TO_POINTER(id)); + + } else { + g_debug("no search found: 0x%x", id); + } + + mwGetBuffer_free(b); +} + + +struct mwServiceResolve *mwServiceResolve_new(struct mwSession *session) { + struct mwServiceResolve *srvc_resolve; + struct mwService *srvc; + + g_return_val_if_fail(session != NULL, NULL); + + srvc_resolve = g_new0(struct mwServiceResolve, 1); + + srvc = MW_SERVICE(srvc_resolve); + + mwService_init(srvc, session, mwService_RESOLVE); + srvc->get_name = get_name; + srvc->get_desc = get_desc; + srvc->recv_create = (mwService_funcRecvCreate) recv_create; + srvc->recv_accept = (mwService_funcRecvAccept) recv_accept; + srvc->recv_destroy = (mwService_funcRecvDestroy) recv_destroy; + srvc->recv = (mwService_funcRecv) recv; + srvc->start = (mwService_funcStart) start; + srvc->stop = (mwService_funcStop) stop; + srvc->clear = (mwService_funcClear) clear; + + return srvc_resolve; +} + + +guint32 mwServiceResolve_resolve(struct mwServiceResolve *srvc, + GList *queries, enum mwResolveFlag flags, + mwResolveHandler handler, + gpointer data, GDestroyNotify cleanup) { + + struct mw_search *search; + struct mwPutBuffer *b; + struct mwOpaque o = { 0, 0 }; + int ret, count = 0; + + g_return_val_if_fail(srvc != NULL, SEARCH_ERROR); + g_return_val_if_fail(handler != NULL, SEARCH_ERROR); + + count = g_list_length(queries); + g_return_val_if_fail(count > 0, SEARCH_ERROR); + + search = search_new(srvc, handler, data, cleanup); + + b = mwPutBuffer_new(); + guint32_put(b, 0x00); /* to be overwritten */ + guint32_put(b, search->id); + guint32_put(b, count); + for(; queries; queries = queries->next) + mwString_put(b, queries->data); + guint32_put(b, flags); + + mwPutBuffer_finalize(&o, b); + + ret = mwChannel_send(srvc->channel, RESOLVE_ACTION, &o); + if(ret) { + search_free(search); + return SEARCH_ERROR; + + } else { + g_hash_table_insert(srvc->searches, + GUINT_TO_POINTER(search->id), search); + return search->id; + } +} + + +void mwServiceResolve_cancelResolve(struct mwServiceResolve *srvc, + guint32 id) { + + g_return_if_fail(srvc != NULL); + g_return_if_fail(srvc->searches != NULL); + + g_hash_table_remove(srvc->searches, GUINT_TO_POINTER(id)); +} + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceResolve_getService(struct mwServiceResolve *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end diff --git a/protocols/Sametime/src/meanwhile/src/srvc_store.c b/protocols/Sametime/src/meanwhile/src/srvc_store.c new file mode 100644 index 0000000000..f537195e08 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/srvc_store.c @@ -0,0 +1,615 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib/glist.h> + +#include "mw_channel.h" +#include "mw_debug.h" +#include "mw_error.h" +#include "mw_message.h" +#include "mw_service.h" +#include "mw_session.h" +#include "mw_srvc_store.h" + + +#define PROTOCOL_TYPE 0x00000025 +#define PROTOCOL_VER 0x00000001 + + +enum storage_action { + action_load = 0x0004, + action_loaded = 0x0005, + action_save = 0x0006, + action_saved = 0x0007, +}; + + +struct mwStorageUnit { + /** key by which data is referenced in service + @see mwStorageKey */ + guint32 key; + + /** Data associated with key in service */ + struct mwOpaque data; +}; + + +struct mwStorageReq { + guint32 id; /**< unique id for this request */ + guint32 result_code; /**< result code for completed request */ + enum storage_action action; /**< load or save */ + struct mwStorageUnit *item; /**< the key/data pair */ + mwStorageCallback cb; /**< callback to notify upon completion */ + gpointer data; /**< user data to pass with callback */ + GDestroyNotify data_free; /**< optionally frees user data */ +}; + + +struct mwServiceStorage { + struct mwService service; + + /** collection of mwStorageReq */ + GList *pending; + + /** current service channel */ + struct mwChannel *channel; + + /** keep track of the counter */ + guint32 id_counter; +}; + + +static void request_get(struct mwGetBuffer *b, struct mwStorageReq *req) { + guint32 id, count, junk; + + if(mwGetBuffer_error(b)) return; + + guint32_get(b, &id); + guint32_get(b, &req->result_code); + + if(req->action == action_loaded) { + guint32_get(b, &count); + + if(count > 0) { + guint32_get(b, &junk); + guint32_get(b, &req->item->key); + + mwOpaque_clear(&req->item->data); + mwOpaque_get(b, &req->item->data); + } + } +} + + +static void request_put(struct mwPutBuffer *b, struct mwStorageReq *req) { + + guint32_put(b, req->id); + guint32_put(b, 1); + + if(req->action == action_save) { + guint32_put(b, 20 + req->item->data.len); /* ugh, offset garbage */ + guint32_put(b, req->item->key); + mwOpaque_put(b, &req->item->data); + + } else { + guint32_put(b, req->item->key); + } +} + + +static int request_send(struct mwChannel *chan, struct mwStorageReq *req) { + struct mwPutBuffer *b; + struct mwOpaque o = { 0, 0 }; + int ret; + + b = mwPutBuffer_new(); + request_put(b, req); + + mwPutBuffer_finalize(&o, b); + ret = mwChannel_send(chan, req->action, &o); + mwOpaque_clear(&o); + + if(! ret) { + if(req->action == action_save) { + req->action = action_saved; + } else if(req->action == action_load) { + req->action = action_loaded; + } + } + + return ret; +} + + +static struct mwStorageReq *request_find(struct mwServiceStorage *srvc, + guint32 id) { + GList *l; + + for(l = srvc->pending; l; l = l->next) { + struct mwStorageReq *r = l->data; + if(r->id == id) return r; + } + + return NULL; +} + + +static const char *action_str(enum storage_action act) { + switch(act) { + case action_load: return "load"; + case action_loaded: return "loaded"; + case action_save: return "save"; + case action_saved: return "saved"; + default: return "UNKNOWN"; + } +} + + +static void request_trigger(struct mwServiceStorage *srvc, + struct mwStorageReq *req) { + + struct mwStorageUnit *item = req->item; + + g_message("storage request %s: key = 0x%x, result = 0x%x, length = %u", + action_str(req->action), + item->key, req->result_code, (guint) item->data.len); + + if(req->cb) + req->cb(srvc, req->result_code, item, req->data); +} + + +static void request_free(struct mwStorageReq *req) { + if(req->data_free) { + req->data_free(req->data); + req->data = NULL; + req->data_free = NULL; + } + + mwStorageUnit_free(req->item); + g_free(req); +} + + +static void request_remove(struct mwServiceStorage *srvc, + struct mwStorageReq *req) { + + srvc->pending = g_list_remove_all(srvc->pending, req); + request_free(req); +} + + +static const char *get_name(struct mwService *srvc) { + return "User Storage"; +} + + +static const char *get_desc(struct mwService *srvc) { + return "Stores user data and settings on the server"; +} + + +static struct mwChannel *make_channel(struct mwServiceStorage *srvc) { + struct mwSession *session; + struct mwChannelSet *cs; + struct mwChannel *chan; + + session = mwService_getSession(MW_SERVICE(srvc)); + cs = mwSession_getChannels(session); + chan = mwChannel_newOutgoing(cs); + + mwChannel_setService(chan, MW_SERVICE(srvc)); + mwChannel_setProtoType(chan, PROTOCOL_TYPE); + mwChannel_setProtoVer(chan, PROTOCOL_VER); + + return mwChannel_create(chan)? NULL: chan; +} + + +static void start(struct mwService *srvc) { + struct mwServiceStorage *srvc_store; + struct mwChannel *chan; + + g_return_if_fail(srvc != NULL); + srvc_store = (struct mwServiceStorage *) srvc; + + chan = make_channel(srvc_store); + if(chan) { + srvc_store->channel = chan; + } else { + mwService_stopped(srvc); + } +} + + +static void stop(struct mwService *srvc) { + + struct mwServiceStorage *srvc_store; + GList *l; + + g_return_if_fail(srvc != NULL); + srvc_store = (struct mwServiceStorage *) srvc; + + if(srvc_store->channel) { + mwChannel_destroy(srvc_store->channel, ERR_SUCCESS, NULL); + srvc_store->channel = NULL; + } + +#if 1 + /* the new way */ + /* remove pending requests. Sometimes we can crash the storage + service, and when that happens, we end up resending the killer + request over and over again, and the service never stays up */ + for(l = srvc_store->pending; l; l = l->next) + request_free(l->data); + + g_list_free(srvc_store->pending); + srvc_store->pending = NULL; + + srvc_store->id_counter = 0; + +#else + /* the old way */ + /* reset all of the started requests to their unstarted states */ + for(l = srvc_store->pending; l; l = l->next) { + struct mwStorageReq *req = l->data; + + if(req->action == action_loaded) { + req->action = action_load; + } else if(req->action == action_saved) { + req->action = action_save; + } + } +#endif + + mwService_stopped(srvc); +} + + +static void recv_channelAccept(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelAccept *msg) { + + struct mwServiceStorage *srvc_stor; + GList *l; + + g_return_if_fail(srvc != NULL); + srvc_stor = (struct mwServiceStorage *) srvc; + + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc_stor->channel); + + /* send all pending requests */ + for(l = srvc_stor->pending; l; l = l->next) { + struct mwStorageReq *req = l->data; + + if(req->action == action_save || req->action == action_load) { + request_send(chan, req); + } + } + + mwService_started(srvc); +} + + +static void recv_channelDestroy(struct mwService *srvc, + struct mwChannel *chan, + struct mwMsgChannelDestroy *msg) { + + struct mwSession *session; + struct mwServiceStorage *srvc_stor; + + g_return_if_fail(srvc != NULL); + g_return_if_fail(chan != NULL); + + session = mwService_getSession(srvc); + g_return_if_fail(session != NULL); + + srvc_stor = (struct mwServiceStorage *) srvc; + srvc_stor->channel = NULL; + + mwService_stop(srvc); + mwSession_senseService(session, mwService_getType(srvc)); +} + + +static void recv(struct mwService *srvc, struct mwChannel *chan, + guint16 type, struct mwOpaque *data) { + + /* process into results, trigger callbacks */ + + struct mwGetBuffer *b; + struct mwServiceStorage *srvc_stor; + struct mwStorageReq *req; + guint32 id; + + g_return_if_fail(srvc != NULL); + srvc_stor = (struct mwServiceStorage *) srvc; + + g_return_if_fail(chan != NULL); + g_return_if_fail(chan == srvc_stor->channel); + g_return_if_fail(data != NULL); + + b = mwGetBuffer_wrap(data); + + id = guint32_peek(b); + req = request_find(srvc_stor, id); + + if(! req) { + g_warning("couldn't find request 0x%x in storage service", id); + mwGetBuffer_free(b); + return; + } + + g_return_if_fail(req->action == type); + request_get(b, req); + + if(mwGetBuffer_error(b)) { + mw_mailme_opaque(data, "storage request 0x%x, type: 0x%x", id, type); + + } else { + request_trigger(srvc_stor, req); + } + + mwGetBuffer_free(b); + request_remove(srvc_stor, req); +} + + +static void clear(struct mwService *srvc) { + struct mwServiceStorage *srvc_stor; + GList *l; + + srvc_stor = (struct mwServiceStorage *) srvc; + + for(l = srvc_stor->pending; l; l = l->next) + request_free(l->data); + + g_list_free(srvc_stor->pending); + srvc_stor->pending = NULL; + + srvc_stor->id_counter = 0; +} + + +struct mwServiceStorage *mwServiceStorage_new(struct mwSession *session) { + struct mwServiceStorage *srvc_store; + struct mwService *srvc; + + srvc_store = g_new0(struct mwServiceStorage, 1); + srvc = MW_SERVICE(srvc_store); + + mwService_init(srvc, session, mwService_STORAGE); + srvc->get_name = get_name; + srvc->get_desc = get_desc; + srvc->recv_accept = recv_channelAccept; + srvc->recv_destroy = recv_channelDestroy; + srvc->recv = recv; + srvc->start = start; + srvc->stop = stop; + srvc->clear = clear; + + return srvc_store; +} + + +struct mwStorageUnit *mwStorageUnit_new(guint32 key) { + struct mwStorageUnit *u; + + u = g_new0(struct mwStorageUnit, 1); + u->key = key; + + return u; +} + + +struct mwStorageUnit *mwStorageUnit_newOpaque(guint32 key, + struct mwOpaque *data) { + struct mwStorageUnit *u; + + u = g_new0(struct mwStorageUnit, 1); + u->key = key; + + if(data) + mwOpaque_clone(&u->data, data); + + return u; +} + + +struct mwStorageUnit *mwStorageUnit_newBoolean(guint32 key, + gboolean val) { + + return mwStorageUnit_newInteger(key, (guint32) val); +} + + +struct mwStorageUnit *mwStorageUnit_newInteger(guint32 key, + guint32 val) { + struct mwStorageUnit *u; + struct mwPutBuffer *b; + + u = g_new0(struct mwStorageUnit, 1); + u->key = key; + + b = mwPutBuffer_new(); + guint32_put(b, val); + mwPutBuffer_finalize(&u->data, b); + + return u; +} + + +struct mwStorageUnit *mwStorageUnit_newString(guint32 key, + const char *str) { + struct mwStorageUnit *u; + struct mwPutBuffer *b; + + u = g_new0(struct mwStorageUnit, 1); + u->key = key; + + b = mwPutBuffer_new(); + mwString_put(b, str); + mwPutBuffer_finalize(&u->data, b); + + return u; +} + + +guint32 mwStorageUnit_getKey(struct mwStorageUnit *item) { + g_return_val_if_fail(item != NULL, 0x00); /* feh, unsafe */ + return item->key; +} + + +gboolean mwStorageUnit_asBoolean(struct mwStorageUnit *item, + gboolean val) { + + return !! mwStorageUnit_asInteger(item, (guint32) val); +} + + +guint32 mwStorageUnit_asInteger(struct mwStorageUnit *item, + guint32 val) { + struct mwGetBuffer *b; + guint32 v; + + g_return_val_if_fail(item != NULL, val); + + b = mwGetBuffer_wrap(&item->data); + + guint32_get(b, &v); + if(! mwGetBuffer_error(b)) val = v; + mwGetBuffer_free(b); + + return val; +} + + +char *mwStorageUnit_asString(struct mwStorageUnit *item) { + struct mwGetBuffer *b; + char *c = NULL; + + g_return_val_if_fail(item != NULL, NULL); + + b = mwGetBuffer_wrap(&item->data); + + mwString_get(b, &c); + + if(mwGetBuffer_error(b)) + g_debug("error obtaining string value from opaque"); + + mwGetBuffer_free(b); + + return c; +} + + +struct mwOpaque *mwStorageUnit_asOpaque(struct mwStorageUnit *item) { + g_return_val_if_fail(item != NULL, NULL); + return &item->data; +} + + +void mwStorageUnit_free(struct mwStorageUnit *item) { + if(! item) return; + + mwOpaque_clear(&item->data); + g_free(item); +} + + +static struct mwStorageReq *request_new(struct mwServiceStorage *srvc, + struct mwStorageUnit *item, + mwStorageCallback cb, + gpointer data, GDestroyNotify df) { + + struct mwStorageReq *req = g_new0(struct mwStorageReq, 1); + + req->id = ++srvc->id_counter; + req->item = item; + req->cb = cb; + req->data = data; + req->data_free = df; + + return req; +} + + +void mwServiceStorage_load(struct mwServiceStorage *srvc, + struct mwStorageUnit *item, + mwStorageCallback cb, + gpointer data, GDestroyNotify d_free) { + + /* - construct a request + - put request at end of pending + - if channel is open and connected + - compose the load message + - send message + - set request to sent + - else + - start service + */ + + struct mwStorageReq *req; + + req = request_new(srvc, item, cb, data, d_free); + req->action = action_load; + + srvc->pending = g_list_append(srvc->pending, req); + + if(MW_SERVICE_IS_STARTED(MW_SERVICE(srvc))) + request_send(srvc->channel, req); +} + + +void mwServiceStorage_save(struct mwServiceStorage *srvc, + struct mwStorageUnit *item, + mwStorageCallback cb, + gpointer data, GDestroyNotify d_free) { + + /* - construct a request + - put request at end of pending + - if channel is open and connected + - compose the save message + - send message + - set request to sent + - else + - start service + */ + + struct mwStorageReq *req; + + req = request_new(srvc, item, cb, data, d_free); + req->action = action_save; + + srvc->pending = g_list_append(srvc->pending, req); + + if(MW_SERVICE_IS_STARTED(MW_SERVICE(srvc))) + request_send(srvc->channel, req); +} + + +/// Miranda NG adaptation start - new method +struct mwService *mwServiceStorage_getService(struct mwServiceStorage *srvc) { + g_return_val_if_fail(srvc != NULL, NULL); + return &(srvc->service); +} +/// Miranda NG adaptation end diff --git a/protocols/Sametime/src/meanwhile/src/st_list.c b/protocols/Sametime/src/meanwhile/src/st_list.c new file mode 100644 index 0000000000..949696a4a1 --- /dev/null +++ b/protocols/Sametime/src/meanwhile/src/st_list.c @@ -0,0 +1,668 @@ + +/* + Meanwhile - Unofficial Lotus Sametime Community Client Library + Copyright (C) 2004 Christopher (siege) O'Brien + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <string.h> +#include <glib/gstring.h> + +#include "mw_debug.h" +#include "mw_util.h" +#include "mw_st_list.h" + + +struct mwSametimeList { + guint ver_major; + guint ver_minor; + guint ver_micro; + + GList *groups; +}; + + +struct mwSametimeGroup { + struct mwSametimeList *list; + + enum mwSametimeGroupType type; + char *name; + char *alias; + gboolean open; + + GList *users; +}; + + +struct mwSametimeUser { + struct mwSametimeGroup *group; + + enum mwSametimeUserType type; + struct mwIdBlock id; + char *name; + char *alias; +}; + + +static void user_free(struct mwSametimeUser *u) { + struct mwSametimeGroup *g; + + g = u->group; + g->users = g_list_remove(g->users, u); + + mwIdBlock_clear(&u->id); + g_free(u->name); + g_free(u->alias); + g_free(u); +} + + +static void group_free(struct mwSametimeGroup *g) { + struct mwSametimeList *l; + + l = g->list; + l->groups = g_list_remove(l->groups, g); + + while(g->users) + mwSametimeUser_free(g->users->data); + + g_free(g->name); + g_free(g->alias); + g_free(g); +} + + +static void list_free(struct mwSametimeList *l) { + while(l->groups) + mwSametimeGroup_free(l->groups->data); + + g_free(l); +} + + +struct mwSametimeList * +mwSametimeList_new() { + + struct mwSametimeList *stl; + + stl = g_new0(struct mwSametimeList, 1); + stl->ver_major = ST_LIST_MAJOR; + stl->ver_minor = ST_LIST_MINOR; + stl->ver_micro = ST_LIST_MICRO; + + return stl; +} + + +void mwSametimeList_setMajor(struct mwSametimeList *l, guint v) { + g_return_if_fail(l != NULL); + l->ver_major = v; +} + + +guint mwSametimeList_getMajor(struct mwSametimeList *l) { + g_return_val_if_fail(l != NULL, 0); + return l->ver_major; +} + + +void mwSametimeList_setMinor(struct mwSametimeList *l, guint v) { + g_return_if_fail(l != NULL); + l->ver_minor = v; +} + + +guint mwSametimeList_getMinor(struct mwSametimeList *l) { + g_return_val_if_fail(l != NULL, 0); + return l->ver_minor; +} + + +void mwSametimeList_setMicro(struct mwSametimeList *l, guint v) { + g_return_if_fail(l != NULL); + l->ver_micro = v; +} + + +guint mwSametimeList_getMicro(struct mwSametimeList *l) { + g_return_val_if_fail(l != NULL, 0); + return l->ver_micro; +} + + +GList *mwSametimeList_getGroups(struct mwSametimeList *l) { + g_return_val_if_fail(l != NULL, NULL); + return g_list_copy(l->groups); +} + + +struct mwSametimeGroup * +mwSametimeList_findGroup(struct mwSametimeList *l, + const char *name) { + GList *s; + + g_return_val_if_fail(l != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(*name != '\0', NULL); + + for(s = l->groups; s; s = s->next) { + struct mwSametimeGroup *g = s->data; + if(! strcmp(g->name, name)) return g; + } + + return NULL; +} + + +void mwSametimeList_free(struct mwSametimeList *l) { + g_return_if_fail(l != NULL); + list_free(l); +} + + +struct mwSametimeGroup * +mwSametimeGroup_new(struct mwSametimeList *list, + enum mwSametimeGroupType type, + const char *name) { + + struct mwSametimeGroup *stg; + + g_return_val_if_fail(list != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(*name != '\0', NULL); + + stg = g_new0(struct mwSametimeGroup, 1); + stg->list = list; + stg->type = type; + stg->name = g_strdup(name); + + list->groups = g_list_append(list->groups, stg); + + return stg; +} + + +enum mwSametimeGroupType mwSametimeGroup_getType(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, mwSametimeGroup_UNKNOWN); + return g->type; +} + + +const char *mwSametimeGroup_getName(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, NULL); + return g->name; +} + + +void mwSametimeGroup_setAlias(struct mwSametimeGroup *g, + const char *alias) { + g_return_if_fail(g != NULL); + + g_free(g->alias); + g->alias = g_strdup(alias); +} + + +const char *mwSametimeGroup_getAlias(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, NULL); + return g->alias; +} + + +void mwSametimeGroup_setOpen(struct mwSametimeGroup *g, gboolean open) { + g_return_if_fail(g != NULL); + g->open = open; +} + + +gboolean mwSametimeGroup_isOpen(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, FALSE); + return g->open; +} + + +struct mwSametimeList *mwSametimeGroup_getList(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, NULL); + return g->list; +} + + +GList *mwSametimeGroup_getUsers(struct mwSametimeGroup *g) { + g_return_val_if_fail(g != NULL, NULL); + return g_list_copy(g->users); +} + + +struct mwSametimeUser * +mwSametimeGroup_findUser(struct mwSametimeGroup *g, + struct mwIdBlock *user) { + GList *s; + + g_return_val_if_fail(g != NULL, NULL); + g_return_val_if_fail(user != NULL, NULL); + + for(s = g->users; s; s = s->next) { + struct mwSametimeUser *u = s->data; + if(mwIdBlock_equal(user, &u->id)) return u; + } + + return NULL; +} + + +void mwSametimeGroup_free(struct mwSametimeGroup *g) { + g_return_if_fail(g != NULL); + g_return_if_fail(g->list != NULL); + group_free(g); +} + + +struct mwSametimeUser * +mwSametimeUser_new(struct mwSametimeGroup *group, + enum mwSametimeUserType type, + struct mwIdBlock *id) { + + struct mwSametimeUser *stu; + + g_return_val_if_fail(group != NULL, NULL); + g_return_val_if_fail(id != NULL, NULL); + + stu = g_new0(struct mwSametimeUser, 1); + stu->group = group; + stu->type = type; + mwIdBlock_clone(&stu->id, id); + + group->users = g_list_append(group->users, stu); + + return stu; +} + + +struct mwSametimeGroup *mwSametimeUser_getGroup(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, NULL); + return u->group; +} + + +enum mwSametimeUserType mwSametimeUser_getType(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, mwSametimeUser_UNKNOWN); + return u->type; +} + + +const char *mwSametimeUser_getUser(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, NULL); + return u->id.user; +} + + +const char *mwSametimeUser_getCommunity(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, NULL); + return u->id.community; +} + + +void mwSametimeUser_setShortName(struct mwSametimeUser *u, const char *name) { + g_return_if_fail(u != NULL); + g_free(u->name); + u->name = g_strdup(name); +} + + +const char *mwSametimeUser_getShortName(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, NULL); + return u->name; +} + + +void mwSametimeUser_setAlias(struct mwSametimeUser *u, const char *alias) { + g_return_if_fail(u != NULL); + g_free(u->alias); + u->alias = g_strdup(alias); +} + + +const char *mwSametimeUser_getAlias(struct mwSametimeUser *u) { + g_return_val_if_fail(u != NULL, NULL); + return u->alias; +} + + +void mwSametimeUser_free(struct mwSametimeUser *u) { + g_return_if_fail(u != NULL); + g_return_if_fail(u->group != NULL); + user_free(u); +} + + +static void str_replace(char *str, char from, char to) { + if(! str) return; + for(; *str; str++) if(*str == from) *str = to; +} + + +static char user_type_to_char(enum mwSametimeUserType type) { + switch(type) { + case mwSametimeUser_NORMAL: return '1'; + case mwSametimeUser_EXTERNAL: return '2'; + case mwSametimeUser_UNKNOWN: + default: return '9'; + } +} + + +static enum mwSametimeUserType user_char_to_type(char type) { + switch(type) { + case '1': return mwSametimeUser_NORMAL; + case '2': return mwSametimeUser_EXTERNAL; + default: return mwSametimeUser_UNKNOWN; + } +} + + +static void user_put(GString *str, struct mwSametimeUser *u) { + char *id, *name, *alias; + char type; + + id = g_strdup(u->id.user); + name = g_strdup(u->name); + alias = g_strdup(u->alias); + type = user_type_to_char(u->type); + + if(id) str_replace(id, ' ', ';'); + if(name) str_replace(name, ' ', ';'); + if(alias) str_replace(alias, ' ', ';'); + + if(!name && alias) { + name = alias; + alias = NULL; + } + + g_string_append_printf(str, "U %s%c:: %s,%s\r\n", + id, type, (name? name: ""), (alias? alias: "")); + + g_free(id); + g_free(name); + g_free(alias); +} + + +static char group_type_to_char(enum mwSametimeGroupType type) { + switch(type) { + case mwSametimeGroup_NORMAL: return '2'; + case mwSametimeGroup_DYNAMIC: return '3'; + case mwSametimeGroup_UNKNOWN: + default: return '9'; + } +} + + +static enum mwSametimeGroupType group_char_to_type(char type) { + switch(type) { + case '2': return mwSametimeGroup_NORMAL; + case '3': return mwSametimeGroup_DYNAMIC; + default: return mwSametimeGroup_UNKNOWN; + } +} + + +static void group_put(GString *str, struct mwSametimeGroup *g) { + char *name, *alias; + char type; + GList *gl; + + name = g_strdup(g->name); + alias = g_strdup((g->alias)? g->alias: name); + type = group_type_to_char(g->type); + + str_replace(name, ' ', ';'); + str_replace(alias, ' ', ';'); + + g_string_append_printf(str, "G %s%c %s %c\r\n", + name, type, alias, (g->open? 'O':'C')); + + for(gl = g->users; gl; gl = gl->next) { + user_put(str, gl->data); + } + + g_free(name); + g_free(alias); +} + + +/** composes a GString with the written contents of a sametime list */ +static GString *list_store(struct mwSametimeList *l) { + GString *str; + GList *gl; + + g_return_val_if_fail(l != NULL, NULL); + + str = g_string_new(NULL); + g_string_append_printf(str, "Version=%u.%u.%u\r\n", + l->ver_major, l->ver_minor, l->ver_micro); + + for(gl = l->groups; gl; gl = gl->next) { + group_put(str, gl->data); + } + + return str; +} + + +char *mwSametimeList_store(struct mwSametimeList *l) { + GString *str; + char *s; + + g_return_val_if_fail(l != NULL, NULL); + + str = list_store(l); + s = str->str; + g_string_free(str, FALSE); + return s; +} + + +void mwSametimeList_put(struct mwPutBuffer *b, struct mwSametimeList *l) { + GString *str; + guint16 len; + + g_return_if_fail(l != NULL); + g_return_if_fail(b != NULL); + + str = list_store(l); + len = (guint16) str->len; + guint16_put(b, len); + mwPutBuffer_write(b, str->str, len); + + g_string_free(str, TRUE); +} + + +static void get_version(const char *line, struct mwSametimeList *l) { + guint major = 0, minor = 0, micro = 0; + int ret; + + ret = sscanf(line, "Version=%u.%u.%u\n", &major, &minor, µ); + if(ret != 3) { + g_warning("strange sametime list version line:\n%s", line); + } + + l->ver_major = major; + l->ver_minor = minor; + l->ver_micro = micro; +} + + +static struct mwSametimeGroup *get_group(const char *line, + struct mwSametimeList *l) { + struct mwSametimeGroup *group; + char *name, *alias; + char type = '2', open = 'O'; + int ret; + + ret = strlen(line); + name = g_malloc0(ret); + alias = g_malloc0(ret); + + ret = sscanf(line, "G %s %s %c\n", + name, alias, &open); + + if(ret < 3) { + g_warning("strange sametime list group line:\n%s", line); + } + + str_replace(name, ';', ' '); + str_replace(alias, ';', ' '); + + if(name && *name) { + int l = strlen(name)-1; + type = name[l]; + name[l] = '\0'; + } + + group = g_new0(struct mwSametimeGroup, 1); + group->list = l; + group->name = name; + group->type = group_char_to_type(type); + group->alias = alias; + group->open = (open == 'O'); + + l->groups = g_list_append(l->groups, group); + + return group; +} + + +static void get_user(const char *line, struct mwSametimeGroup *g) { + struct mwSametimeUser *user; + struct mwIdBlock idb = { 0, 0 }; + char *name, *alias = NULL; + char type = '1'; + int ret; + + ret = strlen(line); + idb.user = g_malloc0(ret); + name = g_malloc0(ret); + + ret = sscanf(line, "U %s %s", + idb.user, name); + + if(ret < 2) { + g_warning("strange sametime list user line:\n%s", line); + } + + str_replace(idb.user, ';', ' '); + str_replace(name, ';', ' '); + + if(idb.user && *idb.user) { + char *tmp = strstr(idb.user, "::"); + if(tmp--) { + type = *(tmp); + *tmp = '\0'; + } + } + + if(name && *name) { + char *tmp = strrchr(name, ','); + if(tmp) { + *tmp++ = '\0'; + if(*tmp) alias = tmp; + } + } + + user = g_new0(struct mwSametimeUser, 1); + user->group = g; + user->id.user = idb.user; + user->type = user_char_to_type(type); + user->name = name; + user->alias = g_strdup(alias); + + g->users = g_list_append(g->users, user); +} + + +/** returns a line from str, and advances str */ +static char *fetch_line(char **str) { + char *start = *str; + char *end; + + /* move to first non-whitespace character */ + while(*start && g_ascii_isspace(*start)) start++; + if(! *start) return NULL; + + for(end = start + 1; *end; end++) { + if(*end == '\n' || *end == '\r') { + *(end++) = '\0'; + break; + } + } + + *str = end; + return start; +} + + +static void list_get(const char *lines, struct mwSametimeList *l) { + char *s = (char *) lines; + char *line; + + struct mwSametimeGroup *g = NULL; + + while( (line = fetch_line(&s)) ) { + switch(*line) { + case 'V': + get_version(line, l); + break; + + case 'G': + g = get_group(line, l); + break; + + case 'U': + get_user(line, g); + break; + + default: + g_warning("unknown sametime list data line:\n%s", line); + } + } +} + + +struct mwSametimeList *mwSametimeList_load(const char *data) { + struct mwSametimeList *l; + + g_return_val_if_fail(data != NULL, NULL); + + l = mwSametimeList_new(); + list_get(data, l); + + return l; +} + + +void mwSametimeList_get(struct mwGetBuffer *b, struct mwSametimeList *l) { + char *str = NULL; + + g_return_if_fail(l != NULL); + g_return_if_fail(b != NULL); + + mwString_get(b, &str); + list_get(str, l); + g_free(str); +} + diff --git a/protocols/Sametime/src/messaging.cpp b/protocols/Sametime/src/messaging.cpp new file mode 100644 index 0000000000..58cc83b600 --- /dev/null +++ b/protocols/Sametime/src/messaging.cpp @@ -0,0 +1,222 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+CSametimeProto* getProtoFromMwConversation(mwConversation* conv)
+{
+ mwServiceIm* serviceIM = mwConversation_getService(conv);
+ mwService* service = mwServiceIm_getService(serviceIM);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+
+void mwIm_conversation_opened(mwConversation* conv)
+{
+ CSametimeProto* proto = getProtoFromMwConversation(conv);
+ proto->debugLog(_T("mwIm_conversation_opened() start"));
+
+ mwIdBlock* idb = mwConversation_getTarget(conv);
+ MCONTACT hContact = proto->FindContactByUserId(idb->user);
+
+ if (!hContact) {
+ proto->debugLog(_T("mwIm_conversation_opened() !hContact"));
+ mwSametimeList* user_list = mwSametimeList_new();
+ mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
+ mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, idb);
+
+ proto->AddContact(stuser, (proto->options.add_contacts ? false : true));
+ proto->GetMoreDetails(idb->user);
+ }
+
+ ContactMessageQueue::iterator i;
+ EnterCriticalSection(&proto->q_cs);
+ if ((i = proto->contact_message_queue.find(hContact)) != proto->contact_message_queue.end()) {
+ while(i->second.size()) {
+ mwConversation_send(conv, mwImSend_PLAIN, (gconstpointer)i->second.front().c_str());
+ i->second.pop();
+ }
+ proto->contact_message_queue.erase(i);
+ }
+ LeaveCriticalSection(&proto->q_cs);
+
+ // gives linker error 'unresolved external symbol' :( So instead we will either add ciphers to the session or not (see session.cpp)
+ //mwConversation_setEncrypted(conv, options.encrypt_session);
+}
+
+/** A conversation has been closed */
+void mwIm_conversation_closed(mwConversation* conv, guint32 err)
+{
+ CSametimeProto* proto = getProtoFromMwConversation(conv);
+ proto->debugLog(_T("mwIm_conversation_closed() start err=[%d]"),err);
+
+ if (err & ERR_FAILURE && err != CONNECTION_RESET) {
+ char* msg = mwError(err);
+ proto->showPopup(TranslateTS(_A2T(msg)), SAMETIME_POPUP_ERROR);
+ g_free(msg);
+ if (err == ERR_NO_COMMON_ENCRYPT && !(proto->options.encrypt_session)) {
+ proto->showPopup(TranslateT("No common encryption method. Try to enable encryption in protocol options."), SAMETIME_POPUP_INFO);
+ }
+ }
+
+ mwIdBlock* idb = mwConversation_getTarget(conv);
+ MCONTACT hContact = proto->FindContactByUserId(idb->user);
+ if (hContact) {
+ ContactMessageQueue::iterator i;
+ EnterCriticalSection(&proto->q_cs);
+ if ((i = proto->contact_message_queue.find(hContact)) != proto->contact_message_queue.end()) {
+ proto->contact_message_queue.erase(i);
+ }
+ LeaveCriticalSection(&proto->q_cs);
+ }
+}
+
+/** A message has been received on a conversation */
+void mwIm_conversation_recv(mwConversation* conv, mwImSendType type, gconstpointer msg)
+{
+ CSametimeProto* proto = getProtoFromMwConversation(conv);
+ proto->debugLog(_T("mwIm_conversation_recv() start"));
+
+ mwIdBlock* idb = mwConversation_getTarget(conv);
+ MCONTACT hContact = proto->FindContactByUserId(idb->user);
+ proto->debugLog(_T("mwIm_conversation_recv() type=[%d] hContact=[%x]"), type, hContact);
+
+ if (type == mwImSend_TYPING) {
+ CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)(GPOINTER_TO_UINT(msg) == 0 ? 0 : 2));
+ return;
+ }
+
+ if (type != mwImSend_PLAIN) return;
+
+ PROTORECVEVENT pre = {0};
+ time_t t = time(NULL);
+ pre.timestamp = t;
+ pre.flags = PREF_UTF;
+ pre.szMessage = (char*)msg;
+ ProtoChainRecvMsg(hContact, &pre);
+
+}
+
+
+void mwIm_place_invite(struct mwConversation* conv, const char* message, const char* title, const char* name)
+{
+ CSametimeProto* proto = getProtoFromMwConversation(conv);
+ proto->debugLog(_T("mwIm_place_invite() start"));
+
+ ///TODO unimplemented
+
+ TCHAR* tszMessage = mir_utf8decodeT(message);
+
+ TCHAR msg[512];
+ mir_sntprintf(msg, SIZEOF(msg), TranslateT("SERVICE UNIMPLEMENTED. %s"), tszMessage);
+ proto->showPopup(msg, SAMETIME_POPUP_INFO);
+
+ mir_free(tszMessage);
+}
+
+
+mwImHandler mwIm_handler = {
+ mwIm_conversation_opened,
+ mwIm_conversation_closed,
+ mwIm_conversation_recv,
+ mwIm_place_invite,
+ NULL
+};
+
+
+HANDLE CSametimeProto::SendMessageToUser(MCONTACT hContact, char* msg_utf8)
+{
+ debugLog(_T("CSametimeProto::SendMessageToUser() hContact=[%x]"), hContact);
+
+ mwAwareIdBlock id_block;
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+
+ mwIdBlock idb;
+ idb.user = id_block.user;
+ idb.community = id_block.community;
+
+ mwConversation* conv = mwServiceIm_getConversation(service_im, &idb);
+ if (conv) {
+ if (!mwConversation_isOpen(conv)) {
+ debugLog(_T("CSametimeProto::SendMessageToUser() mwConversation_isOpen"));
+ EnterCriticalSection(&q_cs);
+ contact_message_queue[hContact].push(msg_utf8);
+ LeaveCriticalSection(&q_cs);
+ mwConversation_open(conv);
+ } else {
+ debugLog(_T("CSametimeProto::SendMessageToUser() !mwConversation_isOpen"));
+ mwConversation_send(conv, mwImSend_PLAIN, (gconstpointer)msg_utf8);
+ }
+
+ free(id_block.user);
+ return (HANDLE)conv;
+ }
+
+ free(id_block.user);
+ }
+
+ return 0;
+}
+
+
+void CSametimeProto::SendTyping(MCONTACT hContact, bool typing)
+{
+ debugLog(_T("CSametimeProto::SendTyping() hContact=[%x] type=[%d]"), hContact, typing);
+
+ mwAwareIdBlock id_block;
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ mwIdBlock idb;
+ idb.user = id_block.user;
+ idb.community = id_block.community;
+
+ mwConversation* conv = mwServiceIm_getConversation(service_im, &idb);
+ if (conv) {
+ if (mwConversation_isOpen(conv)){
+ debugLog(_T("CSametimeProto::SendTyping() send"));
+ mwConversation_send(conv, mwImSend_TYPING, (gconstpointer)GUINT_TO_POINTER(typing ? 1 : 0));
+ }
+ }
+
+ free(id_block.user);
+ }
+}
+
+
+void CSametimeProto::CloseIm(MCONTACT hContact)
+{
+ debugLog(_T("CSametimeProto::CloseIm() hContact=[%x]"), hContact);
+
+ mwAwareIdBlock id_block;
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ mwIdBlock idb;
+ idb.user = id_block.user;
+ idb.community = id_block.community;
+
+ mwConversation* conv = mwServiceIm_getConversation(service_im, &idb);
+ if (conv) {
+ if (mwConversation_isOpen(conv)){
+ debugLog(_T("CSametimeProto::CloseIm() mwConversation_close"));
+ mwConversation_close(conv, 0);
+ }
+ }
+ free(id_block.user);
+ }
+}
+
+void CSametimeProto::InitMessaging()
+{
+ debugLog(_T("CSametimeProto::InitMessaging()"));
+ InitializeCriticalSection(&q_cs);
+ mwSession_addService(session, (mwService*)(service_im = mwServiceIm_new(session, &mwIm_handler)));
+ mwServiceIm_setClientType(service_im, mwImClient_PLAIN);
+}
+
+void CSametimeProto::DeinitMessaging()
+{
+ debugLog(_T("CSametimeProto::DeinitMessaging()"));
+ mwSession_removeService(session, mwService_IM);
+ mwService_free((mwService*)service_im);
+ service_im = 0;
+ DeleteCriticalSection(&q_cs);
+}
+
diff --git a/protocols/Sametime/src/options.cpp b/protocols/Sametime/src/options.cpp new file mode 100644 index 0000000000..d882233f48 --- /dev/null +++ b/protocols/Sametime/src/options.cpp @@ -0,0 +1,369 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+#define DEFAULT_ID (0x1800)
+
+#define NUM_IDS 20
+TCHAR* client_names[NUM_IDS] = {
+ _T("Official Binary Library"),
+ _T("Official Java Applet"),
+ _T("Official Binary Application"),
+ _T("Official Java Application"),
+ _T("Notes v6.5"),
+ _T("Notes v7.0"),
+ _T("ICT"),
+ _T("NotesBuddy"),
+ _T("NotesBuddy v4.15"),
+ _T("Sanity"),
+ _T("Perl"),
+ _T("PMR Alert"),
+ _T("Trillian (SourceForge)"),
+ _T("Trillian (IBM)"),
+ _T("Meanwhile Library"),
+ _T("Meanwhile (Python)"),
+ _T("Meanwhile (Gaim)"),
+ _T("Meanwhile (Adium)"),
+ _T("Meanwhile (Kopete)"),
+ _T("Custom")
+};
+int client_ids[NUM_IDS] = {
+ 0x1000,
+ 0x1001,
+ 0x1002,
+ 0x1003,
+ 0x1200,
+ 0x1210,
+ 0x1300,
+ 0x1400,
+ 0x1405,
+ 0x1600,
+ 0x1625,
+ 0x1650,
+ 0x16aa,
+ 0x16bb,
+ 0x1700,
+ 0x1701,
+ 0x1702,
+ 0x1703,
+ 0x1704,
+ 0xFFFF
+};
+
+
+static INT_PTR CALLBACK DlgProcOptNet(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CSametimeProto* proto = (CSametimeProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch ( msg ) {
+ case WM_INITDIALOG: {
+
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ proto = (CSametimeProto*)lParam;
+
+ {
+ TCHAR verbuf[100];
+ WORD client_ver = proto->GetClientVersion();
+ WORD server_ver = proto->GetServerVersion();
+ if (client_ver)
+ mir_sntprintf(verbuf, SIZEOF(verbuf), _T("Client proto version: %03d.%03d"), (client_ver & 0xFF00) >> 8, client_ver & 0xFF);
+ else
+ mir_sntprintf(verbuf, SIZEOF(verbuf), _T("Disconnected"));
+ SetDlgItemText(hwndDlg, IDC_ST_CLIENTVER, verbuf);
+ if (server_ver)
+ mir_sntprintf(verbuf, SIZEOF(verbuf), _T("Server proto version: %03d.%03d"), (server_ver & 0xFF00) >> 8, server_ver & 0xFF);
+ else
+ mir_sntprintf(verbuf, SIZEOF(verbuf), _T("Disconnected"));
+ SetDlgItemText(hwndDlg, IDC_ST_SERVERVER, verbuf);
+ }
+
+ TCHAR* s;
+ s = mir_utf8decodeT(proto->options.server_name); SetDlgItemText(hwndDlg, IDC_ED_SNAME, s); mir_free(s);
+ s = mir_utf8decodeT(proto->options.id); SetDlgItemText(hwndDlg, IDC_ED_NAME, s); mir_free(s);
+ s = mir_utf8decodeT(proto->options.pword); SetDlgItemText(hwndDlg, IDC_ED_PWORD, s); mir_free(s);
+
+ SetDlgItemInt(hwndDlg, IDC_ED_PORT, proto->options.port, FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_GETSERVERCONTACTS, proto->options.get_server_contacts ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_ADDCONTACTS, proto->options.add_contacts ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_IDLEAWAY, proto->options.idle_as_away ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_OLDDEFAULTVER, proto->options.use_old_default_client_ver ? TRUE : FALSE);
+
+ SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_RESETCONTENT, 0, 0);
+ int pos = 0;
+ bool found = false;
+
+ for (int i = 0; i < NUM_IDS; i++) {
+ pos = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_ADDSTRING, -1, (LPARAM)client_names[i]);
+ SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETITEMDATA, pos, client_ids[i]);
+ if (client_ids[i] == proto->options.client_id) {
+ found = true;
+ SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETCURSEL, pos, 0);
+ SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, client_ids[i], FALSE);
+ if (i != sizeof(client_ids) / sizeof(int) - 1) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_CLIENTID);
+ EnableWindow(hw, false);
+ }
+ }
+ }
+
+ if (!found) {
+ SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_SETCURSEL, pos, 0); // pos is last item, i.e. custom
+ SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, proto->options.client_id, FALSE);
+ }
+
+ if (!ServiceExists(MS_POPUP_ADDPOPUP)) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_ERRPOP);
+ EnableWindow(hw, FALSE);
+ }
+
+ if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_ERRBAL);
+ EnableWindow(hw, FALSE);
+ }
+
+ switch (proto->options.err_method) {
+ case ED_POP: CheckDlgButton(hwndDlg, IDC_RAD_ERRPOP, TRUE); break;
+ case ED_MB: CheckDlgButton(hwndDlg, IDC_RAD_ERRMB, TRUE); break;
+ case ED_BAL: CheckDlgButton(hwndDlg, IDC_RAD_ERRBAL, TRUE); break;
+ }
+
+ if (proto->options.encrypt_session)
+ CheckDlgButton(hwndDlg, IDC_RAD_ENC, TRUE);
+ else
+ CheckDlgButton(hwndDlg, IDC_RAD_NOENC, TRUE);
+
+ return FALSE;
+ }
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ if (HIWORD(wParam) == CBN_SELCHANGE) {
+ int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETCURSEL, 0, 0);
+ int id = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETITEMDATA, sel, 0);
+ bool custom = (id == client_ids[sizeof(client_ids) / sizeof(int) - 1]);
+
+ if (!custom)
+ SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, id, FALSE);
+ else
+ SetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, DEFAULT_ID, FALSE);
+
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_CLIENTID);
+ EnableWindow(hw, custom);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED ) {
+ switch (LOWORD(wParam)) {
+ case IDC_BTN_UPLOADCONTACTS:
+ {
+ HWND hBut = GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS);
+ EnableWindow(hBut, FALSE);
+ hBut = GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS);
+ EnableWindow(hBut, FALSE);
+
+ proto->ExportContactsToServer();
+
+ SendMessage(hwndDlg, WMU_STORECOMPLETE, 0, 0);
+ }
+ return TRUE;
+ case IDC_BTN_IMPORTCONTACTS:
+ {
+ OPENFILENAME ofn = {0};
+ TCHAR import_filename[MAX_PATH];
+ import_filename[0] = 0;
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.lpstrFile = import_filename;
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = CC_FULLOPEN;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFilter = _T("All\0*.*\0");
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ if (GetOpenFileName(&ofn) == TRUE) {
+ HWND hBut = GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS);
+ EnableWindow(hBut, FALSE);
+ hBut = GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS);
+ EnableWindow(hBut, FALSE);
+
+ proto->ImportContactsFromFile(ofn.lpstrFile);
+
+ SendMessage(hwndDlg, WMU_STORECOMPLETE, 0, 0);
+ }
+ }
+ return TRUE;
+ case IDC_CHK_GETSERVERCONTACTS:
+ case IDC_CHK_ENCMESSAGES:
+ case IDC_RAD_ERRMB:
+ case IDC_RAD_ERRBAL:
+ case IDC_RAD_ERRPOP:
+ case IDC_CHK_USERCP:
+ case IDC_CHK_ADDCONTACTS:
+ case IDC_CHK_IDLEAWAY:
+ case IDC_CHK_OLDDEFAULTVER:
+ case IDC_RAD_ENC:
+ case IDC_RAD_NOENC:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ case IDC_RAD_ANSI:
+ case IDC_RAD_UTF8:
+ case IDC_RAD_OEM:
+ case IDC_RAD_UTF7:
+ case IDC_RAD_USERCP:
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDC_CHK_USERCP);
+ EnableWindow(hw, !IsDlgButtonChecked(hwndDlg, IDC_RAD_USERCP));
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WMU_STORECOMPLETE:
+ {
+ HWND hBut = GetDlgItem(hwndDlg, IDC_BTN_UPLOADCONTACTS);
+ EnableWindow(hBut, TRUE);
+ hBut = GetDlgItem(hwndDlg, IDC_BTN_IMPORTCONTACTS);
+ EnableWindow(hBut, TRUE);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY) {
+ TCHAR ws[2048];
+ char* utf;
+
+ GetDlgItemText(hwndDlg, IDC_ED_SNAME, ws, LSTRINGLEN);
+ strcpy(proto->options.server_name, utf = mir_utf8encodeT(ws)); mir_free(utf);
+ GetDlgItemText(hwndDlg, IDC_ED_NAME, ws, LSTRINGLEN);
+ strcpy(proto->options.id, utf = mir_utf8encodeT(ws)); mir_free(utf);
+ GetDlgItemText(hwndDlg, IDC_ED_PWORD, ws, LSTRINGLEN);
+ strcpy(proto->options.pword, utf = mir_utf8encodeT(ws)); mir_free(utf);
+
+ BOOL translated;
+ int port = GetDlgItemInt(hwndDlg, IDC_ED_PORT, &translated, FALSE);
+ if (translated)
+ proto->options.port = port;
+
+ proto->options.get_server_contacts = (IsDlgButtonChecked(hwndDlg, IDC_CHK_GETSERVERCONTACTS) != FALSE);
+
+ int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETCURSEL, 0, 0);
+ int id = SendDlgItemMessage(hwndDlg, IDC_CMB_CLIENT, CB_GETITEMDATA, sel, 0);
+
+ if (id == client_ids[sizeof(client_ids) / sizeof(int) - 1]) {
+ BOOL trans;
+ id = GetDlgItemInt(hwndDlg, IDC_ED_CLIENTID, &trans, FALSE);
+ if (trans)
+ proto->options.client_id = id;
+ } else
+ proto->options.client_id = id;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRMB)) proto->options.err_method = ED_MB;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRBAL)) proto->options.err_method = ED_BAL;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ERRPOP)) proto->options.err_method = ED_POP;
+
+ proto->options.add_contacts = (IsDlgButtonChecked(hwndDlg, IDC_CHK_ADDCONTACTS) != FALSE);
+ proto->options.encrypt_session = (IsDlgButtonChecked(hwndDlg, IDC_RAD_ENC) != FALSE);
+ proto->options.idle_as_away = (IsDlgButtonChecked(hwndDlg, IDC_CHK_IDLEAWAY) != FALSE);
+
+ proto->options.use_old_default_client_ver = (IsDlgButtonChecked(hwndDlg, IDC_CHK_OLDDEFAULTVER) != FALSE);
+
+ proto->SaveOptions();
+
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+
+ return FALSE;
+}
+
+int CSametimeProto::OptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { sizeof(odp) };
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTNET);
+ odp.ptszTitle = m_tszUserName;
+ odp.ptszGroup = LPGENT("Network");
+ odp.pfnDlgProc = DlgProcOptNet;
+ odp.dwInitParam = (LPARAM)this;
+ Options_AddPage(wParam, &odp);
+ return 0;
+}
+
+void CSametimeProto::LoadOptions()
+{
+ DBVARIANT dbv;
+
+ if (!db_get_utf(0, m_szModuleName, "ServerName", &dbv)) {
+ strncpy(options.server_name, dbv.pszVal, LSTRINGLEN);
+ db_free(&dbv);
+ }
+ if (!db_get_utf(0, m_szModuleName, "stid", &dbv)) {
+ strncpy(options.id, dbv.pszVal, LSTRINGLEN);
+ db_free(&dbv);
+ }
+ if (!db_get_utf(0, m_szModuleName, "Password", &dbv)) {
+ strncpy(options.pword, dbv.pszVal, LSTRINGLEN);
+ db_free(&dbv);
+ }
+
+ options.port = db_get_dw(0, m_szModuleName, "ServerPort", DEFAULT_PORT);
+ options.encrypt_session = (db_get_b(0, m_szModuleName, "EncryptSession", 0) == 1);
+
+ options.client_id = db_get_dw(0, m_szModuleName, "ClientID", DEFAULT_ID);
+ options.use_old_default_client_ver = (db_get_b(0, m_szModuleName, "UseOldClientVer", 0) == 1);
+
+ options.get_server_contacts = (db_get_b(0, m_szModuleName, "GetServerContacts", 1) == 1);
+ options.add_contacts = (db_get_b(0, m_szModuleName, "AutoAddContacts", 0) == 1);
+ options.idle_as_away = (db_get_b(0, m_szModuleName, "IdleAsAway", 1) == 1);
+
+ // if popups not installed, will be changed to 'ED_BAL' (balloons) in main.cpp, modules loaded
+ options.err_method = (ErrorDisplay)db_get_b(0, m_szModuleName, "ErrorDisplay", ED_POP);
+ // funny logic :) ... try to avoid message boxes
+ // if want baloons but no balloons, try popups
+ // if want popups but no popups, try baloons
+ // if, after that, you want balloons but no balloons, revert to message boxes
+ if (options.err_method == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) options.err_method = ED_POP;
+ if (options.err_method == ED_POP && !ServiceExists(MS_POPUP_SHOWMESSAGE)) options.err_method = ED_BAL;
+ if (options.err_method == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) options.err_method = ED_MB;
+
+ debugLog(_T("LoadOptions() loaded: ServerName:len=[%d], id:len=[%d], pword:len=[%d]"), options.server_name == NULL ? -1 : strlen(options.server_name), options.id == NULL ? -1 : strlen(options.id), options.pword == NULL ? -1 : strlen(options.pword));
+ debugLog(_T("LoadOptions() loaded: port=[%d], encrypt_session=[%d], client_id=[%d], use_old_default_client_ver=[%d]"), options.port, options.encrypt_session, options.client_id, options.use_old_default_client_ver);
+ debugLog(_T("LoadOptions() loaded: get_server_contacts=[%d], add_contacts=[%d], idle_as_away=[%d], err_method=[%d]"), options.get_server_contacts, options.add_contacts, options.idle_as_away, options.err_method);
+
+}
+
+void CSametimeProto::SaveOptions()
+{
+ db_set_utf(0, m_szModuleName, "ServerName", options.server_name);
+
+ db_set_utf(0, m_szModuleName, "stid", options.id);
+ //db_set_s(0, m_szModuleName, "Nick", options.id);
+ db_set_utf(0, m_szModuleName, "Password", options.pword);
+
+ db_set_dw(0, m_szModuleName, "ServerPort", options.port);
+ db_set_b(0, m_szModuleName, "GetServerContacts", options.get_server_contacts ? 1 : 0);
+ db_set_dw(0, m_szModuleName, "ClientID", options.client_id);
+ db_set_b(0, m_szModuleName, "ErrorDisplay", options.err_method);
+
+ db_set_b(0, m_szModuleName, "AutoAddContacts", options.add_contacts ? 1 : 0);
+ db_set_b(0, m_szModuleName, "EncryptSession", options.encrypt_session ? 1 : 0);
+ db_set_b(0, m_szModuleName, "IdleAsAway", options.idle_as_away ? 1 : 0);
+
+ db_set_b(0, m_szModuleName, "UseOldClientVer", options.use_old_default_client_ver ? 1 : 0);
+}
diff --git a/protocols/Sametime/src/places.cpp b/protocols/Sametime/src/places.cpp new file mode 100644 index 0000000000..c7c0a19adf --- /dev/null +++ b/protocols/Sametime/src/places.cpp @@ -0,0 +1,67 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+/* Stubs, NOT IMPLEMENTED NOW */
+
+void mwServicePlace_opened(struct mwPlace* place)
+{
+}
+
+void mwServicePlace_closed(struct mwPlace* place, guint32 code)
+{
+}
+
+void mwServicePlace_peerJoined(struct mwPlace* place, const struct mwIdBlock* peer)
+{
+}
+
+
+void mwServicePlace_peerParted(struct mwPlace* place, const struct mwIdBlock* peer)
+{
+}
+
+
+void mwServicePlace_peerSetAttribute(struct mwPlace* place, const struct mwIdBlock* peer, guint32 attr, struct mwOpaque* o)
+{
+}
+
+
+void mwServicePlace_peerUnsetAttribute(struct mwPlace* place, const struct mwIdBlock* peer, guint32 attr)
+{
+}
+
+
+void mwServicePlace_message(struct mwPlace* place, const struct mwIdBlock* who, const char* msg)
+{
+}
+
+
+void mwServicePlace_clear(struct mwServicePlace* srvc)
+{
+}
+
+
+mwPlaceHandler mwPlace_handler = {
+ mwServicePlace_opened,
+ mwServicePlace_closed,
+ mwServicePlace_peerJoined,
+ mwServicePlace_peerParted,
+ mwServicePlace_peerSetAttribute,
+ mwServicePlace_peerUnsetAttribute,
+ mwServicePlace_message,
+ mwServicePlace_clear
+};
+
+void CSametimeProto::InitPlaces(mwSession* session)
+{
+ debugLog(_T("CSametimeProto::InitPlaces()"));
+ mwSession_addService(session, (mwService*)(service_places = mwServicePlace_new(session, &mwPlace_handler)));
+}
+
+void CSametimeProto::DeinitPlaces(mwSession* session)
+{
+ debugLog(_T("CSametimeProto::DeinitPlaces()"));
+ mwSession_removeService(session, mwService_PLACE);
+ mwService_free((mwService*)service_places);
+ service_places = 0;
+}
diff --git a/protocols/Sametime/src/resource.h b/protocols/Sametime/src/resource.h new file mode 100644 index 0000000000..3ca8cba566 --- /dev/null +++ b/protocols/Sametime/src/resource.h @@ -0,0 +1,59 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDD_DIALOG1 101
+#define IDD_OPTNET 101
+#define IDI_ICON_PROTO 102
+#define IDI_ICON_LEAVE 104
+#define IDI_ICON_INVITE 105
+#define IDI_ICON_ANNOUNCE 107
+#define IDI_ICON_NOTIFY 108
+#define IDI_ICON_ERROR 109
+#define IDD_SESSIONANNOUNCE 208
+#define IDD_USERSEARCH 209
+#define IDC_ED_SNAME 1000
+#define IDC_ED_NAME 1001
+#define IDC_ED_PWORD 1002
+#define IDC_ED_PORT 1003
+#define IDC_CHK_GETSERVERCONTACTS 1004
+#define IDC_BTN_UPLOADCONTACTS 1005
+#define IDC_CHK_ENCMESSAGES 1006
+#define IDC_BTN_IMPORTCONTACTS 1007
+#define IDC_CHK_UTF8 1008
+#define IDC_CHK_ADDCONTACTS 1008
+#define IDC_CHK_IDLEAWAY 1009
+#define IDC_CMB_CLIENT 1010
+#define IDC_ED_CLIENTID 1011
+#define IDC_RAD_ERRMB 1012
+#define IDC_RAD_ERRPOP 1013
+#define IDC_RAD_ERRBAL 1014
+#define IDC_RAD_ANSI 1015
+#define IDC_CHK_OLDDEFAULTVER 1016
+#define IDC_RAD_UTF8 1017
+#define IDC_CHK_USERCP 1018
+#define IDC_RAD_OEM 1019
+#define IDC_RAD_ENC 1020
+#define IDC_RAD_UTF7 1021
+#define IDC_RAD_NOENC 1022
+#define IDC_RAD_ANSI2 1023
+#define IDC_RAD_USERCP 1024
+#define IDC_ED_ANMSG 1025
+#define IDC_LST_ANTO 1026
+#define IDC_BUT_SELALL 1027
+#define IDC_BUT_SELINV 1028
+#define IDC_ST_CLIENTVER 1029
+#define IDC_ST_SERVERVER 1030
+#define IDC_EDIT1 1031
+#define IDC_ST_LIBVER 1032
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 111
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1033
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/Sametime/src/sametime.cpp b/protocols/Sametime/src/sametime.cpp new file mode 100644 index 0000000000..5cec8f873a --- /dev/null +++ b/protocols/Sametime/src/sametime.cpp @@ -0,0 +1,296 @@ +#include "StdAfx.h"
+#include "sametime.h"
+#include "version.h"
+
+// plugin stuff
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ { 0xf1b0ba1b, 0xc91, 0x4313, { 0x85, 0xeb, 0x22, 0x50, 0x69, 0xd4, 0x4d, 0x1 } } // {F1B0BA1B-0C91-4313-85EB-225069D44D01}
+};
+
+
+HINSTANCE hInst;
+LIST<CSametimeProto> g_Instances(1, PtrKeySortT);
+int hLangpack;
+
+
+// sametime.cpp: Defines the entry point for the DLL application.
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+
+
+// protocol related services
+
+
+/** Copy the name of the protocole into lParam
+* @param wParam : max size of the name
+* @param lParam : reference to a char *, which will hold the name
+*/
+INT_PTR CSametimeProto::GetName(WPARAM wParam, LPARAM lParam)
+{
+ strncpy((char*)lParam, m_szModuleName, wParam);
+ return 0;
+}
+
+/*
+ * Returns the current status
+ */
+INT_PTR CSametimeProto::GetStatus(WPARAM wParam, LPARAM lParam)
+{
+ return m_iStatus;
+}
+
+
+/** Loads the icon corresponding to the status
+* Called by the CList when the status changes.
+* @param wParam : one of the following values : \n
+ <tt>PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE</tt>
+* @return an \c HICON in which the icon has been loaded.
+*/
+INT_PTR CSametimeProto::SametimeLoadIcon(WPARAM wParam, LPARAM lParam)
+{
+
+ UINT id;
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = IDI_ICON_PROTO;
+ break;
+ default:
+ return (int) (HICON) NULL;
+ }
+
+ return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON,
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON),
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0);
+ return 0;
+}
+
+
+//icolib stuff
+static IconItem iconList[] =
+{
+ { LPGEN("Protocol icon"), "protoicon", IDI_ICON_PROTO, 0 }
+ , { LPGEN("Start Conference"), "leaveconference", IDI_ICON_INVITE, 0 }
+ , { LPGEN("Leave Conference"), "startconference", IDI_ICON_LEAVE, 0 }
+ , { LPGEN("Announce"), "announce", IDI_ICON_ANNOUNCE, 0 }
+ , { LPGEN("Notification"), "notify", IDI_ICON_NOTIFY, 0 }
+ , { LPGEN("Error"), "error", IDI_ICON_ERROR, 0 }
+};
+
+void SametimeInitIcons(void)
+{
+ Icon_Register(hInst, "Protocols/Sametime", iconList, SIZEOF(iconList), "SAMETIME");
+}
+
+HANDLE GetIconHandle(int iconId)
+{
+ for (int i = 0; i < SIZEOF(iconList); i++)
+ if (iconList[i].defIconID == iconId)
+ return iconList[i].hIcolib;
+ return NULL;
+}
+
+HICON LoadIconEx(const char* name, BOOL big)
+{
+ char szSettingName[100];
+ mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", "SAMETIME", name);
+ return Skin_GetIcon(szSettingName, big);
+}
+
+void ReleaseIconEx(const char* name, BOOL big)
+{
+ char szSettingName[100];
+ mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", "SAMETIME", name);
+ Skin_ReleaseIcon(szSettingName, big);
+}
+
+
+// Copied from MSN plugin - sent acks need to be from different thread
+void __cdecl sttFakeAckInfoSuccessThread(void* param)
+{
+ TFakeAckParams* tParam = (TFakeAckParams*)param;
+ CSametimeProto* proto = tParam->proto;
+ proto->debugLog(_T("sttFakeAckInfoSuccessThread() start"));
+
+ Sleep(100);
+ proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0);
+
+ proto->debugLog(_T("sttFakeAckInfoSuccessThread() end"));
+ mir_free(tParam);
+ return;
+}
+
+void __cdecl sttFakeAckMessageSuccessThread(void* param)
+{
+ TFakeAckParams* tParam = (TFakeAckParams*)param;
+ CSametimeProto* proto = tParam->proto;
+ proto->debugLog(_T("sttFakeAckMessageSuccessThread() start"));
+
+ Sleep(100);
+ proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)tParam->lParam, 0 );
+
+ proto->debugLog(_T("sttFakeAckMessageSuccessThread() end"));
+ mir_free(tParam);
+ return;
+}
+
+void __cdecl sttFakeAckMessageFailedThread(void* param)
+{
+ TFakeAckParams* tParam = (TFakeAckParams*)param;
+ CSametimeProto* proto = tParam->proto;
+ proto->debugLog(_T("sttFakeAckMessageFailedThread() start"));
+
+ Sleep(100);
+ proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, NULL, tParam->lParam); ///TODO tParam->lParam: add error message
+
+ proto->debugLog(_T("sttFakeAckMessageFailedThread() end"));
+ mir_free(tParam);
+ return;
+}
+
+void __cdecl sttRecvAwayThread(void* param)
+{
+ TFakeAckParams* tParam = (TFakeAckParams*)param;
+ CSametimeProto* proto = tParam->proto;
+ proto->debugLog(_T("sttRecvAwayThread() start"));
+
+ Sleep(100);
+ proto->UserRecvAwayMessage(tParam->hContact);
+
+ proto->debugLog(_T("sttRecvAwayThread() end"));
+ free(tParam);
+ return;
+}
+
+
+int CSametimeProto::OnWindowEvent(WPARAM wParam, LPARAM lParam)
+{
+ MessageWindowEventData* mwed = (MessageWindowEventData*)lParam;
+
+ if (db_get_b(mwed->hContact, m_szModuleName, "ChatRoom", 0))
+ return 0;
+
+ if (mwed && (mwed->uType == MSG_WINDOW_EVT_CLOSING || mwed->uType == MSG_WINDOW_EVT_CLOSE))
+ CloseIm(mwed->hContact);
+
+ return 0;
+}
+
+int CSametimeProto::OnIdleChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (!(lParam & IDF_PRIVACY)) {
+ is_idle = lParam & IDF_ISIDLE ? true : false;
+ SetIdle(is_idle);
+ }
+
+ return 0;
+}
+
+
+int CSametimeProto::OnPreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ if (m_iStatus != ID_STATUS_OFFLINE){
+ LogOut();
+ }
+
+ return 0;
+}
+
+
+int CSametimeProto::OnSametimeContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ MCONTACT hContact = wParam;
+ ContactDeleted(hContact);
+ ChatDeleted(hContact);
+ return 0;
+}
+
+
+void CSametimeProto::SetAllOffline()
+{
+ debugLog(_T("SetAllOffline() start"));
+
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0)) {
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+ continue;
+ } else {
+ db_set_w(hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE);
+ db_set_dw(hContact, m_szModuleName, "IdleTS", 0);
+ }
+ }
+
+}
+
+
+void CSametimeProto::BroadcastNewStatus(int iNewStatus)
+{
+ if (m_iStatus == iNewStatus){
+ return;
+ }
+
+ debugLog(_T("BroadcastNewStatus() m_iStatus=[%d], iNewStatus=[%d]"), m_iStatus, iNewStatus);
+
+ previous_status = m_iStatus;
+ m_iStatus = iNewStatus;
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)previous_status, m_iStatus);
+}
+
+
+static CSametimeProto* sametime_proto_init(const char* pszProtoName, const TCHAR* tszUserName)
+{
+ CSametimeProto* proto = new CSametimeProto(pszProtoName, tszUserName);
+ g_Instances.insert(proto);
+ return proto;
+}
+
+static int sametime_proto_uninit(PROTO_INTERFACE* ppro)
+{
+ CSametimeProto* proto = (CSametimeProto*)ppro;
+ g_Instances.remove(proto);
+ delete proto;
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+
+ PROTOCOLDESCRIPTOR pd = { sizeof(pd) };
+ pd.type = PROTOTYPE_PROTOCOL;
+ pd.szName = "Sametime";
+ pd.fnInit = (pfnInitProto)sametime_proto_init;
+ pd.fnUninit = (pfnUninitProto)sametime_proto_uninit;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload()
+{
+
+ g_Instances.destroy();
+
+ return 0;
+
+}
+
diff --git a/protocols/Sametime/src/sametime.h b/protocols/Sametime/src/sametime.h new file mode 100644 index 0000000000..7554a5d78d --- /dev/null +++ b/protocols/Sametime/src/sametime.h @@ -0,0 +1,121 @@ +#ifndef _SAMETIME_H
+#define _SAMETIME_H
+
+
+//sametime defines
+
+#define FILE_BUFF_SIZE (1024 * 32)
+
+#define MS_SAMETIME_MENULEAVECHAT "/LeaveChat"
+#define MS_SAMETIME_MENUCREATECHAT "/CreateChat"
+
+#define MAX_MESSAGE_SIZE (10 * 1024) // verified limit in official client, thx Periferral
+
+#define LSTRINGLEN 256
+
+#define DEFAULT_PORT 1533
+
+#define WMU_STORECOMPLETE (WM_USER + 110)
+
+
+
+typedef enum {SAMETIME_POPUP_ERROR = 1, SAMETIME_POPUP_INFO = 2 } SametimePopupEnum;
+typedef enum {ED_MB = 1, ED_POP = 2, ED_BAL = 3} ErrorDisplay;
+typedef enum {CPT_USER, CPT_ANSI, CPT_UTF8, CPT_OEM, CPT_UTF7} CodePageType;
+
+
+
+//stl typedef's
+typedef std::queue<std::string> InviteQueue; ///for conference.cpp
+typedef std::queue<std::string> MessageQueue; ///for messaging.cpp
+typedef std::map<MCONTACT, MessageQueue> ContactMessageQueue; ///for messaging.cpp
+
+
+//protocol includes
+#include "resource.h"
+
+
+//methods
+INT_PTR CALLBACK SessionAnnounceDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK CALLBACK SearchDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+void mwResolve_handler_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data);
+
+void SametimeInitIcons(void);
+HANDLE GetIconHandle(int iconId);
+HICON LoadIconEx(const char* name, BOOL big);
+void ReleaseIconEx(const char* name, BOOL big);
+
+
+// services (async thread functions)
+void __cdecl sttFakeAckInfoSuccessThread(void* param);
+void __cdecl sttFakeAckMessageFailedThread(void* param);
+void __cdecl sttFakeAckMessageSuccessThread(void* param);
+void __cdecl sttRecvAwayThread(void* param);
+
+
+//sametime structs
+
+typedef struct Options_tag {
+ char server_name[LSTRINGLEN]; // utf8
+ char id[LSTRINGLEN]; // utf8
+ char pword[LSTRINGLEN]; // utf8
+ int port;
+ bool get_server_contacts;
+ int client_id;
+ ErrorDisplay err_method;
+ bool add_contacts;
+ bool encrypt_session;
+ bool idle_as_away;
+ bool use_old_default_client_ver;
+} SametimeOptions;
+
+typedef struct {
+ int cbSize;
+ char* nick;
+ char* firstName;
+ char* lastName;
+ char* email;
+ char reserved[16];
+ char name[256];
+ char stid[256];
+ bool group;
+} MYPROTOSEARCHRESULT;
+
+typedef struct {
+ size_t nSize;
+ int nFieldCount;
+ TCHAR** pszFields;
+ MYPROTOSEARCHRESULT psr;
+} MYCUSTOMSEARCHRESULTS;
+
+typedef struct FileTransferClientData_tag {
+ char* save_path;
+ HANDLE hFile;
+ bool sending;
+ MCONTACT hContact;
+ struct FileTransferClientData_tag* first;
+ struct FileTransferClientData_tag* next;
+ HANDLE hFt;
+ char* buffer;
+ int ft_number;
+ int ft_count; // number of nodes in list - only valid in first node
+ int totalSize; // total for all files in the list - only valid in first node
+ int sizeToHere; // in a link list of file transfers, the sum of the filesizes of all prior nodes in the list
+ mwFileTransfer* ft;
+} FileTransferClientData;
+
+
+
+// Global variables
+struct CSametimeProto;
+
+extern HINSTANCE hInst;
+extern PLUGININFOEX pluginInfo;
+extern LIST<CSametimeProto> g_Instances;
+
+
+#include "sametime_proto.h"
+
+
+#endif //#ifndef _SAMETIME_H
+
diff --git a/protocols/Sametime/src/sametime_proto.cpp b/protocols/Sametime/src/sametime_proto.cpp new file mode 100644 index 0000000000..eb1839dc3a --- /dev/null +++ b/protocols/Sametime/src/sametime_proto.cpp @@ -0,0 +1,430 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+CSametimeProto::CSametimeProto(const char* pszProtoName, const TCHAR* tszUserName)
+ : PROTO<CSametimeProto>(pszProtoName, tszUserName)
+ , is_idle(false)
+ , idle_status(false)
+ , first_online(true)
+ , idle_timerid(0)
+ , session(NULL)
+ , my_login_info(NULL)
+ , my_conference(NULL)
+ , service_places(NULL)
+ , service_conference(NULL)
+ , server_connection(0)
+{
+
+ // Register m_hNetlibUser user
+ TCHAR name[128];
+ mir_sntprintf(name, SIZEOF(name), TranslateT("%s connection"), m_tszUserName);
+ NETLIBUSER nlu = { 0 };
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_TCHAR | NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS;
+ nlu.szSettingsModule = m_szModuleName;
+ nlu.ptszDescriptiveName = name;
+ m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ RegisterGLibLogger();
+ debugLog(_T("CSametimeProto::CSametimeProto() start m_szModuleName=[%s], m_tszUserName=[%s]"), _A2T(m_szModuleName), m_tszUserName);
+
+ SametimeInitIcons();
+ InitCritSection();
+
+ CreateProtoService(PS_GETNAME, &CSametimeProto::GetName);
+ CreateProtoService(PS_GETSTATUS, &CSametimeProto::GetStatus);
+ CreateProtoService(PS_LOADICON, &CSametimeProto::SametimeLoadIcon);
+
+ HookProtoEvent(ME_SYSTEM_PRESHUTDOWN, &CSametimeProto::OnPreShutdown);
+ HookProtoEvent(ME_MSG_WINDOWEVENT, &CSametimeProto::OnWindowEvent);
+ HookProtoEvent(ME_IDLE_CHANGED, &CSametimeProto::OnIdleChanged);
+ HookProtoEvent(ME_DB_CONTACT_DELETED, &CSametimeProto::OnSametimeContactDeleted);
+ HookProtoEvent(ME_OPT_INITIALISE, &CSametimeProto::OptInit);
+
+ // Initialize temporary DB settings
+ db_set_resident(m_szModuleName, "Status");
+ db_set_resident(m_szModuleName, "IdleTS");
+
+ RegisterPopups();
+ InitAwayMsg();
+
+ mir_snprintf(szProtoGroups, SIZEOF(szProtoGroups), "%s_GROUPS", m_szModuleName);
+
+ m_iStatus = ID_STATUS_OFFLINE;
+ previous_status = ID_STATUS_OFFLINE;
+ SetAllOffline();
+
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, THREAD_SET_CONTEXT, FALSE, 0 );
+
+ InitConferenceMenu();
+ InitSessionMenu();
+ InitGroupChats();
+
+ LoadOptions();
+
+ debugLog(_T("CSametimeProto::CSametimeProto() end"));
+}
+
+CSametimeProto::~CSametimeProto()
+{
+
+ debugLog(_T("CSametimeProto::~CSametimeProto() start"));
+
+ DeinitSessionMenu();
+ DeinitConferenceMenu();
+
+ DeinitAwayMsg();
+ UnregisterPopups();
+ DeinitCritSection();
+
+ debugLog(_T("CSametimeProto::~CSametimeProto() end"));
+
+ UnRegisterGLibLogger();
+ Netlib_CloseHandle(m_hNetlibUser);
+
+}
+
+
+MCONTACT CSametimeProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
+{
+ MYPROTOSEARCHRESULT* sr = (MYPROTOSEARCHRESULT*)psr;
+ debugLog(_T("CSametimeProto::AddToList() flags=[%d]"), flags);
+ return AddSearchedUser(sr, flags & PALF_TEMPORARY);
+}
+
+MCONTACT CSametimeProto::AddToListByEvent(int flags, int iContact, HANDLE hDbEvent)
+{
+ debugLog(_T("CSametimeProto::AddToListByEvent() flags=[%d]"), flags);
+ return 0;
+}
+
+
+int CSametimeProto::Authorize(HANDLE hDbEvent)
+{
+ debugLog(_T("CSametimeProto::Authorize()"));
+ return 1;
+}
+
+int CSametimeProto::AuthDeny(HANDLE hDbEvent, const PROTOCHAR* szReason)
+{
+ debugLog(_T("CSametimeProto::AuthDeny()"));
+ return 1;
+}
+
+
+int CSametimeProto::AuthRecv(MCONTACT hContact, PROTORECVEVENT*)
+{
+ debugLog(_T("CSametimeProto::AuthRecv()"));
+ return 1;
+}
+
+int CSametimeProto::AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage)
+{
+ debugLog(_T("CSametimeProto::AuthRequest()"));
+ return 1;
+}
+
+
+HANDLE CSametimeProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath)
+{
+ debugLog(_T("CSametimeProto::FileAllow() hContact=[%x], szPath=[%s]"), hContact, szPath);
+ char* szPathA = mir_t2a(szPath);
+ HANDLE res = AcceptFileTransfer(hContact, hTransfer, szPathA);
+ mir_free(szPathA);
+ return res;
+}
+
+int CSametimeProto::FileCancel(MCONTACT hContact, HANDLE hTransfer)
+{
+ debugLog(_T("CSametimeProto::FileCancel() hContact=[%x]"), hContact);
+ CancelFileTransfer(hTransfer);
+ return 0;
+}
+
+int CSametimeProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason)
+{
+ debugLog(_T("CSametimeProto::FileDeny() hContact=[%x], szReason=[%s]"), hContact, szReason);
+ RejectFileTransfer(hTransfer);
+ return 0;
+}
+
+int CSametimeProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename)
+{
+ debugLog(_T("CSametimeProto::FileResume() action=[%d]"), &action);
+ return 0;
+}
+
+
+DWORD_PTR CSametimeProto::GetCaps(int type, MCONTACT hContact)
+{
+ int ret = 0;
+ switch (type) {
+ case PFLAGNUM_1:
+ ret = PF1_IM | PF1_BASICSEARCH | PF1_EXTSEARCHUI | PF1_ADDSEARCHRES | PF1_MODEMSG | PF1_FILE | PF1_CHAT;
+ break;
+ case PFLAGNUM_2:
+ ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_HEAVYDND | PF2_LIGHTDND;
+ break;
+ case PFLAGNUM_3:
+ ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_HEAVYDND;
+ break;
+ case PFLAGNUM_4:
+ ret = PF4_SUPPORTTYPING | PF4_IMSENDUTF;
+ break;
+ case PFLAGNUM_5:
+ ret = PF2_LIGHTDND;
+ break;
+ case PFLAG_UNIQUEIDTEXT:
+ ret = (DWORD_PTR) Translate("Id");
+ break;
+ case PFLAG_MAXLENOFMESSAGE:
+ ret = MAX_MESSAGE_SIZE;
+ break;
+ case PFLAG_UNIQUEIDSETTING:
+ ret = (DWORD_PTR) "stid";
+ break;
+ }
+ return ret;
+}
+
+int CSametimeProto::GetInfo(MCONTACT hContact, int infoType)
+{
+ // GetInfo - retrieves a contact info
+ debugLog(_T("CSametimeProto::GetInfo() hContact=[%x], infoType=[%d]"), hContact, infoType);
+
+ if (getByte(hContact, "ChatRoom", 0))
+ return 1;
+
+ if (!session)
+ return 1;
+
+ ///TODO unimplemented - getting contact info
+
+ TFakeAckParams* tfap = (TFakeAckParams*)mir_alloc(sizeof(TFakeAckParams));
+ tfap->proto = this;
+ tfap->hContact = hContact;
+ tfap->lParam = NULL;
+ mir_forkthread(sttFakeAckInfoSuccessThread, (void*)tfap);
+
+ return 0;
+}
+
+
+HANDLE CSametimeProto::SearchBasic(const PROTOCHAR* id)
+{
+ debugLog(_T("CSametimeProto::SearchBasic() id:len=[%d]"), id == NULL ? -1 : _tcslen(id));
+ char* id_utf8 = mir_utf8encodeT(id);
+ int ret = SearchForUser(id_utf8, FALSE);
+ mir_free(id_utf8);
+ return (HANDLE)ret;
+ ///TODO - add timeout (like at GGPROTO::searchthread)
+}
+
+HANDLE CSametimeProto::SearchByEmail(const PROTOCHAR* email)
+{
+ return 0;
+}
+
+HANDLE CSametimeProto::SearchByName(const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName)
+{
+ return 0;
+}
+
+HWND CSametimeProto::SearchAdvanced(HWND owner)
+{
+ TCHAR buf[512];
+ int ret = 0;
+ if (GetDlgItemText(owner, IDC_EDIT1, buf, 512)) {
+ debugLog(_T("CSametimeProto::SearchAdvanced() buf:len=[%d]"), buf == NULL ? -1 : _tcslen(buf));
+ char* buf_utf8 = mir_utf8encodeT(buf);
+ ret = SearchForUser(buf_utf8, TRUE);
+ mir_free(buf_utf8);
+ }
+ return (HWND)ret;
+}
+
+HWND CSametimeProto::CreateExtendedSearchUI(HWND owner)
+{
+ debugLog(_T("CSametimeProto::CreateExtendedSearchUI() start"));
+ return CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_USERSEARCH), owner, SearchDialogFunc, (LPARAM)this);
+}
+
+
+int CSametimeProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT*)
+{
+ debugLog(_T("CSametimeProto::RecvContacts()"));
+ return 1;
+}
+
+int CSametimeProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT* pre)
+{
+ debugLog(_T("CSametimeProto::RecvFile() hContact=[%x]"), hContact);
+
+ db_unset(hContact, "CList", "Hidden");
+ db_unset(hContact, "CList", "NotOnList");
+
+ return Proto_RecvFile(hContact, pre);
+}
+
+int CSametimeProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre)
+{
+ debugLog(_T("CSametimeProto::RecvMsg() hContact=[%x]"), hContact);
+
+ db_unset(hContact, "CList", "Hidden");
+ db_unset(hContact, "CList", "NotOnList");
+
+ return Proto_RecvMessage(hContact, pre);
+}
+
+int CSametimeProto::RecvUrl(MCONTACT hContact, PROTORECVEVENT*)
+{
+ debugLog(_T("CSametimeProto::RecvUrl()"));
+ return 1;
+}
+
+int CSametimeProto::SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT* hContactsList)
+{
+ debugLog(_T("CSametimeProto::SendContacts() flags=[%d], nContacts=[%d]"), flags, nContacts);
+ return 1;
+}
+
+HANDLE CSametimeProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles)
+{
+ debugLog(_T("CSametimeProto::SendFile() hContact=[%x]"), hContact);
+ if (m_iStatus != ID_STATUS_OFFLINE) {
+ if (hContact && ppszFiles && szDescription) {
+ if (db_get_w(hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ return SendFilesToUser(hContact, ppszFiles, szDescription);
+ }
+ }
+ }
+ return 0; // failure
+}
+
+int CSametimeProto::SendMsg(MCONTACT hContact, int flags, const char* msg)
+{
+
+ debugLog(_T("CSametimeProto::SendMsg() hContact=[%x], flags=[%d]"), hContact, flags);
+ char* proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ int ret;
+
+ if (!proto || strcmp(proto, m_szModuleName) != 0 || db_get_w(hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) {
+ TFakeAckParams* tfap = (TFakeAckParams*)mir_alloc(sizeof(TFakeAckParams));
+ tfap->proto = this;
+ tfap->hContact = hContact;
+ tfap->lParam = 0;
+ mir_forkthread(sttFakeAckMessageFailedThread, (void*)tfap);
+ return 0;
+ }
+
+ char* msg_utf8;
+ if (flags & PREF_UNICODE)
+ msg_utf8 = mir_utf8encodeW((wchar_t*)&msg[ strlen( msg )+1 ] );
+ else if (flags & PREF_UTF)
+ msg_utf8 = mir_strdup(msg);
+ else
+ msg_utf8 = mir_utf8encode(msg);
+
+ if (!msg_utf8)
+ return 0;
+
+ ret = (int)SendMessageToUser(hContact, msg_utf8);
+ mir_free(msg_utf8);
+
+ TFakeAckParams* tfap = (TFakeAckParams*)mir_alloc(sizeof(TFakeAckParams));
+ tfap->proto = this;
+ tfap->hContact = hContact;
+ tfap->lParam = (LPARAM)ret;
+ mir_forkthread(sttFakeAckMessageSuccessThread, (void*)tfap);
+
+ return ret;
+}
+
+int CSametimeProto::SendUrl(MCONTACT hContact, int flags, const char* url)
+{
+ debugLog(_T("CSametimeProto::SendUrl()"));
+ return 1;
+}
+
+
+int CSametimeProto::SetApparentMode(MCONTACT hContact, int mode)
+{
+ debugLog(_T("CSametimeProto::SetApparentMode() mode=[%d]"), mode);
+ return 1;
+}
+
+int CSametimeProto::SetStatus(int iNewStatus)
+{
+ debugLog(_T("CSametimeProto::SetStatus() m_iStatus=[%d], m_iDesiredStatus=[%d], iNewStatus=[%d]"), m_iStatus, m_iDesiredStatus, iNewStatus);
+ m_iDesiredStatus = iNewStatus;
+ if (iNewStatus != ID_STATUS_OFFLINE) {
+ if (m_iStatus == ID_STATUS_OFFLINE)
+ LogIn(iNewStatus, m_hNetlibUser);
+ else
+ SetSessionStatus(iNewStatus);
+ } else if (m_iStatus != ID_STATUS_OFFLINE && iNewStatus == ID_STATUS_OFFLINE) {
+ LogOut();
+ }
+
+ return 0;
+}
+
+HANDLE CSametimeProto::GetAwayMsg(MCONTACT hContact)
+{
+ debugLog(_T("CSametimeProto::GetInfo() hContact=[%x], m_iStatus=[%d]"), hContact, m_iStatus);
+ if (hContact && m_iStatus != ID_STATUS_OFFLINE) {
+ TFakeAckParams* tfap;
+ tfap = (TFakeAckParams*)malloc(sizeof(TFakeAckParams));
+ tfap->proto = this;
+ tfap->hContact = hContact;
+ mir_forkthread(sttRecvAwayThread, (void*)tfap);
+ return (HANDLE)1;
+ }
+ return (HANDLE)0;
+}
+
+int CSametimeProto::RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt)
+{
+ debugLog(_T("CSametimeProto::RecvAwayMsg() hContact=[%x], mode=[%d]"), hContact, mode);
+
+ if (evt->flags & PREF_UTF) {
+ TCHAR* pszMsg = mir_utf8decodeT(evt->szMessage);
+ ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)evt->lParam, (LPARAM)pszMsg);
+ mir_free(pszMsg);
+ } else {
+ ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)evt->lParam, (LPARAM)(TCHAR*)_A2T(evt->szMessage));
+ }
+
+ return 0;
+}
+
+int CSametimeProto::SetAwayMsg(int iStatus, const PROTOCHAR* msg)
+{
+ debugLog(_T("CSametimeProto::SetAwayMsg() iStatus=[%d], msg:len=[%d]"), iStatus, msg == NULL ? -1 :_tcslen(msg));
+ SetSessionAwayMessage(iStatus, msg);
+ return 0;
+}
+
+
+int CSametimeProto::UserIsTyping(MCONTACT hContact, int type)
+{
+ debugLog(_T("CSametimeProto::UserIsTyping() hContact=[%x], type=[%d]"), hContact, type);
+ SendTyping(hContact, type == PROTOTYPE_SELFTYPING_ON);
+ return 0;
+}
+
+
+int CSametimeProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam)
+{
+ switch(iEventType) {
+ case EV_PROTO_ONOPTIONS: {
+ debugLog(_T("CSametimeProto::OnEvent() EV_PROTO_ONOPTIONS"));
+ OptInit(wParam, lParam);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
diff --git a/protocols/Sametime/src/sametime_proto.h b/protocols/Sametime/src/sametime_proto.h new file mode 100644 index 0000000000..16cbeb17b0 --- /dev/null +++ b/protocols/Sametime/src/sametime_proto.h @@ -0,0 +1,248 @@ +
+#ifndef _SAMETIME_PROTO_H
+#define _SAMETIME_PROTO_H
+
+
+
+struct CSametimeProto : public PROTO<CSametimeProto>
+{
+
+ CSametimeProto(const char*, const TCHAR* );
+ ~CSametimeProto();
+
+ //====================================================================================
+ // PROTO_INTERFACE
+ //====================================================================================
+
+
+ virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT* psr);
+ virtual MCONTACT __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(MCONTACT hContact, PROTORECVEVENT*);
+ virtual int __cdecl AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage);
+
+ virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath);
+ virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer);
+ virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason);
+ virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename);
+
+ virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
+ virtual int __cdecl GetInfo(MCONTACT 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(MCONTACT hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvFile(MCONTACT hContact, PROTOFILEEVENT*);
+ virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*);
+
+ virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT* hContactsList);
+ virtual HANDLE __cdecl SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles);
+ virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg);
+ virtual int __cdecl SendUrl(MCONTACT hContact, int flags, const char* url);
+
+ virtual int __cdecl SetApparentMode(MCONTACT hContact, int mode);
+ virtual int __cdecl SetStatus(int iNewStatus);
+
+ virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact);
+ virtual int __cdecl RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt);
+ virtual int __cdecl SetAwayMsg(int iStatus, const PROTOCHAR* msg);
+
+ virtual int __cdecl UserIsTyping(MCONTACT hContact, int type);
+
+ virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam);
+
+
+
+ // sametime.cpp
+ int __cdecl OnSametimeContactDeleted(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetName(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl GetStatus(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl SametimeLoadIcon(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnWindowEvent(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnPreShutdown(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnIdleChanged(WPARAM wParam, LPARAM lParam);
+ void SetAllOffline();
+ void BroadcastNewStatus(int iNewStatus);
+
+ // messaging.cpp
+ void InitMessaging();
+ void DeinitMessaging();
+ void SendTyping(MCONTACT hContact, bool typing);
+ HANDLE SendMessageToUser(MCONTACT hContact, char* msg_utf8);
+ void CloseIm(MCONTACT hContact);
+
+ // userlist.cpp
+ int SearchForUser(const char* name, BOOLEAN advanced);
+ MCONTACT AddSearchedUser(MYPROTOSEARCHRESULT* mpsr, bool temporary);
+ MCONTACT AddContact(mwSametimeUser* user, bool temporary);
+ bool GetAwareIdFromContact(MCONTACT hContact, mwAwareIdBlock* id_block);
+ MCONTACT FindContactByUserId(const char* id);
+ void ImportContactsFromList(mwSametimeList* user_list, bool temporary);
+ void ImportContactsFromFile(TCHAR* filename);
+ void ExportContactsToList(mwSametimeList* user_list);
+ void ExportContactsToServer();
+ void UserListAddStored();
+ void InitUserList();
+ void DeinitUserList();
+ void SetContactGroup(MCONTACT hContact, const char* name);
+ void AddGroup(const char* name, bool expanded);
+ void UserListCreate();
+ void UserListDestroy();
+ int GetMoreDetails(const char* name);
+ void UserRecvAwayMessage(MCONTACT hContact);
+ int ContactDeleted(MCONTACT hContact);
+
+ // files.cpp
+ void InitFiles();
+ void DeinitFiles();
+ HANDLE AcceptFileTransfer(MCONTACT hContact, HANDLE hFt, char* save_path);
+ void RejectFileTransfer(HANDLE hFt);
+ void CancelFileTransfer(HANDLE hFt);
+ HANDLE SendFilesToUser(MCONTACT hContact, PROTOCHAR** files, const PROTOCHAR* pszDesc);
+
+ // conference.cpp
+ void InitConference();
+ void InitConferenceMenu();
+ void DeinitConference();
+ void DeinitConferenceMenu();
+ void ClearInviteQueue();
+ void TerminateConference(char* name);
+ int __cdecl GcEventHook(WPARAM wParam, LPARAM lParam);
+ int __cdecl PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+ int ChatDeleted(MCONTACT hContact);
+ INT_PTR __cdecl onMenuLeaveChat(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl onMenuCreateChat(WPARAM wParam, LPARAM lParam);
+
+ // sametime_session.cpp
+ void SessionStarted();
+ void SessionStopping();
+ void InitSessionMenu();
+ void DeinitSessionMenu();
+ int LogIn(int status, HANDLE hNetlibUser);
+ int LogOut();
+ void InitCritSection();
+ void DeinitCritSection();
+ int SetSessionStatus(int status);
+ void UpdateSelfStatus();
+ int SetIdle(bool idle);
+ void SetSessionAwayMessage(int status, const PROTOCHAR* msg);
+ WORD GetClientVersion();
+ WORD GetServerVersion();
+ INT_PTR __cdecl SessionAnnounce(WPARAM wParam, LPARAM lParam);
+ void InitGroupChats();
+ void InitAwayMsg();
+ void DeinitAwayMsg();
+ void InitMeanwhileServices();
+ void DeinitMeanwhileServices();
+
+ // options.cpp
+ int __cdecl OptInit(WPARAM wParam, LPARAM lParam);
+ void LoadOptions();
+ void SaveOptions();
+
+ // utils.cpp
+ void showPopup(const TCHAR* msg, SametimePopupEnum flag);
+ void RegisterPopups();
+ void UnregisterPopups();
+ void RegisterGLibLogger();
+ void UnRegisterGLibLogger();
+
+ // places.cpp
+ void InitPlaces(mwSession* session);
+ void DeinitPlaces(mwSession* session);
+
+
+
+
+ /* properties */
+
+ char szProtoGroups[128];
+ HANDLE mainThread;
+ CRITICAL_SECTION session_cs;
+ mwSession* session;
+ int previous_status;
+ bool is_idle;
+
+ // userlist.cpp
+ mwServiceStorage* service_storage;
+ mwServiceAware* service_aware;
+ mwServiceResolve* service_resolve;
+ mwAwareList* aware_list;
+
+ // files.cpp
+ mwServiceFileTransfer* service_files;
+
+ // messaging.cpp
+ CRITICAL_SECTION q_cs;
+ mwServiceIm* service_im;
+ ContactMessageQueue contact_message_queue;
+
+ // sametime_session.cpp
+ bool first_online; // set our status after the first online status comes from the server
+ HANDLE hSessionAnnounceMenuItem;
+ int login_status;
+ bool idle_status;
+ int idle_timerid;
+ HANDLE server_connection;
+
+ // conference.cpp
+ InviteQueue invite_queue;
+ mwServiceConference* service_conference;
+ mwLoginInfo* my_login_info;
+ mwConference* my_conference;
+ HANDLE hLeaveChatMenuItem;
+ HANDLE hCreateChatMenuItem;
+
+ // options.cpp
+ SametimeOptions options;
+
+ // places.cpp
+ mwServicePlace* service_places;
+
+ // utils.cpp
+ HANDLE hPopupError;
+ HANDLE hPopupNotify;
+ guint gLogHandler;
+
+};
+
+
+
+typedef struct tag_TFakeAckParams {
+ CSametimeProto* proto;
+ MCONTACT hContact;
+ LPARAM lParam;
+} TFakeAckParams;
+
+
+struct SendAnnouncementFunc_arg {
+ CSametimeProto* proto;
+ TCHAR msg[MAX_MESSAGE_SIZE];
+ GList* recipients;
+};
+
+typedef void (*SendAnnouncementFunc)(SendAnnouncementFunc_arg* ad);
+
+struct SessionAnnounceDialogProc_arg {
+ CSametimeProto* proto;
+ SendAnnouncementFunc sendAnnouncementFunc;
+};
+
+
+struct PopupData {
+ SametimePopupEnum flag;
+ TCHAR* title;
+ TCHAR* text;
+ CSametimeProto* proto;
+};
+
+
+#endif //#ifndef _SAMETIME_PROTO_H
+
diff --git a/protocols/Sametime/src/sametime_session.cpp b/protocols/Sametime/src/sametime_session.cpp new file mode 100644 index 0000000000..bc03f86a03 --- /dev/null +++ b/protocols/Sametime/src/sametime_session.cpp @@ -0,0 +1,634 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+/// not in CSametimeProto (used at NETLIBOPENCONNECTION_tag.waitcallback)
+bool continue_connect;
+
+#define MS_SAMETIME_MENUANNOUNCESESSION "/SessionAnnounce"
+
+// utf8 encoded
+struct {
+ char* szOnline;
+ char* szAway;
+ char* szDND;
+} AwayMessages;
+
+
+void __cdecl SessionClear(mwSession* session)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionClear()"));
+}
+
+int __cdecl SessionWrite(mwSession* session, const unsigned char* buf, gsize len)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionWrite() server_connection=[%d], len=[%d]"), proto->server_connection, len);
+ if (!proto->server_connection) return 1;
+ if (Netlib_Send(proto->server_connection, (const char*)buf, len, 0) == SOCKET_ERROR)
+ return 1;
+ return 0;
+}
+
+void __cdecl SessionClose(mwSession* session)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionClose() server_connection=[%d]"), proto->server_connection);
+ Netlib_CloseHandle(proto->server_connection);
+ proto->server_connection = 0;
+}
+
+void CSametimeProto::SessionStarted()
+{
+ UserListCreate();
+ if (options.get_server_contacts) UserListAddStored();
+}
+
+void CSametimeProto::SessionStopping()
+{
+ UserListDestroy();
+}
+
+void CSametimeProto::InitMeanwhileServices()
+{
+ debugLog(_T("InitMeanwhileServices() start"));
+
+ if (options.encrypt_session) {
+ mwSession_addCipher(session, mwCipher_new_RC2_128(session));
+ mwSession_addCipher(session, mwCipher_new_RC2_40(session));
+ }
+
+ InitUserList();
+ InitMessaging();
+ InitFiles();
+ InitConference();
+
+ mwSession_setProperty(session, "PROTO_STRUCT_PTR", this, NULL);
+
+ ///TODO InitMeanwhileServices DeinitMeanwhileServices on LogIn LogOut, do not need restart
+ mwSession_setProperty(session, mwSession_AUTH_USER_ID, options.id, NULL);
+ mwSession_setProperty(session, mwSession_AUTH_PASSWORD, options.pword, NULL);
+ mwSession_setProperty(session, mwSession_CLIENT_TYPE_ID, (void*)options.client_id, NULL);
+
+ if (options.use_old_default_client_ver) {
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MAJOR, GUINT_TO_POINTER(db_get_w(0, m_szModuleName, "ClientVersionMajor", MW_PROTOCOL_VERSION_MAJOR)), 0);
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MINOR, GUINT_TO_POINTER(db_get_w(0, m_szModuleName, "ClientVersionMinor", MW_PROTOCOL_VERSION_MINOR)), 0);
+ } else {
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MAJOR, GUINT_TO_POINTER(db_get_w(0, m_szModuleName, "ClientVersionMajor", 0x001e)), 0);
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MINOR, GUINT_TO_POINTER(db_get_w(0, m_szModuleName, "ClientVersionMinor", 0x196f)), 0);
+ }
+
+}
+
+void CSametimeProto::DeinitMeanwhileServices()
+{
+ debugLog(_T("DeinitMeanwhileServices() start"));
+ DeinitConference();
+ DeinitFiles();
+ DeinitMessaging();
+ DeinitUserList();
+ mwCipher_free(mwSession_getCipher(session, mwCipher_RC2_40));
+ mwCipher_free(mwSession_getCipher(session, mwCipher_RC2_128));
+}
+
+void __cdecl SessionStateChange(mwSession* session, mwSessionState state, gpointer info)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionStateChange() state=[%d]"), state);
+
+ switch(state) {
+
+ case mwSession_STARTING:
+ break;
+
+ case mwSession_HANDSHAKE:
+ break;
+
+ case mwSession_HANDSHAKE_ACK:
+ break;
+
+ case mwSession_STARTED:
+ proto->SessionStarted();
+ break;
+
+ case mwSession_STOPPING:
+ if ((int)info) {// & ERR_FAILURE) {
+ char *msg = mwError((int)info);
+ TCHAR *msgT = mir_utf8decodeT(msg);
+ proto->showPopup(TranslateTS(msgT), SAMETIME_POPUP_ERROR);
+ mir_free(msgT);
+ g_free(msg);
+ }
+ proto->SessionStopping();
+ break;
+
+ case mwSession_STOPPED:
+ break;
+
+ case mwSession_LOGIN_REDIR:
+ proto->debugLog(_T("SessionStateChange() mwSession_LOGIN_REDIR info=[%s]"), _A2T((char*)info));
+ //options.server_name = str((char*)info);
+ strcpy(proto->options.server_name, (char*)info);
+ proto->LogOut();
+ proto->LogIn(proto->login_status, proto->m_hNetlibUser);
+ break;
+
+ case mwSession_LOGIN_CONT:
+ break;
+
+ case mwSession_LOGIN:
+ break;
+
+ case mwSession_LOGIN_ACK:
+ break;
+
+ case mwSession_UNKNOWN:
+ break;
+
+ }
+}
+
+void __cdecl SessionAdmin(struct mwSession* session, const char* text)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionAdmin()"));
+ TCHAR* tt = mir_utf8decodeT(text);
+ MessageBox(0, tt, TranslateT("Sametime Administrator Message"), MB_OK);
+ mir_free(tt);
+}
+
+void __cdecl SessionAnnounce(struct mwSession* session, struct mwLoginInfo* from, gboolean may_reply, const char* text)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionAnnounce()"));
+ TCHAR* stzFrom;
+ TCHAR* stzText;
+ TCHAR stzFromBuff[256];
+ stzFrom = mir_utf8decodeT(from->user_name);
+ stzText = mir_utf8decodeT(text);
+ mir_sntprintf(stzFromBuff, 256, TranslateT("Session Announcement - from '%s'"), stzFrom);
+ MessageBox(0, TranslateTS(stzText), stzFromBuff, MB_OK);
+ mir_free(stzText);
+ mir_free(stzFrom);
+}
+
+void __cdecl SessionSetPrivacyInfo(struct mwSession* session)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+ proto->debugLog(_T("SessionSetPrivacyInfo()"));
+}
+
+void __cdecl SessionSetUserStatus(struct mwSession* session)
+{
+ CSametimeProto* proto = (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+
+ int new_status;
+ struct mwUserStatus us;
+ mwUserStatus_clone(&us, mwSession_getUserStatus(session));
+
+ proto->debugLog(_T("SessionSetUserStatus() us.status=[%d]"), us.status);
+
+ switch(us.status) {
+
+ case mwStatus_ACTIVE:
+ new_status = ID_STATUS_ONLINE;
+ break;
+
+ case mwStatus_AWAY:
+ new_status = ID_STATUS_AWAY;
+ if (proto->idle_status) {
+ // ignore setting to away by idle module, after we've set ourselves idle
+ // most standard clients represent idle and away the same way anyway,
+ // but this allows miranda users to make use of the idle timestamp
+ // but show our status in clist as away
+ proto->BroadcastNewStatus(new_status);
+ mwUserStatus_clear(&us);
+ return;
+ }
+ break;
+
+ case mwStatus_BUSY:
+ new_status = ID_STATUS_DND;
+ break;
+
+ case mwStatus_IDLE:
+ new_status = ID_STATUS_AWAY;
+ if (!proto->first_online && !proto->options.idle_as_away) { // show our status in clist as away if idle when going online or treating idle as away
+ mwUserStatus_clear(&us);
+ return;
+ }
+ break;
+
+ case 8: // new 'in a meeting' status, not handled by meanwhile lib
+ new_status = ID_STATUS_OCCUPIED;
+ break;
+
+ default:
+ {
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT("Unknown user status: %d"), us.status);
+ proto->showPopup(buff, SAMETIME_POPUP_ERROR);
+ proto->debugLog(buff);
+ }
+ mwUserStatus_clear(&us);
+ // just go online...to prevent us getting stuck 'connecting'
+ new_status = ID_STATUS_ONLINE;
+ break;
+
+ }
+
+ proto->m_iDesiredStatus = new_status;
+
+ if (proto->first_online) {
+ proto->first_online = false;
+ //proto->showPopup(TranslateT("Setting login status"), SAMETIME_POPUP_INFO);
+ proto->debugLog(_T("Setting login status"));
+ proto->SetSessionStatus(proto->login_status);
+ } else {
+ proto->BroadcastNewStatus(new_status);
+ }
+
+ mwUserStatus_clear(&us);
+}
+
+void CSametimeProto::UpdateSelfStatus()
+{
+ EnterCriticalSection(&session_cs);
+ if (session) SessionSetUserStatus(session);
+ LeaveCriticalSection(&session_cs);
+}
+
+int CSametimeProto::SetSessionStatus(int status)
+{
+ struct mwUserStatus us;
+ debugLog(_T("SetSessionStatus() start status=[%d]"), status);
+
+ if (idle_timerid) KillTimer(0, idle_timerid);
+
+ us.time = (DWORD)time(0);
+ //us.time = 0;
+
+ switch(status) {
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_ONLINE:
+ us.desc = AwayMessages.szOnline; us.status = mwStatus_ACTIVE;
+ break;
+ case ID_STATUS_NA:
+ case ID_STATUS_INVISIBLE:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ case ID_STATUS_AWAY:
+ us.desc = AwayMessages.szAway; us.status = mwStatus_AWAY;
+ break;
+ case ID_STATUS_OCCUPIED:
+ case ID_STATUS_DND:
+ us.desc = AwayMessages.szDND; us.status = mwStatus_BUSY;
+ break;
+ default:
+ // act as online for unsupported status
+ us.desc = AwayMessages.szOnline; us.status = mwStatus_ACTIVE; break;
+ }
+
+ debugLog(_T("SetSessionStatus() mwSession_setUserStatus us.status=[%d], us.desc:len=[%d]"), us.status, us.desc == NULL ? -1 : strlen(us.desc));
+ mwSession_setUserStatus(session, &us);
+
+ return 0;
+}
+
+VOID CALLBACK IdleTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ CSametimeProto* proto = (CSametimeProto*)idEvent;
+
+ KillTimer(0, proto->idle_timerid);
+ proto->idle_timerid = 0;
+
+ if (proto->idle_status) {
+ struct mwUserStatus us;
+ us.time = (DWORD)time(0);
+ us.status = mwStatus_IDLE;
+ us.desc = 0;
+ mwSession_setUserStatus(proto->session, &us);
+ } else {
+ proto->SetSessionStatus(proto->m_iStatus);
+ }
+}
+
+int CSametimeProto::SetIdle(bool idle)
+{
+ // set a timer, to wait for any autoaway module which might set our status
+ debugLog(_T("CSametimeProto::SetIdle() idle=[%d], idle_status=[%d], idle_timerid=[%d]"), idle, idle_status, idle_timerid);
+ if (idle && !idle_status) {
+ idle_status = true;
+ if (!idle_timerid)
+ idle_timerid = SetTimer(0, (UINT_PTR)this, 200, IdleTimerProc);
+ } else if (idle_status) {
+ idle_status = false;
+ if (!idle_timerid)
+ idle_timerid = SetTimer(0, (UINT_PTR)this, 200, IdleTimerProc);
+ }
+ return 0;
+}
+
+void CSametimeProto::SetSessionAwayMessage(int status, const PROTOCHAR* msgT)
+{
+ debugLog(_T("SetSessionAwayMessage() status=[%d], msgT:len=[%d]"), status, msgT == NULL ? -1 : _tcslen(msgT));
+
+ ptrA msg(mir_utf8encodeT(msgT));
+ if (status == ID_STATUS_ONLINE) {
+ mir_free(AwayMessages.szOnline);
+ if (msg) {
+ AwayMessages.szOnline = mir_strdup(msg);
+ } else AwayMessages.szOnline = 0;
+ } else if (status == ID_STATUS_AWAY) {
+ mir_free(AwayMessages.szAway);
+ if (msg) {
+ AwayMessages.szAway = mir_strdup(msg);
+ } else AwayMessages.szAway = 0;
+ } else if (status == ID_STATUS_DND) {
+ mir_free(AwayMessages.szDND);
+ if (msg) {
+ AwayMessages.szDND = mir_strdup(msg);
+ } else AwayMessages.szDND = 0;
+ } else
+ return; // unsupported status
+
+ if (session){
+ SetSessionStatus(status); // update current away message
+ }
+}
+
+static VOID CALLBACK NullAPC (DWORD_PTR)
+{
+ // This function intentionally left blank
+}
+
+void WakeThread(HANDLE hThread)
+{
+ QueueUserAPC(NullAPC, hThread, 0);
+}
+
+void __cdecl KeepAliveThread(LPVOID param)
+{
+ CSametimeProto* proto = (CSametimeProto*)param;
+ int i = 120;
+ proto->debugLog(_T("KeepAliveThread() start"));
+
+ while(1) {
+
+ if (i <= 0){
+ i = 120;
+ // send keepalive every 120 * 250 = 30000[ms]
+ if (mwSession_isStarted(proto->session) && proto->session){
+ mwSession_sendKeepalive(proto->session);
+ }
+ }
+
+ i--;
+
+ SleepEx(250, TRUE);
+
+ EnterCriticalSection(&(proto->session_cs));
+ if (Miranda_Terminated() || !proto->session) {
+ LeaveCriticalSection(&(proto->session_cs));
+ proto->debugLog(_T("KeepAliveThread() end"));
+ break;
+ }
+ LeaveCriticalSection(&(proto->session_cs));
+ }
+
+ return;
+}
+
+int waitcallback(unsigned int* timeout)
+{
+ return continue_connect ? 1 : 0;
+}
+
+void __cdecl SessionThread(LPVOID param)
+{
+
+ CSametimeProto* proto = (CSametimeProto*)param;
+ HANDLE hNetlibUser = proto->m_hNetlibUser;
+ proto->debugLog(_T("SessionThread() start"));
+
+ continue_connect = true;
+
+ //setup
+ NETLIBOPENCONNECTION conn_data = {0};
+ conn_data.cbSize = sizeof(NETLIBOPENCONNECTION);
+ conn_data.flags = NLOCF_V2;
+ conn_data.szHost = proto->options.server_name;
+ conn_data.wPort = proto->options.port;
+ conn_data.timeout = 20;
+ conn_data.waitcallback = waitcallback;
+
+ proto->BroadcastNewStatus(ID_STATUS_CONNECTING);
+
+ proto->server_connection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn_data);
+
+ if (!proto->server_connection) {
+
+ proto->BroadcastNewStatus(ID_STATUS_OFFLINE);
+
+ if (continue_connect) {
+ // real timeout - not user cancelled
+ proto->showPopup(TranslateT("No server connection!"), SAMETIME_POPUP_ERROR);
+ }
+
+ proto->debugLog(_T("SessionThread() end, no server_connection, continue_connect=[%d]"), continue_connect);
+ return;
+ }
+
+ mwSessionHandler handler = {0};
+ handler.clear = SessionClear;
+ handler.io_write = SessionWrite;
+ handler.io_close = SessionClose;
+ handler.on_stateChange = SessionStateChange;
+ handler.on_admin = SessionAdmin;
+ handler.on_announce = SessionAnnounce;
+ handler.on_setPrivacyInfo = SessionSetPrivacyInfo;
+ handler.on_setUserStatus = SessionSetUserStatus;
+
+ EnterCriticalSection(&proto->session_cs);
+ proto->session = mwSession_new(&handler);
+
+ proto->InitMeanwhileServices();
+
+ mwSession_start(proto->session);
+ LeaveCriticalSection(&proto->session_cs);
+
+ mir_forkthread(KeepAliveThread, (void*)proto);
+
+ unsigned char* recv_buffer = (unsigned char*)mir_alloc(1024 * 32);
+ int bytes;
+ //while(session && server_connection && mwSession_getState(session) != mwSession_STOPPED) {
+ while(proto->server_connection) {// && session) {// && !mwSession_isStopped(session)) { // break on error
+ bytes = Netlib_Recv(proto->server_connection, (char *)recv_buffer, 1024 * 32, 0);
+ proto->debugLog(_T("SessionThread() Netlib_Recv'ed bytes=[%d]"), bytes);
+
+ if (bytes == 0) {
+ break;
+ } else if (bytes == SOCKET_ERROR) {
+ // this is normal - e.g. socket closed due to log off, during blocking read above
+ break;
+ } else {
+ EnterCriticalSection(&proto->session_cs);
+ mwSession_recv(proto->session, recv_buffer, bytes);
+ LeaveCriticalSection(&proto->session_cs);
+ }
+ }
+ mir_free(recv_buffer);
+
+ EnterCriticalSection(&proto->session_cs);
+ proto->DeinitMeanwhileServices();
+ mwSession* old_session = proto->session;
+ proto->session = 0; // kills keepalive thread, if awake
+ mwSession_free(old_session);
+ LeaveCriticalSection(&proto->session_cs);
+
+ proto->BroadcastNewStatus(ID_STATUS_OFFLINE);
+ proto->SetAllOffline();
+ proto->first_online = true;
+
+ proto->debugLog(_T("SessionThread() end"));
+ return;
+}
+
+WORD CSametimeProto::GetClientVersion()
+{
+ if (!session) return 0;
+
+ WORD retval = 0;
+ retval = (int)mwSession_getProperty(session, mwSession_CLIENT_VER_MAJOR) << 8;
+ retval |= (int)mwSession_getProperty(session, mwSession_CLIENT_VER_MINOR);
+ return retval;
+}
+
+WORD CSametimeProto::GetServerVersion()
+{
+ if (!session) return 0;
+
+ WORD retval = 0;
+ retval = (int)mwSession_getProperty(session, mwSession_SERVER_VER_MAJOR) << 8;
+ retval |= (int)mwSession_getProperty(session, mwSession_SERVER_VER_MINOR);
+ return retval;
+}
+
+int CSametimeProto::LogIn(int ls, HANDLE hNetlibUser)
+{
+ debugLog(_T("LogIn() start"));
+
+ EnterCriticalSection(&session_cs);
+ if (session) {
+ LeaveCriticalSection(&session_cs);
+ debugLog(_T("LogIn() end, currently in session"));
+ return 0;
+ }
+ LeaveCriticalSection(&session_cs);
+
+ login_status = ls;
+
+ mir_forkthread(SessionThread, (void*)this);
+
+ return 0;
+}
+
+int CSametimeProto::LogOut()
+{
+ debugLog(_T("LogOut() start"));
+ continue_connect = false;
+
+ EnterCriticalSection(&session_cs);
+ if (session && server_connection && m_iStatus != ID_STATUS_OFFLINE && !mwSession_isStopped(session) && !mwSession_isStopping(session)) {
+ debugLog(_T("LogOut() mwSession_stop"));
+ mwSession_stop(session, 0);
+ }
+ LeaveCriticalSection(&session_cs);
+
+ return 0;
+}
+
+void CSametimeProto::InitAwayMsg()
+{
+ AwayMessages.szOnline = 0;
+ AwayMessages.szAway = 0;
+ AwayMessages.szDND = 0;
+}
+
+void CSametimeProto::DeinitAwayMsg()
+{
+ mir_free(AwayMessages.szOnline);
+ mir_free(AwayMessages.szAway);
+ mir_free(AwayMessages.szDND);
+}
+
+void SendAnnouncement(SendAnnouncementFunc_arg* arg)
+{
+ CSametimeProto* proto = arg->proto;
+ char* utfs = mir_utf8encodeT(arg->msg);
+ if (proto->session && arg->recipients) mwSession_sendAnnounce(proto->session, false , utfs, arg->recipients);
+ mir_free(utfs);
+}
+
+INT_PTR CSametimeProto::SessionAnnounce(WPARAM wParam, LPARAM lParam)
+{
+ debugLog(_T("CSametimeProto::SessionAnnounce() start"));
+ SessionAnnounceDialogProc_arg* sadpArg = (SessionAnnounceDialogProc_arg*)mir_calloc(sizeof(SessionAnnounceDialogProc_arg));
+ sadpArg->proto = this;
+ sadpArg->sendAnnouncementFunc = SendAnnouncement;
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SESSIONANNOUNCE), GetDesktopWindow(), SessionAnnounceDialogProc, (LPARAM)sadpArg);
+ return 0;
+}
+
+void CSametimeProto::InitSessionMenu()
+{
+ debugLog(_T("CSametimeProto::InitSessionMenu()"));
+
+ CreateProtoService(MS_SAMETIME_MENUANNOUNCESESSION, &CSametimeProto::SessionAnnounce);
+
+ char service[128];
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.flags = CMIF_TCHAR;
+ mi.popupPosition = 500085001;
+ mi.position = 2000060000;
+ mi.ptszName = LPGENT("Send Announcement...");
+ mir_snprintf(service, sizeof(service), "%s%s", m_szModuleName, MS_SAMETIME_MENUANNOUNCESESSION);
+ mi.pszService = service;
+ mi.icolibItem = GetIconHandle(IDI_ICON_ANNOUNCE);
+ mi.pszContactOwner = m_szModuleName;
+ hSessionAnnounceMenuItem = Menu_AddContactMenuItem(&mi);
+}
+
+void CSametimeProto::DeinitSessionMenu()
+{
+ debugLog(_T("CSametimeProto::DeinitSessionMenu()"));
+ CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hSessionAnnounceMenuItem, (LPARAM)0);
+}
+
+void CSametimeProto::InitCritSection()
+{
+ debugLog(_T("CSametimeProto::InitCritSection()"));
+ InitializeCriticalSection(&session_cs);
+}
+
+void CSametimeProto::DeinitCritSection()
+{
+ debugLog(_T("CSametimeProto::DeinitCritSection()"));
+ DeleteCriticalSection(&session_cs);
+}
+
+void CSametimeProto::InitGroupChats()
+{
+ debugLog(_T("CSametimeProto::InitGroupChats()"));
+
+ // register with chat module
+ GCREGISTER gcr = { sizeof(gcr) };
+ gcr.pszModule = m_szModuleName;
+ gcr.ptszDispName = m_tszUserName;
+ gcr.dwFlags = 0;
+ gcr.iMaxText = MAX_MESSAGE_SIZE;
+ gcr.nColors = 0;
+ gcr.pColors = 0;
+ CallService(MS_GC_REGISTER, 0, (LPARAM)(GCREGISTER*) &gcr);
+}
diff --git a/protocols/Sametime/src/session_announce_win.cpp b/protocols/Sametime/src/session_announce_win.cpp new file mode 100644 index 0000000000..8cf9cecb8f --- /dev/null +++ b/protocols/Sametime/src/session_announce_win.cpp @@ -0,0 +1,147 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+INT_PTR CALLBACK SessionAnnounceDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+
+ SessionAnnounceDialogProc_arg* arg = (SessionAnnounceDialogProc_arg*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ CSametimeProto* proto;
+ if (arg != NULL) proto = arg->proto;
+
+ switch(uMsg) {
+ case WM_INITDIALOG: {
+
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ SessionAnnounceDialogProc_arg* arg = (SessionAnnounceDialogProc_arg*)lParam;
+ proto = arg->proto;
+ proto->debugLog(_T("SessionAnnounceDialogProc WM_INITDIALOG"));
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_LST_ANTO),LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
+
+ {
+ LVCOLUMN lvc;
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT("Recipients");
+ lvc.cx = 300; // width of column in pixels
+ ListView_InsertColumn(GetDlgItem(hwndDlg, IDC_LST_ANTO), 0, &lvc);
+ }
+
+ //enumerate plugins, fill in list
+ {
+ ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_LST_ANTO));
+ LVITEM lvI;
+ // Some code to create the list-view control.
+ // Initialize LVITEM members that are common to all items.
+ lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE;
+ lvI.iItem=0;
+ lvI.iSubItem=0;
+
+ for (MCONTACT hContact = db_find_first(proto->m_szModuleName); hContact; hContact = db_find_next(hContact, proto->m_szModuleName)) {
+ if (db_get_b(hContact, proto->m_szModuleName, "ChatRoom", 0) == 0
+ && db_get_w(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ {
+ lvI.lParam = (LPARAM)hContact;
+ lvI.pszText = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+ ListView_InsertItem(GetDlgItem(hwndDlg, IDC_LST_ANTO), &lvI);
+ lvI.iItem++;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ case WM_CLOSE:
+ proto->debugLog(_T("SessionAnnounceDialogProc WM_CLOSE"));
+ mir_free(arg);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) == BN_CLICKED ) {
+ switch(LOWORD(wParam)) {
+
+ case IDC_BUT_SELALL: {
+ int size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO));
+ for (int i = 0; i < size; i++) ListView_SetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i, true);
+ }
+ return 0;
+
+ case IDC_BUT_SELINV: {
+ int size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO));
+ for (int i = 0; i < size; i++)
+ ListView_SetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i,
+ !ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i)
+ );
+ }
+ return 0;
+
+ case IDOK: {
+ proto->debugLog(_T("SessionAnnounceDialogProc IDOK BN_CLICKED"));
+ // build SendAnnouncementFunc_arg
+ SendAnnouncementFunc_arg* safArg = (SendAnnouncementFunc_arg*)mir_calloc(sizeof(SendAnnouncementFunc_arg));
+ DBVARIANT dbv;
+ LVITEM lvI = {0};
+
+ char id[1024];
+ strcpy(id, "@U"); // documentation says prepend '@U' to usernames and '@G' to notes group names - but
+ char *p = id + 2; // it's wrong - it works for a list of user id's with no prefix - so we'll do both
+
+ // build recipient list
+ safArg->recipients = 0;
+
+ int size = ListView_GetItemCount(GetDlgItem(hwndDlg, IDC_LST_ANTO));
+ int send_count = 0;
+ for (int i = 0; i < size; i++) {
+ if (ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_LST_ANTO), i)) {
+ lvI.iItem = i;
+ lvI.iSubItem = 0;
+ lvI.mask = LVIF_PARAM;
+ ListView_GetItem(GetDlgItem(hwndDlg, IDC_LST_ANTO), &lvI);
+
+ if (!db_get_utf((MCONTACT)lvI.lParam, proto->m_szModuleName, "stid", &dbv)) {
+ safArg->recipients = g_list_prepend(safArg->recipients, _strdup(dbv.pszVal));
+ strcpy(p, dbv.pszVal);
+ safArg->recipients = g_list_prepend(safArg->recipients, _strdup(id));
+ send_count++;
+ db_free(&dbv);
+ }
+ }
+ }
+
+ if (send_count > 0) {
+ GetWindowText(GetDlgItem(hwndDlg, IDC_ED_ANMSG), safArg->msg, MAX_MESSAGE_SIZE);
+ safArg->proto = proto;
+ SendAnnouncementFunc sendAnnouncementFunc = arg->sendAnnouncementFunc;
+ sendAnnouncementFunc(safArg);
+ }
+
+ // clean up recipient list
+ if (safArg->recipients){
+ for (GList *rit = safArg->recipients; rit; rit = rit->next) {
+ free(rit->data);
+ }
+ g_list_free(safArg->recipients);
+ }
+
+ DestroyWindow(hwndDlg);
+ }
+ return 0;
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return 0;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
\ No newline at end of file diff --git a/protocols/Sametime/src/userlist.cpp b/protocols/Sametime/src/userlist.cpp new file mode 100644 index 0000000000..89e11a0a81 --- /dev/null +++ b/protocols/Sametime/src/userlist.cpp @@ -0,0 +1,836 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+MCONTACT CSametimeProto::FindContactByUserId(const char* id)
+{
+ DBVARIANT dbv;
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
+ if (dbv.pszVal && strcmp(id, dbv.pszVal) == 0) {
+ db_free(&dbv);
+ return hContact;
+ }
+ db_free(&dbv);
+ }
+ }
+ return 0;
+}
+
+bool CSametimeProto::GetAwareIdFromContact(MCONTACT hContact, mwAwareIdBlock* id_block)
+{
+ char* proto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 );
+ DBVARIANT dbv;
+ if ( proto && !strcmp(m_szModuleName, proto)) {
+ if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
+ if (dbv.pszVal) {
+ id_block->type = mwAware_USER;
+ id_block->user = _strdup(dbv.pszVal);
+ id_block->community = 0;
+ db_free(&dbv);
+ return true;
+ }
+ db_free(&dbv);
+ }
+ }
+ return false;
+}
+
+void CSametimeProto::SetContactGroup(MCONTACT hContact, const char* name)
+{
+ db_set_utf(hContact, "CList", "Group", name);
+}
+
+void CSametimeProto::AddGroup(const char* name, bool expanded)
+{
+ if (name && strcmp(name, "MetaContacts Hidden Group") == 0)
+ return;
+
+ if (name && strcmp(name, Translate("None")) == 0)
+ return;
+
+ ptrT ptszGroup(mir_utf8decodeT(name));
+ HANDLE hGroup = Clist_GroupExists(ptszGroup);
+ if (hGroup == NULL) {
+ hGroup = Clist_CreateGroup(NULL, ptszGroup);
+ if (hGroup) {
+ CallService(MS_CLUI_GROUPADDED, (WPARAM)hGroup, 0);
+ CallService(MS_CLIST_GROUPSETEXPANDED, (WPARAM)hGroup, expanded ? 1 : 0);
+ }
+ }
+}
+
+MCONTACT CSametimeProto::AddContact(mwSametimeUser* user, bool temporary)
+{
+
+ debugLog(_T("CSametimeProto::AddContact() start"));
+ const char* id = mwSametimeUser_getUser(user);
+ const char* name = mwSametimeUser_getShortName(user);
+ const char* nick = mwSametimeUser_getAlias(user);
+ //const char* nick = mwSametimeUser_getShortName(user);
+ mwSametimeUserType type = mwSametimeUser_getType(user);
+
+ MCONTACT hContact = FindContactByUserId(id);
+ bool new_contact = false;
+ if (!hContact) {
+ hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ if (!hContact) {
+ debugLog(_T("AddContact(): Failed to create Sametime contact"));
+ return NULL; ///TODO error handling
+ }
+ if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) m_szModuleName) != 0) {
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM) hContact, 0);
+ debugLog(_T("AddContact(): Failed to register Sametime contact"));
+ return NULL; ///TODO error handling
+ }
+ new_contact = true;
+ } else if (!temporary) {
+ db_unset(hContact, "CList", "NotOnList");
+ db_unset(hContact, "CList", "Hidden");
+ }
+
+
+ // add to miranda
+ if (new_contact) db_set_utf(hContact, m_szModuleName, "stid", id);
+
+ if (name && strlen(name))
+ db_set_utf(hContact, m_szModuleName, "Name", name);
+
+ if (nick && strlen(nick)) {
+ db_set_utf(hContact, m_szModuleName, "Nick", nick);
+ } else if (name && strlen(name)) {
+ db_set_utf(hContact, m_szModuleName, "Nick", name);
+ } else {
+ db_set_utf(hContact, m_szModuleName, "Nick", id);
+ }
+
+ db_set_b(hContact, m_szModuleName, "type", (BYTE)type);
+
+ if (new_contact) {
+ //add to our awareness list
+ mwAwareIdBlock id_block;
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ GList* gl = g_list_prepend(NULL, &id_block);
+ mwAwareList_addAware(aware_list, gl);
+ g_list_free(gl);
+ free(id_block.user);
+ }
+ }
+
+ if (temporary) {
+ db_set_b(hContact, "CList", "NotOnList", 1);
+ db_set_b(hContact, "CList", "Hidden", 1);
+ } else {
+ db_unset(hContact, "CList", "NotOnList");
+ db_unset(hContact, "CList", "Hidden");
+ }
+
+ return hContact;
+}
+
+void CSametimeProto::ImportContactsFromList(mwSametimeList* user_list, bool temporary)
+{
+ debugLog(_T("CSametimeProto::ImportContactsFromList() start"));
+ // add contacts
+ mwSametimeGroup* stgroup;
+ mwSametimeUser* stuser;
+ GList *gl, *gtl, *ul, *utl;
+ const char* group_name;
+ const char* group_alias;
+ mwSametimeGroupType group_type;
+ bool group_open;
+
+ gl = gtl = mwSametimeList_getGroups(user_list);
+ for (; gl; gl = gl->next) {
+ char buff[256];
+ stgroup = (mwSametimeGroup*)gl->data;
+
+ group_name = mwSametimeGroup_getName(stgroup);
+ group_alias = mwSametimeGroup_getAlias(stgroup);
+ if (!group_alias) group_alias = group_name;
+
+ group_type = mwSametimeGroup_getType(stgroup);
+ group_open = (mwSametimeGroup_isOpen(stgroup) != 0);
+
+ mir_snprintf(buff, SIZEOF(buff), "GN_%s", group_alias);
+ db_set_utf(0, szProtoGroups, buff, group_name);
+ mir_snprintf(buff, SIZEOF(buff), "GT_%s", group_alias);
+ db_set_b(0, szProtoGroups, buff, (BYTE)group_type);
+ mir_snprintf(buff, SIZEOF(buff), "GO_%s", group_alias);
+ db_set_b(0, szProtoGroups, buff, (BYTE)(group_open ? 1 : 0));
+
+ // inverse mapping
+ mir_snprintf(buff, SIZEOF(buff), "GA_%s", group_name);
+ db_set_utf(0, szProtoGroups, buff, group_alias);
+
+ AddGroup(group_alias, group_open);
+
+ if (group_type == mwSametimeGroup_DYNAMIC) {
+ mwAwareIdBlock id_block;
+ id_block.type = mwAware_GROUP;
+ id_block.user = (char*)group_name;
+ id_block.community = 0;
+
+ GList* gl = g_list_prepend(NULL, &id_block);
+ mwAwareList_addAware(aware_list, gl);
+ g_list_free(gl);
+ }
+
+ ul = utl = mwSametimeGroup_getUsers(stgroup);
+ for (; ul; ul = ul->next) {
+ stuser = (mwSametimeUser*)ul->data;
+ MCONTACT hContact = AddContact(stuser, temporary);
+ if (hContact && group_alias && strcmp(group_alias, Translate("None")) != 0 && strcmp(group_alias, "MetaContacts Hidden Group") != 0) {
+ SetContactGroup(hContact, group_alias);
+ // mark contact as belonging to dynamic group
+ }
+ }
+ g_list_free(utl);
+ }
+ g_list_free(gtl);
+}
+
+void CSametimeProto::ExportContactsToList(mwSametimeList* user_list)
+{
+ debugLog(_T("CSametimeProto::ExportContactsToList() start"));
+ mwSametimeGroup* stgroup = 0;
+ char* group_name;
+ char* group_alias;
+ mwSametimeGroupType group_type;
+ bool group_open;
+
+ mwSametimeUser* stuser;
+ char* user_alias;
+ char* user_shortName;
+ mwSametimeUserType user_type;
+ DBVARIANT dbv, dbv2;
+ char buff[256];
+ mwAwareIdBlock id_block;
+ mwIdBlock uid;
+
+ GList* gl = 0;
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
+ if (dbv.pszVal) {
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ if (!db_get_utf(hContact, "CList", "Group", &dbv2)) {
+ group_alias = _strdup(dbv2.pszVal);
+ db_free(&dbv2);
+ } else
+ group_alias = _strdup(Translate("None"));
+
+ if (group_alias) {
+ mir_snprintf(buff, SIZEOF(buff), "GT_%s", group_alias);
+ group_type = (mwSametimeGroupType)db_get_b(0, szProtoGroups, buff, (BYTE)mwSametimeGroup_NORMAL);
+ // apparently we don't want to upload contacts in dynamic groups - see gaim sametime plugin comments
+ if (group_type == mwSametimeGroup_DYNAMIC) {
+ db_free(&dbv);
+ free(id_block.user);
+ free(group_alias);
+ hContact = db_find_next(hContact, m_szModuleName);
+ continue;
+ }
+
+ mir_snprintf(buff, SIZEOF(buff), "GN_%s", group_alias);
+ if (!db_get_utf(0, szProtoGroups, buff, &dbv2)) {
+ group_name = _strdup(dbv2.pszVal);
+ db_free(&dbv2);
+ } else
+ group_name = _strdup(group_alias);
+
+ //group_open = (db_get_b(0, szProtoGroups, buff, 0) == 1);
+
+ ptrT ptszGroup(mir_utf8decodeT(group_alias));
+ HANDLE hGroup = Clist_GroupExists(ptszGroup);
+ if (hGroup) {
+ int expanded;
+ CallService(MS_CLIST_GROUPGETNAME, (WPARAM)hGroup, (LPARAM)&expanded);
+ group_open = (expanded != 0);
+ } else {
+ mir_snprintf(buff, SIZEOF(buff), "GO_%s", group_alias);
+ group_open = (db_get_b(0, szProtoGroups, buff, 0) == 1);
+ }
+
+ stgroup = 0;
+ stgroup = mwSametimeList_findGroup(user_list, group_name);
+ if (!stgroup) {
+ if (group_name) stgroup = mwSametimeGroup_new(user_list, group_type, group_name);
+ mwSametimeGroup_setAlias(stgroup, group_alias);
+ mwSametimeGroup_setOpen(stgroup, group_open);
+ }
+
+ free(group_name);
+ free(group_alias);
+
+ if (!db_get_utf(hContact, m_szModuleName, "Name", &dbv2)) {
+ user_shortName = _strdup(dbv2.pszVal);
+ db_free(&dbv2);
+ } else
+ user_shortName = 0;
+
+ if (!db_get_utf(hContact, "CList", "MyHandle", &dbv2)) {
+ user_alias = _strdup(dbv2.pszVal);
+ db_free(&dbv2);
+ } else
+ user_alias = 0;
+
+ user_type = (mwSametimeUserType)db_get_b(hContact, m_szModuleName, "type", (BYTE)mwSametimeUser_NORMAL);
+
+ uid.user = id_block.user;
+ uid.community = id_block.community;
+
+ stuser = mwSametimeUser_new(stgroup, user_type, &uid);
+ if (user_shortName) {
+ mwSametimeUser_setShortName(stuser, user_shortName);
+ free(user_shortName);
+ }
+ if (user_alias) {
+ mwSametimeUser_setAlias(stuser, user_alias);
+ free(user_alias);
+ }
+ }
+
+ free(id_block.user);
+ }
+ }
+ db_free(&dbv);
+ }
+ }
+}
+
+void CSametimeProto::ImportContactsFromFile(TCHAR* filename)
+{
+ debugLog(_T("CSametimeProto::ImportContactsFromFile() start"));
+ std::ifstream in(filename);
+ std::string text;
+ std::string line;
+ if (in.is_open()) {
+ while(!in.eof()) {
+ std::getline(in, line);
+ text += line;
+ text += "\r\n";
+ }
+ in.close();
+
+ mwSametimeList* new_list = mwSametimeList_load(text.c_str());
+ ImportContactsFromList(new_list, false);
+ mwSametimeList_free(new_list);
+
+ }
+}
+
+void CSametimeProto::ExportContactsToServer()
+{
+ mwSametimeList* user_list;
+ mwStorageUnit* unit;
+ mwPutBuffer* buff;
+ mwOpaque* op;
+
+ debugLog(_T("CSametimeProto::ExportContactsToServer() start"));
+ if (MW_SERVICE_IS_DEAD(service_storage)) {
+ debugLog(_T("CSametimeProto::ExportContactsToServer() Failed"));
+ showPopup(TranslateT("Failed to upload contacts - Storage service unavailable."), SAMETIME_POPUP_ERROR);
+ return;
+ }
+
+ user_list = mwSametimeList_new();
+ ExportContactsToList(user_list);
+
+ buff = mwPutBuffer_new();
+ mwSametimeList_put(buff, user_list);
+ mwSametimeList_free(user_list);
+
+ /* put the buffer contents into a storage unit */
+ unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+ op = mwStorageUnit_asOpaque(unit);
+ mwPutBuffer_finalize(op, buff);
+
+ /* save the storage unit to the service */
+ mwServiceStorage_save(service_storage, unit, NULL, NULL, NULL);
+}
+
+
+CSametimeProto* getProtoFromMwServiceStorage(mwServiceStorage* srvcStorage)
+{
+ mwService* service = mwServiceStorage_getService(srvcStorage);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+void load_users_callback(mwServiceStorage* srvc, guint32 result, mwStorageUnit *item, gpointer data)
+{
+ CSametimeProto* proto = getProtoFromMwServiceStorage(srvc);
+
+ if (mwStorageUnit_getKey(item) == mwStore_AWARE_LIST) {
+ mwGetBuffer *buff = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
+ if (mwGetBuffer_remaining(buff)) {
+ mwSametimeList* user_list = mwSametimeList_new();
+ mwSametimeList_get(buff, user_list);
+ proto->ImportContactsFromList(user_list, false);
+ mwSametimeList_free(user_list);
+ }
+ }
+}
+
+void CSametimeProto::UserListAddStored()
+{
+ mwStorageUnit* unit;
+ unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+ mwServiceStorage_load(service_storage, unit, &load_users_callback, (gpointer)this, 0);
+}
+
+int CSametimeProto::ContactDeleted(MCONTACT hContact)
+{
+ mwAwareIdBlock id_block;
+
+ if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0))
+ return 0;
+
+ debugLog(_T("CSametimeProto::ContactDeleted()"));
+
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ GList* gl = g_list_prepend(NULL, &id_block);
+ mwAwareList_removeAware(aware_list, gl);
+ g_list_free(gl);
+ free(id_block.user);
+ }
+
+ return 0;
+}
+
+CSametimeProto* getProtoFromMwServiceResolve(mwServiceResolve* srvcResolve)
+{
+ mwService* service = mwServiceResolve_getService(srvcResolve);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+
+void mwResolve_handler_dyngroup_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList *results, gpointer data)
+{
+ CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
+ mwSametimeGroup* stgroup = (mwSametimeGroup*)data;
+
+ mwResolveResult* result;
+ mwResolveMatch* match;
+ g_return_if_fail(results != NULL);
+
+ if (results) {
+ result = (mwResolveResult*)results->data;
+ if (result && result->matches) {
+
+ match = (mwResolveMatch*)result->matches->data;
+ if (match) {
+ mwIdBlock uid;
+ uid.user = match->id;
+ uid.community = 0;
+ mwSametimeUser *stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &uid);
+ mwSametimeUser_setShortName(stuser, match->name);
+
+ MCONTACT hContact = proto->AddContact(stuser, false);
+
+ const char* group_name = mwSametimeGroup_getName(stgroup);
+ const char* group_alias = mwSametimeGroup_getAlias(stgroup);
+ if (!group_alias) group_alias = group_name;
+ if (hContact && group_alias && strcmp(group_alias, Translate("None")) && strcmp(group_alias, "MetaContacts Hidden Group")) {
+ proto->SetContactGroup(hContact, group_alias);
+ }
+ }
+ }
+ }
+
+ if (stgroup)
+ mwSametimeList_free(mwSametimeGroup_getList(stgroup));
+}
+
+
+CSametimeProto* getProtoFromMwAwareList(mwAwareList* list)
+{
+ mwServiceAware* servAwere = mwAwareList_getServiceAware(list);
+ mwService* service = mwServiceAware_getService(servAwere);
+ mwSession* session = mwService_getSession(service);
+ return (CSametimeProto*)mwSession_getProperty(session, "PROTO_STRUCT_PTR");
+}
+
+void mwAwareList_on_aware(mwAwareList* list, mwAwareSnapshot* aware)
+{
+ CSametimeProto* proto = getProtoFromMwAwareList(list);;
+
+ MCONTACT hContact = proto->FindContactByUserId(aware->id.user);
+ char* group = 0;
+ DBVARIANT dbv;
+
+ // update self - necessary for some servers
+ if (aware->online && !db_get_utf(0, proto->m_szModuleName, "stid", &dbv) && strcmp(aware->id.user, dbv.pszVal) == 0) {
+ int new_status = ID_STATUS_OFFLINE;
+
+ switch(aware->status.status) {
+ case mwStatus_ACTIVE:
+ new_status = ID_STATUS_ONLINE;
+ break;
+ case mwStatus_AWAY:
+ new_status = ID_STATUS_AWAY;
+ break;
+ case mwStatus_IDLE:
+ new_status = ID_STATUS_IDLE;
+ break;
+ case mwStatus_BUSY:
+ new_status = ID_STATUS_DND;
+ break;
+ }
+ if (new_status != ID_STATUS_IDLE) //SetSessionStatus(new_status);
+ proto->UpdateSelfStatus();
+
+ db_free(&dbv);
+ }
+
+ if (hContact && !db_get_utf(hContact, "CList", "Group", &dbv)) {
+ group = _strdup(dbv.pszVal);
+ db_free(&dbv);
+ }
+
+ if (aware->group && (!group || strcmp(aware->group, group) || !hContact)) {
+ // dynamic group member we're not already aware of
+ // resolve server alias to user id via resolver
+ mwSametimeList* user_list = mwSametimeList_new();
+ mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_DYNAMIC, aware->group);
+ char buff[256];
+ mir_snprintf(buff, SIZEOF(buff), "GA_%s", aware->group);
+ if (!db_get_utf(0, proto->szProtoGroups, buff, &dbv)) {
+ mwSametimeGroup_setAlias(stgroup, dbv.pszVal);
+ db_free(&dbv);
+ }
+
+ GList* query = g_list_prepend(0, (void*)aware->id.user);
+ mwServiceResolve_resolve(proto->service_resolve, query, mwResolveFlag_USERS, mwResolve_handler_dyngroup_callback, (gpointer)stgroup, 0);
+ g_list_free(query);
+
+ } else if (hContact) {
+
+ if (aware->online) {
+ int new_status = ID_STATUS_OFFLINE;
+
+ switch(aware->status.status) {
+ case mwStatus_ACTIVE:
+ new_status = ID_STATUS_ONLINE;
+ db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
+ db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
+ break;
+ case mwStatus_AWAY:
+ new_status = ID_STATUS_AWAY;
+ db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
+ db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
+ break;
+ case mwStatus_IDLE:
+ if (proto->options.idle_as_away) {
+ new_status = ID_STATUS_AWAY;
+ db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
+ }
+ db_set_dw(hContact, proto->m_szModuleName, "IdleTS", (DWORD)time(0));
+ break;
+ case mwStatus_BUSY:
+ new_status = ID_STATUS_DND;
+ db_set_w(hContact, proto->m_szModuleName, "Status", new_status);
+ db_set_dw(hContact, proto->m_szModuleName, "IdleTS", 0);
+ break;
+ }
+ } else
+ db_set_w(hContact, proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
+
+ if (proto->service_aware) {
+ const char* desc = mwServiceAware_getText(proto->service_aware, &aware->id);
+ if (desc)
+ //db_set_utf(hContact, m_szModuleName, "StatusMsg", desc);
+ db_set_utf(hContact, "CList", "StatusMsg", desc);
+ else
+ //db_set_utf(hContact, m_szModuleName, "StatusMsg", "");
+ //db_unset(hContact, m_szModuleName, "StatusMsg");
+ db_unset(hContact, "CList", "StatusMsg");
+ }
+ }
+
+ if (group) free(group);
+}
+
+
+void mwAwareList_on_attrib(mwAwareList* list, mwAwareIdBlock* id, mwAwareAttribute* attrib)
+{
+}
+
+
+void mwAwareList_clear(mwAwareList* list)
+{
+}
+
+
+mwAwareListHandler mwAwareList_handler = {
+ &mwAwareList_on_aware,
+ &mwAwareList_on_attrib,
+ &mwAwareList_clear
+};
+
+
+void CSametimeProto::UserListCreate()
+{
+ debugLog(_T("CSametimeProto::UserListCreate() start"));
+ mwServiceAware_unsetAttribute(service_aware, mwAttribute_SPEAKERS);
+ mwServiceAware_unsetAttribute(service_aware, mwAttribute_MICROPHONE);
+ mwServiceAware_unsetAttribute(service_aware, mwAttribute_VIDEO_CAMERA);
+ mwServiceAware_setAttributeBoolean(service_aware, mwAttribute_AV_PREFS_SET, TRUE);
+ mwServiceAware_setAttributeBoolean(service_aware, mwAttribute_FILE_TRANSFER, TRUE);
+
+ aware_list = mwAwareList_new(service_aware, &mwAwareList_handler);
+
+ // add all contacts
+
+ DBVARIANT dbv;
+ mwAwareIdBlock id_block;
+ GList *gl = 0;
+
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 0 /*&& proto && !strcmp( PROTO, proto)*/) {
+ if (!db_get_utf(hContact, m_szModuleName, "stid", &dbv)) {
+ if (dbv.pszVal) {
+ if (GetAwareIdFromContact(hContact, &id_block)) {
+ // add user to aware list
+ gl = g_list_prepend(0, &id_block);
+ mwAwareList_addAware(aware_list, gl);
+ free(id_block.user);
+ g_list_free(gl);
+ }
+ }
+ db_free(&dbv);
+ }
+ }
+ }
+
+ // add self - might be necessary for some servers
+ if (!db_get_utf(0, m_szModuleName, "stid", &dbv)) {
+ id_block.type = mwAware_USER;
+ id_block.user = dbv.pszVal;
+ id_block.community = 0;
+
+ gl = g_list_prepend(0, &id_block);
+ mwAwareList_addAware(aware_list, gl);
+ g_list_free(gl);
+
+ db_free(&dbv);
+ }
+}
+
+void CSametimeProto::UserListDestroy()
+{
+ mwAwareList_free(aware_list);
+ aware_list = 0;
+}
+
+void CSametimeProto::UserRecvAwayMessage(MCONTACT hContact)
+{
+ debugLog(_T("CSametimeProto::UserRecvAwayMessage() start hContact=[%x]"), hContact);
+ DBVARIANT dbv;
+ if (!db_get_s((MCONTACT)hContact, "CList", "StatusMsg", &dbv, DBVT_TCHAR)) {
+ ProtoBroadcastAck((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal);
+ db_free(&dbv);
+ } else {
+ ProtoBroadcastAck((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)NULL);
+ }
+}
+
+void mwResolve_handler_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
+{
+ CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
+ BOOL advanced = (BOOL)data;
+
+ MYCUSTOMSEARCHRESULTS mcsr = {0};
+ mcsr.nSize = sizeof(MYCUSTOMSEARCHRESULTS);
+ //MYPROTOSEARCHRESULT mpsr = {0};
+ //mpsr.cbSize = sizeof(MYPROTOSEARCHRESULT);
+ mcsr.psr.nick = mcsr.psr.name;
+
+ mcsr.nFieldCount = 4;
+ TCHAR fields[4][512];
+ TCHAR *fields_addr[4];
+ mcsr.pszFields = fields_addr;
+ mcsr.pszFields[0] = fields[0];
+ mcsr.pszFields[1] = fields[1];
+ mcsr.pszFields[2] = fields[2];
+ mcsr.pszFields[3] = fields[3];
+
+ if (advanced == TRUE) {
+ // send column names
+ mcsr.psr.cbSize = 0;
+ _tcsncpy(mcsr.pszFields[0], TranslateT("Id"), 512);
+ _tcsncpy(mcsr.pszFields[1], TranslateT("Name"), 512);
+ _tcsncpy(mcsr.pszFields[2], TranslateT("Description"), 512);
+ _tcsncpy(mcsr.pszFields[3], TranslateT("Group?"), 512);
+ proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, (HANDLE)id, (LPARAM)&mcsr);
+ }
+
+ mcsr.psr.cbSize = sizeof(MYPROTOSEARCHRESULT);
+
+ if (code == mwResolveCode_SUCCESS) {
+ GList *ri = results, *mri;
+ for (;ri;ri = ri->next) {
+ mri = ((mwResolveResult *)ri->data)->matches;
+ for (;mri;mri = mri->next) {
+ strncpy(mcsr.psr.stid, ((mwResolveMatch *)mri->data)->id, 256);
+ mcsr.psr.stid[255] = 0;
+ MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.stid, -1, mcsr.pszFields[0], 512);
+
+ strncpy(mcsr.psr.name, ((mwResolveMatch *)mri->data)->name, 256);
+ mcsr.psr.name[255] = 0;
+ MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.name, -1, mcsr.pszFields[1], 512);
+
+ if (((mwResolveMatch *)mri->data)->desc)
+ MultiByteToWideChar(CP_UTF8, 0, ((mwResolveMatch *)mri->data)->desc, -1, mcsr.pszFields[2], 512);
+ else
+ mcsr.pszFields[2][0] = 0;
+
+ mcsr.psr.group = (((mwResolveMatch *)mri->data)->type == mwResolveMatch_GROUP);
+ //MultiByteToWideChar(CP_UTF8, 0, mcsr.psr.name, -1, mcsr.pszFields[1], 512);
+ _tcsncpy(mcsr.pszFields[3], mcsr.psr.group ? TranslateT("True") : TranslateT("False"), 512);
+
+ if (advanced == TRUE)
+ proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, (HANDLE)id, (LPARAM)&mcsr);
+ else
+ proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&mcsr.psr);
+ }
+ }
+ proto->ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)id, 0);
+ }
+}
+
+
+void mwResolve_handler_details_callback(mwServiceResolve* srvc, guint32 id, guint32 code, GList* results, gpointer data)
+{
+ CSametimeProto* proto = getProtoFromMwServiceResolve(srvc);
+
+ MYPROTOSEARCHRESULT mpsr = {0};
+ mpsr.cbSize = sizeof(mpsr);
+ mpsr.nick = mpsr.name;
+
+ if (code == mwResolveCode_SUCCESS) {
+ GList *ri = results, *mri;
+ for (;ri;ri = ri->next) {
+ mri = ((mwResolveResult *)ri->data)->matches;
+ for (;mri;mri = mri->next) {
+
+ MCONTACT hContact = proto->FindContactByUserId(((mwResolveMatch*)mri->data)->id);
+ if (hContact) {
+ char* name = ((mwResolveMatch*)mri->data)->name;
+ if (name && strlen(name)) {
+ db_set_utf(hContact, proto->m_szModuleName, "Name", name);
+ db_set_utf(hContact, proto->m_szModuleName, "Nick", name);
+ db_set_utf(hContact, "CList", "MyHandle", name);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+int CSametimeProto::SearchForUser(const char* name, BOOLEAN advanced)
+{
+ if (m_iStatus != ID_STATUS_OFFLINE && service_resolve) {
+ GList *query = g_list_prepend(0, (void*)name);
+ guint32 id = mwServiceResolve_resolve(service_resolve, query, (mwResolveFlag)(mwResolveFlag_USERS | mwResolveFlag_GROUPS), &mwResolve_handler_callback, (gpointer)advanced, 0);
+ g_list_free(query);
+ return id; // search handle
+ }
+ return 0; // fail
+}
+
+
+int CSametimeProto::GetMoreDetails(const char* name)
+{
+ if (m_iStatus != ID_STATUS_OFFLINE && service_resolve) {
+ GList *query = g_list_prepend(0, (void *)name);
+ guint32 id = mwServiceResolve_resolve(service_resolve, query, (mwResolveFlag)(mwResolveFlag_USERS | mwResolveFlag_UNIQUE), &mwResolve_handler_details_callback, NULL, 0);
+ g_list_free(query);
+ return id; // search handle
+ }
+ return 0; // fail
+}
+
+
+INT_PTR CALLBACK CALLBACK SearchDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+MCONTACT CSametimeProto::AddSearchedUser(MYPROTOSEARCHRESULT* mpsr, bool temporary)
+{
+ MCONTACT hContact = 0;
+ debugLog(_T("CSametimeProto::AddSearchedUser() start"));
+ mwSametimeList* user_list = mwSametimeList_new();
+ mwSametimeGroup* stgroup = 0;
+ if (mpsr->group) {
+ stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_DYNAMIC, mpsr->stid);
+ mwSametimeGroup_setAlias(stgroup, mpsr->name);
+ ImportContactsFromList(user_list, temporary);
+ } else {
+ stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
+
+ mwIdBlock uid;
+ uid.user = mpsr->stid;
+ uid.community = 0;
+ mwSametimeUser *stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, &uid);
+ mwSametimeUser_setShortName(stuser, mpsr->name);
+
+ hContact = AddContact(stuser, temporary);
+ mwSametimeList_free(mwSametimeGroup_getList(stgroup));
+ }
+
+ return hContact;
+}
+
+
+void mwServiceAware_on_attrib_callback(mwServiceAware* srvc, mwAwareAttribute* attrib)
+{
+}
+
+void mwServiceAware_clear_callback(mwServiceAware* srvc)
+{
+}
+
+
+void CSametimeProto::InitUserList()
+{
+ debugLog(_T("CSametimeProto::InitUserList()"));
+
+ mwSession_addService(session, (mwService*)(service_storage = mwServiceStorage_new(session)));
+ mwSession_addService(session, (mwService*)(service_resolve = mwServiceResolve_new(session)));
+
+ mwAwareHandler mwAware_handler = {
+ &mwServiceAware_on_attrib_callback,
+ &mwServiceAware_clear_callback
+ };
+ mwSession_addService(session, (mwService*)(service_aware = mwServiceAware_new(session, &mwAware_handler)));
+
+}
+
+void CSametimeProto::DeinitUserList()
+{
+ debugLog(_T("CSametimeProto::DeinitUserList()"));
+
+ mwSession_removeService(session, mwService_AWARE);
+ mwService_free((mwService*)service_aware);
+ service_aware = 0;
+
+ mwSession_removeService(session, mwService_RESOLVE);
+ mwService_free((mwService*)service_resolve);
+ service_resolve = 0;
+
+ mwSession_removeService(session, mwService_STORAGE);
+ mwService_free((mwService*)service_storage);
+ service_storage = 0;
+}
+
diff --git a/protocols/Sametime/src/utils.cpp b/protocols/Sametime/src/utils.cpp new file mode 100644 index 0000000000..40e23fbe4a --- /dev/null +++ b/protocols/Sametime/src/utils.cpp @@ -0,0 +1,170 @@ +#include "StdAfx.h"
+#include "sametime.h"
+
+
+LRESULT CALLBACK PopupWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+ {
+ PUDeletePopup(hWnd);
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ PUDeletePopup(hWnd);
+ break;
+
+ case UM_FREEPLUGINDATA:
+ {
+ PopupData* puData = (PopupData*)PUGetPluginData(hWnd);
+ if (puData != NULL && puData != (PopupData*)CALLSERVICE_NOTFOUND)
+ {
+ mir_free(puData->title);
+ mir_free(puData->text);
+ mir_free(puData);
+ }
+ break;
+ }
+ }
+
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+
+void CSametimeProto::RegisterPopups()
+{
+ TCHAR szDescr[256];
+ char szName[256];
+
+ debugLog(_T("CSametimeProto::RegisterPopups()"));
+
+ POPUPCLASS puc = { sizeof(puc) };
+ puc.PluginWindowProc = PopupWindowProc;
+ puc.flags = PCF_TCHAR;
+ puc.ptszDescription = szDescr;
+ puc.pszName = szName;
+
+ mir_snprintf(szName, SIZEOF(szName), "%s_%s", m_szModuleName, "Notify");
+ mir_sntprintf(szDescr, SIZEOF(szDescr), _T("%s/%s"), m_tszUserName, TranslateT("Notification"));
+ puc.hIcon = CopyIcon(LoadIconEx("notify", FALSE));
+ ReleaseIconEx("notify", FALSE);
+ puc.iSeconds = 8;
+ puc.colorBack = GetSysColor(COLOR_BTNFACE);
+ puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ hPopupNotify = Popup_RegisterClass(&puc);
+
+ mir_snprintf(szName, SIZEOF(szName), "%s_%s", m_szModuleName, "Error");
+ mir_sntprintf(szDescr, SIZEOF(szDescr), _T("%s/%s"), m_tszUserName, TranslateT("Error"));
+ puc.hIcon = CopyIcon(LoadIconEx("error", FALSE));
+ ReleaseIconEx("error", FALSE);
+ puc.iSeconds = 10;
+ puc.colorBack = GetSysColor(COLOR_BTNFACE);
+ puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ hPopupError = Popup_RegisterClass(&puc);
+
+}
+
+
+void CSametimeProto::UnregisterPopups()
+{
+ debugLog(_T("CSametimeProto::RegisterPopups()"));
+ Popup_UnregisterClass(hPopupError);
+ Popup_UnregisterClass(hPopupNotify);
+}
+
+
+void CALLBACK sttMainThreadCallback(PVOID dwParam)
+{
+
+ PopupData* puData = (PopupData*)dwParam;
+ CSametimeProto* proto = puData->proto;
+
+ ErrorDisplay disp = proto->options.err_method;
+ // funny logic :) ... try to avoid message boxes
+ // if want baloons but no balloons, try popups
+ // if want popups but no popups, try baloons
+ // if, after that, you want balloons but no balloons, revert to message boxes
+ if (disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP;
+ if (disp == ED_POP && !ServiceExists(MS_POPUP_ADDPOPUPCLASS)) disp = ED_BAL;
+ if (disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB;
+
+ if (disp == ED_POP){
+
+ POPUPDATACLASS ppd = {sizeof(ppd)};
+ char szName[256];
+ ppd.ptszTitle = puData->title;
+ ppd.ptszText = puData->text;
+ if (puData->flag == SAMETIME_POPUP_ERROR){
+ mir_snprintf(szName, SIZEOF(szName), "%s_%s", proto->m_szModuleName, "Error");
+ } else {
+ mir_snprintf(szName, SIZEOF(szName), "%s_%s", proto->m_szModuleName, "Notify");
+ }
+ CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&ppd);
+
+ } else if (disp == ED_BAL) {
+
+ MIRANDASYSTRAYNOTIFY sn = { sizeof(sn) };
+ sn.szProto = proto->m_szModuleName;
+ sn.tszInfoTitle = puData->title;
+ sn.tszInfo = puData->text;
+ sn.dwInfoFlags = NIIF_INTERN_UNICODE;
+ if (puData->flag == SAMETIME_POPUP_ERROR){
+ sn.dwInfoFlags = sn.dwInfoFlags | NIIF_WARNING;
+ sn.uTimeout = 1000 * 10;
+ } else {
+ sn.dwInfoFlags = sn.dwInfoFlags | NIIF_INFO;
+ sn.uTimeout = 1000 * 8;
+ }
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn);
+
+ } else { //disp == ED_MB
+
+ if (puData->flag == SAMETIME_POPUP_ERROR){
+ MessageBox(NULL, puData->text, puData->title, MB_OK | MB_ICONWARNING);
+ } else {
+ MessageBox(NULL, puData->text, puData->title, MB_OK | MB_ICONINFORMATION);
+ }
+
+ }
+
+ if (disp != ED_POP){
+ mir_free(puData->title);
+ mir_free(puData->text);
+ mir_free(puData);
+ }
+
+}
+
+void CSametimeProto::showPopup(const TCHAR* msg, SametimePopupEnum flag)
+{
+ if (Miranda_Terminated()) return;
+
+ PopupData *puData = (PopupData*)mir_calloc(sizeof(PopupData));
+ puData->flag = flag;
+ puData->title = mir_tstrdup(m_tszUserName);
+ puData->text = mir_tstrdup(msg);
+ puData->proto = this;
+
+ CallFunctionAsync(sttMainThreadCallback, puData);
+}
+
+
+void LogFromGLib(const gchar* log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data)
+{
+ CSametimeProto* proto = (CSametimeProto*)user_data;
+ proto->debugLog(_A2T(message));
+}
+
+void CSametimeProto::RegisterGLibLogger()
+{
+ debugLog(_T("CSametimeProto::RegisterGLibLogger"));
+ gLogHandler = g_log_set_handler(G_LOG_DOMAIN, G_LOG_LEVEL_MASK, LogFromGLib, this);
+}
+
+void CSametimeProto::UnRegisterGLibLogger()
+{
+ debugLog(_T("CSametimeProto::UnRegisterGLibLogger"));
+ if (gLogHandler) g_log_remove_handler(G_LOG_DOMAIN, gLogHandler);
+}
diff --git a/protocols/Sametime/src/version.h b/protocols/Sametime/src/version.h new file mode 100644 index 0000000000..c66789c5b1 --- /dev/null +++ b/protocols/Sametime/src/version.h @@ -0,0 +1,13 @@ +#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 7
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 0
+
+#include <stdver.h>
+
+#define __PLUGIN_NAME "Sametime Protocol"
+#define __DESCRIPTION "Implementation of Instant Messaging for the Lotus Sametime protocol."
+#define __AUTHOR "Scott Ellis, Szymon Tokarz"
+#define __AUTHOREMAIL "mail"/*antispam*/"@"/*antispam*/"scottellis.com.au, wsx22"/*antispam*/"@"/*antispam*/"o2.pl"
+#define __COPYRIGHT "© 2005 Scott Ellis, 2014 wsx22"
+#define __AUTHORWEB "http://miranda-ng.org/p/Sametime/"
\ No newline at end of file |