Mercurial > pidgin.yaz
changeset 7014:67c4e9d39242
[gaim-migrate @ 7577]
Here it is, the bulk of the new Jabber prpl.
Left to do:
- Implement registration
- Implement password changing
- Keep track of conversation threads (since I apparently have to)
- Fix the bugs that always magically appear in code after I commit
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Mon, 29 Sep 2003 15:23:19 +0000 |
parents | 859cafb6433f |
children | dece74f05509 |
files | ChangeLog src/html.c src/protocols/jabber/.cvsignore src/protocols/jabber/AUTHORS.libjabber src/protocols/jabber/AUTHORS.libxode src/protocols/jabber/COPYING.libjabber src/protocols/jabber/COPYING.libxode src/protocols/jabber/ChangeLog.libjabber src/protocols/jabber/ChangeLog.libxode src/protocols/jabber/INSTALL.libjabber src/protocols/jabber/INSTALL.libxode src/protocols/jabber/JEPS src/protocols/jabber/Makefile.am src/protocols/jabber/NEWS.libjabber src/protocols/jabber/NEWS.libxode src/protocols/jabber/README.libjabber src/protocols/jabber/README.libxode src/protocols/jabber/TODO.libjabber src/protocols/jabber/asciitab.h src/protocols/jabber/auth.c src/protocols/jabber/auth.h src/protocols/jabber/buddy.c src/protocols/jabber/buddy.h src/protocols/jabber/chat.c src/protocols/jabber/chat.h src/protocols/jabber/expat.c src/protocols/jabber/genhash.c src/protocols/jabber/hashtable.c src/protocols/jabber/hashtable.h src/protocols/jabber/iasciitab.h src/protocols/jabber/iq.c src/protocols/jabber/iq.h src/protocols/jabber/jabber.c src/protocols/jabber/jabber.h src/protocols/jabber/jconn.c src/protocols/jabber/jid.c src/protocols/jabber/jpacket.c src/protocols/jabber/jutil.c src/protocols/jabber/jutil.h src/protocols/jabber/karma.c src/protocols/jabber/latin1tab.h src/protocols/jabber/lib.h src/protocols/jabber/libxode.h src/protocols/jabber/log.c src/protocols/jabber/log.h src/protocols/jabber/message.c src/protocols/jabber/message.h src/protocols/jabber/nametab.h src/protocols/jabber/parser.c src/protocols/jabber/parser.h src/protocols/jabber/pool.c src/protocols/jabber/pproxy.c src/protocols/jabber/presence.c src/protocols/jabber/presence.h src/protocols/jabber/rate.c src/protocols/jabber/roster.c src/protocols/jabber/roster.h src/protocols/jabber/sha.c src/protocols/jabber/snprintf.c src/protocols/jabber/socket.c src/protocols/jabber/str.c src/protocols/jabber/utf8tab.h src/protocols/jabber/xhash.c src/protocols/jabber/xmldef.h src/protocols/jabber/xmlnode.c src/protocols/jabber/xmlnode.h src/protocols/jabber/xmlparse.c src/protocols/jabber/xmlparse.h src/protocols/jabber/xmlrole.c src/protocols/jabber/xmlrole.h src/protocols/jabber/xmltok.c src/protocols/jabber/xmltok.h src/protocols/jabber/xmltok_impl.c src/protocols/jabber/xmltok_impl.h src/protocols/jabber/xmltok_ns.c src/protocols/jabber/xstream.c |
diffstat | 74 files changed, 4370 insertions(+), 22463 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Sep 29 13:00:55 2003 +0000 +++ b/ChangeLog Mon Sep 29 15:23:19 2003 +0000 @@ -3,6 +3,7 @@ version 0.71 * Display AIM away messages in the tooltip for buddies when they are away. + * Re-write of Jabber protocol plugin version 0.70 (09/28/2003): * Implemented Yahoo's new authentication method (Cerulean Studios)
--- a/src/html.c Mon Sep 29 13:00:55 2003 +0000 +++ b/src/html.c Mon Sep 29 15:23:19 2003 +0000 @@ -468,7 +468,9 @@ ALLOW_TAG("h4"); ALLOW_TAG("h5"); ALLOW_TAG("h6"); - ALLOW_TAG("html"); + /* we only allow html to start the message */ + if(c == html) + ALLOW_TAG("html"); ALLOW_TAG_ALT("i", "em"); ALLOW_TAG_ALT("italic", "em"); ALLOW_TAG("li");
--- a/src/protocols/jabber/.cvsignore Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/.cvsignore Mon Sep 29 15:23:19 2003 +0000 @@ -2,30 +2,11 @@ Makefile .deps .libs -expat.lo -genhash.lo -hashtable.lo -jabber.lo -jconn.lo -jid.lo -jpacket.lo -jutil.lo -karma.lo -libjabber.la -log.lo -pool.lo -pproxy.lo -rate.lo -sha.lo -snprintf.lo -socket.lo -str.lo -xhash.lo -xmlnode.lo -xmlparse.lo -xmlrole.lo -xmltok.lo -xstream.lo +*.lo +*.la +*.dll *.def *.lib -*.dll +.*.swp +.*.swo +.todo.*
--- a/src/protocols/jabber/AUTHORS.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ --- AUTHORS for libjabber - A library for the Jabber server. - -Authors: - Scott Robinson <quad@jabber.org> - Gurer Ozen <palpa@jabber.org> - Jeremie Miller <jer@jeremie.com>
--- a/src/protocols/jabber/AUTHORS.libxode Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ --- AUTHORS for libxode - A library of XML and string helper functions. - -Authors: - Jeremie Miller <jer@jabber.org> - Thomas Muldowney <temas@box5.net> - Dave Smith <dave@jabber.org>
--- a/src/protocols/jabber/COPYING.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License.
--- a/src/protocols/jabber/COPYING.libxode Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License.
--- a/src/protocols/jabber/ChangeLog.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,621 +0,0 @@ -2000-10-30 temas <temas@box5.net> (temas@jabber.org) - - * src/Makefile.am: new libtool version info - - * configure.in: 1.2 final version - -2000-10-20 jer <jer@jabber.org> - - * jpacket.c: fixed it so that we actually check the full packet name (we shouldn't have been cheating) and flagged when bad addresses were used - -2000-10-08 jer <jer@jabber.org> - - * rate.c: renamed to jlimit_* - -2000-10-06 madcat <palpa@jabber.org> - - * jconn.c: jab_auth is not automated anymore. - * jconn.c: fixed seg fault bug in jab_start() (thanks Marco! :) - -2000-06-18 spectre <spectre@portent.net> - - * jconn.c: automated jab_auth, shouldn't be called manually unless - called after registering - * jconn.c: added JDEBUG #ifdefs to monitor incoming/outgoing xml stream - * jconn.c: added jab_reg, registering of users - * jutil.c: added jutil_msgnew, creating of message packets - * jabber.h: added message types to use with jutil_msgnew - * jabber.h: new state (JCONN_STATE_AUTH) for automated authorizing - -2000-06-15 madcat <palpa@jabber.org> - - * jabberx removed from build system, it is now on jabber-x.sourceforge.net - * jabber.h: C++ friendlyness (conditionally compiled extern "C" {} stuff) - -2000-06-01 madcat <palpa@jabber.org> - - * jconn.c: support for anonymous accounts, and new jab_getid() function - -2000-05-24 madcat <palpa@jabber.org> - - * jabberx: new curses gui - -2000-05-21 madcat <palpa@jabber.org> - - * jconn.c: new event handler system, they return jpackets now. - added comments to the functions - - * jabberx: updated to new api - -2000-05-02 temas <temas@box5.net> - - * configure.in: fixes for the libxode checks - -2000-05-01 jer <jeremie@jabber.org> - - * two bug fixes, type=normal and pproxy brokenedness - - * -Wall - - * astyle 4 space indent enforced - -2000-04-28 jer <jeremie@jabber.org> - - * jpacket.c: message type=headline - - * pproxy.c: update for pool heaps - -2000-04-25 jer <jeremie@jabber.org> - - * jid.c: new jid_cmpx() function to compare by optional parts - - * pproxy.c: dumb bug preventing the use of _primary() and user@host addresses - - * util.c: the register utility was broke after 100 keys :) - -2000-04-22 jer <jeremie@jabber.org> - - * by popular demand, the server now eats presence type=available (and normalizes it) - -2000-04-18 jer <jeremie@jabber.org> - - * 1.0pre2 - -2000-04-17 jer <jeremie@jabber.org> - - * jid.c: username limit at 255 - - * log.c: zonestr now in libxode - -2000-04-12 temas <temas@box5.net> - - * Build fixes for non standard prefixes - -2000-04-12 jer <jeremie@jabber.org> - - * roll to 1.0pre1 - - * util.c: jutil_regkey to generate and validate registration keys - -2000-04-10 jer <jeremie@jabber.org> - - * jid.c: jid_cmp was FUBAR under certian compares, ick, it's better now - - * pproxy.c: I rewrote it all... why? because it scared me - - * util.c: lots of goodies transferred from jserver to share with all - -2000-03-28 temas <temas@box5.net> - - * configure.in: no more NONE - -2000-03-28 jer <jeremie@jabber.org> - - * 0.9! - -2000-03-27 e-t <eliot@landrum.cx> - - * Updated README a bit. Not much changed. - * Commited some debian/ files that were missing... - -2000-03-27 jer <jeremie@jabber.org> - - * jid.c: space character is illegal too :) - -2000-03-19 temas <temas@box5.net> - - * RC - -2000-03-19 jer <jeremie@jabber.org> - - * jpacket.c: a little more careful about jpackets now, strict - -2000-03-17 temas <temas@box5.net> - - * configure.in: libxode checks better - - * bump to pre4 - -2000-03-15 jer <jeremie@jabber.org> - - * jid.c: now EXTRA cautious about the jid, validating the characters and length in the username/hostname - -2000-03-13 jer <jeremie@jabber.org> - - * pproxy.c: presence priority is only negative for type=unavailable - -2000-03-12 jer <jeremie@jabber.org> - - * jid.c: jid_nodescan() utility to get nodes with matchin jid's, behaving to jid matching rules - - * jid.c: ignore type:, tolower server, better data validity checking, case insensitive username compares, 64 char limit on user/server - -2000-02-29 temas <temas@box5.net> - - * Makefile.am: get rid of common dir - - * src/Makefile.am: use the libxode stuff better - - * configure.in: libxode and common dir fixes - - * ChangeLog: double spaced e-t's entries cause I like it that way =) - -2000-02-29 e-t <eliot@jabber.org> - - * README: general cleanup. - - * AUTHORS: general cleanup. - - * man/jabber-config.1: added, probably could use a bit more description, - but will do for now. (included Makefiles in man/) - - * Makefile.am: added dir man/ - -2000-02-27 jer <jeremie@jabber.org> - - * jpacket.c: performance tweaks - -2000-02-24 jer <jeremie@jabber.org> - - * common transformed to libxode, use that instead - - * jpacket.c: now nulls out data upon a reset to be safer - - * ppdb.c: bug, check data better! grr - - * jid.c: leaky leaky, handle memory better when appending jid's - -2000-02-20 e-t <eliot@jabber.org> - - * README: Kinda trashed the old one and copied/edited the Jabber standard README. - -2000-02-17 temas <temas@box5.net> - - * Makefile.am: don't have a macros dir anymore - * jabber-config.in: cleanups - - * configure.in: pre2 roll - -2000-02-09 jer <jeremie@jabber.org> - - * jpacket.c: added presence probe subtype - -2000-02-01 temas <temas@box5.net> - - * jabber-config is needed for the macro stuff - -2000-01-31 jer <jeremie@jabber.org> - - * xmlstream->jabstream: renamed all xmlstream to jabstream symbols, so they don't conflict with etherx's xmlstream - -2000-01-25 jer <jeremie@jabber.org> - - * jpacket.c: jpacket_subtype() which breaks down the packet type further and stores it in p->subtype - -2000-01-06 jer <jeremie@jabber.org> - - * jid.c: jid_xres() returns an xmlnode (same pool as the jid) representation of the resource and a standard query string, - for instance: /resource?name=value&foo=bar is an xmlnode for <resource name="value" foo="bar"/> - - * fixed other header prototype misplacements - -2000-01-06 palpa <gozen@isbank.net.tr> - - * bye libjnix, lala libjabber :) - -2000-01-04 palpa <gozen@isbank.net.tr> - - * profile.c: from field added to jnixpf struct - -2000-01-03 palpa <gozen@isbank.net.tr> - - * profile.c: handles jabber:iq:info queries - -2000-01-02 palpa <gozen@isbank.net.tr> - - * jabberx fixed for new api - - * auth.c: _jnix_reg() fixed - - * funcs for updating roster items - - * user field in the roster item struct is changed to (char*) - from (jid). - -2000-01-02 palpa <gozen@isbank.net.tr> - - * jnixr_removeitem() added - -2000-01-01 palpa <gozen@isbank.net.tr> - - * New JNIXC_ROSTER flag automatically requests roster from server. - - * New roster api. - - * Multiclient funcs removed & auth cb changed again. - -1999-12-30 scott <quad@jabber.org> - - * continued adding features and breaking up jabberx. Soon, my pretty, - soon. - - * well, y2k hath struck in some areas of the world. It's still 30 here, - so I'll note I've severely made jabberx awesome. Check it out o-kudasai! - -1999-12-30 palpa <gozen@isbank.net.tr> - - * jnixprivate.h added and private defines/prototypes in - jnix.h are moved in it. - - * com field in the roster item structure removed - -1999-12-29 palpa <gozen@isbank.net.tr> - - * stresstest moved to test dir - - * docs dir added - - * some jabberx fixes - - * user structure added & auth callback changed - - * login(), logoff() funcs for multiclients - -1999-12-29 scott <quad@jabber.org> - - * went to lower bandwidth node defaults - - * continued improving jnixtest. - - * Fixed a bit of roster parsing - -1999-12-28 scott <quad@jabber.org> - - * Re-vamped connection - - * Re-vamped rosters - - * Added more management - - * Fixed jnixtest to WORK - - * Patched a bunch of miscellaneous bugs. - - * patched a few more memory leaks - -1999-12-13 palpa <gozen@isbank.net.tr> - - * new editNode() function - - * id attribute support - - * presence changed for 0.8 - -1999-12-09 disq <disq@sanane.com> - - * fixed auth/register <result> for 0.8 - -1999-12-08 palpa <gozen@isbank.net.tr> - - * test/api.html: added (not finished yet) - - * node.c: msg/prs/iq things now use same set of functions - old msg/prs/iq funcs removed - - * jnix.c: now callbacks are global - - * jnixtest.c: changed to new api - -1999-12-04 palpa <gozen@isbank.net.tr> - - * xmlstream: removed unnecessary callback, fixed xmlstream_stop() - - * jnix: disconnect() now frees jnixc structure - - * auth: fixed/changed/optimized :) - - * jnixtest: auth callback support - -1999-12-03 disq <disq@sanane.com> - - * auth.c: added authorization & registration response callback - - * iq.c: changed jnix_findIQitem, now it takes the jnixqitem as a parameter. - this way we can use this function to search attributes - * jnix.c: frees iq before we call j->cbRoster - -1999-11-25 palpa <gozen@isbank.net.tr> - - * presence.c, iq.c: send functions changed for using spool - -1999-11-25 palpa <gozen@isbank.net.tr> - - * message.c: sendMessage() now creates xml with spool functions - (faster and uses less memory) - -1999-11-24 palpa <gozen@isbank.net.tr> - - * iq.c: newIQ() uses vararg arguments - -1999-11-24 palpa <gozen@isbank.net.tr> - - * jnix.c: JNIXC_NEWUSER now sends auth request after registration - - * jnixtext.c: new command line option, -n : registers new user - -1999-11-23 palpa <gozen@isbank.net.tr> - - * roster.c: parseRoster now correctly gets comment information - - * jnixtext.c: status command renamed to presence - added probe command - -1999-11-22 palpa <gozen@isbank.net.tr> - - * i did some api changes :} - nspace field in the jnixq struct renamed to xmlns - connect() now has a flags (int) field - some #define's changed, look jnix.h for them - old newXXX funcs removed, now all newXXX funcs takes vararg parameters - - * if you call connect with JNIXC_NEWUSER flag, it registers - that user (needs some work to send auth request after that :) - - * new addIQitem() function supports query tags with attributes. - - * roster.c and jnixtest.c patched for this changes. - - * this changes are not fully tested, sorry :} - -1999-11-22 disq <disq@sanane.com> - - * roster.c: added remaining roster routines, does not work mainly ;) - * jnixtest.c: updated - -1999-11-22 palpa <gozen@isbank.net.tr> - - * iq.c: parseIQ() now parses attributes of tags too - -1999-11-22 palpa <gozen@isbank.net.tr> - - * auth.c: jnix_register() added - (jnix_auth() moved to this file too) - -1999-11-22 disq <disq@sanane.com> - - * roster.c: added, parseRoster is there, untested - -1999-11-21 palpa <gozen@isbank.net.tr> - - * presence.c: changes for jnixp from field - -1999-11-21 palpa <gozen@isbank.net.tr> - - * jnix_auth(jnixc j, char *user, char* pass) added to api - This is for multiclients, jnix_connect() automatically - calls it for first user of that connection. - - * message.c: now fully supports jnixm from field. - - * jnix.c: sends auth request after receiving stream tag. - -1999-11-20 tcharron >tcharron@ductape.net - - * More changes to StressTest. - * message.c: _jnix_parsenode() Changed so to field is populated - by the jnixc user field if not specificaly stated in the message - -1999-11-20 palpa <gozen@isbank.net.tr> - - * presence.c: createPresence(int type, ...) added - -1999-11-19 temas <temas@box5.net> - - * added the header to files - -1999-11-17 palpa <gozen@isbank.net.tr> - - * createMessage() fixes/improvements - -1999-11-17 palpa <gozen@isbank.net.tr> - - * createMessage(char *to, ...) added to message api - -1999-11-16 TCharron <tcharron@ductape.net> - - * StressTest will now use full threading, and take - command line option. - -1999-11-15 TCharron <tcharron@ductape.net> - - * Added StressTest directory. This is going to be a program - to put the servers under incredible load. I'm currently using - it to simply login over 900 simo users. In the future, they'll - message eachother, go on and off line, and change status - messages. More to come.. - - (PPsst.. No comments.. Shoot me..) - -1999-11-15 palpa <gozen@isbank.net.tr> - - * sendIQ completed - -1999-11-13 palpa <gozen@isbank.net.tr> - - * parseIQ stuff - -1999-11-13 palpa <gozen@isbank.net.tr> - - * jnixm/p/q structures now have 'from' and 'to' fields instead of 'user' - (necessary for multi client support) - -1999-11-12 palpa <gozen@isbank.net.tr> - - * id field added to jnixm, jnixp, jnixq structures - - * iq callback partially working - - * sendPresence now sends priority - -1999-11-12 palpa <gozen@isbank.net.tr> - - * fixes for new jdebug() stuff - -1999-11-09 palpa <gozen@isbank.net.tr> - - * jnix_isOnline() function added - - * jnix now parses priority data in incoming message and presence nodes - -1999-11-09 palpa <gozen@isbank.net.tr> - - * establish-close callbacks renamed to online-offline - - * offline callback returns the reason of disconnection - - * jnix prefix added to callback typedefs - - * test client fixed for this changes - -1999-11-09 spectre <spectre@winterland.net> - - * added presence stuff, shortcuts and reply cmd to test client - - * and also some visual improvements - -1999-11-09 disq <disq@sanane.com> - - * fixed some /* bug/typo in jnix.h - - * debug(), insane(), _log() now defined even if DEBUG is not defined, but - they're empty functions - -1999-11-07 palpa <gozen@isbank.net.tr> - - * name of the test client changed to jnixtest - - * presence.c: jnix_sendMessage() added - -1999-11-07 disq <disq@sanane.com> - - * fixed typo in presence.c, now compiles - -1999-11-07 palpa <gozen@isbank.net.tr> - - * jnix.c: jnix_disconnect() added - - * presence.c: now it parses incoming presence nodes - - * message.c: some fixes - -1999-11-07 palpa <gozen@isbank.net.tr> - - * presence.c added for putting presence handling functions in - - * jnix_freeMessage() added - - * jnix.c and xmlstream.c now fully uses memory pools - -1999-11-06 palpa <gozen@isbank.net.tr> - - * jnix_newMessage and jnix_chatMessage added - -1999-11-06 spectre <spectre@winterland.net> - - * onMessage callback gets jnixm structure now - - * new ncurses based quick'n'dirty testclient - -1999-11-05 temas <temas@box5.net> - - * test/Makefile.am: testclient should build.. - - * configure.in: Fixed up some of the checks - - * acconfig.h: Make this file so we get a config.h - -1999-11-05 palpa <gozen@isbank.net.tr> - - * xmlstream api changed - -1999-11-04 palpa <gozen@isbank.net.tr> - - * xmlstream.c now uses string pools - -1999-11-04 palpa <gozen@isbank.net.tr> - - * parseMessage() is working - -1999-11-03 palpa <gozen@isbank.net.tr> - - * simple test client added - - * log stuff fixed - - * TODO file added - -1999-11-03 palpa <gozen@isbank.net.tr> - - * connect now takes a jid argument instead of server and user - - * 0.6 stuff removed - -1999-11-03 palpa <gozen@isbank.net.tr> - - * jnix_sendMessage (v0.7 protocol) - - * new jnix_auth for v0.7 - -1999-11-03 palpa <gozen@isbank.net.tr> - - * added message.c for putting message handling functions in - - * connection close/establish and message callbacks are working - -1999-11-02 palpa <gozen@isbank.net.tr> - - * connect, poll, setcb and fd functions implemented - - * pth and tstream stuff removed from xmlstream.c - - * configure.in and makefile.am files in include dir fixed - -1999-10-31 Jer <jeremie@jabber.org> - - * added xmlstream code from jlib for porting - - * fixing includes for common/include - - * jnix.h: rough API attempt - -1999-10-30 temas <temas@box5.net> - - * now use the common dir - -1999-10-29 temas <temas@box5.net> - - * autogen.sh: this is libjnix not jlib - -1999-10-29 Jer <jeremie@jabber.org> - - * birth! stole most of this from jlib
--- a/src/protocols/jabber/ChangeLog.libxode Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -2000-10-30 temas <temas@box5.net> (temas@jabber.org) - - * include/libxode.h: Solaris compiler warnings - - * src/Makefile.am: updated libtool version - - * configure.in: 1.2 version - -2000-10-25 jeremie <jer@jabber.org> - - * pool.c: debug stuff is working again and cool now :) - -2000-10-23 temas <temas@box5.net> (temas@jabber.org) - - * sha.c: replaced with a version from Mozilla, works again for real - -2000-10-20 temas <temas@box5.net> (temas@jabber.org) - - * sha.c: no more memory overrun... exploring other possible bugs - -2000-10-06 jeremie <jer@jabber.org> - - * xstream.c: bug in XSTREAM_ERR event, was passing an overloaded xmlnode (DUH!), it's now a normal <error>error message</error> node that has to be free'd like any other - -2000-09-26 jeremie <jer@jabber.org> - - * xstream.c: bug in put_vattrib() fixed - -2000-08-05 jeremie <jer@jabber.org> - - * xstream.c: moved primatives for xmlstream from libetherx to libxode, much cleaner and nicer now and usable in more places independent of IO - -2000-06-15 madcat <palpa@jabber.org> - - * xmlnode.c: static keyword added to local functions - * libxode.h: C++ friendlyness (conditionally compiled extern "C" {} stuff) - -2000-05-22 madcat <palpa@jabber.org> - - * sha.c: endianness fix - -2000-05-20 madcat <palpa@jabber.org> - - * xmlnode.c xmlnode2str() : indentation fixed, root node with no child problem fixed - -2000-05-13 madcat <palpa@jabber.org> - - * xmlnode.c: added comments to some functions - * xmlnode.c: xode_node2str() morphed into xmlnode2str() - * README: pth dependency statement removed - -2000-05-06 madcat <palpa@jabber.org> - - * new function: xode_node2str() - it's the non-recursive version of xmlnode2str() - -2000-05-03 jer <jeremie@jabber.org> - - * pool.c: last minute fixes, important part is the byte boundary fix for some platforms to prevent a Bus Error - -2000-05-01 jer <jeremie@jabber.org> - - * astyle of 4 space indent applied to *.c - -2000-05-01 temas <temas@box5.net> - - * sha.c: moved to uint32 - - * configure.in: check some type sizes - - * libxode.h: define uint32 from size checks - -2000-04-29 madcat <palpa@jabber.org> - - * str.c: evil strcat() in spool_print() replaced with j_strcat() - -2000-04-28 jer <jeremie@jabber.org> - - * str.c: added spools() utility wrapper around spool_* - - * pool.c: rewrite to use heaps, much more efficient and stuff, and modular cleanup is built into the pool now - -2000-04-26 temas <temas@box5.net> - - * SHA1 is fixed, and no longer requires endian.h - - * libxode-config is created - -2000-04-22 jer <jeremie@jabber.org> - - * str.c: added simple base64 decode - -2000-04-20 jer <jeremie@jabber.org> - - * str.c: added some more convenience wrappers - -2000-04-18 jer <jeremie@jabber.org> - - * 1.0pre2 - -2000-04-17 jer <jeremie@jabber.org> - - * str.c: zonestr - - * pool.c: labels and better debugging - -2000-04-14 jer <jeremie@jabber.org> - - * xmlnode.c: made xmlnode_get_data() a little smarter, searching for it - -2000-04-12 jer <jeremie@jabber.org> - - * 1.0pre1 - - * added str_hash_code function for the ghash utility - -2000-04-11 temas <temas@box5.net> - - * hash generation routines moved into libxode - - * sha support is now built in, supplies 4 functions to the users see sha.c - for more info - -2000-03-28 jer <jeremie@jabber.org> - - * 0.9! - -2000-03-27 e-t <eliot@landrum.cx> - - * README: minor updates. - -2000-03-19 temas <temas@box5.net - - * RC - -2000-03-17 temas <temas@box5.net> - - * quick bump to pre4 - -2000-03-12 jer <jeremie@jabber.org> - - * xmlnode.c: xmlnode_insert_cdata() didn't make sure the parent existed, duh - -2000-03-02 temas <temas@box5.net> - - * src/snprintf.c: Use apaches snprintf replacement - - * include/libxode.h: patch up for snprintf - -2000-02-29 temas <temas@box5.net> - - * configure.in: pre3 - - * snprintf.c: make this not build correctly if certain defines are set - - * ChangeLog: cleaned up jer's mess - -2000-02-29 e-t <eliot@landrum.cx> - - * Added a complete README. - * Added a complete AUTHORS. - -2000-02-27 jer <jeremie@jabber.org> - - * pool.c: now has a debug version that tracks all stats - -2000-02-23 temas <temas@box5.net> - - * moved the common dir into what is now known as libxode - -2000-02-21 jer <jeremie@jabber.org> - - * xmlnode.c: xmlnode_get_tag() had a bug under certian queries - -2000-01-30 jer <jeremie@jabber.org> - - * xmlnode.c: few places in the core functions that weren't too - tolerant of bad data :) - -2000-01-28 jer <jeremie@jabber.org> - - * xmlnode.c: fixed bug in xmlnode_get_data with parsing NTYPE_ATTRIB nodes - - * xmlnode.c: fixed bug in xmlnode_get_tag, a check failed and ?queries - would fail - - * xmlnode.c: created xmlnode_insert_tag_node() for convenience - -2000-01-22 jer <jeremie@jabber.org> - - * xmlnode.c: added xmlnode_new_tag_pool() and xmlnode_dup_pool() - convenience functions to force the pool to use - -2000-01-19 jer <jeremie@jabber.org> - - * xmlnode.c: changed xmlnode_get_data() to automatically do - xmlnode_get_firstchild if you pass it a tag - - * xmlnode.c: upgraded xmlnode_get_tag() to support queries, and - convenience xmlnode_get_tag_data() - -2000-01-19 jer <jeremie@jabber.org> - - * pool.c: added pool_size(p) to return the bytes used in the pool - - * added ChangeLog for common
--- a/src/protocols/jabber/INSTALL.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure - -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM - -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Operation Controls -================== - - `configure' recognizes the following options to control how it -operates. - -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. - -`--help' - Print a summary of the options to `configure', and exit. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`configure' also accepts some other, not widely useful, options.
--- a/src/protocols/jabber/INSTALL.libxode Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure - -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM - -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Operation Controls -================== - - `configure' recognizes the following options to control how it -operates. - -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. - -`--help' - Print a summary of the options to `configure', and exit. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`configure' also accepts some other, not widely useful, options.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/JEPS Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,55 @@ +0004: NEED + Data Gathering and Reporting +0011: NEED (or just do disco?) + Jabber Browsing +0012: DONE + Last Activity +0018: DONE (Is it?) + Presence (Invisible) +0022: DONE (replace?) + Message Events +0030: NEED + Service Discovery +0045: DONE + Multi-User Chat +0052: NEED + File Transfer +0054: DONE (ugly) + vCard +0060: NEED + Pub-Sub +0071: DONE (needs spec confirmation) + XHTML-IM +0073: NEED + Basic IM Protocol Suite +0077: NEED 0.71 + In-Band Registration +0078: DONE + Non-SASL Authentication +0080: NEED (Do we?) + Geographic Location Information +0082: DONE + Jabber Date and Time Profiles +0084: NEED + User Avatars in Jabber +0085: NEED + Chat State Notifications +0086: DONE + Legacy Errors +0089: WATCH + Generic Alerts +0090: DONE + Entity Time +0091: DONE + Delayed Delivery +0092: DONE + Software Version +0093: NEED + Roster Item Exchange +0100: NEED + Gateway Interaction (Transports) +0115: WATCH + Client Capabilities +0017: NEED + Advanced IM Protocol Suite +
--- a/src/protocols/jabber/Makefile.am Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/Makefile.am Mon Sep 29 15:23:19 2003 +0000 @@ -1,53 +1,30 @@ -EXTRA_DIST = \ - xmltok_impl.c \ - xmltok_ns.c \ - Makefile.mingw \ - win32/posix.uname.c \ - win32/utsname.h +EXTRA_DIST = win32/posix.uname.c \ + win32/utsname.h pkgdir = $(libdir)/gaim -JABBERSOURCES = \ - asciitab.h \ - expat.c \ - genhash.c \ - hashtable.c \ - hashtable.h \ - karma.c \ - iasciitab.h \ - latin1tab.h \ - lib.h \ - libxode.h \ - nametab.h \ - pool.c \ - sha.c \ - snprintf.c \ - socket.c \ - str.c \ - utf8tab.h \ - xhash.c \ - xmldef.h \ - xmlnode.c \ - xmlparse.c \ - xmlparse.h \ - xmlrole.c \ - xmlrole.h \ - xmltok.c \ - xmltok.h \ - xmltok_impl.h \ - xstream.c \ - \ - jabber.h \ - jconn.c \ - jid.c \ - jpacket.c \ - jutil.c \ - log.c \ - log.h \ - pproxy.c \ - rate.c \ - \ - jabber.c +JABBERSOURCES = auth.c \ + auth.h \ + buddy.c \ + buddy.h \ + chat.c \ + chat.h \ + iq.c \ + iq.h \ + jabber.c \ + jabber.h \ + jutil.c \ + jutil.h \ + message.c \ + message.h \ + parser.c \ + parser.h \ + presence.c \ + presence.h \ + roster.c \ + roster.h \ + xmlnode.c \ + xmlnode.h AM_CFLAGS = $(st) @@ -57,14 +34,16 @@ st = -DSTATIC noinst_LIBRARIES = libjabber.a +pkg_LTLIBRARIES = libjabber_a_SOURCES = $(JABBERSOURCES) -libjabber_a_CFLAGS = $(AM_CFLAGS) +libjabber_a_CFLAGS = $(AM_CFLAGS) else st = pkg_LTLIBRARIES = libjabber.la +noinst_LIBRARIES = libjabber_la_SOURCES = $(JABBERSOURCES)
--- a/src/protocols/jabber/README.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ - libjabber README - Jabber Documentation Team - March 27, 2000 - ____________________________________________________________ - - Table of Contents - - - 1. Introduction - - 1.1 General - 1.2 What This Package Is - - 2. Getting Things Installed - - 2.1 Dependencies - 2.2 Compilation and Installation - 2.3 Problems/Bugs - - 3. Jabber Information - - 3.1 General Information - 3.2 Developer Information - ______________________________________________________________________ - - 1. Introduction - - 1.1. General - - This document gives pointers for information on this package as well - as links to learn more about the Jabber project and about - participating in the project. - - Copyright information can be found in each package directory in the - files "COPYRIGHT" and "COPYING." - - 1.2. What This Package Is - - Currently, libjabber provides Jabber server software with various - library functions. - - - 2. Getting Things Installed - - 2.1. Dependencies - - Apart from your standard UNIX fare, this package is dependent on the - following: - - o libxode, available from http://download.jabber.org/ - - 2.2. Compilation and Installation - - To install as super user do the following in the libjabber root directory: - - ______________________________________________________________________ - ./configure - make - (become root) - make install - ldconfig - ______________________________________________________________________ - - 2.3. Problems/Bugs - - Submit bug reports at http://bugs.jabber.org. - - For additional real-time support, many members of the development team - frequent jabber groupchat in jdev@conference.jabber.org and irc at - irc.openprojects.net in #jabber. - - - 3. Jabber Information - - 3.1. General Information - - For general information about Jabber, including a quick introduction - to Jabber concepts, see the FAQ at http://docs.jabber.org/. - - 3.2. Developer Information - - There are many areas of Jabber that developers can contribute to. - Jabber encompasses many fields of expertise and anyone that is willing - to help can contribute. - - You may want to delve into the internals of the Jabber project at - http://docs.jabber.org/ and http://protocol.jabber.org/. - - Or maybe you would like to go ahead become a developer on the project. - Just go on over to http://jabber.org/ and register. You may also - sign up for the main Jabber mailing list (JDEV).
--- a/src/protocols/jabber/README.libxode Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ - libxode README - Jabber Documentation Team - March 27, 2000 - ____________________________________________________________ - - Table of Contents - - - 1. Introduction - - 1.1 General - 1.2 What This Package Is - - 2. Getting Things Installed - - 2.1 Dependencies - 2.2 Compilation and Installation - 2.3 Problems/Bugs - - 3. Jabber Information - - 3.1 General Information - 3.2 Developer Information - ______________________________________________________________________ - - 1. Introduction - - 1.1. General - - This document gives pointers for information on this package as well - as links to learn more about the Jabber project and about - participating in the project. - - Copyright information can be found in each package directory in the - files "COPYRIGHT" and "COPYING." - - 1.2. What libxode is - - libxode provides a library of XML, memory, and string helper functions. - - Jabber server software uses libxode extensively. - - - 2. Getting it Installed - - 2.1. Dependencies - - Apart from the standard UNIX fare, this package isn't dependent on - anything. - - 2.2. Compilation and Installation - - To install as super user do the following in the libxode root directory: - - ______________________________________________________________________ - ./configure - make - (become root) - make install - ldconfig - ______________________________________________________________________ - - 2.3. Problems/Bugs - - Submit bug reports at http://bugs.jabber.org. - - For additional real-time support, many members of the development team - frequent jabber groupchat in jdev@conference.jabber.org and irc at - irc.openprojects.net in #jabber. - - - 3. Jabber Information - - 3.1. General Information - - For general information about Jabber, including a quick introduction - to Jabber concepts, see the FAQ at http://docs.jabber.org/. - - 3.2. Developer Information - - There are many areas of Jabber that developers can contribute to. - Jabber encompasses many fields of expertise and anyone that is willing - to help can contribute. - - You may want to delve into the internals of the Jabber project at - http://docs.jabber.org/ and http://protocol.jabber.org/. - - Or maybe you would like to go ahead become a developer on the project. - Just go on over to http://jabber.org/ and register. You may also - sign up for the main Jabber mailing list (JDEV).
--- a/src/protocols/jabber/TODO.libjabber Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - -* update StressTest -* documentation - -* any ideas? :)
--- a/src/protocols/jabber/asciitab.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/auth.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,378 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" + +#include "jutil.h" +#include "auth.h" +#include "xmlnode.h" +#include "jabber.h" +#include "iq.h" +#include "sha.h" + +#include "debug.h" +#include "md5.h" +#include "util.h" +#include "sslconn.h" + + +void +jabber_auth_start(JabberStream *js, xmlnode *packet) +{ + xmlnode *mechs, *mechnode; + xmlnode *starttls; + + gboolean digest_md5 = FALSE; + + if(gaim_ssl_is_supported() && + (starttls = xmlnode_get_child(packet, "starttls"))) { + jabber_send_raw(js, + "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); + return; + } + + mechs = xmlnode_get_child(packet, "mechanisms"); + + if(!mechs) { + gaim_connection_error(js->gc, _("Invalid response from server")); + return; + } + + for(mechnode = mechs->child; mechnode; mechnode = mechnode->next) + { + if(mechnode->type == NODE_TYPE_TAG) { + char *mech_name = xmlnode_get_data(mechnode); + if(mech_name && !strcmp(mech_name, "DIGEST-MD5")) + digest_md5 = TRUE; + g_free(mech_name); + } + } + + if(digest_md5) { + jabber_send_raw(js, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + " mechanism='DIGEST-MD5' />"); + } else { + gaim_connection_error(js->gc, + _("Server does not use any supported authentication method")); + } +} + +static void auth_old_result_cb(JabberStream *js, xmlnode *packet) +{ + const char *type = xmlnode_get_attrib(packet, "type"); + + if(type && !strcmp(type, "error")) { + xmlnode *error = xmlnode_get_child(packet, "error"); + const char *err_code; + char *err_text; + char *buf; + + err_code = xmlnode_get_attrib(error, "code"); + err_text = xmlnode_get_data(error); + + if(!err_code) + err_code = ""; + if(!err_text) + err_text = g_strdup(_("Unknown")); + + if(!strcmp(err_code, "401")) + js->gc->wants_to_die = TRUE; + + buf = g_strdup_printf("Error %s: %s", + err_code, err_text); + + gaim_connection_error(js->gc, buf); + g_free(err_text); + g_free(buf); + } + jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); +} + +static void auth_old_cb(JabberStream *js, xmlnode *packet) +{ + JabberIq *iq; + xmlnode *query, *x; + gboolean digest = FALSE; + const char *pw = gaim_account_get_password(js->gc->account); + + query = xmlnode_get_child(packet, "query"); + if(js->stream_id && xmlnode_get_child(query, "digest")) { + digest = TRUE; + } else if(!xmlnode_get_child(query, "password")) { + gaim_connection_error(js->gc, + _("Server does not use any supported authentication method")); + return; + } + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); + query = xmlnode_get_child(iq->node, "query"); + x = xmlnode_new_child(query, "username"); + xmlnode_insert_data(x, js->user->node, -1); + x = xmlnode_new_child(query, "resource"); + xmlnode_insert_data(x, js->user->resource, -1); + + if(digest) { + unsigned char hashval[20]; + char *s, h[41], *p; + int i; + + x = xmlnode_new_child(query, "digest"); + s = g_strdup_printf("%s%s", js->stream_id, pw); + shaBlock((unsigned char *)s, strlen(s), hashval); + p = h; + for(i=0; i<20; i++, p+=2) + snprintf(p, 3, "%02x", hashval[i]); + xmlnode_insert_data(x, h, -1); + g_free(s); + } else { + x = xmlnode_new_child(query, "password"); + xmlnode_insert_data(x, pw, -1); + } + + jabber_iq_set_callback(iq, auth_old_result_cb); + + jabber_iq_send(iq); +} + +void jabber_auth_start_old(JabberStream *js) +{ + JabberIq *iq; + xmlnode *query, *username; + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:auth"); + + query = xmlnode_get_child(iq->node, "query"); + username = xmlnode_new_child(query, "username"); + xmlnode_insert_data(username, js->user->node, -1); + + jabber_iq_set_callback(iq, auth_old_cb); + + jabber_iq_send(iq); +} + +static GHashTable* parse_challenge(const char *challenge) +{ + GHashTable *ret = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + char **pairs; + int i; + + pairs = g_strsplit(challenge, ",", -1); + + for(i=0; pairs[i]; i++) { + char **keyval = g_strsplit(pairs[i], "=", 2); + if(keyval[0] && keyval[1]) { + if(keyval[1][0] == '"' && keyval[1][strlen(keyval[1])-1] == '"') + g_hash_table_replace(ret, g_strdup(keyval[0]), g_strndup(keyval[1]+1, strlen(keyval[1])-2)); + else + g_hash_table_replace(ret, g_strdup(keyval[0]), g_strdup(keyval[1])); + } + g_strfreev(keyval); + } + + g_strfreev(pairs); + + return ret; +} + +static unsigned char* +generate_response_value(JabberID *jid, const char *passwd, const char *nonce, + const char *cnonce, const char *a2) +{ + md5_state_t ctx; + md5_byte_t result[16]; + + char *x, *y, *a1, *ha1, *ha2, *kd, *z; + + x = g_strdup_printf("%s:%s:%s", jid->node, jid->domain, passwd); + md5_init(&ctx); + md5_append(&ctx, x, strlen(x)); + md5_finish(&ctx, result); + + y = g_strndup(result, 16); + + a1 = g_strdup_printf("%s:%s:%s:%s@%s/%s", y, nonce, cnonce, jid->node, + jid->domain, jid->resource); + + md5_init(&ctx); + md5_append(&ctx, a1, strlen(a1)); + md5_finish(&ctx, result); + + ha1 = tobase16(result, 16); + + md5_init(&ctx); + md5_append(&ctx, a2, strlen(a2)); + md5_finish(&ctx, result); + + ha2 = tobase16(result, 16); + + kd = g_strdup_printf("%s:%s:00000001:%s:auth:%s", ha1, nonce, cnonce, ha2); + + md5_init(&ctx); + md5_append(&ctx, kd, strlen(kd)); + md5_finish(&ctx, result); + + z = tobase16(result, 16); + + g_free(x); + g_free(y); + g_free(a1); + g_free(ha1); + g_free(ha2); + g_free(kd); + + return z; +} + +void +jabber_auth_handle_challenge(JabberStream *js, xmlnode *packet) +{ + char *enc_in = xmlnode_get_data(packet); + char *dec_in; + char *enc_out; + GHashTable *parts; + + frombase64(enc_in, &dec_in, NULL); + + parts = parse_challenge(dec_in); + + /* we're actually supposed to prompt the user for a realm if + * the server doesn't send one, but that really complicates things, + * so i'm not gonna worry about it until is poses a problem to someone, + * or I get really bored */ + + if(g_hash_table_lookup(parts, "realm")) { + /* assemble a response, and send it */ + /* see RFC 2831 */ + GString *response = g_string_new(""); + char *a2; + char *auth_resp; + char *buf; + char *cnonce; + char *realm; + char *nonce; + + cnonce = g_strdup_printf("%p%u%p", js, (int)time(NULL), packet); + nonce = g_hash_table_lookup(parts, "nonce"); + realm = g_hash_table_lookup(parts, "realm"); + + a2 = g_strdup_printf("AUTHENTICATE:xmpp/%s", realm); + auth_resp = generate_response_value(js->user, + gaim_account_get_password(js->gc->account), nonce, cnonce, a2); + g_free(a2); + + a2 = g_strdup_printf(":xmpp/%s", realm); + js->expected_rspauth = generate_response_value(js->user, + gaim_account_get_password(js->gc->account), nonce, cnonce, a2); + g_free(a2); + + + g_string_append_printf(response, "username=\"%s\"", js->user->node); + g_string_append_printf(response, ",realm=\"%s\"", realm); + g_string_append_printf(response, ",nonce=\"%s\"", nonce); + g_string_append_printf(response, ",cnonce=\"%s\"", cnonce); + g_string_append_printf(response, ",nc=00000001"); + g_string_append_printf(response, ",qop=auth"); + g_string_append_printf(response, ",digest-uri=\"xmpp/%s\"", realm); + g_string_append_printf(response, ",response=%s", auth_resp); + g_string_append_printf(response, ",charset=utf-8"); + g_string_append_printf(response, ",authzid=\"%s\"", + gaim_account_get_username(js->gc->account)); + + g_free(auth_resp); + g_free(cnonce); + + enc_out = tobase64(response->str, response->len); + + gaim_debug(GAIM_DEBUG_MISC, "jabber", "decoded response (%d): %s\n", response->len, response->str); + + buf = g_strdup_printf("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>", enc_out); + + jabber_send_raw(js, buf); + + g_free(buf); + + g_free(enc_out); + + g_string_free(response, TRUE); + } else if (g_hash_table_lookup(parts, "rspauth")) { + char *rspauth = g_hash_table_lookup(parts, "rspauth"); + + + if(rspauth && !strcmp(rspauth, js->expected_rspauth)) { + jabber_send_raw(js, + "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"); + } else { + gaim_connection_error(js->gc, _("Invalid challenge from server")); + } + g_free(js->expected_rspauth); + } + + g_free(enc_in); + g_free(dec_in); + g_hash_table_destroy(parts); +} + +void jabber_auth_handle_success(JabberStream *js, xmlnode *packet) +{ + const char *ns = xmlnode_get_attrib(packet, "xmlns"); + + if(!ns || strcmp(ns, "urn:ietf:params:xml:ns:xmpp-sasl")) { + gaim_connection_error(js->gc, _("Invalid response from server")); + return; + } + + jabber_stream_set_state(js, JABBER_STREAM_REINITIALIZING); +} + +void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet) +{ + const char *ns = xmlnode_get_attrib(packet, "xmlns"); + + if(!ns) + gaim_connection_error(js->gc, _("Invalid response from server")); + else if(!strcmp(ns, "urn:ietf:params:xml:ns:xmpp-sasl")) { + if(xmlnode_get_child(packet, "bad-protocol")) { + gaim_connection_error(js->gc, _("Bad Protocol")); + } else if(xmlnode_get_child(packet, "encryption-required")) { + js->gc->wants_to_die = TRUE; + gaim_connection_error(js->gc, _("Encryption Required")); + } else if(xmlnode_get_child(packet, "invalid-authzid")) { + js->gc->wants_to_die = TRUE; + gaim_connection_error(js->gc, _("Invalid authzid")); + } else if(xmlnode_get_child(packet, "invalid-mechanism")) { + js->gc->wants_to_die = TRUE; + gaim_connection_error(js->gc, _("Invalid Mechanism")); + } else if(xmlnode_get_child(packet, "invalid-realm")) { + gaim_connection_error(js->gc, _("Invalid Realm")); + } else if(xmlnode_get_child(packet, "mechanism-too-weak")) { + js->gc->wants_to_die = TRUE; + gaim_connection_error(js->gc, _("Mechanism Too Weak")); + } else if(xmlnode_get_child(packet, "not-authorized")) { + js->gc->wants_to_die = TRUE; + gaim_connection_error(js->gc, _("Not Authorized")); + } else if(xmlnode_get_child(packet, "temporary-auth-failure")) { + gaim_connection_error(js->gc, + _("Temporary Authentication Failure")); + } else { + gaim_connection_error(js->gc, _("Authentication Failure")); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/auth.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,34 @@ +/** + * @file auth.h Authentication routines + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_AUTH_H_ +#define _GAIM_JABBER_AUTH_H_ + +#include "jabber.h" +#include "xmlnode.h" + +void jabber_auth_start(JabberStream *js, xmlnode *packet); +void jabber_auth_start_old(JabberStream *js); +void jabber_auth_handle_challenge(JabberStream *js, xmlnode *packet); +void jabber_auth_handle_success(JabberStream *js, xmlnode *packet); +void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet); + +#endif /* _GAIM_JABBER_AUTH_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/buddy.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,845 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" +#include "debug.h" +#include "multi.h" +#include "notify.h" +#include "request.h" +#include "util.h" + +#include "buddy.h" +#include "chat.h" +#include "jabber.h" +#include "iq.h" +#include "presence.h" +#include "xmlnode.h" + + +JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name, + gboolean create) +{ + JabberBuddy *jb; + JabberID *jid = jabber_id_new(name); + char *realname; + + if(!jid) + return NULL; + + if(jid->node) + realname = g_strdup_printf("%s@%s", jid->node, jid->domain); + else + realname = g_strdup(jid->domain); + + jb = g_hash_table_lookup(js->buddies, realname); + + if(!jb && create) { + jb = g_new0(JabberBuddy, 1); + g_hash_table_insert(js->buddies, g_strdup(realname), jb); + } + g_free(realname); + + jabber_id_free(jid); + + return jb; +} + + +JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, + const char *resource) +{ + JabberBuddyResource *jbr = NULL; + GList *l; + + if(!jb) + return NULL; + + for(l = jb->resources; l; l = l->next) + { + if(!jbr && !resource) { + jbr = l->data; + } else if(!resource) { + if(((JabberBuddyResource *)l->data)->priority >= jbr->priority) + jbr = l->data; + } else if(((JabberBuddyResource *)l->data)->name) { + if(!strcmp(((JabberBuddyResource *)l->data)->name, resource)) { + jbr = l->data; + break; + } + } + } + + return jbr; +} + +void jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, + int priority, int state, const char *status) +{ + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); + + if(!jbr) { + jbr = g_new0(JabberBuddyResource, 1); + jbr->name = g_strdup(resource); + jbr->capabilities = JABBER_CAP_XHTML; + jb->resources = g_list_append(jb->resources, jbr); + } + jbr->priority = priority; + jbr->state = state; + if(jbr->status) + g_free(jbr->status); + jbr->status = g_strdup(status); +} + +void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource) +{ + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); + + if(!jbr) + return; + + jb->resources = g_list_remove(jb->resources, jbr); + + g_free(jbr->name); + if(jbr->status) + g_free(jbr->status); + g_free(jbr); +} + +const char *jabber_buddy_get_status_msg(JabberBuddy *jb) +{ + JabberBuddyResource *jbr; + + if(!jb) + return NULL; + + jbr = jabber_buddy_find_resource(jb, NULL); + + if(!jbr) + return NULL; + + return jbr->status; +} + +/******* + * This is the old vCard stuff taken from the old prpl. vCards, by definition + * are a temporary thing until jabber can get its act together and come up + * with a format for user information, hence the namespace of 'vcard-temp' + * + * Since I don't feel like putting that much work into something that's + * _supposed_ to go away, i'm going to just copy the kludgy old code here, + * and make it purdy when jabber comes up with a standards-track JEP to + * replace vcard-temp + * --Nathan + *******/ + +/*---------------------------------------*/ +/* Jabber "set info" (vCard) support */ +/*---------------------------------------*/ + +/* + * V-Card format: + * + * <vCard prodid='' version='' xmlns=''> + * <FN></FN> + * <N> + * <FAMILY/> + * <GIVEN/> + * </N> + * <NICKNAME/> + * <URL/> + * <ADR> + * <STREET/> + * <EXTADD/> + * <LOCALITY/> + * <REGION/> + * <PCODE/> + * <COUNTRY/> + * </ADR> + * <TEL/> + * <EMAIL/> + * <ORG> + * <ORGNAME/> + * <ORGUNIT/> + * </ORG> + * <TITLE/> + * <ROLE/> + * <DESC/> + * <BDAY/> + * </vCard> + * + * See also: + * + * http://docs.jabber.org/proto/html/vcard-temp.html + * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd + */ + +/* + * Cross-reference user-friendly V-Card entry labels to vCard XML tags + * and attributes. + * + * Order is (or should be) unimportant. For example: we have no way of + * knowing in what order real data will arrive. + * + * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag + * name, XML tag's parent tag "path" (relative to vCard node). + * + * List is terminated by a NULL label pointer. + * + * Entries with no label text, but with XML tag and parent tag + * entries, are used by V-Card XML construction routines to + * "automagically" construct the appropriate XML node tree. + * + * Thoughts on future direction/expansion + * + * This is a "simple" vCard. + * + * It is possible for nodes other than the "vCard" node to have + * attributes. Should that prove necessary/desirable, add an + * "attributes" pointer to the vcard_template struct, create the + * necessary tag_attr structs, and add 'em to the vcard_dflt_data + * array. + * + * The above changes will (obviously) require changes to the vCard + * construction routines. + */ + +struct vcard_template { + char *label; /* label text pointer */ + char *text; /* entry text pointer */ + int visible; /* should entry field be "visible?" */ + int editable; /* should entry field be editable? */ + char *tag; /* tag text */ + char *ptag; /* parent tag "path" text */ + char *url; /* vCard display format if URL */ +} vcard_template_data[] = { + {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, + {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, + {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, + {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, + {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, + {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, + {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, + {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, + {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, + {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, + {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, + {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, + {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, + {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, + {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, + {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, + {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, + {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, + {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, + {"", NULL, TRUE, TRUE, "N", NULL, NULL}, + {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, + {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, + {NULL, NULL, 0, 0, NULL, NULL, NULL} +}; + +/* + * The "vCard" tag's attibute list... + */ +struct tag_attr { + char *attr; + char *value; +} vcard_tag_attr_list[] = { + {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, + {"version", "2.0", }, + {"xmlns", "vcard-temp", }, + {NULL, NULL}, +}; + + +/* + * Insert a tag node into an xmlnode tree, recursively inserting parent tag + * nodes as necessary + * + * Returns pointer to inserted node + * + * Note to hackers: this code is designed to be re-entrant (it's recursive--it + * calls itself), so don't put any "static"s in here! + */ +static xmlnode *insert_tag_to_parent_tag(xmlnode *start, const char *parent_tag, const char *new_tag) +{ + xmlnode *x = NULL; + + /* + * If the parent tag wasn't specified, see if we can get it + * from the vCard template struct. + */ + if(parent_tag == NULL) { + struct vcard_template *vc_tp = vcard_template_data; + + while(vc_tp->label != NULL) { + if(strcmp(vc_tp->tag, new_tag) == 0) { + parent_tag = vc_tp->ptag; + break; + } + ++vc_tp; + } + } + + /* + * If we have a parent tag... + */ + if(parent_tag != NULL ) { + /* + * Try to get the parent node for a tag + */ + if((x = xmlnode_get_child(start, parent_tag)) == NULL) { + /* + * Descend? + */ + char *grand_parent = g_strdup(parent_tag); + char *parent; + + if((parent = strrchr(grand_parent, '/')) != NULL) { + *(parent++) = '\0'; + x = insert_tag_to_parent_tag(start, grand_parent, parent); + } else { + x = xmlnode_new_child(start, grand_parent); + } + g_free(grand_parent); + } else { + /* + * We found *something* to be the parent node. + * Note: may be the "root" node! + */ + xmlnode *y; + if((y = xmlnode_get_child(x, new_tag)) != NULL) { + return(y); + } + } + } + + /* + * insert the new tag into its parent node + */ + return(xmlnode_new_child((x == NULL? start : x), new_tag)); +} + +/* + * Send vCard info to Jabber server + */ +void jabber_set_info(GaimConnection *gc, const char *info) +{ + JabberIq *iq; + JabberStream *js = gc->proto_data; + xmlnode *vc_node; + + + /* + * Send only if there's actually any *information* to send + */ + vc_node = xmlnode_from_str(info, -1); + + if(vc_node) { + if (vc_node->name && + !g_ascii_strncasecmp(vc_node->name, "vcard", 5)) { + iq = jabber_iq_new(js, JABBER_IQ_SET); + xmlnode_insert_child(iq->node, vc_node); + jabber_iq_send(iq); + } else { + xmlnode_free(vc_node); + } + } +} + +/* + * This is the callback from the "ok clicked" for "set vCard" + * + * Formats GSList data into XML-encoded string and returns a pointer + * to said string. + * + * g_free()'ing the returned string space is the responsibility of + * the caller. + */ +static void +jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) +{ + GaimAccount *account; + xmlnode *vc_node; + GaimRequestField *field; + const char *text; + char *p; + const struct vcard_template *vc_tp; + struct tag_attr *tag_attr; + + vc_node = xmlnode_new("vCard"); + + for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) + xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value); + + for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { + if (*vc_tp->label == '\0') + continue; + + field = gaim_request_fields_get_field(fields, vc_tp->tag); + text = gaim_request_field_string_get_value(field); + + gaim_debug(GAIM_DEBUG_INFO, "jabber", + "Setting %s to '%s'\n", vc_tp->tag, text); + + if (text != NULL && *text != '\0') { + xmlnode *xp; + + if ((xp = insert_tag_to_parent_tag(vc_node, + NULL, vc_tp->tag)) != NULL) { + + xmlnode_insert_data(xp, text, -1); + } + } + } + + p = xmlnode_to_str(vc_node); + xmlnode_free(vc_node); + + account = gaim_connection_get_account(gc); + + if (account != NULL) { + gaim_account_set_user_info(account, p); + + if (gc != NULL) + serv_set_info(gc, p); + } + + g_free(p); +} + +/* + * This gets executed by the proto action + * + * Creates a new GaimRequestFields struct, gets the XML-formatted user_info + * string (if any) into GSLists for the (multi-entry) edit dialog and + * calls the set_vcard dialog. + */ +void jabber_setup_set_info(GaimConnection *gc) +{ + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + const struct vcard_template *vc_tp; + char *user_info; + char *cdata; + xmlnode *x_vc_data = NULL; + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(NULL); + gaim_request_fields_add_group(fields, group); + + /* + * Get existing, XML-formatted, user info + */ + if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) + x_vc_data = xmlnode_from_str(user_info, -1); + else + user_info = g_strdup(""); + + /* + * Set up GSLists for edit with labels from "template," data from user info + */ + for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { + xmlnode *data_node; + if((vc_tp->label)[0] == '\0') + continue; + if(vc_tp->ptag == NULL) { + data_node = xmlnode_get_child(x_vc_data, vc_tp->tag); + } else { + gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); + data_node = xmlnode_get_child(x_vc_data, tag); + g_free(tag); + } + if(data_node) + cdata = xmlnode_get_data(data_node); + else + cdata = NULL; + + if(strcmp(vc_tp->tag, "DESC") == 0) { + field = gaim_request_field_string_new(vc_tp->tag, + _(vc_tp->label), cdata, + TRUE); + } else { + field = gaim_request_field_string_new(vc_tp->tag, + _(vc_tp->label), cdata, + FALSE); + } + + gaim_request_field_group_add_field(group, field); + } + + if(x_vc_data != NULL) + xmlnode_free(x_vc_data); + + g_free(user_info); + + gaim_request_fields(gc, _("Edit Jabber vCard"), + _("Edit Jabber vCard"), + _("All items below are optional. Enter only the " + "information with which you feel comfortable."), + fields, + _("Save"), G_CALLBACK(jabber_format_info), + _("Cancel"), NULL, + gc); +} + +/*---------------------------------------*/ +/* End Jabber "set info" (vCard) support */ +/*---------------------------------------*/ + +/****** + * end of that ancient crap that needs to die + ******/ + + +static void jabber_vcard_parse(JabberStream *js, xmlnode *packet) +{ + GList *resources; + const char *from = xmlnode_get_attrib(packet, "from"); + JabberBuddy *jb; + JabberBuddyResource *jbr; + GString *info_text; + const char *resource_name; + char *title; + xmlnode *vcard; + + if(!from) + return; + + resource_name = jabber_get_resource(from); + + jb = jabber_buddy_find(js, from, TRUE); + info_text = g_string_new(""); + + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", _("Jabber ID"), + from); + + if(resource_name) { + jbr = jabber_buddy_find_resource(jb, resource_name); + if(jbr) { + char *purdy = strdup_withhtml(jbr->status); + g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/>\n", + _("Status"), jabber_get_state_string(jbr->state), + purdy ? ": " : "", + purdy ? purdy : ""); + g_free(purdy); + } else { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Status"), _("Unknown")); + } + } else { + for(resources = jb->resources; resources; resources = resources->next) { + char *purdy; + jbr = resources->data; + purdy = strdup_withhtml(jbr->status); + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Resource"), jbr->name); + g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/><br/>\n", + _("Status"), jabber_get_state_string(jbr->state), + purdy ? ": " : "", + purdy ? purdy : ""); + g_free(purdy); + } + } + + if((vcard = xmlnode_get_child(packet, "vCard"))) { + xmlnode *child; + for(child = vcard->child; child; child = child->next) + { + xmlnode *child2; + char *text; + + if(child->type != NODE_TYPE_TAG) + continue; + + text = xmlnode_get_data(child); + if(text && !strcmp(child->name, "FN")) { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Full Name"), text); + } else if(!strcmp(child->name, "N")) { + for(child2 = child->child; child2; child2 = child2->next) + { + char *text2; + + if(child2->type != NODE_TYPE_TAG) + continue; + + text2 = xmlnode_get_data(child2); + if(text2 && !strcmp(child2->name, "FAMILY")) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", + _("Family Name"), text2); + } else if(text2 && !strcmp(child2->name, "GIVEN")) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", + _("Given Name"), text2); + } else if(text2 && !strcmp(child2->name, "MIDDLE")) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", + _("Middle Name"), text2); + } + g_free(text2); + } + } else if(text && !strcmp(child->name, "NICKNAME")) { + serv_got_alias(js->gc, from, text); + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Nickname"), text); + } else if(text && !strcmp(child->name, "BDAY")) { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Birthday"), text); + } else if(!strcmp(child->name, "ADR")) { + /* show which address it is */ + if(child->child) + g_string_append_printf(info_text, "<b>%s:</b><br/>\n", + _("Address")); + for(child2 = child->child; child2; child2 = child2->next) + { + char *text2; + + if(child2->type != NODE_TYPE_TAG) + continue; + + text2 = xmlnode_get_data(child2); + if(text2 && !strcmp(child2->name, "POBOX")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("P.O. Box"), text2); + } else if(text2 && !strcmp(child2->name, "EXTADR")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Extended Address"), text2); + } else if(text2 && !strcmp(child2->name, "STREET")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Street Address"), text2); + } else if(text2 && !strcmp(child2->name, "LOCALITY")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Locality"), text2); + } else if(text2 && !strcmp(child2->name, "REGION")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Region"), text2); + } else if(text2 && !strcmp(child2->name, "PCODE")) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Postal Code"), text2); + } else if(text2 && (!strcmp(child2->name, "CTRY") + || !strcmp(child2->name, "COUNTRY"))) { + g_string_append_printf(info_text, + " <b>%s:</b> %s<br/>\n", + _("Country"), text2); + } + g_free(text2); + } + } else if(!strcmp(child->name, "TEL")) { + char *number; + if((child2 = xmlnode_get_child(child, "NUMBER"))) { + /* show what kind of number it is */ + number = xmlnode_get_data(child2); + if(number) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", _("Telephone"), number); + g_free(number); + } + } else if((number = xmlnode_get_data(child))) { + /* lots of clients (including gaim) do this, but it's + * out of spec */ + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", _("Telephone"), number); + g_free(number); + } + } else if(!strcmp(child->name, "EMAIL")) { + char *userid; + if((child2 = xmlnode_get_child(child, "USERID"))) { + /* show what kind of email it is */ + userid = xmlnode_get_data(child2); + if(userid) { + g_string_append_printf(info_text, + "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>\n", + _("Email"), userid, userid); + g_free(userid); + } + } else if((userid = xmlnode_get_data(child))) { + /* lots of clients (including gaim) do this, but it's + * out of spec */ + g_string_append_printf(info_text, + "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>\n", + _("Email"), userid, userid); + g_free(userid); + } + } else if(!strcmp(child->name, "ORG")) { + for(child2 = child->child; child2; child2 = child2->next) + { + char *text2; + + if(child2->type != NODE_TYPE_TAG) + continue; + + text2 = xmlnode_get_data(child2); + if(text2 && !strcmp(child2->name, "ORGNAME")) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", + _("Organization Name"), text2); + } else if(text2 && !strcmp(child2->name, "ORGUNIT")) { + g_string_append_printf(info_text, + "<b>%s:</b> %s<br/>\n", + _("Organization Unit"), text2); + } + g_free(text2); + } + } else if(text && !strcmp(child->name, "TITLE")) { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Title"), text); + } else if(text && !strcmp(child->name, "ROLE")) { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Role"), text); + } else if(text && !strcmp(child->name, "DESC")) { + g_string_append_printf(info_text, "<b>%s:</b> %s<br/>\n", + _("Description"), text); + } + g_free(text); + } + } + + title = g_strdup_printf("User info for %s", from); + + gaim_notify_formatted(NULL, title, _("Jabber Profile"), + NULL, info_text->str, NULL, NULL); + + g_free(title); + g_string_free(info_text, TRUE); +} + +void jabber_buddy_get_info(GaimConnection *gc, const char *who) +{ + JabberStream *js = gc->proto_data; + JabberIq *iq; + xmlnode *vcard; + + iq = jabber_iq_new(js, JABBER_IQ_GET); + + xmlnode_set_attrib(iq->node, "to", who); + vcard = xmlnode_new_child(iq->node, "vCard"); + xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); + + jabber_iq_set_callback(iq, jabber_vcard_parse); + + jabber_iq_send(iq); +} + +void jabber_buddy_get_info_chat(GaimConnection *gc, int id, + const char *resource) +{ + JabberStream *js = gc->proto_data; + JabberChat *chat = jabber_chat_find_by_id(js, id); + char *full_jid; + + if(!chat) + return; + + full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, resource); + jabber_buddy_get_info(gc, full_jid); + g_free(full_jid); +} + +static void jabber_buddy_set_invisibility(JabberStream *js, const char *who, + gboolean invisible) +{ + JabberBuddy *jb = jabber_buddy_find(js, who, TRUE); + xmlnode *presence; + + presence = jabber_presence_create(js->gc->away_state, js->gc->away); + xmlnode_set_attrib(presence, "to", who); + if(invisible) { + xmlnode_set_attrib(presence, "type", "invisible"); + jb->invisible |= JABBER_INVIS_BUDDY; + } else { + jb->invisible &= ~JABBER_INVIS_BUDDY; + } + + jabber_send(js, presence); + xmlnode_free(presence); +} + +static void jabber_buddy_make_invisible(GaimConnection *gc, const char *name) +{ + JabberStream *js = gc->proto_data; + jabber_buddy_set_invisibility(js, name, TRUE); +} + +static void jabber_buddy_make_visible(GaimConnection *gc, const char *name) +{ + JabberStream *js = gc->proto_data; + jabber_buddy_set_invisibility(js, name, FALSE); +} + +static void jabber_buddy_cancel_presence_notification(GaimConnection *gc, + const char *name) +{ + JabberStream *js = gc->proto_data; + + /* I wonder if we should prompt the user before doing this */ + jabber_presence_subscription_set(js, name, "unsubscribed"); +} + +static void jabber_buddy_rerequest_auth(GaimConnection *gc, const char *name) +{ + JabberStream *js = gc->proto_data; + + jabber_presence_subscription_set(js, name, "subscribe"); +} + +GList *jabber_buddy_menu(GaimConnection *gc, const char *name) +{ + GList *m = NULL; + struct proto_buddy_menu *pbm; + JabberStream *js = gc->proto_data; + JabberBuddy *jb = jabber_buddy_find(js, name, TRUE); + + pbm = g_new0(struct proto_buddy_menu, 1); + if(jb->invisible & JABBER_INVIS_BUDDY) { + pbm->label = _("Un-hide From"); + pbm->callback = jabber_buddy_make_visible; + } else { + pbm->label = _("Temporarily Hide From"); + pbm->callback = jabber_buddy_make_invisible; + } + pbm->gc = gc; + m = g_list_append(m, pbm); + + if(jb->subscription & JABBER_SUB_FROM) { + pbm = g_new0(struct proto_buddy_menu, 1); + pbm->label = _("Cancel Presence Notification"); + pbm->callback = jabber_buddy_cancel_presence_notification; + pbm->gc = gc; + m = g_list_append(m, pbm); + } + + if(!(jb->subscription & JABBER_SUB_TO)) { + pbm = g_new0(struct proto_buddy_menu, 1); + pbm->label = _("Re-request authorization"); + pbm->callback = jabber_buddy_rerequest_auth; + pbm->gc = gc; + m = g_list_append(m, pbm); + } + + return m; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/buddy.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,72 @@ +/** + * @file buddy.h Buddy handlers + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_BUDDY_H_ +#define _GAIM_JABBER_BUDDY_H_ + +#include "jabber.h" + +typedef struct _JabberBuddyResource { + char *name; + int priority; + int state; + char *status; + enum { + JABBER_CAP_XHTML = 1 << 1, + JABBER_CAP_COMPOSING = 1 << 2 + } capabilities; +} JabberBuddyResource; + +typedef struct _JabberBuddy { + GList *resources; + char *error_msg; + enum { + JABBER_INVISIBLE_NONE = 0, + JABBER_INVISIBLE_SERVER = 1 << 1, + JABBER_INVIS_BUDDY = 1 << 2 + } invisible; + enum { + JABBER_SUB_NONE = 0, + JABBER_SUB_PENDING = 1 << 1, + JABBER_SUB_TO = 1 << 2, + JABBER_SUB_FROM = 1 << 3, + JABBER_SUB_BOTH = (JABBER_SUB_TO | JABBER_SUB_FROM) + } subscription; +} JabberBuddy; + +JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name, + gboolean create); +JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, + const char *resource); +void jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, + int priority, int state, const char *status); +void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource); +const char *jabber_buddy_get_status_msg(JabberBuddy *jb); +void jabber_buddy_get_info(GaimConnection *gc, const char *who); +void jabber_buddy_get_info_chat(GaimConnection *gc, int id, + const char *resource); + +GList *jabber_buddy_menu(GaimConnection *gc, const char *name); + +void jabber_set_info(GaimConnection *gc, const char *info); +void jabber_setup_set_info(GaimConnection *gc); + +#endif /* _GAIM_JABBER_BUDDY_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/chat.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,249 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" +#include "debug.h" +#include "multi.h" /* for proto_chat_entry */ + +#include "chat.h" +#include "message.h" + +GList *jabber_chat_info(GaimConnection *gc) +{ + GList *m = NULL; + struct proto_chat_entry *pce; + JabberStream *js = gc->proto_data; + + pce = g_new0(struct proto_chat_entry, 1); + pce->label = _("Room:"); + pce->identifier = "room"; + m = g_list_append(m, pce); + + /* we're gonna default to a conference server I know is true, until + * I can figure out how to disco for a chat server */ + pce = g_new0(struct proto_chat_entry, 1); + pce->label = _("Server:"); + pce->identifier = "server"; + pce->def = "conference.jabber.org"; + m = g_list_append(m, pce); + + pce = g_new0(struct proto_chat_entry, 1); + pce->label = _("Handle:"); + pce->identifier = "handle"; + pce->def = js->user->node; + m = g_list_append(m, pce); + + pce = g_new0(struct proto_chat_entry, 1); + pce->label = _("Password:"); + pce->identifier = "password"; + pce->secret = TRUE; + m = g_list_append(m, pce); + + return m; +} + +JabberChat *jabber_chat_find(JabberStream *js, const char *room, + const char *server) +{ + JabberChat *chat; + char *room_jid; + + room_jid = g_strdup_printf("%s@%s", room, server); + + chat = g_hash_table_lookup(js->chats, room_jid); + g_free(room_jid); + + return chat; +} + +struct _find_by_id_data { + int id; + JabberChat *chat; +}; + +void find_by_id_foreach_cb(gpointer key, gpointer value, gpointer user_data) +{ + JabberChat *chat = value; + struct _find_by_id_data *fbid = user_data; + + if(chat->id == fbid->id) + fbid->chat = chat; +} + +JabberChat *jabber_chat_find_by_id(JabberStream *js, int id) +{ + JabberChat *chat; + struct _find_by_id_data *fbid = g_new0(struct _find_by_id_data, 1); + g_hash_table_foreach(js->chats, find_by_id_foreach_cb, fbid); + chat = fbid->chat; + g_free(fbid); + return chat; +} + +void jabber_chat_invite(GaimConnection *gc, int id, const char *msg, + const char *name) +{ + JabberStream *js = gc->proto_data; + JabberChat *chat; + xmlnode *message, *body, *x, *invite; + char *room_jid; + + chat = jabber_chat_find_by_id(js, id); + if(!chat) + return; + + message = xmlnode_new("message"); + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + + if(chat->muc) { + xmlnode_set_attrib(message, "to", room_jid); + x = xmlnode_new_child(message, "x"); + xmlnode_set_attrib(x, "xmlns", "http://jabber.org/protocol/muc#user"); + invite = xmlnode_new_child(x, "invite"); + xmlnode_set_attrib(invite, "to", name); + body = xmlnode_new_child(invite, "reason"); + xmlnode_insert_data(body, msg, -1); + } else { + xmlnode_set_attrib(message, "to", name); + body = xmlnode_new_child(message, "body"); + xmlnode_insert_data(body, msg, -1); + x = xmlnode_new_child(message, "x"); + xmlnode_set_attrib(x, "jid", room_jid); + xmlnode_set_attrib(x, "xmlns", "jabber:x:conference"); + } + + jabber_send(js, message); + xmlnode_free(message); + g_free(room_jid); +} + +void jabber_chat_whisper(GaimConnection *gc, int id, const char *who, + const char *message) +{ + JabberStream *js = gc->proto_data; + JabberChat *chat; + char *full_jid; + + chat = jabber_chat_find_by_id(js, id); + + /* TODO: we get real Jabber IDs from MUC sometimes, we need to cache + * them eventually */ + full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, who); + + jabber_message_send_im(gc, full_jid, message, 0); + + g_free(full_jid); +} + +void jabber_chat_join(GaimConnection *gc, GHashTable *data) +{ + JabberChat *chat; + char *room, *server, *handle, *passwd; + xmlnode *presence, *x; + char *room_jid, *full_jid; + JabberStream *js = gc->proto_data; + + room = g_hash_table_lookup(data, "room"); + server = g_hash_table_lookup(data, "server"); + handle = g_hash_table_lookup(data, "handle"); + passwd = g_hash_table_lookup(data, "password"); + + if(!room || !server || !handle) + return; + + if(jabber_chat_find(js, room, server)) + return; + + room_jid = g_strdup_printf("%s@%s", room, server); + + chat = g_new0(JabberChat, 1); + chat->js = gc->proto_data; + + chat->room = g_strdup(room); + chat->server = g_strdup(server); + chat->nick = g_strdup(handle); + + g_hash_table_insert(js->chats, room_jid, chat); + + presence = xmlnode_new("presence"); + full_jid = g_strdup_printf("%s/%s", room_jid, handle); + xmlnode_set_attrib(presence, "to", full_jid); + g_free(full_jid); + + x = xmlnode_new_child(presence, "x"); + xmlnode_set_attrib(x, "xmlns", "http://jabber.org/protocol/muc"); + + if(passwd && *passwd) { + xmlnode *password = xmlnode_new_child(x, "password"); + xmlnode_insert_data(password, passwd, -1); + } + + jabber_send(js, presence); + xmlnode_free(presence); +} + +void jabber_chat_leave(GaimConnection *gc, int id) +{ + JabberStream *js = gc->proto_data; + JabberChat *chat = jabber_chat_find_by_id(js, id); + char *room_jid; + xmlnode *presence; + + if(!chat) + return; + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + gaim_debug(GAIM_DEBUG_INFO, "jabber", "%s is leaving chat %s\n", + chat->nick, room_jid); + presence = xmlnode_new("presence"); + xmlnode_set_attrib(presence, "to", room_jid); + xmlnode_set_attrib(presence, "type", "unavailable"); + jabber_send(js, presence); + xmlnode_free(presence); +} + +void jabber_chat_destroy(JabberChat *chat) +{ + JabberStream *js = chat->js; + char *room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + + g_hash_table_remove(js->chats, room_jid); + g_free(room_jid); + + g_free(chat->room); + g_free(chat->server); + g_free(chat->nick); + g_free(chat); +} + +gboolean jabber_chat_find_buddy(GaimConversation *conv, const char *name) +{ + GList *m = gaim_chat_get_users(GAIM_CHAT(conv)); + + while(m) { + if(!strcmp(m->data, name)) + return TRUE; + m = m->next; + } + + return FALSE; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/chat.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,55 @@ +/** + * @file chat.h Chat stuff + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_CHAT_H_ +#define _GAIM_JABBER_CHAT_H_ + +#include "internal.h" +#include "connection.h" +#include "conversation.h" + +#include "jabber.h" + + +typedef struct _JabberChat { + JabberStream *js; + char *room; + char *server; + char *nick; + int id; + GaimConversation *conv; + gboolean muc; +} JabberChat; + +GList *jabber_chat_info(GaimConnection *gc); +void jabber_chat_join(GaimConnection *gc, GHashTable *data); +JabberChat *jabber_chat_find(JabberStream *js, const char *room, + const char *server); +JabberChat *jabber_chat_find_by_id(JabberStream *js, int id); +void jabber_chat_destroy(JabberChat *chat); +gboolean jabber_chat_find_buddy(GaimConversation *conv, const char *name); +void jabber_chat_whisper(GaimConnection *gc, int id, const char *who, + const char *message); +void jabber_chat_invite(GaimConnection *gc, int id, const char *message, + const char *name); +void jabber_chat_leave(GaimConnection *gc, int id); + +#endif /* _GAIM_JABBER_CHAT_H_ */
--- a/src/protocols/jabber/expat.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -void expat_startElement(void* userdata, const char* name, const char** atts) -{ - /* get the xmlnode pointed to by the userdata */ - xmlnode *x = userdata; - xmlnode current = *x; - - if (current == NULL) - { - /* allocate a base node */ - current = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(current, atts); - *x = current; - } - else - { - *x = xmlnode_insert_tag(current, name); - xmlnode_put_expat_attribs(*x, atts); - } -} - -void expat_endElement(void* userdata, const char* name) -{ - xmlnode *x = userdata; - xmlnode current = *x; - - current->complete = 1; - current = xmlnode_get_parent(current); - - /* if it's NULL we've hit the top folks, otherwise back up a level */ - if(current != NULL) - *x = current; -} - -void expat_charData(void* userdata, const char* s, int len) -{ - xmlnode *x = userdata; - xmlnode current = *x; - - xmlnode_insert_cdata(current, s, len); -} - - -xmlnode xmlnode_str(char *str, int len) -{ - XML_Parser p; - xmlnode *x, node; /* pointer to an xmlnode */ - - if(NULL == str) - return NULL; - - x = malloc(sizeof(void *)); - - *x = NULL; /* pointer to NULL */ - p = XML_ParserCreate(NULL); - XML_SetUserData(p, x); - XML_SetElementHandler(p, expat_startElement, expat_endElement); - XML_SetCharacterDataHandler(p, expat_charData); - if(!XML_Parse(p, str, len, 1)) - { - /* jdebug(ZONE,"xmlnode_str_error: %s",(char *)XML_ErrorString(XML_GetErrorCode(p)));*/ - xmlnode_free(*x); - *x = NULL; - } - node = *x; - free(x); - XML_ParserFree(p); - return node; /* return the xmlnode x points to */ -} - -xmlnode xmlnode_file(char *file) -{ - XML_Parser p; - xmlnode *x, node; /* pointer to an xmlnode */ - char buf[BUFSIZ]; - int done, fd, len; - - if(NULL == file) - return NULL; - - fd = open(file,O_RDONLY); - if(fd < 0) - return NULL; - - x = malloc(sizeof(void *)); - - *x = NULL; /* pointer to NULL */ - p = XML_ParserCreate(NULL); - XML_SetUserData(p, x); - XML_SetElementHandler(p, expat_startElement, expat_endElement); - XML_SetCharacterDataHandler(p, expat_charData); - do{ - len = read(fd, buf, BUFSIZ); - done = len < BUFSIZ; - if(!XML_Parse(p, buf, len, done)) - { - /* jdebug(ZONE,"xmlnode_file_parseerror: %s",(char *)XML_ErrorString(XML_GetErrorCode(p)));*/ - xmlnode_free(*x); - *x = NULL; - done = 1; - } - }while(!done); - - node = *x; - XML_ParserFree(p); - free(x); - close(fd); - return node; /* return the xmlnode x points to */ -} - -char* xmlnode_file_borked(char *file) -{ - XML_Parser p; - char buf[BUFSIZ]; - static char err[1024]; - int fd, len, done; - - if(NULL == file) - return "no file specified"; - - fd = open(file,O_RDONLY); - if(fd < 0) - return "unable to open file"; - - p = XML_ParserCreate(NULL); - while(1) - { - len = read(fd, buf, BUFSIZ); - done = len < BUFSIZ; - if(!XML_Parse(p, buf, len, done)) - { - snprintf(err,1023,"%s at line %d and column %d",XML_ErrorString(XML_GetErrorCode(p)),XML_GetErrorLineNumber(p),XML_GetErrorColumnNumber(p)); - XML_ParserFree(p); - close(fd); - return err; - } - } -} - -int xmlnode2file(char *file, xmlnode node) -{ - char *doc, *ftmp; - int fd, i; - - if(file == NULL || node == NULL) - return -1; - - ftmp = spools(xmlnode_pool(node),file,".t.m.p",xmlnode_pool(node)); - fd = open(ftmp, O_CREAT | O_WRONLY | O_TRUNC, 0600); - if(fd < 0) - return -1; - - doc = xmlnode2str(node); - i = write(fd,doc,strlen(doc)); - if(i < 0) - return -1; - - close(fd); - - if(rename(ftmp,file) < 0) - { - unlink(ftmp); - return -1; - } - return 1; -} - -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts) -{ - int i = 0; - if (atts == NULL) return; - while (atts[i] != '\0') - { - xmlnode_put_attrib(owner, atts[i], atts[i+1]); - i += 2; - } -}
--- a/src/protocols/jabber/genhash.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -/*** stubs that hook back to new xhash */ - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp) -{ - return xhash_new(buckets); -} - -HASHTABLE ghash_create_pool(pool p, int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp) -{ - xht h = xhash_new(buckets); - pool_cleanup(p, (pool_cleaner)xhash_free, h); - return h; -} - -void ghash_destroy(HASHTABLE tbl) -{ - xhash_free(tbl); -} - -void *ghash_get(HASHTABLE tbl, const void *key) -{ - return xhash_get(tbl, key); -} - -int ghash_put(HASHTABLE tbl, const void *key, void *value) -{ - xhash_put(tbl, key, value); - return 1; -} - -int ghash_remove(HASHTABLE tbl, const void *key) -{ - xhash_zap(tbl, key); - return 1; -} - - -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data) -{ - int i; - xhn n; - xht h = (xht)tbl; - - for(i = 0; i < h->prime; i++) - for(n = &h->zen[i]; n != NULL; n = n->next) - if(n->key != NULL && n->val != NULL) - (*func)(user_data, n->key, n->val); - - return 1; -} - - -int _xhasher(const char *key); -int str_hash_code(const char *s) -{ - return _xhasher(s); -} -
--- a/src/protocols/jabber/hashtable.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -csompliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" - -#ifdef XML_UNICODE_WCHAR_T -#ifndef XML_UNICODE -#define XML_UNICODE -#endif -#endif - -#include "hashtable.h" - -#define INIT_SIZE 64 - -static -int keyeq(KEY s1, KEY s2) -{ - for (; *s1 == *s2; s1++, s2++) - if (*s1 == 0) - return 1; - return 0; -} - -static -unsigned long hash(KEY s) -{ - unsigned long h = 0; - while (*s) - h = (h << 5) + h + (unsigned char)*s++; - return h; -} - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) -{ - size_t i; - if (table->size == 0) { - if (!createSize) - return 0; - table->v = calloc(INIT_SIZE, sizeof(NAMED *)); - if (!table->v) - return 0; - table->size = INIT_SIZE; - table->usedLim = INIT_SIZE / 2; - i = hash(name) & (table->size - 1); - } - else { - unsigned long h = hash(name); - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) { - if (keyeq(name, table->v[i]->name)) - return table->v[i]; - } - if (!createSize) - return 0; - if (table->used == table->usedLim) { - /* check for overflow */ - size_t newSize = table->size * 2; - NAMED **newV = calloc(newSize, sizeof(NAMED *)); - if (!newV) - return 0; - for (i = 0; i < table->size; i++) - if (table->v[i]) { - size_t j; - for (j = hash(table->v[i]->name) & (newSize - 1); - newV[j]; - j == 0 ? j = newSize - 1 : --j) - ; - newV[j] = table->v[i]; - } - free(table->v); - table->v = newV; - table->size = newSize; - table->usedLim = newSize/2; - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) - ; - } - } - table->v[i] = calloc(1, createSize); - if (!table->v[i]) - return 0; - table->v[i]->name = name; - (table->used)++; - return table->v[i]; -} - -void hashTableDestroy(HASH_TABLE *table) -{ - size_t i; - for (i = 0; i < table->size; i++) { - NAMED *p = table->v[i]; - if (p) - free(p); - } - free(table->v); -} - -void hashTableInit(HASH_TABLE *p) -{ - p->size = 0; - p->usedLim = 0; - p->used = 0; - p->v = 0; -} - -void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) -{ - iter->p = table->v; - iter->end = iter->p + table->size; -} - -NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) -{ - while (iter->p != iter->end) { - NAMED *tem = *(iter->p)++; - if (tem) - return tem; - } - return 0; -} -
--- a/src/protocols/jabber/hashtable.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -#include <stddef.h> - -#ifdef XML_UNICODE - -#ifdef XML_UNICODE_WCHAR_T -typedef const wchar_t *KEY; -#else /* not XML_UNICODE_WCHAR_T */ -typedef const unsigned short *KEY; -#endif /* not XML_UNICODE_WCHAR_T */ - -#else /* not XML_UNICODE */ - -typedef const char *KEY; - -#endif /* not XML_UNICODE */ - -typedef struct { - KEY name; -} NAMED; - -typedef struct { - NAMED **v; - size_t size; - size_t used; - size_t usedLim; -} HASH_TABLE; - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize); -void hashTableInit(HASH_TABLE *); -void hashTableDestroy(HASH_TABLE *); - -typedef struct { - NAMED **p; - NAMED **end; -} HASH_TABLE_ITER; - -void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); -NAMED *hashTableIterNext(HASH_TABLE_ITER *);
--- a/src/protocols/jabber/iasciitab.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/iq.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,231 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" +#include "debug.h" +#include "prefs.h" + +#include "iq.h" +#include "roster.h" + + +JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type) +{ + JabberIq *iq; + + iq = g_new0(JabberIq, 1); + + iq->type = type; + + iq->node = xmlnode_new("iq"); + switch(iq->type) { + case JABBER_IQ_SET: + xmlnode_set_attrib(iq->node, "type", "set"); + break; + case JABBER_IQ_GET: + xmlnode_set_attrib(iq->node, "type", "get"); + break; + case JABBER_IQ_ERROR: + xmlnode_set_attrib(iq->node, "type", "error"); + break; + case JABBER_IQ_RESULT: + xmlnode_set_attrib(iq->node, "type", "result"); + break; + case JABBER_IQ_NONE: + /* this shouldn't ever happen */ + break; + } + + iq->js = js; + + if(type == JABBER_IQ_GET || type == JABBER_IQ_SET) { + iq->id = jabber_get_next_id(js); + xmlnode_set_attrib(iq->node, "id", iq->id); + } + + return iq; +} + +JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type, + const char *xmlns) +{ + JabberIq *iq = jabber_iq_new(js, type); + xmlnode *query; + + query = xmlnode_new_child(iq->node, "query"); + xmlnode_set_attrib(query, "xmlns", xmlns); + + return iq; +} + +void jabber_iq_set_callback(JabberIq *iq, JabberCallback *callback) +{ + iq->callback = callback; +} + +void jabber_iq_set_id(JabberIq *iq, const char *id) +{ + if(iq->id) + g_free(iq->id); + + if(id) { + xmlnode_set_attrib(iq->node, "id", id); + iq->id = g_strdup(id); + } else { + xmlnode_remove_attrib(iq->node, "id"); + iq->id = NULL; + } +} + +void jabber_iq_send(JabberIq *iq) +{ + g_return_if_fail(iq != NULL); + + jabber_send(iq->js, iq->node); + + if(iq->id && iq->callback) + g_hash_table_insert(iq->js->callbacks, g_strdup(iq->id), iq->callback); + + jabber_iq_free(iq); +} + +void jabber_iq_free(JabberIq *iq) +{ + g_return_if_fail(iq != NULL); + + g_free(iq->id); + xmlnode_free(iq->node); + g_free(iq); +} + +static void jabber_iq_handle_last(JabberStream *js, xmlnode *packet) +{ + JabberIq *iq; + const char *from; + const char *id; + xmlnode *query; + char *idle_time; + + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + + iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); + jabber_iq_set_id(iq, id); + xmlnode_set_attrib(iq->node, "to", from); + + query = xmlnode_get_child(iq->node, "query"); + + idle_time = g_strdup_printf("%ld", js->idle ? time(NULL) - js->idle : 0); + xmlnode_set_attrib(query, "seconds", idle_time); + g_free(idle_time); +} + +static void jabber_iq_handle_time(JabberStream *js, xmlnode *packet) +{ + const char *from, *id; + JabberIq *iq; + char buf[1024]; + xmlnode *query; + time_t now_t; + struct tm now; + time(&now_t); + localtime_r(&now_t, &now); + + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + + iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:time"); + jabber_iq_set_id(iq, id); + xmlnode_set_attrib(iq->node, "to", from); + + query = xmlnode_get_child(iq->node, "query"); + + strftime(buf, sizeof(buf), "%Y%m%dT%T", &now); + xmlnode_insert_data(xmlnode_new_child(query, "utc"), buf, -1); + strftime(buf, sizeof(buf), "%Z", &now); + xmlnode_insert_data(xmlnode_new_child(query, "tz"), buf, -1); + strftime(buf, sizeof(buf), "%d %b %Y %T", &now); + xmlnode_insert_data(xmlnode_new_child(query, "display"), buf, -1); + + jabber_iq_send(iq); +} + +static void jabber_iq_handle_version(JabberStream *js, xmlnode *packet) +{ + JabberIq *iq; + const char *from, *id; + xmlnode *query; + char *os = NULL; + + if(!gaim_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { + struct utsname osinfo; + + uname(&osinfo); + os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, + osinfo.machine); + } + + from = xmlnode_get_attrib(packet, "from"); + id = xmlnode_get_attrib(packet, "id"); + + iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); + xmlnode_set_attrib(iq->node, "to", from); + jabber_iq_set_id(iq, id); + + query = xmlnode_get_child(iq->node, "query"); + + xmlnode_insert_data(xmlnode_new_child(query, "name"), PACKAGE, -1); + xmlnode_insert_data(xmlnode_new_child(query, "version"), VERSION, -1); + if(os) { + xmlnode_insert_data(xmlnode_new_child(query, "os"), os, -1); + g_free(os); + } + + jabber_iq_send(iq); +} + +void jabber_iq_parse(JabberStream *js, xmlnode *packet) +{ + xmlnode *query; + const char *xmlns; + + query = xmlnode_get_child(packet, "query"); + + if(!query) + return; + + xmlns = xmlnode_get_attrib(query, "xmlns"); + + if(!xmlns) + return; + + if(!strcmp(xmlns, "jabber:iq:roster")) { + jabber_roster_parse(js, packet); + } else if(!strcmp(xmlns, "jabber:iq:last")) { + jabber_iq_handle_last(js, packet); + } else if(!strcmp(xmlns, "jabber:iq:time")) { + jabber_iq_handle_time(js, packet); + } else if(!strcmp(xmlns, "jabber:iq:version")) { + jabber_iq_handle_version(js, packet); + } else { + gaim_debug(GAIM_DEBUG_WARNING, "jabber", "Unknown query: %s\n", xmlns); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/iq.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,58 @@ +/** + * @file iq.h JabberID handlers + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_IQ_H_ +#define _GAIM_JABBER_IQ_H_ + +#include "jabber.h" + +typedef struct _JabberIq JabberIq; + +typedef enum { + JABBER_IQ_SET, + JABBER_IQ_GET, + JABBER_IQ_RESULT, + JABBER_IQ_ERROR, + JABBER_IQ_NONE +} JabberIqType; + +struct _JabberIq { + JabberIqType type; + char *id; + xmlnode *node; + + JabberCallback *callback; + + JabberStream *js; +}; + +JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type); +JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type, + const char *xmlns); + +void jabber_iq_parse(JabberStream *js, xmlnode *packet); + +void jabber_iq_set_callback(JabberIq *iq, JabberCallback *cb); + +void jabber_iq_send(JabberIq *iq); +void jabber_iq_free(JabberIq *iq); + +#endif /* _GAIM_JABBER_IQ_H_ */
--- a/src/protocols/jabber/jabber.c Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/jabber.c Mon Sep 29 15:23:19 2003 +0000 @@ -1,14 +1,13 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * gaim + * gaim - Jabber Protocol Plugin * - * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> - * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx> + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -21,2932 +20,430 @@ */ #include "internal.h" -#ifdef _WIN32 -# include "utsname.h" -#endif - -#include "account.h" -#include "accountopt.h" +/* #include "conversation.h" -#include "debug.h" #include "ft.h" #include "multi.h" #include "notify.h" -#include "prpl.h" +#include "proxy.h" #include "request.h" #include "util.h" -#include "html.h" -#include "sslconn.h" + +*/ -/* XXX */ -#include "gaim.h" +#include "account.h" +#include "accountopt.h" +#include "debug.h" +#include "html.h" +#include "message.h" +#include "multi.h" +#include "prpl.h" +#include "server.h" -#ifdef MAX -# undef MAX -#endif -#ifdef MIN -# undef MIN -#endif +#include "auth.h" +#include "buddy.h" +#include "chat.h" +#include "iq.h" +#include "jutil.h" +#include "message.h" +#include "parser.h" +#include "presence.h" +#include "jabber.h" +#include "roster.h" -#include "jabber.h" -#include "proxy.h" +#define JABBER_CONNECT_STEPS (js->gsc ? 8 : 5) static GaimPlugin *my_protocol = NULL; -/* The priv member of gjconn's is a gaim_connection for now. */ -#define GJ_GC(x) ((GaimConnection *)(x)->priv) -/* Confused? That makes three of us. -Robot101 */ -#define GC_GJ(x) ((gjconn)((struct jabber_data *)(x)->proto_data)->gjc) - -#define JABBER_CONNECT_STEPS 5 - -#define IQID_AUTH "__AUTH__" - -#define IQ_NONE -1 -#define IQ_AUTH 0 -#define IQ_ROSTER 1 - -#define UC_AWAY (0x02 | UC_UNAVAILABLE) -#define UC_CHAT 0x04 -#define UC_XA (0x08 | UC_UNAVAILABLE) -#define UC_DND (0x10 | UC_UNAVAILABLE) -#define UC_ERROR (0x20 | UC_UNAVAILABLE) - -#define DEFAULT_SERVER "jabber.org" -#define DEFAULT_GROUPCHAT "conference.jabber.org" -#define DEFAULT_PORT 5222 - -#define USEROPT_PORT 0 -#define USEROPT_CONN_SERVER 1 - -#define JABBER_TYPING_NOTIFY_INT 15 /* Delay (in seconds) between sending typing notifications */ - -#define JABBER_KEEPALIVE_STRING " \t " - -/* - * Note: "was_connected" may seem redundant, but it was needed and I - * didn't want to touch the Jabber state stuff not specific to Gaim. - */ -typedef struct gjconn_struct { - /* Core structure */ - pool p; /* Memory allocation pool */ - int state; /* Connection state flag */ - int was_connected; /* We were once connected */ - int fd; /* Connection file descriptor */ - jid user; /* User info */ - char *pass; /* User passwd */ - - /* Stream stuff */ - int id; /* id counter for jab_getid() function */ - char idbuf[9]; /* temporary storage for jab_getid() */ - char *sid; /* stream id from server, for digest auth */ - XML_Parser parser; /* Parser instance */ - xmlnode current; /* Current node in parsing instance.. */ - - /* Event callback ptrs */ - void (*on_state)(struct gjconn_struct *gjc, int state); - void (*on_packet)(struct gjconn_struct *gjc, jpacket p); - - GHashTable *queries; /* query tracker */ - - void *priv; - - GaimSslConnection *gsc; - -} *gjconn, gjconn_struct; - -typedef void (*gjconn_state_h)(gjconn gjc, int state); -typedef void (*gjconn_packet_h)(gjconn gjc, jpacket p); - -static gjconn gjab_new(char *user, char *pass, void *priv); -static void gjab_delete(gjconn gjc); -static void gjab_state_handler(gjconn gjc, gjconn_state_h h); -static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h); -static void gjab_start(gjconn gjc); -static void gjab_stop(gjconn gjc); -/* -static int gjab_getfd(gjconn gjc); -static jid gjab_getjid(gjconn gjc); -static char *gjab_getsid(gjconn gjc); -*/ -static char *gjab_getid(gjconn gjc); -static void gjab_send(gjconn gjc, xmlnode x); -static void gjab_send_raw(gjconn gjc, const char *str); -static void gjab_recv(gjconn gjc); -static void gjab_auth(gjconn gjc); - -/* - * It is *this* to which we point the gaim_connection proto_data - */ -struct jabber_data { - gjconn gjc; - gboolean did_import; - GSList *chats; - time_t idle; - GHashTable *buddies; - GSList *file_transfers; -}; - -/* - * Used in jabber_buddy_data.invisible, below - */ -#define JABBER_NOT_INVIS 0x00 -#define JABBER_SERV_INVIS 0x01 /* Invisible set on server */ -#define JABBER_BUD_INVIS 0x02 /* Invisible set on buddy */ +static void jabber_stream_init(JabberStream *js) +{ + char *open_stream; -/* - * Used in jabber_buddy_data.subscription, below - */ -#define JABBER_SUB_NONE 0x0 -#define JABBER_SUB_PENDING 0x1 -#define JABBER_SUB_TO 0x2 -#define JABBER_SUB_FROM 0x4 -#define JABBER_SUB_BOTH (JABBER_SUB_TO | JABBER_SUB_FROM) - - -/* - * It is *this* to which we point the buddy proto_data - */ -struct jabber_buddy_data { - GSList *resources; - char *error_msg; - unsigned invisible; /* We've set presence type invisible for this buddy */ - unsigned subscription; /* subscription type for this buddy */ -}; - -/* - * per-resource info - */ -typedef struct jabber_resource_info { - char *name; - int priority; - int state; - char *away_msg; - char *thread_id; - gboolean has_composing; - gboolean has_xhtml; -} *jab_res_info; + open_stream = g_strdup_printf("<stream:stream to='%s' " + "xmlns='jabber:client' " + "xmlns:stream='http://etherx.jabber.org/streams' " + "version='1.0'>", js->user->domain); -/* - * For our own jid handling - * - * We do our own so we can cleanly parse buddy names - * (user@server/resource) and rid ourselves of the - * struct when we're done with it. The Jabber lib - * structs last the life of the pool--we frequently - * don't want that. - * - * We use the real jid structs so we can make use of - * jid_safe(), jid_cmp() and some others. - * - * BE CAREFUL using the Jabber lib routines. - * Many of them assume pool use and are not - * amenable to use with our own! - * - * We give them special names so we know, throughout - * the code, that they're not alloc'd out of pool - * memory and we can, and must, dispose of them when - * we're done with 'em. - */ -#define gaim_jid_struct jid_struct -typedef struct gaim_jid_struct *gaim_jid; - -/* - * Jabber "chat group" info. Pointers to these go in jabber_data - * pending and existing chats lists. - */ -struct jabber_chat { - gaim_jid gjid; - GaimConnection *gc; - GaimConversation *b; - int id; - int state; -}; + jabber_send_raw(js, open_stream); -/* - * Jabber chat states... - * - * Note: due to a bug in one version of the Jabber server, subscriptions - * to chat groups aren't (always?) properly removed at the server. The - * result is clients receive Jabber "presence" notifications for JIDs - * they no longer care about. The problem with such vestigial notifies is - * that we really have no way of telling if it's vestigial or if it's a - * valid "buddy" presence notification. So we keep jabber_chat structs - * around after leaving a chat group and simply mark them "closed." That - * way we can test for such errant presence notifications. I.e.: if we - * get a presence notfication from a JID that matches a chat group JID, - * we disregard it. - */ -#define JCS_PENDING 1 /* pending */ -#define JCS_ACTIVE 2 /* active */ -#define JCS_CLOSED 3 /* closed */ - - -#define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); } - -static void jabber_handlevcard(gjconn, xmlnode, char *); - -static char *jabber_normalize(const char *s); - -static char *create_valid_jid(const char *given, char *server, char *resource) -{ - char *valid; - char *tmp; - - if (!(tmp = strchr(given, '@'))) - valid = g_strdup_printf("%s@%s/%s", given, server, resource); - else if (!strchr(tmp, '/')) - valid = g_strdup_printf("%s/%s", given, resource); - else - valid = g_strdup(given); - - return valid; + g_free(open_stream); } - -/* - * Dispose of a gaim_jid_struct - */ -static void gaim_jid_free(gaim_jid gjid) +static void jabber_session_initialized_cb(JabberStream *js, xmlnode *packet) { - if(gjid) { - if(gjid->resource) - free(gjid->resource); - if(gjid->user) - free(gjid->user); - if(gjid->server) - free(gjid->server); - if(gjid->full) - free(gjid->full); - free(gjid); + const char *type = xmlnode_get_attrib(packet, "type"); + if(type && !strcmp(type, "result")) { + jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); + } else { + gaim_connection_error(js->gc, _("Error initializing session")); } } -/* - * Create a new gjid struct - * - * Unlike jid_new(), also creates "full." - * - * Shamelessly copied, in part, from jid.c: jid_new() - * - * Caller is responsible for freeing the space allocated by this via - * gaim_jid_free(). - * - * JFIXME: Has a local declaration for jid.c:jid_safe(). I've put in a - * request to have that added to libjabber's lib.h file. (JSeymour) - */ -static gaim_jid gaim_jid_new(char *name) +static void jabber_session_init(JabberStream *js) { - extern jid jid_safe(jid); /* *retch* */ - - gaim_jid gjid = NULL; - - if(name && strlen(name)) { - char *server, *resource, *type, *str; - int full_len = 0; - - /* user@server/resource */ - - str = strdup(name); /* we mangle a copy */ - - gjid = calloc(1, sizeof(struct gaim_jid_struct)); - - if((resource = strstr(str, "/")) != NULL) { - *resource = '\0'; - ++resource; - if((full_len = strlen(resource)) > 0) { - gjid->resource = strdup(resource); - ++full_len; /* for later "/" addition */ - } - } else { - resource = str + strlen(str); /* point to end */ - } - - type = strstr(str, ":"); - if(type != NULL && type < resource) { - *type = '\0'; - ++type; - str = type; /* ignore the type: prefix */ - } + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET); + xmlnode *session; - server = strstr(str, "@"); - - /* - * if there's no @, it's just the server address - */ - if(server == NULL || server > resource) { - gjid->server = strdup(str); - full_len += strlen(str); - } else { - *server = '\0'; - ++server; - gjid->server = strdup(server); - full_len += strlen(server) + 1; /* account for later "@" */ - if(strlen(str) > 0) { - gjid->user = strdup(str); - full_len += strlen(str); - } - } - - free(str); + jabber_iq_set_callback(iq, jabber_session_initialized_cb); - if(!jid_safe(gjid)) { - gaim_jid_free(gjid); - gjid = NULL; - } else { - if(full_len) { - char *s = gjid->full = malloc(++full_len); + session = xmlnode_new_child(iq->node, "session"); + xmlnode_set_attrib(session, "xmlns", "urn:ietf:params:xml:ns:xmpp-session"); - if(gjid->user) { - strcpy(s, gjid->user); - s += strlen(gjid->user); - } - if(gjid->server) { - if(s > gjid->full) - *(s++) = '@'; - strcpy(s, gjid->server); - s += strlen(gjid->server); - } - if(gjid->resource) { - *(s++) = '/'; - strcpy(s, gjid->resource); - } - } - } - } - - return gjid; + jabber_iq_send(iq); } -/* - * Get a "username@server" from unadorned "username" - * - * If there's no "@server" part and "who" doesn't match the - * gjconn server (which would indicate that "who" *is* the - * server in case of server messages), the gjconn server is - * appended. - * - * If incl_resource is TRUE (non-0), the returned string - * includes the "/resource" part (if it exists), otherwise not. - * - * Allocates space for returned string. Caller is - * responsible for freeing it with g_free(). - * - * If "gjid" is non-null, sets that as well. Caller is - * reponsible for freeing that via gaim_jid_free() when done - * with it. - */ -static gchar *get_realwho(gjconn gjc, const char *who, int incl_resource, gaim_jid *gjid) +static void jabber_stream_handle_error(JabberStream *js, xmlnode *packet) { - gaim_jid my_gjid; - gchar *my_who; - gchar *realwho = NULL; - - if(!(who && who[0])) { - return NULL; - } + xmlnode *textnode; + char *error_text = NULL; + const char *text; + char *buf; - /* - * Bare username and "username" not the server itself? - */ - if(!strchr(who, '@') && strcasecmp(who, gjc->user->server)) { - my_who = g_strdup_printf("%s@%s", who, gjc->user->server); + if(xmlnode_get_child(packet, "bad-format")) { + text = _("Bad Format"); + } else if(xmlnode_get_child(packet, "bad-namespace-prefix")) { + text = _("Bad Namespace Prefix"); + } else if(xmlnode_get_child(packet, "conflict")) { + js->gc->wants_to_die = TRUE; + text = _("Resource Conflict"); + } else if(xmlnode_get_child(packet, "connection-timeout")) { + text = _("Connection Timeout"); + } else if(xmlnode_get_child(packet, "host-gone")) { + text = _("Host Gone"); + } else if(xmlnode_get_child(packet, "host-unknown")) { + text = _("Host Unknown"); + } else if(xmlnode_get_child(packet, "improper-addressing")) { + text = _("Improper Addressing"); + } else if(xmlnode_get_child(packet, "internal-server-error")) { + text = _("Internal Server Error"); + } else if(xmlnode_get_child(packet, "invalid-id")) { + text = _("Invalid ID"); + } else if(xmlnode_get_child(packet, "invalid-namespace")) { + text = _("Invalid Namespace"); + } else if(xmlnode_get_child(packet, "invalid-xml")) { + text = _("Invalid XML"); + } else if(xmlnode_get_child(packet, "nonmatching-hosts")) { + text = _("Non-matching Hosts"); + } else if(xmlnode_get_child(packet, "not-authorized")) { + text = _("Not Authorized"); + } else if(xmlnode_get_child(packet, "policy-violation")) { + text = _("Policy Violation"); + } else if(xmlnode_get_child(packet, "remote-connection-failed")) { + text = _("Remote Connection Failed"); + } else if(xmlnode_get_child(packet, "resource-constraint")) { + text = _("Resource Constraint"); + } else if(xmlnode_get_child(packet, "restricted-xml")) { + text = _("Restricted XML"); + } else if(xmlnode_get_child(packet, "see-other-host")) { + text = _("See Other Host"); + } else if(xmlnode_get_child(packet, "system-shutdown")) { + text = _("System Shutdown"); + } else if(xmlnode_get_child(packet, "undefined-condition")) { + text = _("Undefined Condition"); + } else if(xmlnode_get_child(packet, "unsupported-encoding")) { + text = _("Unsupported Condition"); + } else if(xmlnode_get_child(packet, "unsupported-stanza-type")) { + text = _("Unsupported Stanza Type"); + } else if(xmlnode_get_child(packet, "unsupported-version")) { + text = _("Unsupported Version"); + } else if(xmlnode_get_child(packet, "xml-not-well-formed")) { + text = _("XML Not Well Formed"); } else { - my_who = g_strdup(who); + text = _("Stream Error"); } - if((my_gjid = gaim_jid_new(my_who)) != NULL) { - /* - * If there's no "user" part, "who" was just the server or perhaps a transport (?) - */ - if(my_gjid->user) { - /* - * Include "/resource" bit? - */ - if(incl_resource) { - realwho = g_strdup(my_gjid->full); - } else { - realwho = g_strdup_printf("%s@%s", my_gjid->user, my_gjid->server); - } - } else { - realwho = g_strdup(my_gjid->server); - } - } - - g_free(my_who); - - if(gjid) { - *gjid = my_gjid; - } else { - gaim_jid_free(my_gjid); - } - - return realwho; -} - -static gjconn gjab_new(char *user, char *pass, void *priv) -{ - pool p; - gjconn gjc; + if((textnode = xmlnode_get_child(packet, "text"))) + error_text = xmlnode_get_data(textnode); - if (!user) - return (NULL); - - p = pool_new(); - if (!p) - return (NULL); - gjc = pmalloc_x(p, sizeof(gjconn_struct), 0); - if (!gjc) { - pool_free(p); /* no need for this anymore! */ - return (NULL); - } - gjc->p = p; - - if((gjc->user = jid_new(p, user)) == NULL) { - pool_free(p); /* no need for this anymore! */ - return (NULL); - } - - gjc->pass = strdup(pass); - - gjc->state = JCONN_STATE_OFF; - gjc->was_connected = 0; - gjc->id = 1; - gjc->fd = -1; - - gjc->priv = priv; - - return gjc; -} - -static void gjab_delete(gjconn gjc) -{ - if (!gjc) - return; - - gjab_stop(gjc); - free(gjc->pass); - pool_free(gjc->p); + buf = g_strdup_printf("%s%s%s", text, + error_text ? ": " : "", + error_text ? error_text : ""); + gaim_connection_error(js->gc, buf); + g_free(buf); + if(error_text) + g_free(error_text); } -static void gjab_state_handler(gjconn gjc, gjconn_state_h h) -{ - if (!gjc) - return; - - gjc->on_state = h; -} - -static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h) -{ - if (!gjc) - return; - - gjc->on_packet = h; -} - -static void gjab_stop(gjconn gjc) -{ - if (!gjc || gjc->state == JCONN_STATE_OFF) - return; +static void tls_init(JabberStream *js); - gjab_send_raw(gjc, "</stream:stream>"); - gjc->state = JCONN_STATE_OFF; - gjc->was_connected = 0; - if(gjc->gsc) - gaim_ssl_close(gjc->gsc); - else - close(gjc->fd); - gjc->fd = -1; - XML_ParserFree(gjc->parser); - gjc->parser = NULL; -} - -/* -static int gjab_getfd(gjconn gjc) -{ - if (gjc) - return gjc->fd; - else - return -1; -} - -static jid gjab_getjid(gjconn gjc) +void jabber_process_packet(JabberStream *js, xmlnode *packet) { - if (gjc) - return (gjc->user); - else - return NULL; -} - -static char *gjab_getsid(gjconn gjc) -{ - if (gjc) - return (gjc->sid); - else - return NULL; -} -*/ - -static char *gjab_getid(gjconn gjc) -{ - snprintf(gjc->idbuf, 8, "%d", gjc->id++); - return &gjc->idbuf[0]; -} + const char *id = xmlnode_get_attrib(packet, "id"); + const char *type = xmlnode_get_attrib(packet, "type"); + JabberCallback *callback; -static void gjab_send(gjconn gjc, xmlnode x) -{ - if (gjc && gjc->state != JCONN_STATE_OFF) { - char *buf = xmlnode2str(x); - if (buf) { - if(gjc->gsc) { - if(gaim_ssl_write(gjc->gsc, buf, strlen(buf)) < 0) { - gaim_connection_error(GJ_GC(gjc), _("Write error")); - } else { - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send (ssl): %s\n", buf); - } - } else { -#ifndef _WIN32 - if(write(gjc->fd, buf, strlen(buf)) < 0) { -#else - if(send(gjc->fd, buf, strlen(buf), 0) < 0) { -#endif - gaim_connection_error(GJ_GC(gjc), _("Write error")); - } else { - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send: %s\n", buf); - } - } + if(!strcmp(packet->name, "iq")) { + if(type && (!strcmp(type, "result") || !strcmp(type, "error")) && id + && *id && (callback = g_hash_table_lookup(js->callbacks, id))) + callback(js, packet); + else + jabber_iq_parse(js, packet); + } else if(!strcmp(packet->name, "presence")) { + jabber_presence_parse(js, packet); + } else if(!strcmp(packet->name, "message")) { + jabber_message_parse(js, packet); + } else if(!strcmp(packet->name, "stream:features")) { + if(js->state == JABBER_STREAM_AUTHENTICATING) { + jabber_auth_start(js, packet); + } else if(js->state == JABBER_STREAM_REINITIALIZING) { + jabber_session_init(js); + } else { + gaim_debug(GAIM_DEBUG_WARNING, "jabber", + "Unexpected stream:features packet, ignoring\n", js->state); } + } else if(!strcmp(packet->name, "stream:error")) { + jabber_stream_handle_error(js, packet); + } else if(!strcmp(packet->name, "challenge")) { + if(js->state == JABBER_STREAM_AUTHENTICATING) + jabber_auth_handle_challenge(js, packet); + } else if(!strcmp(packet->name, "success")) { + if(js->state == JABBER_STREAM_AUTHENTICATING) + jabber_auth_handle_success(js, packet); + } else if(!strcmp(packet->name, "failure")) { + if(js->state == JABBER_STREAM_AUTHENTICATING) + jabber_auth_handle_failure(js, packet); + } else if(!strcmp(packet->name, "proceed")) { + if(js->state == JABBER_STREAM_AUTHENTICATING && !js->gsc) + tls_init(js); + } else { + gaim_debug(GAIM_DEBUG_WARNING, "jabber", "Unknown packet: %s\n", + packet->name); } } -static void gjab_send_raw(gjconn gjc, const char *str) +void jabber_send_raw(JabberStream *js, const char *data) { - if (gjc && gjc->state != JCONN_STATE_OFF) { - /* - * JFIXME: No error detection?!?! - */ - if(gjc->gsc) { - if(gaim_ssl_write(gjc->gsc, str, strlen(str)) < 0) { - gaim_connection_error(GJ_GC(gjc), _("Write error")); - } else { - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw (ssl): %s\n", str); - } - } else { -#ifndef _WIN32 - if(write(gjc->fd, str, strlen(str)) < 0) { -#else - if(send(gjc->fd, str, strlen(str), 0) < 0) { -#endif - gaim_connection_error(GJ_GC(gjc), _("Write error")); - } - /* printing keepalives to the debug window is really annoying */ - if(strcmp(str, JABBER_KEEPALIVE_STRING)) - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw: %s\n", str); - } - } -} + int ret; -static void gjab_reqroster(gjconn gjc) -{ - xmlnode x; - - x = jutil_iqnew(JPACKET__GET, NS_ROSTER); - xmlnode_put_attrib(x, "id", gjab_getid(gjc)); - - gjab_send(gjc, x); - xmlnode_free(x); -} + /* because printing a tab to debug every minute gets old */ + if(strcmp(data, "\t")) + gaim_debug(GAIM_DEBUG_MISC, "jabber", "Sending%s: %s\n", + js->gsc ? " (ssl)" : "", data); -static void gjab_reqauth(gjconn gjc) -{ - xmlnode x, y, z; - char *user; - - if (!gjc) - return; - - x = jutil_iqnew(JPACKET__GET, NS_AUTH); - xmlnode_put_attrib(x, "id", IQID_AUTH); - y = xmlnode_get_tag(x, "query"); - - user = gjc->user->user; - - if (user) { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); + if(js->gsc) { + ret = gaim_ssl_write(js->gsc, data, strlen(data)); + } else { + ret = write(js->fd, data, strlen(data)); } - gjab_send(gjc, x); - xmlnode_free(x); + if(ret < 0) + gaim_connection_error(js->gc, _("Write error")); + } -static void gjab_auth(gjconn gjc) +void jabber_send(JabberStream *js, xmlnode *packet) { - xmlnode x, y, z; - char *hash, *user; - - if (!gjc) - return; - - x = jutil_iqnew(JPACKET__SET, NS_AUTH); - xmlnode_put_attrib(x, "id", IQID_AUTH); - y = xmlnode_get_tag(x, "query"); - - user = gjc->user->user; - - if (user) { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } + char *txt; - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, gjc->user->resource, -1); - - if (gjc->sid) { - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "digest authentication (sid %s)\n", gjc->sid); - z = xmlnode_insert_tag(y, "digest"); - hash = pmalloc(x->p, strlen(gjc->sid) + strlen(gjc->pass) + 1); - strcpy(hash, gjc->sid); - strcat(hash, gjc->pass); - hash = shahash(hash); - xmlnode_insert_cdata(z, hash, 40); - } else { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, gjc->pass, -1); - } - - gjab_send(gjc, x); - xmlnode_free(x); - - return; + txt = xmlnode_to_str(packet); + jabber_send_raw(js, txt); + g_free(txt); } -static void gjab_recv(gjconn gjc) +static void jabber_keepalive(GaimConnection *gc) { - static char buf[4096]; - int len; - - if (!gjc || gjc->state == JCONN_STATE_OFF) - return; -#ifndef _WIN32 - if ((len = read(gjc->fd, buf, sizeof(buf) - 1)) > 0) { -#else - if ((len = recv(gjc->fd, buf, sizeof(buf) - 1, 0)) > 0) { -#endif - buf[len] = '\0'; - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "input (len %d): %s\n", len, buf); - XML_Parse(gjc->parser, buf, len, 0); - } else if (len < 0 || errno != EAGAIN) { - STATE_EVT(JCONN_STATE_OFF) - } + jabber_send_raw(gc->proto_data, "\t"); } -static void gjab_ssl_recv(gpointer data, GaimSslConnection *gsc, +static void +jabber_recv_cb_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond) { - static char buf[4096]; + GaimConnection *gc = data; + JabberStream *js = gc->proto_data; int len; - GaimConnection *gc = data; - struct jabber_data *jd; - gjconn gjc; + static char buf[4096]; - - if (!g_list_find(gaim_connections_get_all(), gc)) { + if(!g_list_find(gaim_connections_get_all(), gc)) { gaim_ssl_close(gsc); return; } - jd = gc->proto_data; - gjc= jd->gjc; - - if (!gjc || gjc->state == JCONN_STATE_OFF) - return; - - if((len = gaim_ssl_read(gsc, buf, sizeof(buf) -1)) > 0) { + if((len = gaim_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) { buf[len] = '\0'; - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "input (ssl) (len %d): %s\n", len, buf); - XML_Parse(gjc->parser, buf, len, 0); - } else if(len < 0) { - STATE_EVT(JCONN_STATE_OFF) - } -} - -static void startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - gjconn gjc = (gjconn) userdata; - - if (gjc->current) { - /* Append the node to the current one */ - x = xmlnode_insert_tag(gjc->current, name); - xmlnode_put_expat_attribs(x, attribs); - - gjc->current = x; - } else { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - if (strcmp(name, "stream:stream") == 0) { - /* special case: name == stream:stream */ - /* id attrib of stream is stored for digest auth */ - gjc->sid = g_strdup(xmlnode_get_attrib(x, "id")); - gjc->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON); - xmlnode_free(x); - } else { - gjc->current = x; - } + gaim_debug(GAIM_DEBUG_INFO, "jabber", "Recv (ssl)(%d): %s\n", len, buf); + jabber_parser_process(js, buf, len); } } -static void endElement(void *userdata, const char *name) -{ - gjconn gjc = (gjconn) userdata; - xmlnode x; - jpacket p; - - if (gjc->current == NULL) { - /* we got </stream:stream> */ - STATE_EVT(JCONN_STATE_OFF) - return; - } - - x = xmlnode_get_parent(gjc->current); - - if (!x) { - /* it is time to fire the event */ - p = jpacket_new(gjc->current); - - if (gjc->on_packet) - (gjc->on_packet) (gjc, p); - else - xmlnode_free(gjc->current); - } - - gjc->current = x; -} - -static void jabber_callback(gpointer data, gint source, GaimInputCondition condition) +static void +jabber_recv_cb(gpointer data, gint source, GaimInputCondition condition) { GaimConnection *gc = data; - struct jabber_data *jd = (struct jabber_data *)gc->proto_data; - - gjab_recv(jd->gjc); -} + JabberStream *js = gc->proto_data; + int len; + static char buf[4096]; -static void charData(void *userdata, const char *s, int slen) -{ - gjconn gjc = (gjconn) userdata; + if(!g_list_find(gaim_connections_get_all(), gc)) + return; - if (gjc->current) - xmlnode_insert_cdata(gjc->current, s, slen); + if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) { + buf[len] = '\0'; + gaim_debug(GAIM_DEBUG_INFO, "jabber", "Recv (%d): %s\n", len, buf); + jabber_parser_process(js, buf, len); + } } - -static void gjab_start_stream(gjconn gjc) -{ - xmlnode x; - char *t, *t2; - - gjc->state = JCONN_STATE_CONNECTED; - STATE_EVT(JCONN_STATE_CONNECTED) - - /* start stream */ - x = jutil_header(NS_CLIENT, gjc->user->server); - t = xmlnode2str(x); - /* this is ugly, we can create the string here instead of jutil_header */ - /* what do you think about it? -madcat */ - t2 = strstr(t, "/>"); - *t2++ = '>'; - *t2 = '\0'; - gjab_send_raw(gjc, "<?xml version='1.0'?>"); - gjab_send_raw(gjc, t); - xmlnode_free(x); -} - -static void gjab_ssl_connected(gpointer data, GaimSslConnection *gsc, +static void +jabber_login_callback_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond) { GaimConnection *gc = data; - struct jabber_data *jd; - gjconn gjc; + JabberStream *js = gc->proto_data; - if (!g_list_find(gaim_connections_get_all(), gc)) { + if(!g_list_find(gaim_connections_get_all(), gc)) { gaim_ssl_close(gsc); return; } - jd = gc->proto_data; - gjc = jd->gjc; + js->gsc = gsc; - gjab_start_stream(gjc); + if(js->state == JABBER_STREAM_CONNECTING) + jabber_send_raw(js, "<?xml version='1.0' ?>"); - /* this seems wrong, but... */ - - gaim_ssl_input_add(gsc, gjab_ssl_recv, gc); + jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); + gaim_ssl_input_add(gsc, jabber_recv_cb_ssl, gc); } -static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) + +static void +jabber_login_callback(gpointer data, gint source, GaimInputCondition cond) { GaimConnection *gc = data; - struct jabber_data *jd; - gjconn gjc; + JabberStream *js = gc->proto_data; - if (!g_list_find(gaim_connections_get_all(), gc)) { + if(!g_list_find(gaim_connections_get_all(), gc)) { close(source); return; } - jd = gc->proto_data; - gjc = jd->gjc; + js->fd = source; - gjc->fd = source; + if(js->state == JABBER_STREAM_CONNECTING) + jabber_send_raw(js, "<?xml version='1.0' ?>"); - if (source == -1) { - STATE_EVT(JCONN_STATE_OFF) - return; - } + jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); + gc->inpa = gaim_input_add(js->fd, GAIM_INPUT_READ, jabber_recv_cb, gc); +} - gjab_start_stream(gjc); - - gc->inpa = gaim_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); +static void tls_init(JabberStream *js) +{ + gaim_input_remove(js->gc->inpa); + js->gc->inpa = 0; + js->gsc = gaim_ssl_connect_fd(js->gc->account, js->fd, + jabber_login_callback_ssl, js->gc); } -static void gjab_start(gjconn gjc) +static void +jabber_login(GaimAccount *account) { - GaimAccount *account; - int port, rc; - const char *connect_server; + int rc; + GaimConnection *gc = gaim_account_get_connection(account); + const char *connect_server = gaim_account_get_string(account, + "connect_server", ""); const char *server; - - if (!gjc || gjc->state != JCONN_STATE_OFF) - return; + JabberStream *js; - account = GJ_GC(gjc)->account; - port = gaim_account_get_int(account, "port", DEFAULT_PORT); - connect_server = gaim_account_get_string(account, "connect_server", ""); - server = connect_server[0] ? connect_server : gjc->user->server; + gc->flags |= GAIM_CONNECTION_HTML; + js = gc->proto_data = g_new0(JabberStream, 1); + js->gc = gc; + js->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + js->buddies = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + js->user = jabber_id_new(gaim_account_get_username(account)); + server = connect_server[0] ? connect_server : js->user->domain; - gjc->parser = XML_ParserCreate(NULL); - XML_SetUserData(gjc->parser, (void *)gjc); - XML_SetElementHandler(gjc->parser, startElement, endElement); - XML_SetCharacterDataHandler(gjc->parser, charData); + jabber_stream_set_state(js, JABBER_STREAM_CONNECTING); if(gaim_account_get_bool(account, "old_ssl", FALSE) && gaim_ssl_is_supported()) { - gjc->gsc = gaim_ssl_connect(account, server, port, - gjab_ssl_connected, GJ_GC(gjc)); - } - - if(!gjc->gsc) { - rc = gaim_proxy_connect(account, server, port, gjab_connected, - GJ_GC(gjc)); - if (!account->gc || (rc != 0)) { - STATE_EVT(JCONN_STATE_OFF) - return; - } - } -} - -/* - * Find chat by chat group name - */ -static GaimConversation *find_chat(GaimConnection *gc, char *name) -{ - GSList *bcs = gc->buddy_chats; - GaimConversation *b = NULL; - char *chat = g_strdup(normalize(name)); - - while (bcs) { - b = bcs->data; - if (!strcasecmp(normalize(b->name), chat)) - break; - b = NULL; - bcs = bcs->next; - } - - g_free(chat); - return b; -} - -/* - * Find chat by "chat id" - * - * Returns: 0 on success and jabber_chat pointer set - * or -EINVAL on error and jabber_chat pointer is - * undefined. - * - * TBD: Slogging through the buddy_chats list seems - * redundant since the chat i.d. is mirrored in the - * jabber_chat struct list. But that's the way it - * was, so that's the way I'm leaving it--for now. - */ -static int jabber_find_chat_by_convo_id(GaimConnection *gc, int id, struct jabber_chat **jc) -{ - GSList *bcs = gc->buddy_chats; - GaimConversation *b = NULL; - struct jabber_data *jd = gc->proto_data; - - *jc = NULL; - - while(bcs != NULL) { - b = bcs->data; - if (id == gaim_chat_get_id(GAIM_CHAT(b))) - break; - bcs = bcs->next; - } - - if (bcs != NULL) { - bcs = jd->chats; - while (bcs != NULL) { - *jc = bcs->data; - if ((*jc)->state == JCS_ACTIVE && (*jc)->b == b) - break; - bcs = bcs->next; - } - } - - return(bcs == NULL? -EINVAL : 0); -} - -/* - * Find any chat - */ -static struct jabber_chat *find_any_chat(GaimConnection *gc, jid chat) -{ - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc = NULL; - - while (jcs) { - jc = jcs->data; - if (!jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) - break; - jc = NULL; - jcs = jcs->next; - } - - return jc; -} - - -/* - * Find existing/active Jabber chat - */ -static struct jabber_chat *find_existing_chat(GaimConnection *gc, jid chat) -{ - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc = NULL; - - while (jcs) { - jc = jcs->data; - if (jc->state == JCS_ACTIVE && !jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) - break; - jc = NULL; - jcs = jcs->next; - } - - return jc; -} - -/* - * Find pending chat - */ -static struct jabber_chat *find_pending_chat(GaimConnection *gc, jid chat) -{ - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc = NULL; - - while (jcs) { - jc = jcs->data; - if (jc->state == JCS_PENDING && !jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) - break; - jc = NULL; - jcs = jcs->next; - } - - return jc; -} - -static gboolean find_chat_buddy(GaimConversation *b, char *name) -{ - GList *m = gaim_chat_get_users(GAIM_CHAT(b)); - - while (m) { - if (!strcmp(m->data, name)) - return TRUE; - m = m->next; - } - - return FALSE; -} - -/* - * Remove a buddy from the (gaim) buddylist (if he's on it) - */ -static void jabber_remove_gaim_buddy(GaimConnection *gc, const char *buddyname) -{ - GaimBuddy *b; - - if ((b = gaim_find_buddy(gc->account, buddyname)) != NULL) { - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "removing buddy [1]: %s\n", buddyname); - gaim_blist_remove_buddy(b); - gaim_blist_save(); - } -} - -static void jabber_change_passwd(GaimConnection *gc, const char *old, const char *new) -{ - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if(strcmp(old, gjc->pass)) - { - gaim_notify_error(gc, NULL, - _("Unable to change password."), - _("The current password you entered is incorrect. " - "Your password has not been changed.")); - } - else if(!strcmp(old, new)) - { - gaim_notify_error(gc, NULL, - _("Unable to change password."), - _("The new password you entered is the same as " - "your current password. " - "Your password remains the same.")); - } - else - { - xmlnode x, y, z; - char *id; - - x = jutil_iqnew(JPACKET__SET, NS_REGISTER); - xmlnode_put_attrib(x, "to", gjc->user->server); - y = xmlnode_get_tag(x, "query"); - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, gjc->user->user, -1); - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, new, -1); - - id = gjab_getid(gjc); - xmlnode_put_attrib(x, "id", id); - - free(gjc->pass); - gjc->pass = strdup(new); - - g_hash_table_insert(gjc->queries, g_strdup(id), g_strdup("change_password")); - - gjab_send(gjc, x); - xmlnode_free(x); - } -} - -/* - * Return pointer to jabber_buddy_data if buddy found. Create if necessary. - */ -static struct jabber_buddy_data* jabber_find_buddy(GaimConnection *gc, const char *buddy, gboolean create) -{ - struct jabber_data *jd; - gpointer val; - char *realwho; - - if (gc == NULL) - return NULL; - - jd = gc->proto_data; - if((realwho = get_realwho(jd->gjc, buddy, FALSE, NULL)) == NULL) - return NULL; - - val = g_hash_table_lookup(jd->buddies, realwho); - if(val) { - g_free(realwho); - return (struct jabber_buddy_data *)val; - - } else if (create) { - struct jabber_buddy_data *jbd = g_new0(struct jabber_buddy_data, 1); - jbd->invisible = JABBER_NOT_INVIS; - g_hash_table_insert(jd->buddies, g_strdup(realwho), jbd); - g_free(realwho); - return jbd; - } else { - g_free(realwho); - return NULL; - } -} - -/* - * find a resource by name, or if no name given, return the "default" resource - * default being the highest priority one. - */ - -static jab_res_info jabber_find_resource(GaimConnection *gc, const char *who) -{ - GSList *resources; - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, who, FALSE); - jab_res_info jri = NULL; - char *res = strstr(who, "/"); - - if(res) - res++; - - if(jbd) - { - resources = jbd->resources; - while(resources) - { - if(!jri && !res) { - jri = (jab_res_info) resources->data; - } else if(!res) { /* we're looking for the default priority, so... */ - if(((jab_res_info) resources->data)->priority >= jri->priority) - jri = (jab_res_info) resources->data; - } else if(((jab_res_info)resources->data)->name) { - if(!strcasecmp(((jab_res_info) resources->data)->name, res)) { - jri = (jab_res_info) resources->data; - break; - } - } - resources = resources->next; - } - } - - return jri; -} - -#if 0 -static gboolean jabber_is_default_resource(GaimConnection *gc, const char *who) -{ - jab_res_info jri = jabber_find_resource(gc, who); - char *buddy = g_strdup(who); - char *resource = strrchr(buddy, '/'); - - if(!resource || !strcmp(resource+1, jri->name)) { - g_free(buddy); - return TRUE; - } - - g_free(buddy); - return FALSE; -} -#endif - -/* - * if the resource doesn't exist, create it. otherwise, just update the priority - */ -static void jabber_track_resource(GaimConnection *gc, - char *buddy, - char *res, - int priority, - int state) -{ - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); - - if(jbd) { - char *who; - jab_res_info jri; - if(res) - who = g_strdup_printf("%s/%s", buddy, res); - else - who = g_strdup(buddy); - jri = jabber_find_resource(gc, who); - g_free(who); - if(!jri) { - jri = g_new0(struct jabber_resource_info, 1); - jri->name = g_strdup(res); - jri->away_msg = NULL; - jri->has_xhtml = TRUE; - jbd->resources = g_slist_append(jbd->resources, jri); - } - jri->priority = priority; - jri->state = state; - } -} - -/* - * remove the resource, if it exists - */ -static void jabber_remove_resource(GaimConnection *gc, char *buddy, char *res) -{ - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, FALSE); - if(jbd) { - char *who; - jab_res_info jri; - if(res) - who = g_strdup_printf("%s/%s", buddy, res); - else - who = g_strdup(buddy); - jri = jabber_find_resource(gc, who); - g_free(who); - if(jri) { - if(jri->name) - g_free(jri->name); - if(jri->away_msg) - g_free(jri->away_msg); - jbd->resources = g_slist_remove(jbd->resources, jri); - g_free(jri); - } - } -} - -/* - * grab the away message for the default resource - */ -static char *jabber_lookup_away(gjconn gjc, char *name) -{ - jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); - - if(!jri) - return _("Unknown"); - - return jri->away_msg; -} -static const char *jabber_get_state_string(int s) { - switch(s) { - case UC_AWAY: - return _("Away"); - case UC_CHAT: - return _("Chatty"); - case UC_XA: - return _("Extended Away"); - case UC_DND: - return _("Do Not Disturb"); - default: - return _("Available"); - } -} - -static void jabber_track_away(gjconn gjc, jpacket p, char *type) -{ - jab_res_info jri = NULL; - - if(!p || !p->from || !p->from->user) - return; - - jri = jabber_find_resource(GJ_GC(gjc), jid_full(p->from)); - - if(!jri) - return; - - if(jri->away_msg) - g_free(jri->away_msg); - - jri->away_msg = g_strdup(xmlnode_get_tag_data(p->x, "status")); -} - -static void jabber_convo_closed(GaimConnection *gc, const char *name) -{ - jab_res_info jri = jabber_find_resource(gc, name); - - if(jri) { - if(jri->thread_id) - g_free(jri->thread_id); - - jri->thread_id = NULL; - } -} - -static void jabber_track_convo_thread(gjconn gjc, char *name, char *thread_id) -{ - jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); - - if(jri) { - if(jri->thread_id) - g_free(jri->thread_id); - - jri->thread_id = g_strdup(thread_id); - } -} - -static char *jabber_get_convo_thread(gjconn gjc, const char *name) -{ - char *ct = NULL; - jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); - - if(jri) { - if(jri->thread_id) - ct = g_strdup(jri->thread_id); - } - - return ct; -} - - -static time_t str_to_time(char *timestamp) -{ - struct tm t; - time_t retval = 0; - char buf[32]; - char *c; - int tzoff = 0; - - time(&retval); - localtime_r(&retval, &t); - - snprintf(buf, sizeof(buf), "%s", timestamp); - c = buf; - - /* 4 digit year */ - if(!sscanf(c, "%04d", &t.tm_year)) return 0; - c+=4; - if(*c == '-') - c++; - - t.tm_year -= 1900; - - /* 2 digit month */ - if(!sscanf(c, "%02d", &t.tm_mon)) return 0; - c+=2; - if(*c == '-') - c++; - - t.tm_mon -= 1; - - /* 2 digit day */ - if(!sscanf(c, "%02d", &t.tm_mday)) return 0; - c+=2; - - if(*c == 'T') { /* we have more than a date, keep going */ - c++; /* skip the "T" */ - - /* 2 digit hour */ - if(sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec)) { - int tzhrs, tzmins; - c+=8; - if(*c == '.') /* dealing with precision we don't care about */ - c += 4; - - if((*c == '+' || *c == '-') && - sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { - tzoff = tzhrs*60*60 + tzmins*60; - if(*c == '+') - tzoff *= -1; - } - -#ifdef HAVE_TM_GMTOFF - tzoff += t.tm_gmtoff; -#else -# ifdef HAVE_TIMEZONE - tzset(); /* making sure */ - tzoff -= timezone; -# endif -#endif - } - } - retval = mktime(&t); - - retval += tzoff; - - return retval; -} - -static void jabber_handlemessage(gjconn gjc, jpacket p) -{ - xmlnode y, subj; - time_t time_sent = time(NULL); - gboolean typing = FALSE; - gboolean has_xhtml = TRUE; - - char *from = NULL, *msg = NULL, *type = NULL, *topic = NULL; - char *thread_id = NULL; - char *conference_room = NULL; - char m[BUF_LONG * 2]; - - type = xmlnode_get_attrib(p->x, "type"); - - if ((y = xmlnode_get_tag(p->x, "thread"))) - thread_id = xmlnode_get_data(y); - - y = xmlnode_get_firstchild(p->x); - - while(y) { - if(NSCHECK(y, NS_DELAY)) { - char *timestamp = xmlnode_get_attrib(y, "stamp"); - if(timestamp) - time_sent = str_to_time(timestamp); - } else if(NSCHECK(y, "jabber:x:event")) { - if(xmlnode_get_tag(y, "composing")) - typing = TRUE; - } else if(NSCHECK(y, "jabber:x:conference")) { - conference_room = xmlnode_get_attrib(y, "jid"); - } - y = xmlnode_get_nextsibling(y); - } - - if (!type || !strcasecmp(type, "normal") || !strcasecmp(type, "chat")) { - - from = jid_full(p->from); - /* a gross hack because i'm a nice guy */ - if ((y = xmlnode_get_tag(p->x, "html")) && xmlnode_get_tag(y, "body")) { - msg = xmlnode2str(y); - } else if ((y = xmlnode_get_tag(p->x, "body"))) { - msg = xmlnode_get_data(y); - has_xhtml = FALSE; - } - - if (!from) - return; - - if (conference_room) { - GHashTable *components = g_hash_table_new_full(g_str_hash, - g_str_equal, g_free, g_free); - char **data; - - data = g_strsplit(conference_room, "@", 2); - g_hash_table_replace(components, g_strdup("room"), - g_strdup(data[0])); - g_hash_table_replace(components, g_strdup("server"), - g_strdup(data[1])); - g_hash_table_replace(components, g_strdup("handle"), - g_strdup(gjc->user->user)); - g_strfreev(data); - - serv_got_chat_invite(GJ_GC(gjc), conference_room, from, msg, components); - } else if (msg) { /* whisper */ - struct jabber_chat *jc; - g_snprintf(m, sizeof(m), "%s", msg); - if (((jc = find_existing_chat(GJ_GC(gjc), p->from)) != NULL) && jc->b) - serv_got_chat_in(GJ_GC(gjc), - gaim_chat_get_id(GAIM_CHAT(jc->b)), - p->from->resource, 1, m, time_sent); - else { - int flags = 0; - jab_res_info jri = jabber_find_resource(GJ_GC(gjc), from); - if(jri) { - if(typing) - jri->has_composing = TRUE; - jri->has_xhtml = has_xhtml; - } - jabber_track_convo_thread(gjc, from, thread_id); - if (gaim_find_conversation_with_account(from, GJ_GC(gjc)->account)) - serv_got_im(GJ_GC(gjc), from, m, flags, - time_sent); - else { - if(p->from->user) { - from = g_strdup_printf("%s@%s", p->from->user, - p->from->server); - } else { - /* server message? */ - from = g_strdup(p->from->server); - } - serv_got_im(GJ_GC(gjc), from, m, flags, time_sent); - g_free(from); - } - } - } else { - /* a non-message message! */ - from = g_strdup_printf("%s@%s", p->from->user, p->from->server); - if(typing) - serv_got_typing(GJ_GC(gjc), from, 0, GAIM_TYPING); - else - serv_got_typing_stopped(GJ_GC(gjc), from); - g_free(from); - } - - } else if (!strcasecmp(type, "error")) { - if ((y = xmlnode_get_tag(p->x, "error"))) { - type = xmlnode_get_attrib(y, "code"); - msg = xmlnode_get_data(y); - } - - if (msg) { - from = g_strdup_printf(_("Jabber Error %s"), type ? type : ""); - gaim_notify_error(GJ_GC(gjc), NULL, from, msg); - g_free(from); - } - } else if (!strcasecmp(type, "groupchat")) { - struct jabber_chat *jc; - static int i = 0; - - /* a gross hack because i'm a nice guy */ - if ((y = xmlnode_get_tag(p->x, "html")) && xmlnode_get_tag(y, "body")) { - msg = xmlnode2str(y); - } else if ((y = xmlnode_get_tag(p->x, "body"))) { - msg = xmlnode_get_data(y); - } - - if ((subj = xmlnode_get_tag(p->x, "subject"))) { - topic = xmlnode_get_data(subj); - } - - jc = find_existing_chat(GJ_GC(gjc), p->from); - if (!jc) { - /* we're not in this chat. are we supposed to be? */ - if ((jc = find_pending_chat(GJ_GC(gjc), p->from)) != NULL) { - /* yes, we're supposed to be. so now we are. */ - jc->b = serv_got_joined_chat(GJ_GC(gjc), i++, p->from->user); - jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); - jc->state = JCS_ACTIVE; - } else { - /* no, we're not supposed to be. */ - return; - } - } - if (p->from->resource) { - if (!y) { - if (!find_chat_buddy(jc->b, p->from->resource)) { - gaim_chat_add_user(GAIM_CHAT(jc->b), - p->from->resource, NULL); - } else if ((y = xmlnode_get_tag(p->x, "status"))) { - jabber_track_away(gjc, p, NULL); - } - } else if (jc->b && msg) { - char buf[8192]; - - if (topic) { - char tbuf[8192]; - g_snprintf(tbuf, sizeof(tbuf), "%s", topic); - gaim_chat_set_topic(GAIM_CHAT(jc->b), - p->from->resource, tbuf); - } - - g_snprintf(buf, sizeof(buf), "%s", msg); - serv_got_chat_in(GJ_GC(gjc), - gaim_chat_get_id(GAIM_CHAT(jc->b)), - p->from->resource, 0, buf, time_sent); - } - } else { /* message from the server */ - if(jc->b && topic) { - char tbuf[8192]; - g_snprintf(tbuf, sizeof(tbuf), "%s", topic); - gaim_chat_set_topic(GAIM_CHAT(jc->b), "", tbuf); - } - } - - } else { - gaim_debug(GAIM_DEBUG_WARNING, "jabber", - "unhandled message %s\n", type); - } -} - -static void jabber_handlepresence(gjconn gjc, jpacket p) -{ - char *from, *type; - GaimBuddy *b = NULL; - gaim_jid gjid; - char *buddy; - xmlnode y; - char *show; - int state = 0; - GaimConversation *cnv = NULL; - struct jabber_chat *jc = NULL; - int priority = 0; - struct jabber_buddy_data *jbd; - - from = xmlnode_get_attrib(p->x, "from"); - type = xmlnode_get_attrib(p->x, "type"); - - if((buddy = get_realwho(gjc, from, FALSE, &gjid)) == NULL) - return; - - if (gjid->user == NULL) { - /* FIXME: transport */ - g_free(buddy); - gaim_jid_free(gjid); - return; - } - - jbd = jabber_find_buddy(GJ_GC(gjc), buddy, TRUE); - - if(jbd->error_msg) { - g_free(jbd->error_msg); - jbd->error_msg = NULL; - } - - if(type && !strcasecmp(type, "error")) { - state = UC_ERROR; - if((y = xmlnode_get_tag(p->x, "error")) != NULL) { - jbd->error_msg = g_strdup_printf(_("Error %s: %s"), - xmlnode_get_attrib(y, "code"), xmlnode_get_data(y)); - } else { - jbd->error_msg = g_strdup(_("Unknown Error in presence")); - } - } else { - if ((y = xmlnode_get_tag(p->x, "show"))) { - show = xmlnode_get_data(y); - if (!show) { - state = 0; - } else if (!strcasecmp(show, "away")) { - state = UC_AWAY; - } else if (!strcasecmp(show, "chat")) { - state = UC_CHAT; - } else if (!strcasecmp(show, "xa")) { - state = UC_XA; - } else if (!strcasecmp(show, "dnd")) { - state = UC_DND; - } - } else { - state = 0; - } - } - - if ((y = xmlnode_get_tag(p->x, "priority"))) - priority = atoi(xmlnode_get_data(y)); - - /* um. we're going to check if it's a chat. if it isn't, and there are pending - * chats, create the chat. if there aren't pending chats and we don't have the - * buddy on our list, simply bail out. */ - if ((cnv = find_chat(GJ_GC(gjc), gjid->user)) == NULL) { - static int i = 0x70; - if ((jc = find_pending_chat(GJ_GC(gjc), gjid)) != NULL) { - jc->b = cnv = serv_got_joined_chat(GJ_GC(gjc), i++, gjid->user); - jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); - jc->state = JCS_ACTIVE; - } else if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddy)) == NULL) { - g_free(buddy); - gaim_jid_free(gjid); - return; - } - } - - if (state == UC_ERROR || (type && (strcasecmp(type, "unavailable") == 0))) - jabber_remove_resource(GJ_GC(gjc), buddy, gjid->resource); - else { - jabber_track_resource(GJ_GC(gjc), buddy, gjid->resource, priority, state); - - /* keep track of away msg somewhat the same as the yahoo plugin */ - jabber_track_away(gjc, p, type); + js->gsc = gaim_ssl_connect(account, server, + gaim_account_get_int(account, "port", 5222), + jabber_login_callback_ssl, gc); } - if (!cnv) { - /* this is where we handle presence information for "regular" buddies */ - jab_res_info jri = jabber_find_resource(GJ_GC(gjc), buddy); - if(jri) { - serv_got_update(GJ_GC(gjc), buddy, 1, 0, b->signon, b->idle, jri->state); - } else - serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0); - - } else { - if (gjid->resource) { - if (type && (!strcasecmp(type, "unavailable"))) { - struct jabber_data *jd; - if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) { - g_free(buddy); - gaim_jid_free(gjid); - return; - } - jd = jc->gc->proto_data; - /* if it's not ourselves...*/ - if (strcmp(gjid->resource, jc->gjid->resource) && jc->b) { - gaim_chat_remove_user(GAIM_CHAT(jc->b), gjid->resource, - NULL); - g_free(buddy); - gaim_jid_free(gjid); - return; - } - - jc->state = JCS_CLOSED; - serv_got_chat_left(GJ_GC(gjc), jc->id); - /* - * TBD: put back some day? - jd->chats = g_slist_remove(jd->chats, jc); - g_free(jc); - */ - } else { - if ((!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) || !jc->b) { - g_free(buddy); - gaim_jid_free(gjid); - return; - } - if (!find_chat_buddy(jc->b, gjid->resource)) { - gaim_chat_add_user(GAIM_CHAT(jc->b), gjid->resource, NULL); - } - } - } - } - - g_free(buddy); - gaim_jid_free(gjid); - - return; -} - -/* - * Used only by Jabber accept/deny add stuff just below - */ -struct jabber_add_permit { - GaimConnection *gc; - gchar *user; -}; - -/* - * Common part for Jabber accept/deny adds - * - * "type" says whether we'll permit/deny the subscribe request - */ -static void jabber_accept_deny_add(struct jabber_add_permit *jap, const char *type) -{ - xmlnode g = xmlnode_new_tag("presence"); - - xmlnode_put_attrib(g, "to", jap->user); - xmlnode_put_attrib(g, "type", type); - gjab_send(GC_GJ(jap->gc), g); - - xmlnode_free(g); -} - -/* - * Callback from "accept" in gaim_request_action() invoked - * by jabber_handles10n() - */ -static void jabber_accept_add(struct jabber_add_permit *jap) -{ - if(g_list_find(gaim_connections_get_all(), jap->gc)) { - jabber_accept_deny_add(jap, "subscribed"); - /* - * If we don't already have the buddy on *our* buddylist, - * ask if we want him or her added. - */ - if(gaim_find_buddy(jap->gc->account, jap->user) == NULL) { - show_got_added(jap->gc, NULL, jap->user, NULL, NULL); - } - } - - g_free(jap->user); - g_free(jap); -} - -/* - * Callback from "deny/cancel" in gaim_request_action() invoked - * by jabber_handles10n() - */ -static void jabber_deny_add(struct jabber_add_permit *jap) -{ - if(g_list_find(gaim_connections_get_all(), jap->gc)) { - jabber_accept_deny_add(jap, "unsubscribed"); - } - - g_free(jap->user); - g_free(jap); -} - -/* - * Handle subscription requests - */ -static void jabber_handles10n(gjconn gjc, jpacket p) -{ - xmlnode g; - char *Jid = xmlnode_get_attrib(p->x, "from"); - char *type = xmlnode_get_attrib(p->x, "type"); - - g = xmlnode_new_tag("presence"); - xmlnode_put_attrib(g, "to", Jid); - - if (!strcmp(type, "subscribe")) { - /* - * A "subscribe to us" request was received - put up the approval dialog - */ - struct jabber_add_permit *jap = g_new0(struct jabber_add_permit, 1); - gchar *msg = g_strdup_printf(_("The user %s wants to add you to their buddy list."), - Jid); - - jap->gc = GJ_GC(gjc); - jap->user = g_strdup(Jid); - - gaim_request_action(jap->gc, NULL, msg, NULL, 0, jap, 2, - _("Authorize"), G_CALLBACK(jabber_accept_add), - _("Deny"), G_CALLBACK(jabber_deny_add)); - - g_free(msg); - xmlnode_free(g); /* Never needed it here anyway */ - return; - - } else if (!strcmp(type, "unsubscribe")) { - /* - * An "unsubscribe to us" was received - simply "approve" it - */ - xmlnode_put_attrib(g, "type", "unsubscribed"); - } else { - /* - * Did we attempt to subscribe to somebody and they do not exist? - */ - if (!strcmp(type, "unsubscribed")) { - xmlnode y; - char *status; - if((y = xmlnode_get_tag(p->x, "status")) && (status = xmlnode_get_data(y)) && - !strcmp(status, "Not Found")) { - char *msg = g_strdup_printf(_("The Jabber user %s does not exist and was therefore " - "not added to your roster."), - xmlnode_get_attrib(p->x, "from")); - gaim_notify_error(GJ_GC(gjc), NULL, _("No such user."), msg); - g_free(msg); - } - } - - xmlnode_free(g); - return; - } - - gjab_send(gjc, g); - xmlnode_free(g); -} - -/* - * Pending subscription to a buddy? - */ -#define BUD_SUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ - (ask) != NULL && !strcasecmp((ask), "subscribe")) - -/* - * Subscribed to a buddy? - */ -#define BUD_SUBD_TO(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ - ((ask) == NULL || !strcasecmp((ask), "subscribe"))) - -/* - * Pending unsubscription to a buddy? - */ -#define BUD_USUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ - (ask) != NULL && !strcasecmp((ask), "unsubscribe")) - -/* - * Unsubscribed to a buddy? - */ -#define BUD_USUBD_TO(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ - ((ask) == NULL || !strcasecmp((ask), "unsubscribe"))) - -/* - * If a buddy is added or removed from the roster on another resource - * jabber_handlebuddy is called - * - * Called with roster item node. - */ -static void jabber_handlebuddy(gjconn gjc, xmlnode x) -{ - xmlnode g; - char *who, *name, *sub, *ask; - gaim_jid gjid; - GaimBuddy *b = NULL; - struct jabber_buddy_data *jbd = NULL; - char *buddyname, *groupname = NULL; - - who = xmlnode_get_attrib(x, "jid"); - name = xmlnode_get_attrib(x, "name"); - sub = xmlnode_get_attrib(x, "subscription"); - ask = xmlnode_get_attrib(x, "ask"); - - if((buddyname = get_realwho(gjc, who, FALSE, &gjid)) == NULL) - return; - - - /* JFIXME: jabber_handleroster() had a "FIXME: transport" at this - * equivilent point. So... - * - * We haven't done anything interesting to this point, so we'll - * violate Good Coding Structure here by simply bailing out. - */ - if(!gjid->user) { - g_free(buddyname); - gaim_jid_free(gjid); - return; - } - gaim_jid_free(gjid); - - if((g = xmlnode_get_tag(x, "group")) != NULL) { - groupname = xmlnode_get_data(g); - } - - /* - * Add or remove a buddy? Change buddy's alias or group? - */ - if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) { - if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddyname)) == NULL) { - GaimGroup *g; - b = gaim_buddy_new(GJ_GC(gjc)->account, buddyname, name); - - if(!groupname) - groupname = _("Buddies"); - - if (!(g = gaim_find_group(groupname))) { - g = gaim_group_new(groupname); - gaim_blist_add_group(g, NULL); - } - - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "adding buddy [4]: %s\n", buddyname); - gaim_blist_add_buddy(b, NULL, g, NULL); - gaim_blist_save(); - } else { - gboolean save = FALSE; - GaimGroup *c_grp = gaim_find_buddys_group(b); - - /* - * If the buddy's in a new group or his/her alias is changed... - */ - if(groupname && c_grp && strcmp(c_grp->name, groupname)) { - GaimGroup *g = gaim_find_group(groupname); - if(!g) { - g = gaim_group_new(groupname); - gaim_blist_add_group(g, NULL); - } - - gaim_blist_add_buddy(b, NULL, g, NULL); - save = TRUE; - } - - if(name && (!b->alias || strcmp(b->alias, name))) { - gaim_blist_alias_buddy(b, name); - save = TRUE; - } - - if(save) - gaim_blist_save(); - } - } else if (BUD_USUB_TO_PEND(sub, ask) || BUD_USUBD_TO(sub, ask) || !strcasecmp(sub, "remove")) { - jabber_remove_gaim_buddy(GJ_GC(gjc), buddyname); - } - if(b && (jbd = jabber_find_buddy(b->account->gc, buddyname, TRUE)) != NULL) { - jbd->subscription = JABBER_SUB_NONE; - if(!strcasecmp(sub, "to")) - jbd->subscription |= JABBER_SUB_TO; - else if(!strcasecmp(sub, "from")) - jbd->subscription |= JABBER_SUB_FROM; - else if(!strcasecmp(sub, "both")) - jbd->subscription |= JABBER_SUB_BOTH; - - if(ask && !strcasecmp(ask, "subscribe")) - jbd->subscription |= JABBER_SUB_PENDING; - } - - g_free(buddyname); - -} - -static void jabber_handleroster(gjconn gjc, xmlnode querynode) -{ - xmlnode x; - - x = xmlnode_get_firstchild(querynode); - while (x) { - jabber_handlebuddy(gjc, x); - x = xmlnode_get_nextsibling(x); - } - - x = xmlnode_new_tag("presence"); - gjab_send(gjc, x); - xmlnode_free(x); -} - -static void jabber_handleauthresp(gjconn gjc, jpacket p) -{ - if (jpacket_subtype(p) == JPACKET__RESULT) { - if (xmlnode_has_children(p->x)) { - xmlnode query = xmlnode_get_tag(p->x, "query"); - gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), - 4, JABBER_CONNECT_STEPS); - if (!xmlnode_get_tag(query, "digest")) { - g_free(gjc->sid); - gjc->sid = NULL; - } - gjab_auth(gjc); - } else { - gaim_debug(GAIM_DEBUG_INFO, "jabber", "auth success\n"); - - gaim_connection_set_state(GJ_GC(gjc), GAIM_CONNECTED); - serv_finish_login(GJ_GC(gjc)); - - ((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE; - - gjab_reqroster(gjc); - } - } else { - xmlnode xerr; - char *errmsg = NULL; - int errcode = 0; - - gaim_debug(GAIM_DEBUG_ERROR, "jabber", "auth failed\n"); - xerr = xmlnode_get_tag(p->x, "error"); - if (xerr) { - char msg[BUF_LONG]; - errmsg = xmlnode_get_data(xerr); - if (xmlnode_get_attrib(xerr, "code")) { - errcode = atoi(xmlnode_get_attrib(xerr, "code")); - g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg); - } else - g_snprintf(msg, sizeof(msg), "%s", errmsg); - gaim_connection_error(GJ_GC(gjc), msg); - } else { - gaim_connection_error(GJ_GC(gjc), _("Unknown login error")); - } - } -} - -static void jabber_handleversion(gjconn gjc, xmlnode iqnode) { - xmlnode querynode, x; - char *id, *from; - char os[1024]; - struct utsname osinfo; - - uname(&osinfo); - g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querynode = xmlnode_get_tag(x, "query"); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), VERSION, -1); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1); - - gjab_send(gjc, x); - - xmlnode_free(x); -} - -static void jabber_handletime(gjconn gjc, xmlnode iqnode) { - xmlnode querynode, x; - char *id, *from; - time_t now_t; - struct tm *now; - char buf[1024]; - - time(&now_t); - now = localtime(&now_t); - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, NS_TIME); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querynode = xmlnode_get_tag(x, "query"); - - strftime(buf, 1024, "%Y%m%dT%T", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1); - strftime(buf, 1024, "%Z", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1); - strftime(buf, 1024, "%d %b %Y %T", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1); - - gjab_send(gjc, x); + if(!js->gsc) { + rc = gaim_proxy_connect(account, server, + gaim_account_get_int(account, "port", 5222), + jabber_login_callback, gc); - xmlnode_free(x); -} - -struct jabber_xfer_data { - struct g_url *url; - GString *headers; - gboolean newline; - - char *iq_id; - - struct jabber_data *jd; -}; - -static void jabber_xfer_init(GaimXfer *xfer) -{ - struct jabber_xfer_data *data = xfer->data; - gaim_xfer_start(xfer, -1, data->url->address, data->url->port); -} - -static void jabber_xfer_free(GaimXfer *xfer) -{ - struct jabber_xfer_data *data = xfer->data; - data->jd->file_transfers = g_slist_remove(data->jd->file_transfers, xfer); - - g_string_free(data->headers, TRUE); - g_free(data->url); - g_free(data->iq_id); - g_free(data); - - xfer->data = NULL; -} - -static void jabber_xfer_end(GaimXfer *xfer) -{ - struct jabber_xfer_data *data = xfer->data; - xmlnode x; - - x = xmlnode_new_tag("iq"); - xmlnode_put_attrib(x, "type", "result"); - xmlnode_put_attrib(x, "to", xfer->who); - xmlnode_put_attrib(x, "id", data->iq_id); - - gjab_send(data->jd->gjc, x); - - xmlnode_free(x); - - jabber_xfer_free(xfer); -} - -static void jabber_xfer_start(GaimXfer *xfer) -{ - struct jabber_xfer_data *data = xfer->data; - char *buf = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", - data->url->page, data->url->address); - write(xfer->fd, buf, strlen(buf)); - g_free(buf); -} - -static size_t jabber_xfer_read(char **buffer, GaimXfer *xfer) { - struct jabber_xfer_data *data = xfer->data; - char test; - int size; - - if(read(xfer->fd, &test, sizeof(test)) > 0) { - data->headers = g_string_append_c(data->headers, test); - if(test == '\r') - return 0; - if(test == '\n') { - if(data->newline) { - gchar *lenstr = strstr(data->headers->str, "Content-Length: "); - if(lenstr) { - sscanf(lenstr, "Content-Length: %d", &size); - gaim_xfer_set_size(xfer, size); - } - gaim_xfer_set_read_fnc(xfer, NULL); - return 0; - } else - data->newline = TRUE; - return 0; - } - data->newline = FALSE; - return 0; - } - return 0; -} - -static void jabber_xfer_cancel_send(GaimXfer *xfer) { -} - -static void jabber_xfer_cancel_recv(GaimXfer *xfer) { - struct jabber_xfer_data *data = xfer->data; - xmlnode x,y; - - x = xmlnode_new_tag("iq"); - xmlnode_put_attrib(x, "type", "error"); - xmlnode_put_attrib(x, "to", xfer->who); - xmlnode_put_attrib(x, "id", data->iq_id); - y = xmlnode_insert_tag(x, "error"); - /* FIXME: need to handle other kinds of errors here */ - xmlnode_put_attrib(y, "code", "406"); - xmlnode_insert_cdata(y, "File Transfer Refused", -1); - - gjab_send(data->jd->gjc, x); - - xmlnode_free(x); - - jabber_xfer_free(xfer); -} - -static void jabber_handleoob(gjconn gjc, xmlnode iqnode) { - struct jabber_xfer_data *xfer_data; - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - GaimXfer *xfer; - char *msg = NULL; - char *filename; - xmlnode querynode = xmlnode_get_tag(iqnode, "query"); - xmlnode urlnode,descnode; - - if(!querynode) - return; - urlnode = xmlnode_get_tag(querynode, "url"); - if(!urlnode) - return; - descnode = xmlnode_get_tag(querynode, "desc"); - if(descnode) - msg = xmlnode_get_data(descnode); - - xfer_data = g_new0(struct jabber_xfer_data, 1); - xfer_data->url = parse_url(xmlnode_get_data(urlnode)); - xfer_data->jd = jd; - xfer_data->headers = g_string_new(""); - xfer_data->iq_id = g_strdup(xmlnode_get_attrib(iqnode, "id")); - - xfer = gaim_xfer_new(GJ_GC(gjc)->account, GAIM_XFER_RECEIVE, - xmlnode_get_attrib(iqnode, "from")); - xfer->data = xfer_data; - - filename = g_strdup(g_strrstr(xfer_data->url->page, "/")); - if(!filename) - filename = g_strdup(xfer_data->url->page); - - gaim_xfer_set_filename(xfer, filename); - - g_free(filename); - - gaim_xfer_set_init_fnc(xfer, jabber_xfer_init); - gaim_xfer_set_end_fnc(xfer, jabber_xfer_end); - gaim_xfer_set_cancel_send_fnc(xfer, jabber_xfer_cancel_send); - gaim_xfer_set_cancel_recv_fnc(xfer, jabber_xfer_cancel_recv); - gaim_xfer_set_read_fnc(xfer, jabber_xfer_read); - gaim_xfer_set_start_fnc(xfer, jabber_xfer_start); - - jd->file_transfers = g_slist_append(jd->file_transfers, xfer); - - gaim_xfer_request(xfer); -} - -static void jabber_handlelast(gjconn gjc, xmlnode iqnode) { - xmlnode x, querytag; - char *id, *from; - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - char idle_time[32]; - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querytag = xmlnode_get_tag(x, "query"); - g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0); - xmlnode_put_attrib(querytag, "seconds", idle_time); - - gjab_send(gjc, x); - xmlnode_free(x); -} - -/* - * delete == TRUE: delete found entry - * - * returns pointer to (local) copy of value if found, NULL otherwise - * - * Note: non-reentrant! Local static storage re-used on subsequent calls. - * If you're going to need to keep the returned value, make a copy! - */ -static gchar *jabber_track_queries(GHashTable *queries, gchar *key, gboolean delete) -{ - gpointer my_key, my_val; - static gchar *ret_val = NULL; - - if(ret_val != NULL) { - g_free(ret_val); - ret_val = NULL; - } - - /* self-protection */ - if(queries != NULL && key != NULL) { - if(g_hash_table_lookup_extended(queries, key, &my_key, &my_val)) { - ret_val = g_strdup((gchar *) my_val); - if(delete) { - g_hash_table_remove(queries, key); - g_free(my_key); - g_free(my_val); - } - } + if (rc != 0) + gaim_connection_error(gc, _("Unable to create socket")); } - - return(ret_val); -} - -static void jabber_handlepacket(gjconn gjc, jpacket p) -{ - char *id, *from, *to; - switch (p->type) { - case JPACKET_MESSAGE: - jabber_handlemessage(gjc, p); - break; - case JPACKET_PRESENCE: - jabber_handlepresence(gjc, p); - break; - case JPACKET_IQ: - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jpacket_subtype: %d\n", jpacket_subtype(p)); - - id = xmlnode_get_attrib(p->x, "id"); - if (id != NULL && !strcmp(id, IQID_AUTH)) { - jabber_handleauthresp(gjc, p); - break; - } - - if (jpacket_subtype(p) == JPACKET__SET) { - xmlnode querynode; - querynode = xmlnode_get_tag(p->x, "query"); - from = xmlnode_get_attrib(p->x, "from"); - to = xmlnode_get_attrib(p->x, "to"); - if (NSCHECK(querynode, "jabber:iq:roster") && (!from || !strcmp(from, to))) { - jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode)); - } else if(NSCHECK(querynode, "jabber:iq:oob")) { - jabber_handleoob(gjc, p->x); - } - } else if (jpacket_subtype(p) == JPACKET__GET) { - xmlnode querynode; - querynode = xmlnode_get_tag(p->x, "query"); - if (NSCHECK(querynode, NS_VERSION)) { - jabber_handleversion(gjc, p->x); - } else if (NSCHECK(querynode, NS_TIME)) { - jabber_handletime(gjc, p->x); - } else if (NSCHECK(querynode, "jabber:iq:last")) { - jabber_handlelast(gjc, p->x); - } - } else if (jpacket_subtype(p) == JPACKET__RESULT) { - xmlnode querynode, vcard; - char *xmlns, *from; - - /* - * TBD: ISTM maybe this part could use a serious re-work? - */ - from = xmlnode_get_attrib(p->x, "from"); - querynode = xmlnode_get_tag(p->x, "query"); - vcard = xmlnode_get_tag(p->x, "vCard"); - if (!vcard) - vcard = xmlnode_get_tag(p->x, "VCARD"); - - if (NSCHECK(querynode, NS_ROSTER)) { - jabber_handleroster(gjc, querynode); - } else if (NSCHECK(querynode, NS_VCARD)) { - jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ - jabber_handlevcard(gjc, querynode, from); - } else if (vcard) { - jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ - jabber_handlevcard(gjc, vcard, from); - } else if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL) { - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jabber:iq:query: %s\n", xmlns); - } else { - char *val; - - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jabber:iq: %s\n", xmlnode2str(p->x)); - - /* handle "null" query results */ - if((val = jabber_track_queries(gjc->queries, id, TRUE)) != NULL) { - if(strcmp((char *) val, "vCard") == 0) { - /* - * No actual vCard, but there's other stuff. This - * way the user always gets some kind of response. - */ - jabber_handlevcard(gjc, NULL, from); - } else if(!strcmp((char *) val, "change_password")) { - char buf[BUF_LONG]; - sprintf(buf, _("Password successfully changed.")); - - gaim_notify_info(GJ_GC(gjc), NULL, buf, NULL); - } - } - } - - } else if (jpacket_subtype(p) == JPACKET__ERROR) { - xmlnode xerr; - char *from, *errmsg = NULL; - int errcode = 0; - - from = xmlnode_get_attrib(p->x, "from"); - xerr = xmlnode_get_tag(p->x, "error"); - if (xerr) { - errmsg = xmlnode_get_data(xerr); - if (xmlnode_get_attrib(xerr, "code")) - errcode = atoi(xmlnode_get_attrib(xerr, "code")); - } - - from = g_strdup_printf("Jabber Error %d (%s)", errcode, from); - gaim_notify_error(GJ_GC(gjc), NULL, from, errmsg); - g_free(from); - - } - - break; - case JPACKET_S10N: - jabber_handles10n(gjc, p); - break; - default: - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x)); - } - - xmlnode_free(p->x); - - return; -} - -static void jabber_handlestate(gjconn gjc, int state) -{ - switch (state) { - case JCONN_STATE_OFF: - if(gjc->was_connected) { - gaim_connection_error(GJ_GC(gjc), _("Connection lost")); - } else { - gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); - } - break; - case JCONN_STATE_CONNECTED: - gjc->was_connected = 1; - gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), 2, JABBER_CONNECT_STEPS); - break; - case JCONN_STATE_ON: - gaim_connection_update_progress(GJ_GC(gjc), _("Requesting Authentication Method"), 3, JABBER_CONNECT_STEPS); - gjab_reqauth(gjc); - break; - default: - gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); - } - return; -} - -static void jabber_login(GaimAccount *account) -{ - GaimConnection *gc = gaim_account_get_connection(account); - struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); - char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); - - gc->flags |= GAIM_CONNECTION_HTML; - - jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); - jd->chats = NULL; /* we have no chats yet */ - - gaim_connection_update_progress(gc, _("Connecting"), 1, JABBER_CONNECT_STEPS); - - if (!(jd->gjc = gjab_new(loginname, account->password, gc))) { - g_free(loginname); - gaim_debug(GAIM_DEBUG_ERROR, "jabber", - "unable to connect (jab_new failed)\n"); - gaim_connection_error(gc, _("Unable to connect")); - return; - } - - g_free(loginname); - gjab_state_handler(jd->gjc, jabber_handlestate); - gjab_packet_handler(jd->gjc, jabber_handlepacket); - jd->gjc->queries = g_hash_table_new(g_str_hash, g_str_equal); - gjab_start(jd->gjc); -} - -static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { - g_free(key); - g_free(val); - return TRUE; -} - -static gboolean jabber_destroy_buddy_hash(gpointer key, gpointer val, gpointer data) { - struct jabber_buddy_data *jbd = val; - while (jbd->resources) { - g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->name); - if(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg) - g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg); - g_free(((GSList *)jbd->resources)->data); - jbd->resources = g_slist_remove(jbd->resources, ((GSList *)jbd->resources)->data); - - } - if(jbd->error_msg) - g_free(jbd->error_msg); - g_free(key); - g_free(jbd); - return TRUE; -} - - -static gboolean jabber_free(gpointer data) -{ - struct jabber_data *jd = data; - - if(jd->gjc != NULL) { - g_free(jd->gjc->sid); - gjab_delete(jd->gjc); - jd->gjc = NULL; - } - g_free(jd); - - return FALSE; } static void jabber_close(GaimConnection *gc) { - struct jabber_data *jd = gc->proto_data; - - if(jd) { - GSList *jcs = jd->chats; - - /* Free-up the jabber_chat struct allocs and the list */ - while (jcs) { - gaim_jid_free(((struct jabber_chat *)jcs->data)->gjid); - g_free(jcs->data); - jcs = jcs->next; - } - g_slist_free(jd->chats); - - /* Free-up the buddy data hash */ - if(jd->buddies != NULL) - { - g_hash_table_foreach_remove(jd->buddies, jabber_destroy_buddy_hash, NULL); - g_hash_table_destroy(jd->buddies); - jd->buddies = NULL; - } + JabberStream *js = gc->proto_data; - /* Free-up the pending queries memories and the list */ - if(jd->gjc != NULL && jd->gjc->queries != NULL) { - g_hash_table_foreach_remove(jd->gjc->queries, jabber_destroy_hash, NULL); - g_hash_table_destroy(jd->gjc->queries); - jd->gjc->queries = NULL; - } - } - if (gc->inpa) - gaim_input_remove(gc->inpa); - - if(jd) { - g_timeout_add(0, jabber_free, jd); - if(jd->gjc != NULL) - xmlnode_free(jd->gjc->current); - } - gc->proto_data = NULL; -} - -static int jabber_send_typing(GaimConnection *gc, const char *who, int typing) -{ - xmlnode x, y; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - jab_res_info jri = jabber_find_resource(gc, who); + jabber_send_raw(js, "</stream:stream>"); - if(!jri || !jri->has_composing) - return 0; - - if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) - return 0; - - x = xmlnode_new_tag("message"); - xmlnode_put_attrib(x, "to", realwho); - - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); - - if(typing == GAIM_TYPING) - xmlnode_insert_tag(y, "composing"); - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - g_free(realwho); - return JABBER_TYPING_NOTIFY_INT; -} + if(js->gsc) { + gaim_ssl_close(js->gsc); + } else { + close(js->fd); + } -static void insert_message(xmlnode x, const char *message, gboolean use_xhtml) { - xmlnode y; - char *buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body>%s</body></html>", message); - char *xhtml, *plain; - - html_to_xhtml(buf, &xhtml, &plain); - g_free(buf); - - y = xmlnode_insert_tag(x, "body"); - xmlnode_insert_cdata(y, plain, -1); - g_free(plain); + g_markup_parse_context_free(js->context); - if(use_xhtml) { - y = xmlnode_str(xhtml, strlen(xhtml)); - if(y) { - xmlnode_insert_tag_node(x, y); - xmlnode_free(y); - } else { - gaim_debug(GAIM_DEBUG_ERROR, "jabber", - "holy cow, html_to_xhtml didn't work right!\n"); - gaim_debug(GAIM_DEBUG_ERROR, "jabber", - "the invalid XML: %s\n", xhtml); - } - } - g_free(xhtml); + g_hash_table_destroy(js->callbacks); + g_hash_table_destroy(js->buddies); + if(js->stream_id) + g_free(js->stream_id); + jabber_id_free(js->user); + g_free(js); } -static int jabber_send_im(GaimConnection *gc, const char *who, const char *message, GaimImFlags flags) -{ - xmlnode x, y; - char *thread_id = NULL; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - jab_res_info jri = jabber_find_resource(gc, who); - - if (!who || !message) - return 0; - - x = xmlnode_new_tag("message"); - xmlnode_put_attrib(x, "to", who); - - thread_id = jabber_get_convo_thread(gjc, who); - if(thread_id) - { - if(strcmp(thread_id, "")) { - y = xmlnode_insert_tag(x, "thread"); - xmlnode_insert_cdata(y, thread_id, -1); - } - g_free(thread_id); - } - - xmlnode_put_attrib(x, "type", "chat"); - - /* let other clients know we support typing notification */ - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); - xmlnode_insert_tag(y, "composing"); - - if (message && strlen(message)) { - insert_message(x, message, jri ? jri->has_xhtml : TRUE); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - return 1; -} - -/* - * Add/update buddy's roster entry on server - * - * If "alias" or "group" are NULL, gets them from Gaim's current buddylist values - * for the buddy. - */ -static void jabber_roster_update(GaimConnection *gc, const char *name, const char *alias, const char *group) +void jabber_stream_set_state(JabberStream *js, JabberStreamState state) { - xmlnode x, y; - char *realwho; - gjconn gjc; - GaimBuddy *buddy = NULL; - GaimGroup *buddy_group = NULL; - const char *my_alias = NULL; - const char *my_group = NULL; - - if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) { - gaim_jid gjid; - gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) - return; - - /* FIXME: transport */ - if(gjid->user == NULL) { - g_free(realwho); - gaim_jid_free(gjid); - return; - } - gaim_jid_free(gjid); - - x = jutil_iqnew(JPACKET__SET, NS_ROSTER); - y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); - xmlnode_put_attrib(y, "jid", realwho); - - buddy = gaim_find_buddy(gc->account, realwho); - - /* - * See if there's an explict (new?) alias for the buddy or we can pull - * one out of current Gaim buddylist data for him. - */ - if(alias && alias[0] != '\0') { - my_alias = alias; - } else if(buddy && buddy->alias) { - my_alias = buddy->alias; - } - - /* If there's an alias for the buddy, it's not 0-length - * and it doesn't match his JID, add the "name" attribute. - */ - if(my_alias != NULL && my_alias[0] != '\0' && strcmp(realwho, my_alias)) - { - xmlnode_put_attrib(y, "name", my_alias); - } - - /* - * See if there's an explict (new?) group for the buddy or pull - * one out of current Gaim buddylist data for him. - */ - if(group && group[0] != '\0') { - my_group = group; - } else if((buddy_group = gaim_find_buddys_group(buddy)) != NULL) { - my_group = buddy_group->name; - } - - /* - * Send what group the buddy's in along with the roster item. - */ - if(my_group != NULL && my_group[0] != '\0') { - xmlnode z = xmlnode_insert_tag(y, "group"); - xmlnode_insert_cdata(z, my_group, -1); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - - xmlnode_free(x); - g_free(realwho); + js->state = state; + switch(state) { + case JABBER_STREAM_OFFLINE: + break; + case JABBER_STREAM_CONNECTING: + gaim_connection_update_progress(js->gc, _("Connecting"), 1, + JABBER_CONNECT_STEPS); + break; + case JABBER_STREAM_INITIALIZING: + gaim_connection_update_progress(js->gc, _("Initializing Stream"), + js->gsc ? 5 : 2, JABBER_CONNECT_STEPS); + jabber_stream_init(js); + jabber_parser_setup(js); + break; + case JABBER_STREAM_AUTHENTICATING: + gaim_connection_update_progress(js->gc, _("Authenticating"), + js->gsc ? 6 : 3, JABBER_CONNECT_STEPS); + if(js->protocol_version == JABBER_PROTO_0_9) + jabber_auth_start_old(js); + break; + case JABBER_STREAM_REINITIALIZING: + gaim_connection_update_progress(js->gc, _("Re-initializing Stream"), + 6, JABBER_CONNECT_STEPS); + jabber_stream_init(js); + break; + case JABBER_STREAM_CONNECTED: + gaim_connection_set_state(js->gc, GAIM_CONNECTED); + jabber_roster_request(js); + jabber_presence_send(js->gc, js->gc->away_state, js->gc->away); + serv_finish_login(js->gc); + break; } } -/* - * Add/update buddy's alias on server - * - * This is just a roster update using existing, local buddylist data - */ -static void jabber_alias_buddy(GaimConnection *gc, const char *name, const char *alias) -{ - jabber_roster_update(gc, name, alias, NULL); -} - -/* - * Change buddy's group on server roster - */ -static void jabber_group_change(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) -{ - if(old_group && new_group && strcmp(old_group, new_group)) - jabber_roster_update(gc, name, NULL, new_group); -} - -/* - * Group rename - * - * Jabber doesn't have "groups," per se. "Group" is simply a JID attribute. - * So we iterate through the list of buddies that are in the group and change - * the group attribute for each of them. - */ -static void jabber_rename_group(GaimConnection *gc, - const char *old_group, - const char *new_group, - GList *members) -{ - if(old_group && new_group && strcmp(old_group, new_group)) - while(members) { - jabber_group_change(gc, (char *)(members->data), old_group, new_group); - members = members->next; - } -} - -static void jabber_add_buddy(GaimConnection *gc, const char *name, GaimGroup *group) +char *jabber_get_next_id(JabberStream *js) { - xmlnode x; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - gaim_jid gjid; - GaimAccount *account = gaim_connection_get_account(gc); - - if (!((struct jabber_data *)gc->proto_data)->did_import) - return; - - /* - * If there's no name or the name is ourself - */ - if(!name || !strcmp(gaim_account_get_username(account), name)) - return; - - if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) { - char *msg = g_strdup_printf(_("The user %s is an invalid Jabber I.D. and was " - "therefore not added."), name); - gaim_notify_error(gc, NULL, _("Unable to add buddy."), - _("Jabber Error")); - g_free(msg); - jabber_remove_gaim_buddy(gc, name); - return; - } - - /* FIXME: transport */ - if(gjid->user == NULL) { - g_free(realwho); - gaim_jid_free(gjid); - return; - } - gaim_jid_free(gjid); - - x = xmlnode_new_tag("presence"); - xmlnode_put_attrib(x, "to", realwho); - xmlnode_put_attrib(x, "type", "subscribe"); - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - - jabber_roster_update(gc, realwho, NULL, NULL); - - g_free(realwho); -} - -static void jabber_remove_buddy(GaimConnection *gc, const char *name, const char *group) -{ - xmlnode x; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) - return; - - x = xmlnode_new_tag("presence"); - xmlnode_put_attrib(x, "to", realwho); - xmlnode_put_attrib(x, "type", "unsubscribe"); - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - g_free(realwho); - xmlnode_free(x); + return g_strdup_printf("gaim%d", js->next_id++); } -#if 0 /* Faceprint! Look here! */ -/* - * Remove a buddy item from the roster entirely - */ -static void jabber_remove_buddy_roster_item(GaimConnection *gc, char *name) -{ - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - char *realwho; - - if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { - xmlnode x = jutil_iqnew(JPACKET__SET, NS_ROSTER); - xmlnode y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); - xmlnode_put_attrib(y, "jid", realwho); - xmlnode_put_attrib(y, "subscription", "remove"); - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - g_free(realwho); - xmlnode_free(x); - } -} -#endif - -/* - * Unsubscribe a buddy from our presence - */ -static void jabber_unsubscribe_buddy_from_us(GaimConnection *gc, const char *name) +void jabber_idle_set(GaimConnection *gc, int idle) { - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - char *realwho; - - if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { - xmlnode g = xmlnode_new_tag("presence"); - xmlnode_put_attrib(g, "to", realwho); - xmlnode_put_attrib(g, "type", "unsubscribed"); - gjab_send(gjc, g); - xmlnode_free(g); - } -} - -/* - * Common code for setting ourselves invisible/visible to buddy - */ -static void jabber_invisible_to_buddy_common(GaimConnection *gc, const char *name, gboolean invisible) -{ - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - char *realwho; - - if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, TRUE); - xmlnode g = xmlnode_new_tag("presence"); - - xmlnode_put_attrib(g, "to", realwho); - - if(invisible) - xmlnode_put_attrib(g, "type", "invisible"); - - gjab_send(gjc, g); - - g_free(realwho); - xmlnode_free(g); + JabberStream *js = gc->proto_data; - if(jbd) { - if(invisible) { - jbd->invisible |= JABBER_BUD_INVIS; - } else { - jbd->invisible &= ~JABBER_BUD_INVIS; - } - } - } -} - -/* - * Make ourselves temporarily invisible to a buddy - */ -static void jabber_invisible_to_buddy(GaimConnection *gc, const char *name) -{ - jabber_invisible_to_buddy_common(gc, name, TRUE); -} - -/* - * Make ourselves visible to a buddy - */ -static void jabber_visible_to_buddy(GaimConnection *gc, const char *name) -{ - jabber_invisible_to_buddy_common(gc, name, FALSE); -} - -/* - * Function used by the g_hash_table_foreach() in invisible_to_all_buddies() to - * actually set the status. - * - * key is unused - * value is the pointer to the jabber_buddy_data struct - * data is gboolean: TRUE (invisible) or FALSE (not invisible) - */ -static void set_invisible_to_buddy_status(gpointer key, gpointer val, gpointer data) { - struct jabber_buddy_data *jbd = val; - gboolean invisible = GPOINTER_TO_INT(data); - - if(jbd) { - if(invisible) { - jbd->invisible = JABBER_SERV_INVIS | JABBER_BUD_INVIS; - } else { - /* - * If we've asserted server-level invisibility, cancelling - * it removes explicit buddy invisibility settings too. - */ - if(jbd->invisible & JABBER_SERV_INVIS) - jbd->invisible = JABBER_NOT_INVIS; - } - } -} - -/* - * Show we've set ourselves invisible/visible to all buddies on the server - * - * Used when we set server-wide invisibility so that individual buddy menu - * entries show the proper option. - */ -static void invisible_to_all_buddies(GaimConnection *gc, gboolean invisible) -{ - struct jabber_data *jd = gc->proto_data; - - if(jd->buddies != NULL) - g_hash_table_foreach(jd->buddies, set_invisible_to_buddy_status, GINT_TO_POINTER(invisible)); + js->idle = idle ? time(NULL) - idle : idle; } static const char *jabber_list_icon(GaimAccount *a, GaimBuddy *b) @@ -2954,578 +451,110 @@ return "jabber"; } -static void jabber_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne) +static void jabber_list_emblems(GaimBuddy *b, char **se, char **sw, + char **nw, char **ne) { - struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); + JabberStream *js; + JabberBuddy *jb; + + if(!b->account->gc) + return; + js = b->account->gc->proto_data; + jb = jabber_buddy_find(js, b->name, FALSE); if(!GAIM_BUDDY_IS_ONLINE(b)) { - if (jbd && jbd->error_msg) + if(jb && jb->error_msg) *nw = "error"; - if(jbd && (jbd->subscription & JABBER_SUB_PENDING || - !(jbd->subscription & JABBER_SUB_TO))) + if(jb && (jb->subscription & JABBER_SUB_PENDING || + !(jb->subscription & JABBER_SUB_TO))) *se = "notauthorized"; else *se = "offline"; - } else { switch (b->uc) { - case UC_AWAY: - *se = "away"; - break; - case UC_CHAT: - *se = "chat"; - break; - case UC_XA: - *se = "extendedaway"; - break; - case UC_DND: - *se = "dnd"; - break; - case UC_ERROR: - *se = "error"; - break; + case JABBER_STATE_AWAY: + *se = "away"; + break; + case JABBER_STATE_CHAT: + *se = "chat"; + break; + case JABBER_STATE_XA: + *se = "extendedaway"; + break; + case JABBER_STATE_DND: + *se = "extendedaway"; + break; + case JABBER_STATE_ERROR: + *se = "error"; + break; } } } -static GList *jabber_chat_info(GaimConnection *gc) +static char *jabber_status_text(GaimBuddy *b) { - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - static char *confserv = NULL; /* this pointer must be persistent */ - gchar *server; - - GList *m = NULL; - struct proto_chat_entry *pce; - - /* This is a scientific wild-ass guess... - * - * If there are more than two "components" to the current server name, - * lop-off the left-most component and replace with "conference." - */ - if(confserv != NULL) { - g_free(confserv); /* dispose of the old value */ - } - - if((server = g_strdup(gjc->user->server)) == NULL) { - confserv = g_strdup(DEFAULT_GROUPCHAT); - } else { - gchar **splits, **index; - gchar *tmp; - int cnt = 0; - - - index = splits = g_strsplit(server, ".", -1); /* split the connected server */ - - while(*(index++)) /* index to the end--counting the parts */ - ++cnt; - - /* - * If we've more than two parts, point to the second part. Else point - * to the start. - */ - if(cnt > 2) { - index -= cnt; - } else { - index = splits; - } - - /* Put it together */ - confserv = g_strjoin(".", "conference", (tmp = g_strjoinv(".", index)), NULL); - - g_free(server); /* we don't need this stuff no more */ - g_free(tmp); - g_strfreev(splits); - } - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("Room:"); - pce->identifier = "room"; - m = g_list_append(m, pce); - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("Server:"); - pce->identifier = "server"; - pce->def = confserv; - m = g_list_append(m, pce); - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("Handle:"); - pce->identifier = "handle"; - pce->def = gjc->user->user; - m = g_list_append(m, pce); - - return m; -} - -static void jabber_join_chat(GaimConnection *gc, GHashTable *data) -{ - xmlnode x; - char *room, *server, *handle; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc; - gaim_jid gjid; - - room = g_hash_table_lookup(data, "room"); - server = g_hash_table_lookup(data, "server"); - handle = g_hash_table_lookup(data, "handle"); + JabberBuddy *jb = jabber_buddy_find(b->account->gc->proto_data, b->name, + FALSE); + char *ret = NULL; - if (!room || !server || !handle) - return; - - realwho = create_valid_jid(room, server, handle); - gaim_debug(GAIM_DEBUG_INFO, "jabber", "%s\n", realwho); - - if((gjid = gaim_jid_new(realwho)) == NULL) { - char *msg = g_strdup_printf("The Jabber I.D. %s is invalid.", realwho); - gaim_notify_error(gc, NULL, _("Unable to join chat"), msg); - g_free(msg); - g_free(realwho); - return; - } - - if((jc = find_any_chat(gc, gjid)) != NULL) { - switch(jc->state) { - case JCS_PENDING: - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "attempt to re-join already pending Jabber chat! (ignoring)\n"); - g_free(realwho); /* yuck! */ - gaim_jid_free(gjid); - return; - case JCS_ACTIVE: - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "attempt to re-join already active Jabber chat! (ignoring)\n"); - g_free(realwho); /* yuck! */ - gaim_jid_free(gjid); - return; - case JCS_CLOSED: - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "rejoining previously closed Jabber chat\n"); - break; - default: - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "found Jabber chat in unknown state! (ignoring)\n"); - g_free(realwho); /* yuck! */ - gaim_jid_free(gjid); - return; - } + if(jb && !GAIM_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) { + ret = g_strdup(_("Not Authorized")); + } else if(jb && !GAIM_BUDDY_IS_ONLINE(b) && jb->error_msg) { + ret = g_strdup(jb->error_msg); } else { - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "joining completely new Jabber chat\n"); - jc = g_new0(struct jabber_chat, 1); - jc->gjid = gjid; - jc->gc = gc; - ((struct jabber_data *)gc->proto_data)->chats = g_slist_append(jcs, jc); - // add_buddy(gc->account, _("Chats"), realwho, realwho); - } + char *stripped = strip_html(jabber_buddy_get_status_msg(jb)); - jc->state = JCS_PENDING; - - x = jutil_presnew(0, realwho, NULL); - gjab_send(gjc, x); - xmlnode_free(x); - g_free(realwho); -} + if(!stripped && b->uc & UC_UNAVAILABLE) + stripped = g_strdup(jabber_get_state_string(b->uc)); -static void jabber_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) -{ - xmlnode x, y; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - struct jabber_chat *jc = NULL; - char *realwho, *subject; - - if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) - return; - - /* find which chat we're inviting to */ - if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) - return; - - x = xmlnode_new_tag("message"); - xmlnode_put_attrib(x, "to", realwho); - - g_free(realwho); - - y = xmlnode_insert_tag(x, "x"); - xmlnode_put_attrib(y, "xmlns", "jabber:x:conference"); - subject = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); - xmlnode_put_attrib(y, "jid", subject); - g_free(subject); - - if (message && strlen(message)) { - insert_message(x, message, FALSE); + if(stripped) { + ret = g_markup_escape_text(stripped, -1); + g_free(stripped); + } } - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); -} - -static void jabber_chat_leave(GaimConnection *gc, int id) -{ - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - struct jabber_chat *jc = NULL; - char *chatname; - xmlnode x; - - /* Find out which chat we're leaving */ - if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) - return; - - chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); - x = jutil_presnew(0, chatname, NULL); - g_free(chatname); - xmlnode_put_attrib(x, "type", "unavailable"); - gjab_send(gjc, x); - xmlnode_free(x); - jc->b = NULL; -} - -static int jabber_chat_send(GaimConnection *gc, int id, const char *message) -{ - xmlnode x, y; - struct jabber_chat *jc = NULL; - char *chatname; - int retval = 0; - - /* Find out which chat we're sending to */ - if((retval = jabber_find_chat_by_convo_id(gc, id, &jc)) != 0) - return(retval); - - x = xmlnode_new_tag("message"); - xmlnode_put_attrib(x, "from", jc->gjid->full); - chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); - xmlnode_put_attrib(x, "to", chatname); - g_free(chatname); - xmlnode_put_attrib(x, "type", "groupchat"); - - if (message && strlen(message) > strlen("/topic ") && - !g_ascii_strncasecmp(message, "/topic ", strlen("/topic "))) { - char buf[8192]; - y = xmlnode_insert_tag(x, "subject"); - xmlnode_insert_cdata(y, message + strlen("/topic "), -1); - y = xmlnode_insert_tag(x, "body"); - g_snprintf(buf, sizeof(buf), "/me has changed the subject to: %s", message + strlen("/topic")); - xmlnode_insert_cdata(y, buf, -1); - } else if (message && strlen(message)) { - insert_message(x, message, FALSE); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - return 0; -} - -static void jabber_chat_whisper(GaimConnection *gc, int id, const char *who, const char *message) -{ - xmlnode x; - struct jabber_chat *jc = NULL; - char *chatname; - - /* Find out which chat we're whispering to */ - if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) - return; - - x = xmlnode_new_tag("message"); - xmlnode_put_attrib(x, "from", jc->gjid->full); - chatname = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); - xmlnode_put_attrib(x, "to", chatname); - g_free(chatname); - xmlnode_put_attrib(x, "type", "normal"); - - if (message && strlen(message)) { - insert_message(x, message, FALSE); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); -} - -static char *jabber_normalize(const char *s) -{ - static char buf[BUF_LEN]; - char *t, *u; - int x = 0; - - g_return_val_if_fail((s != NULL), NULL); - - /* Somebody called us with s == NULL once... */ - if(s == NULL) { - return(NULL); - } else { - u = t = g_utf8_strdown(s, -1); - - while (*t && (x < BUF_LEN - 1)) { - if (*t != ' ') - buf[x++] = *t; - t++; - } - buf[x] = '\0'; - g_free(u); - - if (!strchr(buf, '@')) { - strcat(buf, "@" DEFAULT_SERVER); /* this isn't always right, but eh */ - } else if ((u = strchr(strchr(buf, '@'), '/')) != NULL) { - *u = '\0'; - } - - return buf; - } -} - -static void jabber_get_info(GaimConnection *gc, const char *who) { - xmlnode x; - char *id; - char *realwho; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - - if((realwho = get_realwho(gjc, who, TRUE, NULL)) == NULL) - return; - - x = jutil_iqnew(JPACKET__GET, NS_VCARD); - xmlnode_put_attrib(x, "to", realwho); - - g_free(realwho); - - id = gjab_getid(gjc); - xmlnode_put_attrib(x, "id", id); - - g_hash_table_insert(jd->gjc->queries, g_strdup(id), g_strdup("vCard")); - - gjab_send(gjc, x); - - xmlnode_free(x); -} - -static void jabber_get_error_msg(GaimConnection *gc, const char *who) { - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - gchar **str_arr = (gchar **) g_new(gpointer, 3); - gchar **ap = str_arr; - gchar *realwho, *final; - struct jabber_buddy_data *jbd; - - if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) { - g_strfreev(str_arr); - return; - } - - jbd = jabber_find_buddy(gc, realwho, TRUE); - - *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); - *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Error"), jbd->error_msg); - *ap = NULL; - - final= g_strjoinv(NULL, str_arr); - - g_strfreev(str_arr); - - g_show_info_text(gc, realwho, 2, final, NULL); - g_free(realwho); - g_free(final); -} - -static void jabber_get_away_msg(GaimConnection *gc, const char *who) { - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - int num_resources; - gaim_jid gjid; - char *buddy = get_realwho(gjc, who, FALSE, &gjid); - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); - gchar **str_arr; - gchar **ap; - gchar *realwho, *final; - GSList *resources; - int i; - - if(!buddy) - return; - - if(!gjid->resource) { - num_resources = g_slist_length(jbd->resources); - resources = jbd->resources; - } else { - num_resources = 1; - resources = jbd->resources; - while(strcasecmp(((jab_res_info)resources->data)->name, gjid->resource)) - resources = resources->next; - } - - gaim_jid_free(gjid); - - /* space for all elements: Jabber I.D. + "status" + NULL (list terminator) */ - str_arr = (gchar **) g_new(gpointer, num_resources*2 + 1); - ap = str_arr; - - for(i=0; i<num_resources; i++) - { - jab_res_info jri = resources->data; - char *status; - realwho = g_strdup_printf("%s/%s", buddy, jri->name); - status = strdup_withhtml(jabber_lookup_away(gjc, realwho)); - *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); - *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", _("Status"), jabber_get_state_string(jri->state), status ? ": " : "", status ? status : ""); - g_free(status); - g_free(realwho); - resources = resources->next; - } - - *ap = NULL; - - g_free(buddy); - - final= g_strjoinv(NULL, str_arr); - g_strfreev(str_arr); - - g_show_info_text(gc, who, 2, final, NULL); - g_free(final); - -} - -static void jabber_get_cb_info(GaimConnection *gc, int cid, const char *who) { - struct jabber_chat *jc = NULL; - char *realwho; - - /* Find out which chat */ - if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) - return; - - realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); - - jabber_get_info(gc, realwho); - g_free(realwho); -} - -static void jabber_get_cb_away_msg(GaimConnection *gc, int cid, const char *who) { - struct jabber_chat *jc = NULL; - char *realwho; - - /* Find out which chat */ - if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) - return; - - realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); - - jabber_get_away_msg(gc, realwho); - g_free(realwho); - + return ret; } static char *jabber_tooltip_text(GaimBuddy *b) { - struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); - jab_res_info jri = jabber_find_resource(b->account->gc, b->name); + JabberBuddy *jb = jabber_buddy_find(b->account->gc->proto_data, b->name, + FALSE); + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, NULL); char *ret = NULL; - if(jri) { - char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), - b->name)); + + if(jbr) { char *text = NULL; - if(stripped) - text = g_markup_escape_text(stripped, strlen(stripped)); + if(jbr->status) { + char *stripped; + stripped = strip_html(jbr->status); + text = g_markup_escape_text(stripped, -1); + g_free(stripped); + } + ret = g_strdup_printf("<b>%s:</b> %s%s%s", _("Status"), - jabber_get_state_string(jri->state), text ? ": " : "", + jabber_get_state_string(jbr->state), + text ? ": " : "", text ? text : ""); - - if(stripped) { - g_free(stripped); + if(text) g_free(text); - } - } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && - (jbd->subscription & JABBER_SUB_PENDING || - !(jbd->subscription & JABBER_SUB_TO))) { - ret = g_strdup_printf("<b>%s:</b> %s", _("Status"), _("Not Authorized")); + } else if(jb && !GAIM_BUDDY_IS_ONLINE(b) && jb->error_msg) { + ret = g_strdup_printf("<b>%s:</b> %s", + _("Error"), jb->error_msg); + } else if(jb && !GAIM_BUDDY_IS_ONLINE(b) && + (jb->subscription & JABBER_SUB_PENDING || + !(jb->subscription & JABBER_SUB_TO))) { + ret = g_strdup_printf("<b>%s:</b> %s", + _("Status"), _("Not Authorized")); } - return ret; -} -static char *jabber_status_text(GaimBuddy *b) -{ - struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); - char *ret = NULL; - if (b->uc & UC_UNAVAILABLE) { - char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), - b->name)); - if(!stripped) { - jab_res_info jri = jabber_find_resource(b->account->gc, b->name); - if(jri) - stripped = g_strdup(jabber_get_state_string(jri->state)); - } - ret = g_markup_escape_text(stripped, strlen(stripped)); - g_free(stripped); - } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && - (jbd->subscription & JABBER_SUB_PENDING || - !(jbd->subscription & JABBER_SUB_TO))) { - ret = g_strdup(_("Not Authorized")); - } return ret; } -static void jabber_rereq_auth(GaimConnection *gc, const char *who) { - jabber_add_buddy(gc, who, NULL); -} - -static GList *jabber_buddy_menu(GaimConnection *gc, const char *who) { - GList *m = NULL; - struct proto_buddy_menu *pbm; - GaimBuddy *b = gaim_find_buddy(gc->account, who); - - if(b->uc == UC_ERROR) - { - pbm = g_new0(struct proto_buddy_menu, 1); - pbm->label = _("View Error Msg"); - pbm->callback = jabber_get_error_msg; - pbm->gc = gc; - m = g_list_append(m, pbm); - } else { - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - char *realwho = get_realwho(gjc, who, FALSE, NULL); - struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, FALSE); - - g_free(realwho); - - pbm = g_new0(struct proto_buddy_menu, 1); - pbm->label = _("Get Away Msg"); - pbm->callback = jabber_get_away_msg; - pbm->gc = gc; - m = g_list_append(m, pbm); - - pbm = g_new0(struct proto_buddy_menu, 1); - if(jbd && (jbd->invisible & JABBER_BUD_INVIS)) { - pbm->label = _("Un-hide From"); - pbm->callback = jabber_visible_to_buddy; - } else { - pbm->label = _("Temporarily Hide From"); - pbm->callback = jabber_invisible_to_buddy; - } - - pbm->gc = gc; - m = g_list_append(m, pbm); - pbm = g_new0(struct proto_buddy_menu, 1); - pbm->label = _("Cancel Presence Notification"); - pbm->callback = jabber_unsubscribe_buddy_from_us; - pbm->gc = gc; - m = g_list_append(m, pbm); - - if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && - !(jbd->subscription & JABBER_SUB_TO)) { - pbm = g_new0(struct proto_buddy_menu, 1); - pbm->label = _("Re-request authorization"); - pbm->callback = jabber_rereq_auth; - pbm->gc = gc; - m = g_list_append(m, pbm); - } - } - - return m; -} - -static GList *jabber_away_states(GaimConnection *gc) { +static GList *jabber_away_states(GaimConnection *gc) +{ GList *m = NULL; m = g_list_append(m, _("Online")); @@ -3539,864 +568,6 @@ return m; } -static void jabber_set_away(GaimConnection *gc, const char *state, const char *message) -{ - xmlnode x, y; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - GSList *jcs; - struct jabber_chat *jc; - char *chatname; - gboolean invisible = FALSE; - - if (gc->away) { - g_free(gc->away); - gc->away = NULL; - } - - x = xmlnode_new_tag("presence"); - - if (!strcmp(state, GAIM_AWAY_CUSTOM)) { - /* oh goody. Gaim is telling us what to do. */ - if (message) { - /* Gaim wants us to be away */ - char *stripped; - - /* Jabber supports XHTML in IMs, but not in away messages. */ - html_to_xhtml(message, NULL, &stripped); - - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "away", -1); - y = xmlnode_insert_tag(x, "status"); - xmlnode_insert_cdata(y, stripped, -1); - - gc->away = g_strdup(stripped); - g_free(stripped); - } else { - /* Gaim wants us to not be away */ - /* but for Jabber, we can just send presence with no other information. */ - } - } else { - /* state is one of our own strings. it won't be NULL. */ - if (!strcmp(state, _("Online"))) { - /* once again, we don't have to put anything here */ - } else if (!strcmp(state, _("Chatty"))) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "chat", -1); - gc->away = g_strdup(""); - } else if (!strcmp(state, _("Away"))) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "away", -1); - gc->away = g_strdup(""); - } else if (!strcmp(state, _("Extended Away"))) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "xa", -1); - gc->away = g_strdup(""); - } else if (!strcmp(state, _("Do Not Disturb"))) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "dnd", -1); - gc->away = g_strdup(""); - } else if (!strcmp(state, _("Invisible"))) { - xmlnode_put_attrib(x, "type", "invisible"); - gc->away = g_strdup(""); - invisible = TRUE; - } - } - - gjab_send(gjc, x); /* Notify "individuals" */ - - /* - * As of jabberd-1.4.2: simply sending presence to the server doesn't result in - * it being propagated to conference rooms. So we wade thru the list of chats, - * sending our new presence status to each and every one. - */ - for(jcs = jd->chats; jcs; jcs = jcs->next) { - jc = jcs->data; - if(jc->state == JCS_ACTIVE) { - xmlnode_put_attrib(x, "from", jc->gjid->full); - chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); - xmlnode_put_attrib(x, "to", chatname); - gjab_send(gjc, x); - g_free(chatname); - } - } - - xmlnode_free(x); - - invisible_to_all_buddies(gc, invisible); -} - -static void jabber_set_idle(GaimConnection *gc, int idle) { - struct jabber_data *jd = (struct jabber_data *)gc->proto_data; - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "jabber_set_idle: setting idle %i\n", idle); - jd->idle = idle ? time(NULL) - idle : idle; -} - -static void jabber_keepalive(GaimConnection *gc) { - struct jabber_data *jd = (struct jabber_data *)gc->proto_data; - gjab_send_raw(jd->gjc, JABBER_KEEPALIVE_STRING); -} - -/*---------------------------------------*/ -/* Jabber "set info" (vCard) support */ -/*---------------------------------------*/ - -/* - * V-Card format: - * - * <vCard prodid='' version='' xmlns=''> - * <FN></FN> - * <N> - * <FAMILY/> - * <GIVEN/> - * </N> - * <NICKNAME/> - * <URL/> - * <ADR> - * <STREET/> - * <EXTADD/> - * <LOCALITY/> - * <REGION/> - * <PCODE/> - * <COUNTRY/> - * </ADR> - * <TEL/> - * <EMAIL/> - * <ORG> - * <ORGNAME/> - * <ORGUNIT/> - * </ORG> - * <TITLE/> - * <ROLE/> - * <DESC/> - * <BDAY/> - * </vCard> - * - * See also: - * - * http://docs.jabber.org/proto/html/vcard-temp.html - * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd - */ - -/* - * Cross-reference user-friendly V-Card entry labels to vCard XML tags - * and attributes. - * - * Order is (or should be) unimportant. For example: we have no way of - * knowing in what order real data will arrive. - * - * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag - * name, XML tag's parent tag "path" (relative to vCard node). - * - * List is terminated by a NULL label pointer. - * - * Entries with no label text, but with XML tag and parent tag - * entries, are used by V-Card XML construction routines to - * "automagically" construct the appropriate XML node tree. - * - * Thoughts on future direction/expansion - * - * This is a "simple" vCard. - * - * It is possible for nodes other than the "vCard" node to have - * attributes. Should that prove necessary/desirable, add an - * "attributes" pointer to the vcard_template struct, create the - * necessary tag_attr structs, and add 'em to the vcard_dflt_data - * array. - * - * The above changes will (obviously) require changes to the vCard - * construction routines. - */ - -struct vcard_template { - char *label; /* label text pointer */ - char *text; /* entry text pointer */ - int visible; /* should entry field be "visible?" */ - int editable; /* should entry field be editable? */ - char *tag; /* tag text */ - char *ptag; /* parent tag "path" text */ - char *url; /* vCard display format if URL */ -} vcard_template_data[] = { - {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, - {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, - {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, - {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, - {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, - {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, - {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, - {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, - {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, - {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, - {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, - {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, - {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, - {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, - {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, - {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, - {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, - {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, - {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, - {"", NULL, TRUE, TRUE, "N", NULL, NULL}, - {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, - {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, - {NULL, NULL, 0, 0, NULL, NULL, NULL} -}; - -/* - * The "vCard" tag's attibute list... - */ -struct tag_attr { - char *attr; - char *value; -} vcard_tag_attr_list[] = { - {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, - {"version", "2.0", }, - {"xmlns", "vcard-temp", }, - {NULL, NULL}, -}; - - -/* - * Used by routines to parse an XML-encoded string into an xmlnode tree - */ -typedef struct { - XML_Parser parser; - xmlnode current; -} *xmlstr2xmlnode_parser, xmlstr2xmlnode_parser_struct; - - -/* - * Display a Jabber vCard - */ -static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from) -{ - GaimConnection *gc = GJ_GC(gjc); - char *cdata, *status; - struct vcard_template *vc_tp = vcard_template_data; - - /* space for all vCard elements + Jabber I.D. + "status" + NULL (list terminator) */ - gchar **str_arr = (gchar **) g_new(gpointer, - (sizeof(vcard_template_data)/sizeof(struct vcard_template)) + 3); - gchar **ap = str_arr; - gchar *buddy, *final; - - jab_res_info jri; - - if((buddy = get_realwho(gjc, from, TRUE, NULL)) == NULL) { - g_strfreev(str_arr); - return; - } - - jri = jabber_find_resource(GJ_GC(gjc), buddy); - - *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), buddy); - - for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { - if(strcmp(vc_tp->tag, "DESC") == 0) - continue; /* special handling later */ - if(vc_tp->ptag == NULL) { - cdata = xmlnode_get_tag_data(querynode, vc_tp->tag); - } else { - gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); - cdata = xmlnode_get_tag_data(querynode, tag); - g_free(tag); - } - if(cdata != NULL) { - if(vc_tp->url == NULL) { - *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _(vc_tp->label), cdata); - } else { - gchar *fmt = g_strdup_printf("<B>%%s:</B> %s<BR>\n", vc_tp->url); - *ap++ = g_strdup_printf(fmt, _(vc_tp->label), cdata, cdata); - g_free(fmt); - } - } - } - - - status = strdup_withhtml(jabber_lookup_away(gjc, buddy)); - *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", - _("Status"), - jri ? jabber_get_state_string(jri->state) : "", - jri && status ? ": " : "", status ? status : ""); - g_free(status); - - /* - * "Description" handled as a special case: get a copy of the - * string and HTML-ize. - */ - if((cdata = xmlnode_get_tag_data(querynode, "DESC")) != NULL) { - gchar *tmp = g_strdup_printf("<HR>%s<BR>", cdata); - *ap++ = strdup_withhtml(tmp); - g_free(tmp); - } - - *ap = NULL; - - final= g_strjoinv(NULL, str_arr); - g_strfreev(str_arr); - - g_show_info_text(gc, buddy, 2, final, NULL); - g_free(buddy); - g_free(final); -} - -/* - * Used by XML_Parse on parsing CDATA - */ -static void xmlstr2xmlnode_charData(void *userdata, const char *s, int slen) -{ - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - - if (xmlp->current) - xmlnode_insert_cdata(xmlp->current, s, slen); -} - -/* - * Used by XML_Parse to start or append to an xmlnode - */ -static void xmlstr2xmlnode_startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - - if (xmlp->current) { - /* Append the node to the current one */ - x = xmlnode_insert_tag(xmlp->current, name); - xmlnode_put_expat_attribs(x, attribs); - - xmlp->current = x; - } else { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - xmlp->current = x; - } -} - -/* - * Used by XML_Parse to end an xmlnode - */ -static void xmlstr2xmlnode_endElement(void *userdata, const char *name) -{ - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - xmlnode x; - - if (xmlp->current != NULL && (x = xmlnode_get_parent(xmlp->current)) != NULL) { - xmlp->current = x; - } -} - -/* - * Parse an XML-encoded string into an xmlnode tree - * - * Caller is responsible for freeing the returned xmlnode - */ -static xmlnode xmlstr2xmlnode(char *xmlstring) -{ - xmlstr2xmlnode_parser my_parser = g_new(xmlstr2xmlnode_parser_struct, 1); - xmlnode x = NULL; - - my_parser->parser = XML_ParserCreate(NULL); - my_parser->current = NULL; - - XML_SetUserData(my_parser->parser, (void *)my_parser); - XML_SetElementHandler(my_parser->parser, xmlstr2xmlnode_startElement, xmlstr2xmlnode_endElement); - XML_SetCharacterDataHandler(my_parser->parser, xmlstr2xmlnode_charData); - XML_Parse(my_parser->parser, xmlstring, strlen(xmlstring), 0); - - x = my_parser->current; - - XML_ParserFree(my_parser->parser); - g_free(my_parser); - - return(x); -} - -/* - * Insert a tag node into an xmlnode tree, recursively inserting parent tag - * nodes as necessary - * - * Returns pointer to inserted node - * - * Note to hackers: this code is designed to be re-entrant (it's recursive--it - * calls itself), so don't put any "static"s in here! - */ -static xmlnode insert_tag_to_parent_tag(xmlnode start, const char *parent_tag, const char *new_tag) -{ - xmlnode x = NULL; - - /* - * If the parent tag wasn't specified, see if we can get it - * from the vCard template struct. - */ - if(parent_tag == NULL) { - struct vcard_template *vc_tp = vcard_template_data; - - while(vc_tp->label != NULL) { - if(strcmp(vc_tp->tag, new_tag) == 0) { - parent_tag = vc_tp->ptag; - break; - } - ++vc_tp; - } - } - - /* - * If we have a parent tag... - */ - if(parent_tag != NULL ) { - /* - * Try to get the parent node for a tag - */ - if((x = xmlnode_get_tag(start, parent_tag)) == NULL) { - /* - * Descend? - */ - char *grand_parent = strcpy(g_malloc(strlen(parent_tag) + 1), parent_tag); - char *parent; - - if((parent = strrchr(grand_parent, '/')) != NULL) { - *(parent++) = '\0'; - x = insert_tag_to_parent_tag(start, grand_parent, parent); - } else { - x = xmlnode_insert_tag(start, grand_parent); - } - g_free(grand_parent); - } else { - /* - * We found *something* to be the parent node. - * Note: may be the "root" node! - */ - xmlnode y; - if((y = xmlnode_get_tag(x, new_tag)) != NULL) { - return(y); - } - } - } - - /* - * insert the new tag into its parent node - */ - return(xmlnode_insert_tag((x == NULL? start : x), new_tag)); -} - -/* - * Send vCard info to Jabber server - */ -static void jabber_set_info(GaimConnection *gc, const char *info) -{ - xmlnode x, vc_node; - char *id; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - gchar *info2; - - x = xmlnode_new_tag("iq"); - xmlnode_put_attrib(x, "type", "set"); - - id = gjab_getid(gjc); - - xmlnode_put_attrib(x, "id", id); - - /* - * Send only if there's actually any *information* to send - */ - info2 = g_strdup(info); - vc_node = xmlstr2xmlnode(info2); - - if(vc_node) { - if (xmlnode_get_name(vc_node) && - !g_ascii_strncasecmp(xmlnode_get_name(vc_node), "vcard", 5)) { - xmlnode_insert_tag_node(x, vc_node); - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jabber: vCard packet: %s\n", xmlnode2str(x)); - gjab_send(gjc, x); - } - xmlnode_free(vc_node); - } - - xmlnode_free(x); - g_free(info2); -} - -/* - * This is the callback from the "ok clicked" for "set vCard" - * - * Formats GSList data into XML-encoded string and returns a pointer - * to said string. - * - * g_free()'ing the returned string space is the responsibility of - * the caller. - */ -static void -jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) -{ - GaimAccount *account; - xmlnode vc_node; - GaimRequestField *field; - const char *text; - char *p; - const struct vcard_template *vc_tp; - struct tag_attr *tag_attr; - - vc_node = xmlnode_new_tag("vCard"); - - for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) - xmlnode_put_attrib(vc_node, tag_attr->attr, tag_attr->value); - - for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { - if (*vc_tp->label == '\0') - continue; - - field = gaim_request_fields_get_field(fields, vc_tp->tag); - text = gaim_request_field_string_get_value(field); - - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "Setting %s to '%s'\n", vc_tp->tag, text); - - if (text != NULL && *text != '\0') { - xmlnode xp; - - if ((xp = insert_tag_to_parent_tag(vc_node, - NULL, vc_tp->tag)) != NULL) { - - xmlnode_insert_cdata(xp, text, -1); - } - } - } - - p = g_strdup(xmlnode2str(vc_node)); - xmlnode_free(vc_node); - - account = gaim_connection_get_account(gc); - - if (account != NULL) { - gaim_account_set_user_info(account, p); - - if (gc != NULL) - serv_set_info(gc, p); - } - - g_free(p); -} - -/* - * This gets executed by the proto action - * - * Creates a new GaimRequestFields struct, gets the XML-formatted user_info - * string (if any) into GSLists for the (multi-entry) edit dialog and - * calls the set_vcard dialog. - */ -static void jabber_setup_set_info(GaimConnection *gc) -{ - GaimRequestFields *fields; - GaimRequestFieldGroup *group; - GaimRequestField *field; - const struct vcard_template *vc_tp; - char *user_info; - char *cdata; - xmlnode x_vc_data = NULL; - - fields = gaim_request_fields_new(); - group = gaim_request_field_group_new(NULL); - gaim_request_fields_add_group(fields, group); - - /* - * Get existing, XML-formatted, user info - */ - if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) - x_vc_data = xmlstr2xmlnode(user_info); - else - user_info = g_strdup(""); - - /* - * Set up GSLists for edit with labels from "template," data from user info - */ - for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { - if((vc_tp->label)[0] == '\0') - continue; - if(vc_tp->ptag == NULL) { - cdata = xmlnode_get_tag_data(x_vc_data, vc_tp->tag); - } else { - gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); - cdata = xmlnode_get_tag_data(x_vc_data, tag); - g_free(tag); - } - if(strcmp(vc_tp->tag, "DESC") == 0) { - field = gaim_request_field_string_new(vc_tp->tag, - _(vc_tp->label), cdata, - TRUE); -#if 0 - multi_text_list_update(&(b->multi_text_items), - vc_tp->label, cdata, TRUE); -#endif - } else { - field = gaim_request_field_string_new(vc_tp->tag, - _(vc_tp->label), cdata, - FALSE); -#if 0 - data = multi_entry_list_update(&(b->multi_entry_items), - vc_tp->label, cdata, TRUE); - data->visible = vc_tp->visible; - data->editable = vc_tp->editable; -#endif - } - - gaim_request_field_group_add_field(group, field); - } - - if(x_vc_data != NULL) { - xmlnode_free(x_vc_data); - } else { - /* - * I'm commenting this out for now. faceprint can look at it - * later. The comment below says this is going away "real soon now," - * but it's probably been here a really long time. Getting this - * to work with the multi-field stuff won't be pretty, since we're - * manually going to have to search through all fields for the - * label and update. - * - * -- ChipX86 - */ -#if 0 - /* - * Early Beta versions had a different user_info storage format--let's - * see if that works. - * - * This goes away RSN. - */ - const char *record_separator = "<BR>"; - const char *field_separator = ": "; - gchar **str_list, **str_list_ptr, **str_list2; - - if((str_list = g_strsplit(user_info, record_separator, 0)) != NULL) { - for(str_list_ptr = str_list; *str_list_ptr != NULL; ++str_list_ptr) { - str_list2 = g_strsplit(*str_list_ptr, field_separator, 2); - if(str_list2[0] != NULL && str_list2[1] != NULL) { - g_strstrip(str_list2[0]); - g_strstrip(str_list2[1]); - /* this is ugly--so far */ - if(strcmp(str_list2[0], "Description") == 0) { - multi_text_list_update(&(b->multi_text_items), - str_list2[0], str_list2[1], FALSE); - } else { - multi_entry_list_update(&(b->multi_entry_items), - str_list2[0], str_list2[1], FALSE); - } - } - g_strfreev(str_list2); - } - g_strfreev(str_list); - } -#endif - } - - g_free(user_info); - - gaim_request_fields(gc, _("Edit Jabber vCard"), - _("Edit Jabber vCard"), - _("All items below are optional. Enter only the " - "information with which you feel comfortable."), - fields, - _("Save"), G_CALLBACK(jabber_format_info), - _("Cancel"), NULL, - gc); -} - -/*---------------------------------------*/ -/* End Jabber "set info" (vCard) support */ -/*---------------------------------------*/ - -/*----------------------------------------*/ -/* Jabber "user registration" support */ -/*----------------------------------------*/ - -/* - * Three of the following four functions duplicate much of what - * exists elsewhere: - * - * jabber_handleregresp() - * gjab_reqreg() - * jabber_handle_registration_state() - * - * It may be that an additional flag could be added to one of - * the "local" structs and the duplicated code modified to - * account for it--thus eliminating the duplication. Then again: - * doing it the way it is may be much cleaner. - * - * TBD: Code to support requesting additional information server - * wants at registration--incl. dialog. - */ - -/* - * Like jabber_handlepacket(), only different - */ -static void jabber_handleregresp(gjconn gjc, jpacket p) -{ - if (jpacket_subtype(p) == JPACKET__RESULT) { - xmlnode querynode; - - if((querynode = xmlnode_get_tag(p->x, "query")) != NULL) { - char *xmlns; - - /* we damn well *better* have this! */ - if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL && - strcmp(xmlns, NS_REGISTER) == 0) { - - char *tag; - xmlnode child = xmlnode_get_firstchild(querynode); - - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "got registration requirments response!\n"); - - while(child != NULL) { - if((tag = xmlnode_get_name(child)) != NULL) { - char *data; - - fprintf(stderr, "DBG: got node: \"%s\"\n", tag); - fflush(stderr); - - if((data = xmlnode_get_data(child)) != NULL) { - fprintf(stderr, "DBG: got data: \"%s\"\n", data); - fflush(stderr); - } - } - child = xmlnode_get_nextsibling(child); - } - } - } else { - gaim_debug(GAIM_DEBUG_INFO, "jabber", - "registration successful!\n"); - - gaim_connection_notice(GJ_GC(gjc), _("Server Registration successful!")); - gaim_connection_destroy(GJ_GC(gjc)); - } - - } else { - xmlnode xerr; - char *errmsg = NULL; - int errcode = 0; - - gaim_debug(GAIM_DEBUG_ERROR, "jabber", "registration failed\n"); - xerr = xmlnode_get_tag(p->x, "error"); - if (xerr) { - char msg[BUF_LONG]; - errmsg = xmlnode_get_data(xerr); - if (xmlnode_get_attrib(xerr, "code")) { - errcode = atoi(xmlnode_get_attrib(xerr, "code")); - g_snprintf(msg, sizeof(msg), _("Error %d: %s"), errcode, errmsg); - } else - g_snprintf(msg, sizeof(msg), "%s", errmsg); - gaim_connection_error(GJ_GC(gjc), msg); - } else { - gaim_connection_error(GJ_GC(gjc), _("Unknown registration error")); - } - } -} - -/* - * Like gjab_reqauth(), only different - */ -static void gjab_reqreg(gjconn gjc) -{ - xmlnode x, y, z; - char *user; - - if (!gjc) - return; - - x = jutil_iqnew(JPACKET__SET, NS_REGISTER); - y = xmlnode_get_tag(x, "query"); - - user = gjc->user->user; - - if (user) { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, gjc->pass, -1); - - gaim_debug(GAIM_DEBUG_MISC, "jabber", - "jabber: registration packet: %s\n", xmlnode2str(x)); - gjab_send(gjc, x); - xmlnode_free(x); -} - -/* - * Like jabber_handlestate(), only different - */ -static void jabber_handle_registration_state(gjconn gjc, int state) -{ - switch (state) { - case JCONN_STATE_OFF: - if(gjc->was_connected) { - gaim_connection_error(GJ_GC(gjc), _("Connection lost")); - } else { - gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); - } - break; - case JCONN_STATE_CONNECTED: - gjc->was_connected = 1; - /* - * TBD? - gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), - 2, JABBER_CONNECT_STEPS); - */ - break; - case JCONN_STATE_ON: - /* - * TBD? - gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), - _("Requesting Authentication Method"), 3, - JABBER_CONNECT_STEPS); - */ - gjab_reqreg(gjc); - /* - * TBD: A work-in-progress - gjab_reqregreqs(gjc); - */ - break; - default: - gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); - } - return; -} - -/* - * Like jabber_login(), only different - */ -void jabber_register_user(GaimAccount *account) -{ - GaimConnection *gc = gaim_account_get_connection(account); - struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); - char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); - - /* - * These do nothing during registration - */ - jd->buddies = NULL; - jd->chats = NULL; - - if ((jd->gjc = gjab_new(loginname, account->password, gc)) == NULL) { - g_free(loginname); - gaim_debug(GAIM_DEBUG_ERROR, "jabber", - "unable to connect (jab_new failed)\n"); - gaim_connection_error(gc, _("Unable to connect")); - } else { - gjab_state_handler(jd->gjc, jabber_handle_registration_state); - gjab_packet_handler(jd->gjc, jabber_handleregresp); - jd->gjc->queries = NULL; - gjab_start(jd->gjc); - } - - g_free(loginname); -} - -/*----------------------------------------*/ -/* End Jabber "user registration" support */ -/*----------------------------------------*/ - static GList *jabber_actions(GaimConnection *gc) { GList *m = NULL; @@ -4408,19 +579,7 @@ pam->gc = gc; m = g_list_append(m, pam); - /* - pam = g_new0(struct proto_actions_menu, 1); - pam->label = _("Set Dir Info"); - pam->callback = show_set_dir; - pam->gc = gc; - m = g_list_append(m, pam); - */ - - pam = g_new0(struct proto_actions_menu, 1); - pam->label = _("Change Password"); - pam->callback = show_change_passwd; - pam->gc = gc; - m = g_list_append(m, pam); + /* XXX: Change Password */ return m; } @@ -4428,7 +587,7 @@ static GaimPluginProtocolInfo prpl_info = { GAIM_PROTO_JABBER, - OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC, + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME, NULL, NULL, jabber_list_icon, @@ -4441,20 +600,20 @@ jabber_chat_info, jabber_login, jabber_close, - jabber_send_im, + jabber_message_send_im, jabber_set_info, jabber_send_typing, - jabber_get_info, - jabber_set_away, + jabber_buddy_get_info, + jabber_presence_send, NULL, NULL, NULL, NULL, - jabber_set_idle, - jabber_change_passwd, - jabber_add_buddy, + jabber_idle_set, + NULL, /* change_passwd */ /* XXX */ + jabber_roster_add_buddy, NULL, - jabber_remove_buddy, + jabber_roster_remove_buddy, NULL, NULL, NULL, @@ -4462,21 +621,21 @@ NULL, NULL, NULL, - jabber_join_chat, + jabber_chat_join, jabber_chat_invite, jabber_chat_leave, jabber_chat_whisper, - jabber_chat_send, + jabber_message_send_chat, jabber_keepalive, - jabber_register_user, - jabber_get_cb_info, - jabber_get_cb_away_msg, - jabber_alias_buddy, - jabber_group_change, - jabber_rename_group, + NULL, /* register_user */ /* XXX tell the user success/failure */ + jabber_buddy_get_info_chat, NULL, - jabber_convo_closed, - jabber_normalize + jabber_roster_alias_change, + jabber_roster_group_change, + jabber_roster_group_rename, + NULL, + NULL, /* convo_closed */ /* XXX: thread_ids */ + NULL /* normalize */ }; static GaimPluginInfo info = @@ -4512,31 +671,31 @@ GaimAccountUserSplit *split; GaimAccountOption *option; - /* Splits */ split = gaim_account_user_split_new(_("Server"), "jabber.org", '@'); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); split = gaim_account_user_split_new(_("Resource"), "Gaim", '/'); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - /* Account Options */ - if(gaim_ssl_is_supported()) { - option = gaim_account_option_bool_new(_("Use SSL"), "old_ssl", FALSE); + option = gaim_account_option_bool_new(_("Force Old SSL"), "old_ssl", FALSE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); } - option = gaim_account_option_int_new(_("Port"), "port", DEFAULT_PORT); + option = gaim_account_option_int_new(_("Port"), "port", 5222); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); + option); option = gaim_account_option_string_new(_("Connect server"), - "connect_server", NULL); + "connect_server", NULL); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); + option); my_protocol = plugin; + + gaim_prefs_add_none("/plugins/prpl/jabber"); + gaim_prefs_add_bool("/plugins/prpl/jabber/hide_os", FALSE); } GAIM_INIT_PLUGIN(jabber, init_plugin, info);
--- a/src/protocols/jabber/jabber.h Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/jabber.h Mon Sep 29 15:23:19 2003 +0000 @@ -1,322 +1,83 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. +/** + * @file jabber.h + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * 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. * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include <sys/types.h> -/*this must happen before sys/socket.h or freebsd won't compile*/ - -#ifndef _WIN32 -#include <syslog.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <strings.h> -#include <unistd.h> -#endif - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <stdarg.h> -#include <sys/time.h> -#include <time.h> -#include <ctype.h> - -#include "libxode.h" - -#ifndef INCL_JABBER_H -#define INCL_JABBER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* --------------------------------------------------------- */ -/* */ -/* JID structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JID_RESOURCE 1 -#define JID_USER 2 -#define JID_SERVER 4 +#ifndef _GAIM_JABBER_H_ +#define _GAIM_JABBER_H_ -typedef struct jid_struct -{ - pool p; - char* resource; - char* user; - char* server; - char* full; - struct jid_struct *next; /* for lists of jids */ -} *jid; - -jid jid_new(pool p, char *idstr); /* Creates a jabber id from the idstr */ -void jid_set(jid id, char *str, int item); /* Individually sets jid components */ -char* jid_full(jid id); /* Builds a string type=user/resource@server from the jid data */ -int jid_cmp(jid a, jid b); /* Compares two jid's, returns 0 for perfect match */ -int jid_cmpx(jid a, jid b, int parts); /* Compares just the parts specified as JID_|JID_ */ -jid jid_append(jid a, jid b); /* Appending b to a (list), no dups */ -xmlnode jid_xres(jid id); /* Returns xmlnode representation of the resource?query=string */ -xmlnode jid_nodescan(jid id, xmlnode x); /* Scans the children of the node for a matching jid attribute */ - +#include <glib.h> +#include "connection.h" +#include "sslconn.h" -/* --------------------------------------------------------- */ -/* */ -/* JPacket structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JPACKET_UNKNOWN 0x00 -#define JPACKET_MESSAGE 0x01 -#define JPACKET_PRESENCE 0x02 -#define JPACKET_IQ 0x04 -#define JPACKET_S10N 0x08 - -#define JPACKET__UNKNOWN 0 -#define JPACKET__NONE 1 -#define JPACKET__ERROR 2 -#define JPACKET__CHAT 3 -#define JPACKET__GROUPCHAT 4 -#define JPACKET__GET 5 -#define JPACKET__SET 6 -#define JPACKET__RESULT 7 -#define JPACKET__SUBSCRIBE 8 -#define JPACKET__SUBSCRIBED 9 -#define JPACKET__UNSUBSCRIBE 10 -#define JPACKET__UNSUBSCRIBED 11 -#define JPACKET__AVAILABLE 12 -#define JPACKET__UNAVAILABLE 13 -#define JPACKET__PROBE 14 -#define JPACKET__HEADLINE 15 +#include "jutil.h" +#include "xmlnode.h" -typedef struct jpacket_struct -{ - unsigned char type; - int subtype; - int flag; - void* aux1; - xmlnode x; - jid to; - jid from; - char* iqns; - xmlnode iq; - pool p; -} *jpacket, _jpacket; - -jpacket jpacket_new(xmlnode x); /* Creates a jabber packet from the xmlnode */ -jpacket jpacket_reset(jpacket p); /* Resets the jpacket values based on the xmlnode */ -int jpacket_subtype(jpacket p); /* Returns the subtype value (looks at xmlnode for it) */ - +typedef enum { + JABBER_STREAM_OFFLINE, + JABBER_STREAM_CONNECTING, + JABBER_STREAM_INITIALIZING, + JABBER_STREAM_AUTHENTICATING, + JABBER_STREAM_REINITIALIZING, + JABBER_STREAM_CONNECTED +} JabberStreamState; -/* --------------------------------------------------------- */ -/* */ -/* Presence Proxy DB structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct ppdb_struct -{ - jid id; /* entry data */ - int pri; - xmlnode x; - struct ppdb_struct* user; /* linked list for user@server */ - pool p; /* db-level data */ - struct ppdb_struct* next; -} _ppdb, *ppdb; - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x); /* Inserts presence into the proxy */ -xmlnode ppdb_primary(ppdb db, jid id); /* Fetches the matching primary presence for the id */ -void ppdb_free(ppdb db); /* Frees the db and all entries */ -xmlnode ppdb_get(ppdb db, jid id); /* Called successively to return each presence xmlnode */ - /* for the id and children, returns NULL at the end */ - - -/* --------------------------------------------------------- */ -/* */ -/* Simple Jabber Rate limit functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct jlimit_struct +typedef struct _JabberStream { - char *key; - int start; - int points; - int maxt, maxp; - pool p; -} *jlimit, _jlimit; - -jlimit jlimit_new(int maxt, int maxp); -void jlimit_free(jlimit r); -int jlimit_check(jlimit r, char *key, int points); - + int fd; -/* --------------------------------------------------------- */ -/* */ -/* Error structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct terror_struct -{ - int code; - char msg[64]; -} terror; - -#define TERROR_BAD (terror){400,"Bad Request"} -#define TERROR_AUTH (terror){401,"Unauthorized"} -#define TERROR_PAY (terror){402,"Payment Required"} -#define TERROR_FORBIDDEN (terror){403,"Forbidden"} -#define TERROR_NOTFOUND (terror){404,"Not Found"} -#define TERROR_NOTALLOWED (terror){405,"Not Allowed"} -#define TERROR_NOTACCEPTABLE (terror){406,"Not Acceptable"} -#define TERROR_REGISTER (terror){407,"Registration Required"} -#define TERROR_REQTIMEOUT (terror){408,"Request Timeout"} -#define TERROR_CONFLICT (terror){409,"Conflict"} + GMarkupParseContext *context; + xmlnode *current; -#define TERROR_INTERNAL (terror){500,"Internal Server Error"} -#define TERROR_NOTIMPL (terror){501,"Not Implemented"} -#define TERROR_EXTERNAL (terror){502,"Remote Server Error"} -#define TERROR_UNAVAIL (terror){503,"Service Unavailable"} -#define TERROR_EXTTIMEOUT (terror){504,"Remote Server Timeout"} -#define TERROR_DISCONNECTED (terror){510,"Disconnected"} - -/* --------------------------------------------------------- */ -/* */ -/* Namespace constants */ -/* */ -/* --------------------------------------------------------- */ -#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0) + enum { + JABBER_PROTO_0_9, + JABBER_PROTO_1_0 + } protocol_version; + char *stream_id; + JabberStreamState state; -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" -#define NS_AUTH "jabber:iq:auth" -#define NS_REGISTER "jabber:iq:register" -#define NS_ROSTER "jabber:iq:roster" -#define NS_OFFLINE "jabber:x:offline" -#define NS_AGENT "jabber:iq:agent" -#define NS_AGENTS "jabber:iq:agents" -#define NS_DELAY "jabber:x:delay" -#define NS_VERSION "jabber:iq:version" -#define NS_TIME "jabber:iq:time" -#define NS_VCARD "vcard-temp" -#define NS_PRIVATE "jabber:iq:private" -#define NS_SEARCH "jabber:iq:search" -#define NS_OOB "jabber:iq:oob" -#define NS_XOOB "jabber:x:oob" -#define NS_ADMIN "jabber:iq:admin" -#define NS_FILTER "jabber:iq:filter" -#define NS_AUTH_0K "jabber:iq:auth:0k" + /* SASL authentication */ + char *expected_rspauth; + GHashTable *buddies; + gboolean roster_parsed; -/* --------------------------------------------------------- */ -/* */ -/* Message Types */ -/* */ -/* --------------------------------------------------------- */ -#define TMSG_NORMAL "normal" -#define TMSG_ERROR "error" -#define TMSG_CHAT "chat" -#define TMSG_GROUPCHAT "groupchat" -#define TMSG_HEADLINE "headline" - + GHashTable *chats; -/* --------------------------------------------------------- */ -/* */ -/* JUtil functions */ -/* */ -/* --------------------------------------------------------- */ -xmlnode jutil_presnew(int type, char *to, char *status); /* Create a skeleton presence packet */ -xmlnode jutil_iqnew(int type, char *ns); /* Create a skeleton iq packet */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body); - /* Create a skeleton message packet */ -xmlnode jutil_header(char* xmlns, char* server); /* Create a skeleton stream packet */ -int jutil_priority(xmlnode x); /* Determine priority of this packet */ -void jutil_tofrom(xmlnode x); /* Swaps to/from fields on a packet */ -xmlnode jutil_iqresult(xmlnode x); /* Generate a skeleton iq/result, given a iq/query */ -char* jutil_timestamp(void); /* Get stringified timestamp */ -void jutil_error(xmlnode x, terror E); /* Append an <error> node to x */ -void jutil_delay(xmlnode msg, char *reason); /* Append a delay packet to msg */ -char* jutil_regkey(char *key, char *seed); /* pass a seed to generate a key, pass the key again to validate (returns it) */ + GHashTable *callbacks; + int next_id; + time_t idle; -/* --------------------------------------------------------- */ -/* */ -/* JConn structures & functions */ -/* */ -/* --------------------------------------------------------- */ -#define JCONN_STATE_OFF 0 -#define JCONN_STATE_CONNECTED 1 -#define JCONN_STATE_ON 2 -#define JCONN_STATE_AUTH 3 - -typedef struct jconn_struct -{ - /* Core structure */ - pool p; /* Memory allocation pool */ - int state; /* Connection state flag */ - int fd; /* Connection file descriptor */ - jid user; /* User info */ - char *pass; /* User passwd */ + JabberID *user; + GaimConnection *gc; + GaimSslConnection *gsc; +} JabberStream; - /* Stream stuff */ - int id; /* id counter for jab_getid() function */ - char idbuf[9]; /* temporary storage for jab_getid() */ - char *sid; /* stream id from server, for digest auth */ - XML_Parser parser; /* Parser instance */ - xmlnode current; /* Current node in parsing instance.. */ +typedef void (JabberCallback)(JabberStream *js, xmlnode *packet); - /* Event callback ptrs */ - void (*on_state)(struct jconn_struct *j, int state); - void (*on_packet)(struct jconn_struct *j, jpacket p); - -} *jconn, jconn_struct; - -typedef void (*jconn_state_h)(jconn j, int state); -typedef void (*jconn_packet_h)(jconn j, jpacket p); - +void jabber_process_packet(JabberStream *js, xmlnode *packet); +void jabber_send(JabberStream *js, xmlnode *data); +void jabber_send_raw(JabberStream *js, const char *data); -jconn jab_new(char *user, char *pass); -void jab_delete(jconn j); -void jab_state_handler(jconn j, jconn_state_h h); -void jab_packet_handler(jconn j, jconn_packet_h h); -void jab_start(jconn j); -void jab_stop(jconn j); - -int jab_getfd(jconn j); -jid jab_getjid(jconn j); -char *jab_getsid(jconn j); -char *jab_getid(jconn j); +void jabber_stream_set_state(JabberStream *js, JabberStreamState state); -void jab_send(jconn j, xmlnode x); -void jab_send_raw(jconn j, const char *str); -void jab_recv(jconn j); -void jab_poll(jconn j, int timeout); - -char *jab_auth(jconn j); -char *jab_reg(jconn j); +char *jabber_get_next_id(JabberStream *js); - - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_JABBER_H */ +#endif /* _GAIM_JABBER_H_ */
--- a/src/protocols/jabber/jconn.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,489 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include "jabber.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -/* local macros for launching event handlers */ -#define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); } - -/* prototypes of the local functions */ -static void startElement(void *userdata, const char *name, const char **attribs); -static void endElement(void *userdata, const char *name); -static void charData(void *userdata, const char *s, int slen); - -/* - * jab_new -- initialize a new jabber connection - * - * parameters - * user -- jabber id of the user - * pass -- password of the user - * - * results - * a pointer to the connection structure - * or NULL if allocations failed - */ -jconn jab_new(char *user, char *pass) -{ - pool p; - jconn j; - - if(!user) return(NULL); - - p = pool_new(); - if(!p) return(NULL); - j = pmalloc_x(p, sizeof(jconn_struct), 0); - if(!j) return(NULL); - j->p = p; - - j->user = jid_new(p, user); - j->pass = pstrdup(p, pass); - - j->state = JCONN_STATE_OFF; - j->id = 1; - j->fd = -1; - - return j; -} - -/* - * jab_delete -- free a jabber connection - * - * parameters - * j -- connection - * - */ -void jab_delete(jconn j) -{ - if(!j) return; - - jab_stop(j); - pool_free(j->p); -} - -/* - * jab_state_handler -- set callback handler for state change - * - * parameters - * j -- connection - * h -- name of the handler function - */ -void jab_state_handler(jconn j, jconn_state_h h) -{ - if(!j) return; - - j->on_state = h; -} - -/* - * jab_packet_handler -- set callback handler for incoming packets - * - * parameters - * j -- connection - * h -- name of the handler function - */ -void jab_packet_handler(jconn j, jconn_packet_h h) -{ - if(!j) return; - - j->on_packet = h; -} - - -/* - * jab_start -- start connection - * - * parameters - * j -- connection - * - */ -void jab_start(jconn j) -{ - xmlnode x; - char *t,*t2; - - if(!j || j->state != JCONN_STATE_OFF) return; - - j->parser = XML_ParserCreate(NULL); - XML_SetUserData(j->parser, (void *)j); - XML_SetElementHandler(j->parser, startElement, endElement); - XML_SetCharacterDataHandler(j->parser, charData); - - j->fd = make_netsocket(5222, j->user->server, NETSOCKET_CLIENT); - if(j->fd < 0) { - STATE_EVT(JCONN_STATE_OFF) - return; - } - j->state = JCONN_STATE_CONNECTED; - STATE_EVT(JCONN_STATE_CONNECTED) - - /* start stream */ - x = jutil_header(NS_CLIENT, j->user->server); - t = xmlnode2str(x); - /* this is ugly, we can create the string here instead of jutil_header */ - /* what do you think about it? -madcat */ - t2 = strstr(t,"/>"); - *t2++ = '>'; - *t2 = '\0'; - jab_send_raw(j,"<?xml version='1.0'?>"); - jab_send_raw(j,t); - xmlnode_free(x); - - j->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON) - -} - -/* - * jab_stop -- stop connection - * - * parameters - * j -- connection - */ -void jab_stop(jconn j) -{ - if(!j || j->state == JCONN_STATE_OFF) return; - - j->state = JCONN_STATE_OFF; - close(j->fd); - j->fd = -1; - XML_ParserFree(j->parser); -} - -/* - * jab_getfd -- get file descriptor of connection socket - * - * parameters - * j -- connection - * - * returns - * fd of the socket or -1 if socket was not connected - */ -int jab_getfd(jconn j) -{ - if(j) - return j->fd; - else - return -1; -} - -/* - * jab_getjid -- get jid structure of user - * - * parameters - * j -- connection - */ -jid jab_getjid(jconn j) -{ - if(j) - return(j->user); - else - return NULL; -} - -/* jab_getsid -- get stream id - * This is the id of server's <stream:stream> tag and used for - * digest authorization. - * - * parameters - * j -- connection - */ -char *jab_getsid(jconn j) -{ - if(j) - return(j->sid); - else - return NULL; -} - -/* - * jab_getid -- get a unique id - * - * parameters - * j -- connection - */ -char *jab_getid(jconn j) -{ - snprintf(j->idbuf, 8, "%d", j->id++); - return &j->idbuf[0]; -} - -/* - * jab_send -- send xml data - * - * parameters - * j -- connection - * x -- xmlnode structure - */ -void jab_send(jconn j, xmlnode x) -{ - if (j && j->state != JCONN_STATE_OFF) - { - char *buf = xmlnode2str(x); - if (buf) write(j->fd, buf, strlen(buf)); -#ifdef JDEBUG - printf ("out: %s\n", buf); -#endif - } -} - -/* - * jab_send_raw -- send a string - * - * parameters - * j -- connection - * str -- xml string - */ -void jab_send_raw(jconn j, const char *str) -{ - if (j && j->state != JCONN_STATE_OFF) - write(j->fd, str, strlen(str)); -#ifdef JDEBUG - printf ("out: %s\n", str); -#endif -} - -/* - * jab_recv -- read and parse incoming data - * - * parameters - * j -- connection - */ -void jab_recv(jconn j) -{ - static char buf[4096]; - int len; - - if(!j || j->state == JCONN_STATE_OFF) - return; - - len = read(j->fd, buf, sizeof(buf)-1); - if(len>0) - { - buf[len] = '\0'; -#ifdef JDEBUG - printf (" in: %s\n", buf); -#endif - XML_Parse(j->parser, buf, len, 0); - } - else if(len<0) - { - STATE_EVT(JCONN_STATE_OFF); - jab_stop(j); - } -} - -/* - * jab_poll -- check socket for incoming data - * - * parameters - * j -- connection - * timeout -- poll timeout - */ -void jab_poll(jconn j, int timeout) -{ - fd_set fds; - struct timeval tv; - - if (!j || j->state == JCONN_STATE_OFF) - return; - - FD_ZERO(&fds); - FD_SET(j->fd, &fds); - - if (timeout < 0) - { - if (select(j->fd + 1, &fds, NULL, NULL, NULL) > 0) - jab_recv(j); - } - else - { - tv.tv_sec = 0; - tv.tv_usec = timeout; - if (select(j->fd + 1, &fds, NULL, NULL, &tv) > 0) - jab_recv(j); - } -} - -/* - * jab_auth -- authorize user - * - * parameters - * j -- connection - * - * returns - * id of the iq packet - */ -char *jab_auth(jconn j) -{ - xmlnode x,y,z; - char *hash, *user, *id; - - if(!j) return(NULL); - - x = jutil_iqnew(JPACKET__SET, NS_AUTH); - id = jab_getid(j); - xmlnode_put_attrib(x, "id", id); - y = xmlnode_get_tag(x,"query"); - - user = j->user->user; - - if (user) - { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, j->user->resource, -1); - - if (j->sid) - { - z = xmlnode_insert_tag(y, "digest"); - hash = pmalloc(x->p, strlen(j->sid)+strlen(j->pass)+1); - strcpy(hash, j->sid); - strcat(hash, j->pass); - hash = shahash(hash); - xmlnode_insert_cdata(z, hash, 40); - } - else - { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, j->pass, -1); - } - - jab_send(j, x); - xmlnode_free(x); - return id; -} - -/* - * jab_reg -- register user - * - * parameters - * j -- connection - * - * returns - * id of the iq packet - */ -char *jab_reg(jconn j) -{ - xmlnode x,y,z; - char *user, *id; - - if (!j) return(NULL); - - x = jutil_iqnew(JPACKET__SET, NS_REGISTER); - id = jab_getid(j); - xmlnode_put_attrib(x, "id", id); - y = xmlnode_get_tag(x,"query"); - - user = j->user->user; - - if (user) - { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, j->user->resource, -1); - - if (j->pass) - { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, j->pass, -1); - } - - jab_send(j, x); - xmlnode_free(x); - j->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON) - return id; -} - - -/* local functions */ - -static void startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - jconn j = (jconn)userdata; - - if(j->current) - { - /* Append the node to the current one */ - x = xmlnode_insert_tag(j->current, name); - xmlnode_put_expat_attribs(x, attribs); - - j->current = x; - } - else - { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - if(strcmp(name, "stream:stream") == 0) { - /* special case: name == stream:stream */ - /* id attrib of stream is stored for digest auth */ - j->sid = xmlnode_get_attrib(x, "id"); - /* STATE_EVT(JCONN_STATE_AUTH) */ - } else { - j->current = x; - } - } -} - -static void endElement(void *userdata, const char *name) -{ - jconn j = (jconn)userdata; - xmlnode x; - jpacket p; - - if(j->current == NULL) { - /* we got </stream:stream> */ - STATE_EVT(JCONN_STATE_OFF) - return; - } - - x = xmlnode_get_parent(j->current); - - if(x == NULL) - { - /* it is time to fire the event */ - p = jpacket_new(j->current); - - if(j->on_packet) - (j->on_packet)(j, p); - else - xmlnode_free(j->current); - } - - j->current = x; -} - -static void charData(void *userdata, const char *s, int slen) -{ - jconn j = (jconn)userdata; - - if (j->current) - xmlnode_insert_cdata(j->current, s, slen); -}
--- a/src/protocols/jabber/jid.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -jid jid_safe(jid id) -{ - unsigned char *str; - - if(strlen(id->server) == 0 || strlen(id->server) > 255) - return NULL; - - /* lowercase the hostname, make sure it's valid characters */ - for(str = id->server; *str != '\0'; str++) - { - *str = tolower(*str); - if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return NULL; - } - - /* cut off the user */ - if(id->user != NULL && strlen(id->user) > 64) - id->user[64] = '\0'; - - /* check for low and invalid ascii characters in the username */ - if(id->user != NULL) - for(str = id->user; *str != '\0'; str++) - if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return NULL; - - return id; -} - -jid jid_new(pool p, char *idstr) -{ - char *server, *resource, *type, *str; - jid id; - - if(p == NULL || idstr == NULL || strlen(idstr) == 0) - return NULL; - - /* user@server/resource */ - - str = pstrdup(p, idstr); - - id = pmalloco(p,sizeof(struct jid_struct)); - id->p = p; - - resource = strstr(str,"/"); - if(resource != NULL) - { - *resource = '\0'; - ++resource; - if(strlen(resource) > 0) - id->resource = resource; - }else{ - resource = str + strlen(str); /* point to end */ - } - - type = strstr(str,":"); - if(type != NULL && type < resource) - { - *type = '\0'; - ++type; - str = type; /* ignore the type: prefix */ - } - - server = strstr(str,"@"); - if(server == NULL || server > resource) - { /* if there's no @, it's just the server address */ - id->server = str; - }else{ - *server = '\0'; - ++server; - id->server = server; - if(strlen(str) > 0) - id->user = str; - } - - return jid_safe(id); -} - -void jid_set(jid id, char *str, int item) -{ - char *old; - - if(id == NULL) - return; - - /* invalidate the cached copy */ - id->full = NULL; - - switch(item) - { - case JID_RESOURCE: - if(str != NULL && strlen(str) != 0) - id->resource = pstrdup(id->p, str); - else - id->resource = NULL; - break; - case JID_USER: - old = id->user; - if(str != NULL && strlen(str) != 0) - id->user = pstrdup(id->p, str); - else - id->user = NULL; - if(jid_safe(id) == NULL) - id->user = old; /* revert if invalid */ - break; - case JID_SERVER: - old = id->server; - id->server = pstrdup(id->p, str); - if(jid_safe(id) == NULL) - id->server = old; /* revert if invalid */ - break; - } - -} - -char *jid_full(jid id) -{ - spool s; - - if(id == NULL) - return NULL; - - /* use cached copy */ - if(id->full != NULL) - return id->full; - - s = spool_new(id->p); - - if(id->user != NULL) - spooler(s, id->user,"@",s); - - spool_add(s, id->server); - - if(id->resource != NULL) - spooler(s, "/",id->resource,s); - - id->full = spool_print(s); - return id->full; -} - -/* parses a /resource?name=value&foo=bar into an xmlnode representing <resource name="value" foo="bar"/> */ -xmlnode jid_xres(jid id) -{ - char *cur, *qmark, *amp, *eq; - xmlnode x; - - if(id == NULL || id->resource == NULL) return NULL; - - cur = pstrdup(id->p, id->resource); - qmark = strstr(cur, "?"); - if(qmark == NULL) return NULL; - *qmark = '\0'; - qmark++; - - x = _xmlnode_new(id->p, cur, NTYPE_TAG); - - cur = qmark; - while(cur != '\0') - { - eq = strstr(cur, "="); - if(eq == NULL) break; - *eq = '\0'; - eq++; - - amp = strstr(eq, "&"); - if(amp != NULL) - { - *amp = '\0'; - amp++; - } - - xmlnode_put_attrib(x,cur,eq); - - if(amp != NULL) - cur = amp; - else - break; - } - - return x; -} - -/* local utils */ -int _jid_nullstrcmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return strcmp(a,b); -} -int _jid_nullstrcasecmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return strcasecmp(a,b); -} - -int jid_cmp(jid a, jid b) -{ - if(a == NULL || b == NULL) - return -1; - - if(_jid_nullstrcmp(a->resource, b->resource) != 0) return -1; - if(_jid_nullstrcasecmp(a->user, b->user) != 0) return -1; - if(_jid_nullstrcmp(a->server, b->server) != 0) return -1; - - return 0; -} - -/* suggested by Anders Qvist <quest@valdez.netg.se> */ -int jid_cmpx(jid a, jid b, int parts) -{ - if(a == NULL || b == NULL) - return -1; - - if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1; - if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1; - if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1; - - return 0; -} - -/* makes a copy of b in a's pool, requires a valid a first! */ -jid jid_append(jid a, jid b) -{ - jid next; - - if(a == NULL) - return NULL; - - if(b == NULL) - return a; - - next = a; - while(next != NULL) - { - /* check for dups */ - if(jid_cmp(next,b) == 0) - break; - if(next->next == NULL) - next->next = jid_new(a->p,jid_full(b)); - next = next->next; - } - return a; -} - -xmlnode jid_nodescan(jid id, xmlnode x) -{ - xmlnode cur; - pool p; - jid tmp; - - if(id == NULL || xmlnode_get_firstchild(x) == NULL) return NULL; - - p = pool_new(); - for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) - { - if(xmlnode_get_type(cur) != NTYPE_TAG) continue; - - tmp = jid_new(p,xmlnode_get_attrib(cur,"jid")); - if(tmp == NULL) continue; - - if(jid_cmp(tmp,id) == 0) break; - } - pool_free(p); - - return cur; -} - -jid jid_user(jid a) -{ - jid ret; - - if(a == NULL || a->resource == NULL) return a; - - ret = pmalloco(a->p,sizeof(struct jid_struct)); - ret->p = a->p; - ret->user = a->user; - ret->server = a->server; - - return ret; -}
--- a/src/protocols/jabber/jpacket.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -jpacket jpacket_new(xmlnode x) -{ - jpacket p; - - if(x == NULL) - return NULL; - - p = pmalloc(xmlnode_pool(x),sizeof(_jpacket)); - p->x = x; - - return jpacket_reset(p); -} - -jpacket jpacket_reset(jpacket p) -{ - char *val; - xmlnode x; - - x = p->x; - memset(p,0,sizeof(_jpacket)); - p->x = x; - p->p = xmlnode_pool(x); - - if(strncmp(xmlnode_get_name(x),"message",7) == 0) - { - p->type = JPACKET_MESSAGE; - }else if(strncmp(xmlnode_get_name(x),"presence",8) == 0) - { - p->type = JPACKET_PRESENCE; - val = xmlnode_get_attrib(x, "type"); - if(val == NULL) - p->subtype = JPACKET__AVAILABLE; - else if(strcmp(val,"unavailable") == 0) - p->subtype = JPACKET__UNAVAILABLE; - else if(strcmp(val,"probe") == 0) - p->subtype = JPACKET__PROBE; - else if(strcmp(val,"error") == 0) - p->subtype = JPACKET__ERROR; - else if(strcmp(val,"invisible") == 0) - p->subtype = JPACKET__INVISIBLE; - else if(*val == 's' || *val == 'u') - p->type = JPACKET_S10N; - else if(strcmp(val,"available") == 0) - { /* someone is using type='available' which is frowned upon */ - xmlnode_hide_attrib(x,"type"); - p->subtype = JPACKET__AVAILABLE; - }else - p->type = JPACKET_UNKNOWN; - }else if(strncmp(xmlnode_get_name(x),"iq",2) == 0) - { - p->type = JPACKET_IQ; - p->iq = xmlnode_get_tag(x,"?xmlns"); - p->iqns = xmlnode_get_attrib(p->iq,"xmlns"); - } - - /* set up the jids if any, flag packet as unknown if they are unparseable */ - val = xmlnode_get_attrib(x,"to"); - if(val != NULL) - if((p->to = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - val = xmlnode_get_attrib(x,"from"); - if(val != NULL) - if((p->from = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - - return p; -} - - -int jpacket_subtype(jpacket p) -{ - char *type; - int ret = p->subtype; - - if(ret != JPACKET__UNKNOWN) - return ret; - - ret = JPACKET__NONE; /* default, when no type attrib is specified */ - type = xmlnode_get_attrib(p->x, "type"); - if(j_strcmp(type,"error") == 0) - ret = JPACKET__ERROR; - else - switch(p->type) - { - case JPACKET_MESSAGE: - if(j_strcmp(type,"chat") == 0) - ret = JPACKET__CHAT; - else if(j_strcmp(type,"groupchat") == 0) - ret = JPACKET__GROUPCHAT; - else if(j_strcmp(type,"headline") == 0) - ret = JPACKET__HEADLINE; - break; - case JPACKET_S10N: - if(j_strcmp(type,"subscribe") == 0) - ret = JPACKET__SUBSCRIBE; - else if(j_strcmp(type,"subscribed") == 0) - ret = JPACKET__SUBSCRIBED; - else if(j_strcmp(type,"unsubscribe") == 0) - ret = JPACKET__UNSUBSCRIBE; - else if(j_strcmp(type,"unsubscribed") == 0) - ret = JPACKET__UNSUBSCRIBED; - break; - case JPACKET_IQ: - if(j_strcmp(type,"get") == 0) - ret = JPACKET__GET; - else if(j_strcmp(type,"set") == 0) - ret = JPACKET__SET; - else if(j_strcmp(type,"result") == 0) - ret = JPACKET__RESULT; - break; - } - - p->subtype = ret; - return ret; -}
--- a/src/protocols/jabber/jutil.c Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/jutil.c Mon Sep 29 15:23:19 2003 +0000 @@ -1,295 +1,185 @@ -/* -------------------------------------------------------------------------- - * - * License +/* + * gaim - Jabber Protocol Plugin * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ + */ +#include "internal.h" +#include "server.h" + +#include "presence.h" +#include "jutil.h" -#include "lib.h" +time_t str_to_time(const char *timestamp) +{ + struct tm t; + time_t retval = 0; + char buf[32]; + char *c; + int tzoff = 0; -#ifdef _WIN32 -#include "win32dep.h" -#endif + time(&retval); + localtime_r(&retval, &t); + + snprintf(buf, sizeof(buf), "%s", timestamp); + c = buf; -/* util for making presence packets */ -xmlnode jutil_presnew(int type, char *to, char *status) -{ - xmlnode pres; + /* 4 digit year */ + if(!sscanf(c, "%04d", &t.tm_year)) return 0; + c+=4; + if(*c == '-') + c++; - pres = xmlnode_new_tag("presence"); - switch(type) - { - case JPACKET__SUBSCRIBE: - xmlnode_put_attrib(pres,"type","subscribe"); - break; - case JPACKET__UNSUBSCRIBE: - xmlnode_put_attrib(pres,"type","unsubscribe"); - break; - case JPACKET__SUBSCRIBED: - xmlnode_put_attrib(pres,"type","subscribed"); - break; - case JPACKET__UNSUBSCRIBED: - xmlnode_put_attrib(pres,"type","unsubscribed"); - break; - case JPACKET__PROBE: - xmlnode_put_attrib(pres,"type","probe"); - break; - case JPACKET__UNAVAILABLE: - xmlnode_put_attrib(pres,"type","unavailable"); - break; - case JPACKET__INVISIBLE: - xmlnode_put_attrib(pres,"type","invisible"); - break; - } - if(to != NULL) - xmlnode_put_attrib(pres,"to",to); - if(status != NULL) - xmlnode_insert_cdata(xmlnode_insert_tag(pres,"status"),status,strlen(status)); + t.tm_year -= 1900; + + /* 2 digit month */ + if(!sscanf(c, "%02d", &t.tm_mon)) return 0; + c+=2; + if(*c == '-') + c++; + + t.tm_mon -= 1; - return pres; -} + /* 2 digit day */ + if(!sscanf(c, "%02d", &t.tm_mday)) return 0; + c+=2; + if(*c == 'T') { /* we have more than a date, keep going */ + c++; /* skip the "T" */ -/* util for making IQ packets */ -xmlnode jutil_iqnew(int type, char *ns) -{ - xmlnode iq; + /* 2 digit hour */ + if(sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec)) { + int tzhrs, tzmins; + c+=8; + if(*c == '.') /* dealing with precision we don't care about */ + c += 4; - iq = xmlnode_new_tag("iq"); - switch(type) - { - case JPACKET__GET: - xmlnode_put_attrib(iq,"type","get"); - break; - case JPACKET__SET: - xmlnode_put_attrib(iq,"type","set"); - break; - case JPACKET__RESULT: - xmlnode_put_attrib(iq,"type","result"); - break; - case JPACKET__ERROR: - xmlnode_put_attrib(iq,"type","error"); - break; - } - xmlnode_put_attrib(xmlnode_insert_tag(iq,"query"),"xmlns",ns); - - return iq; -} - -/* util for making message packets */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body) -{ - xmlnode msg; + if((*c == '+' || *c == '-') && + sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { + tzoff = tzhrs*60*60 + tzmins*60; + if(*c == '+') + tzoff *= -1; + } - msg = xmlnode_new_tag("message"); - xmlnode_put_attrib (msg, "type", type); - xmlnode_put_attrib (msg, "to", to); - - if (subj) - { - xmlnode_insert_cdata (xmlnode_insert_tag (msg, "subject"), subj, strlen (subj)); +#ifdef HAVE_TM_GMTOFF + tzoff += t.tm_gmtoff; +#else +# ifdef HAVE_TIMEZONE + tzset(); /* making sure */ + tzoff -= timezone; +# endif +#endif + } } - - xmlnode_insert_cdata (xmlnode_insert_tag (msg, "body"), body, strlen (body)); + retval = mktime(&t); - return msg; -} + retval += tzoff; -/* util for making stream packets */ -xmlnode jutil_header(char* xmlns, char* server) -{ - xmlnode result; - if ((xmlns == NULL)||(server == NULL)) - return NULL; - result = xmlnode_new_tag("stream:stream"); - xmlnode_put_attrib(result, "xmlns:stream", "http://etherx.jabber.org/streams"); - xmlnode_put_attrib(result, "xmlns", xmlns); - xmlnode_put_attrib(result, "to", server); - - return result; + return retval; } -/* returns the priority on a presence packet */ -int jutil_priority(xmlnode x) -{ - char *str; - int p; - - if(x == NULL) - return -1; - - if(xmlnode_get_attrib(x,"type") != NULL) - return -1; - - x = xmlnode_get_tag(x,"priority"); - if(x == NULL) - return 0; - - str = xmlnode_get_data((x)); - if(str == NULL) - return 0; - - p = atoi(str); - if(p >= 0) - return p; - else - return 0; -} - -void jutil_tofrom(xmlnode x) -{ - char *to, *from; - - to = xmlnode_get_attrib(x,"to"); - from = xmlnode_get_attrib(x,"from"); - xmlnode_put_attrib(x,"from",to); - xmlnode_put_attrib(x,"to",from); -} - -xmlnode jutil_iqresult(xmlnode x) -{ - xmlnode cur; - - jutil_tofrom(x); - - xmlnode_put_attrib(x,"type","result"); - - /* hide all children of the iq, they go back empty */ - for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) - xmlnode_hide(cur); - - return x; -} - -char *jutil_timestamp(void) -{ - time_t t; - struct tm *new_time; - static char timestamp[18]; - int ret; - - t = time(NULL); - - if(t == (time_t)-1) - return NULL; - new_time = gmtime(&t); - - ret = snprintf(timestamp, 18, "%d%02d%02dT%02d:%02d:%02d", 1900+new_time->tm_year, - new_time->tm_mon+1, new_time->tm_mday, new_time->tm_hour, - new_time->tm_min, new_time->tm_sec); - - if(ret == -1) - return NULL; - - return timestamp; +const char *jabber_get_state_string(int s) { + switch(s) { + case JABBER_STATE_AWAY: + return _("Away"); + break; + case JABBER_STATE_CHAT: + return _("Chatty"); + break; + case JABBER_STATE_XA: + return _("Extended Away"); + break; + case JABBER_STATE_DND: + return _("Do Not Disturb"); + break; + default: + return _("Available"); + break; + } } -void jutil_error(xmlnode x, terror E) +JabberID* +jabber_id_new(const char *str) { - xmlnode err; - char code[4]; + char *at; + char *slash; + + JabberID *jid; - xmlnode_put_attrib(x,"type","error"); - err = xmlnode_insert_tag(x,"error"); + if(!str) + return NULL; - snprintf(code,4,"%d",E.code); - xmlnode_put_attrib(err,"code",code); - if(E.msg != NULL) - xmlnode_insert_cdata(err,E.msg,strlen(E.msg)); + jid = g_new0(JabberID, 1); + + at = strchr(str, '@'); + slash = strchr(str, '/'); - jutil_tofrom(x); -} - -void jutil_delay(xmlnode msg, char *reason) -{ - xmlnode delay; + if(at) { + jid->node = g_strndup(str, at-str); + if(slash) { + jid->domain = g_strndup(at+1, slash-(at+1)); + jid->resource = g_strdup(slash+1); + } else { + jid->domain = g_strdup(at+1); + } + } else { + if(slash) { + jid->domain = g_strndup(str, slash-str); + jid->resource = g_strdup(slash+1); + } else { + jid->domain = g_strdup(str); + } + } - delay = xmlnode_insert_tag(msg,"x"); - xmlnode_put_attrib(delay,"xmlns",NS_DELAY); - xmlnode_put_attrib(delay,"from",xmlnode_get_attrib(msg,"to")); - xmlnode_put_attrib(delay,"stamp",jutil_timestamp()); - if(reason != NULL) - xmlnode_insert_cdata(delay,reason,strlen(reason)); + return jid; } -#define KEYBUF 100 - -char *jutil_regkey(char *key, char *seed) +void +jabber_id_free(JabberID *jid) { - static char keydb[KEYBUF][41]; - static char seeddb[KEYBUF][41]; - static int last = -1; - char *str, strint[32]; - int i; - - /* blanket the keydb first time */ - if(last == -1) - { - last = 0; - memset(&keydb,0,KEYBUF*41); - memset(&seeddb,0,KEYBUF*41); - srand(time(NULL)); - } - - /* creation phase */ - if(key == NULL && seed != NULL) - { - /* create a random key hash and store it */ - sprintf(strint,"%d",rand()); - strcpy(keydb[last],shahash(strint)); - - /* store a hash for the seed associated w/ this key */ - strcpy(seeddb[last],shahash(seed)); - - /* return it all */ - str = keydb[last]; - last++; - if(last == KEYBUF) last = 0; - return str; - } - - /* validation phase */ - str = shahash(seed); - for(i=0;i<KEYBUF;i++) - if(j_strcmp(keydb[i],key) == 0 && j_strcmp(seeddb[i],str) == 0) - { - seeddb[i][0] = '\0'; /* invalidate this key */ - return keydb[i]; - } - - return NULL; + if(jid) { + if(jid->node) + g_free(jid->node); + if(jid->domain) + g_free(jid->domain); + if(jid->resource) + g_free(jid->resource); + g_free(jid); + } } + +const char *jabber_get_resource(const char *jid) +{ + char *slash; + + slash = strrchr(jid, '/'); + if(slash) + return slash+1; + else + return NULL; +} + +char *jabber_get_bare_jid(const char *jid) +{ + char *slash; + slash = strrchr(jid, '/'); + + if(slash) + return g_strndup(jid, slash - jid); + else + return g_strdup(jid); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/jutil.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,41 @@ +/** + * @file jutil.h utility functions + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_JID_H_ +#define _GAIM_JABBER_JID_H_ + + +typedef struct _JabberID { + char *node; + char *domain; + char *resource; +} JabberID; + +JabberID* jabber_id_new(const char *str); +void jabber_id_free(JabberID *jid); + +const char *jabber_get_resource(const char *jid); +char *jabber_get_bare_jid(const char *jid); + +time_t str_to_time(const char *timestamp); +const char *jabber_get_state_string(int state); + +#endif /* _GAIM_JABBER_JID_H_ */
--- a/src/protocols/jabber/karma.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ -#include "lib.h" - -void karma_copy(struct karma *new, struct karma *old) -{ - new->init = old->init; - new->val = old->val; - new->bytes = old->bytes; - new->max = old->max; - new->inc = old->inc; - new->dec = old->dec; - new->penalty = old->penalty; - new->restore = old->restore; - new->last_update = old->last_update; - new->reset_meter = old->reset_meter; -} - -struct karma *karma_new(pool p) -{ - struct karma *new; - if(p == NULL) - return NULL; - - new = pmalloco(p, sizeof(struct karma)); - new->init = 0; - new->bytes = 0; - new->val = KARMA_INIT; - new->max = KARMA_MAX; - new->inc = KARMA_INC; - new->dec = KARMA_DEC; - new->penalty = KARMA_PENALTY; - new->restore = KARMA_RESTORE; - new->last_update = 0; - new->reset_meter = KARMA_RESETMETER; - - return new; -} - -void karma_increment(struct karma *k) -{ - /* set the current time, and check if we can increment */ - time_t cur_time = time(NULL); - int punishment_over = 0; - - /* only increment every KARMA_HEARTBEAT seconds */ - if( ( k->last_update + KARMA_HEARTBEAT > cur_time ) && k->last_update != 0) - return; - - /* if incrementing will raise >= 0 */ - if( ( k->val < 0 ) && ( k->val + k->inc >= 0 ) ) - punishment_over = 1; - - /* increment the karma value */ - k->val += k->inc; - if( k->val > k->max ) k->val = k->max; /* can only be so good */ - - /* lower our byte count, if we have good karma */ - if( k->val > 0 ) k->bytes -= ( KARMA_READ_MAX(k->val) ); - if( k->bytes < 0 ) k->bytes = 0; - - /* our karma has *raised* to 0 */ - if( punishment_over ) - /* Set Restore value and clear byte meter */ - { - k->val = k->restore; - /* Total absolution for transgression */ - if(k->reset_meter) k->bytes = 0; - } - - /* reset out counter */ - k->last_update = cur_time; -} - -void karma_decrement(struct karma *k, long bytes_read) -{ - - /* Increment the bytes read since last since last karma_increment */ - k->bytes += bytes_read; - - /* Check if our byte meter has exceeded the Max bytes our meter is allowed. */ - - if(k->bytes > KARMA_READ_MAX(k->val)) - { - /* Our meter has exceeded it's allowable lower our karma */ - k->val -= k->dec; - - /* if below zero, set to penalty */ - if(k->val <= 0) k->val = k->penalty; - } -} - -/* returns 0 on okay check, 1 on bad check */ -int karma_check(struct karma *k,long bytes_read) -{ - /* Check the need to increase or decrease karma */ - karma_increment(k); - karma_decrement(k, bytes_read); - - /* check its karma */ - if(k->val <= 0) - return 1; /* bad */ - - /* everything is okay */ - return 0; -}
--- a/src/protocols/jabber/latin1tab.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, -/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
--- a/src/protocols/jabber/lib.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,686 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - -#include <sys/types.h> -/*this must happen before sys/socket.h or freebsd won't compile*/ - -#ifndef _WIN32 -#include <syslog.h> -#include <strings.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <unistd.h> -#else -#include <winsock.h> -#endif - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <sys/time.h> -#include <stdarg.h> -#include <ctype.h> -#include <time.h> - -#include "xmlparse.h" - -/* -** Arrange to use either varargs or stdargs -*/ - -#define MAXSHORTSTR 203 /* max short string length */ -#define QUAD_T unsigned long long - -#ifdef __STDC__ - -#include <stdarg.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_END va_end(ap) - -#else /* __STDC__ */ - -# include <varargs.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) -# define VA_END va_end(ap) - -#endif /* __STDC__ */ - - -#ifndef INCL_LIB_H -#define INCL_LIB_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_SNPRINTF -extern int ap_snprintf(char *, size_t, const char *, ...); -#define snprintf ap_snprintf -#endif - -#ifndef HAVE_VSNPRINTF -extern int ap_vsnprintf(char *, size_t, const char *, va_list ap); -#define vsnprintf ap_vsnprintf -#endif - -#define ZONE zonestr(__FILE__,__LINE__) -char *zonestr(char *file, int line); - -/* --------------------------------------------------------- */ -/* */ -/* Pool-based memory management routines */ -/* */ -/* --------------------------------------------------------- */ - -#undef POOL_DEBUG -/* - flip these, this should be a prime number for top # of pools debugging -#define POOL_DEBUG 40009 -*/ - -/* pheap - singular allocation of memory */ -struct pheap -{ - void *block; - int size, used; -}; - -/* pool_cleaner - callback type which is associated - with a pool entry; invoked when the pool entry is - free'd */ -typedef void (*pool_cleaner)(void *arg); - -/* pfree - a linked list node which stores an - allocation chunk, plus a callback */ -struct pfree -{ - pool_cleaner f; - void *arg; - struct pheap *heap; - struct pfree *next; -}; - -/* pool - base node for a pool. Maintains a linked list - of pool entries (pfree) */ -typedef struct pool_struct -{ - int size; - struct pfree *cleanup; - struct pheap *heap; -#ifdef POOL_DEBUG - char name[8], zone[32]; - int lsize; -} _pool, *pool; -#define pool_new() _pool_new(ZONE) -#define pool_heap(i) _pool_new_heap(i,ZONE) -#else -} _pool, *pool; -#define pool_heap(i) _pool_new_heap(i,NULL) -#define pool_new() _pool_new(NULL) -#endif - -pool _pool_new(char *zone); /* new pool :) */ -pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */ -void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */ -void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */ -void *pmalloco(pool p, int size); /* YAPW for zeroing the block */ -char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */ -void pool_stat(int full); /* print to stderr the changed pools and reset */ -char *pstrdupx(pool p, const char *src); /* temp stub */ -void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */ -void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */ -int pool_size(pool p); /* returns total bytes allocated in this pool */ - - - - -/* --------------------------------------------------------- */ -/* */ -/* Socket helper stuff */ -/* */ -/* --------------------------------------------------------- */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define NETSOCKET_SERVER 0 -#define NETSOCKET_CLIENT 1 -#define NETSOCKET_UDP 2 - -int make_netsocket(unsigned short port, char *host, int type); -struct in_addr *make_addr(char *host); -int set_fd_close_on_exec(int fd, int flag); - - -/* --------------------------------------------------------- */ -/* */ -/* String management routines */ -/* */ -/* --------------------------------------------------------- */ -char *j_strdup(const char *str); /* provides NULL safe strdup wrapper */ -char *j_strcat(char *dest, char *txt); /* strcpy() clone */ -int j_strcmp(const char *a, const char *b); /* provides NULL safe strcmp wrapper */ -int j_strcasecmp(const char *a, const char *b); /* provides NULL safe strcasecmp wrapper */ -int j_strncmp(const char *a, const char *b, int i); /* provides NULL safe strncmp wrapper */ -int j_strncasecmp(const char *a, const char *b, int i); /* provides NULL safe strncasecmp wrapper */ -int j_strlen(const char *a); /* provides NULL safe strlen wrapper */ -int j_atoi(const char *a, int def); /* checks for NULL and uses default instead, convienence */ -void str_b64decode(char *str); /* what it says */ - - -/* --------------------------------------------------------- */ -/* */ -/* SHA calculations */ -/* */ -/* --------------------------------------------------------- */ -#if (SIZEOF_INT == 4) -typedef unsigned int uint32; -#elif (SIZEOF_SHORT == 4) -typedef unsigned short uint32; -#else -typedef unsigned int uint32; -#endif /* HAVEUINT32 */ - -char *shahash(char *str); /* NOT THREAD SAFE */ -void shahash_r(const char* str, char hashbuf[40]); /* USE ME */ - -int strprintsha(char *dest, int *hashval); - - -/* --------------------------------------------------------- */ -/* */ -/* Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct xhn_struct -{ - struct xhn_struct *next; - const char *key; - void *val; -} *xhn, _xhn; - -typedef struct xht_struct -{ - pool p; - int prime; - struct xhn_struct *zen; -} *xht, _xht; - -xht xhash_new(int prime); -void xhash_put(xht h, const char *key, void *val); -void *xhash_get(xht h, const char *key); -void xhash_zap(xht h, const char *key); -void xhash_free(xht h); -typedef void (*xhash_walker)(xht h, const char *key, void *val, void *arg); -void xhash_walk(xht h, xhash_walker w, void *arg); - -/* --------------------------------------------------------- */ -/* */ -/* DEPRECIATED Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef int (*KEYHASHFUNC)(const void *key); -typedef int (*KEYCOMPAREFUNC)(const void *key1, const void *key2); -typedef int (*TABLEWALKFUNC)(void *user_data, const void *key, void *data); - -typedef void *HASHTABLE; - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp); -HASHTABLE ghash_create_pool(pool p, int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp); -void ghash_destroy(HASHTABLE tbl); -void *ghash_get(HASHTABLE tbl, const void *key); -int ghash_put(HASHTABLE tbl, const void *key, void *value); -int ghash_remove(HASHTABLE tbl, const void *key); -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data); -int str_hash_code(const char *s); - - -/* --------------------------------------------------------- */ -/* */ -/* XML escaping utils */ -/* */ -/* --------------------------------------------------------- */ -char *strescape(pool p, char *buf); /* Escape <>&'" chars */ -char *strunescape(pool p, char *buf); - - -/* --------------------------------------------------------- */ -/* */ -/* String pools (spool) functions */ -/* */ -/* --------------------------------------------------------- */ -struct spool_node -{ - char *c; - struct spool_node *next; -}; - -typedef struct spool_struct -{ - pool p; - int len; - struct spool_node *last; - struct spool_node *first; -} *spool; - -spool spool_new(pool p); /* create a string pool */ -void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */ -char *spool_print(spool s); /* return a big string */ -void spool_add(spool s, char *str); /* add a single char to the pool */ -char *spools(pool p, ...); /* wrap all the spooler stuff in one function, the happy fun ball! */ - - -/* --------------------------------------------------------- */ -/* */ -/* xmlnodes - Document Object Model */ -/* */ -/* --------------------------------------------------------- */ -#define NTYPE_TAG 0 -#define NTYPE_ATTRIB 1 -#define NTYPE_CDATA 2 - -#define NTYPE_LAST 2 -#define NTYPE_UNDEF -1 - -/* -------------------------------------------------------------------------- - Node structure. Do not use directly! Always use accessor macros - and methods! - -------------------------------------------------------------------------- */ -typedef struct xmlnode_t -{ - char* name; - unsigned short type; - char* data; - int data_sz; - int complete; - pool p; - struct xmlnode_t* parent; - struct xmlnode_t* firstchild; - struct xmlnode_t* lastchild; - struct xmlnode_t* prev; - struct xmlnode_t* next; - struct xmlnode_t* firstattrib; - struct xmlnode_t* lastattrib; -} _xmlnode, *xmlnode; - -/* Node creation routines */ -xmlnode xmlnode_wrap(xmlnode x,const char* wrapper); -xmlnode xmlnode_new_tag(const char* name); -xmlnode xmlnode_new_tag_pool(pool p, const char* name); -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name); -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size); -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node); -void xmlnode_insert_node(xmlnode parent, xmlnode node); -xmlnode xmlnode_str(char *str, int len); -xmlnode xmlnode_file(char *file); -char* xmlnode_file_borked(char *file); /* same as _file but returns the parsing error */ -xmlnode xmlnode_dup(xmlnode x); /* duplicate x */ -xmlnode xmlnode_dup_pool(pool p, xmlnode x); - -/* Node Memory Pool */ -pool xmlnode_pool(xmlnode node); -xmlnode _xmlnode_new(pool p, const char *name, unsigned int type); - -/* Node editing */ -void xmlnode_hide(xmlnode child); -void xmlnode_hide_attrib(xmlnode parent, const char *name); - -/* Node deletion routine, also frees the node pool! */ -void xmlnode_free(xmlnode node); - -/* Locates a child tag by name and returns it */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name); -char* xmlnode_get_tag_data(xmlnode parent, const char* name); - -/* Attribute accessors */ -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value); -char* xmlnode_get_attrib(xmlnode owner, const char* name); -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts); - -/* Bastard am I, but these are fun for internal use ;-) */ -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value); -void* xmlnode_get_vattrib(xmlnode owner, const char* name); - -/* Node traversal routines */ -xmlnode xmlnode_get_firstattrib(xmlnode parent); -xmlnode xmlnode_get_firstchild(xmlnode parent); -xmlnode xmlnode_get_lastchild(xmlnode parent); -xmlnode xmlnode_get_nextsibling(xmlnode sibling); -xmlnode xmlnode_get_prevsibling(xmlnode sibling); -xmlnode xmlnode_get_parent(xmlnode node); - -/* Node information routines */ -char* xmlnode_get_name(xmlnode node); -char* xmlnode_get_data(xmlnode node); -int xmlnode_get_datasz(xmlnode node); -int xmlnode_get_type(xmlnode node); - -int xmlnode_has_children(xmlnode node); -int xmlnode_has_attribs(xmlnode node); - -/* Node-to-string translation */ -char* xmlnode2str(xmlnode node); - -/* Node-to-terminated-string translation - -- useful for interfacing w/ scripting langs */ -char* xmlnode2tstr(xmlnode node); - -int xmlnode_cmp(xmlnode a, xmlnode b); /* compares a and b for equality */ - -int xmlnode2file(char *file, xmlnode node); /* writes node to file */ - -/* Expat callbacks */ -void expat_startElement(void* userdata, const char* name, const char** atts); -void expat_endElement(void* userdata, const char* name); -void expat_charData(void* userdata, const char* s, int len); - -/*********************** - * XSTREAM Section - ***********************/ - -#define XSTREAM_MAXNODE 1000000 -#define XSTREAM_MAXDEPTH 100 - -#define XSTREAM_ROOT 0 /* root element */ -#define XSTREAM_NODE 1 /* normal node */ -#define XSTREAM_CLOSE 2 /* closed </stream:stream> */ -#define XSTREAM_ERR 4 /* parser error */ - -typedef void (*xstream_onNode)(int type, xmlnode x, void *arg); /* xstream event handler */ - -typedef struct xstream_struct -{ - XML_Parser parser; - xmlnode node; - char *cdata; - int cdata_len; - pool p; - xstream_onNode f; - void *arg; - int status; - int depth; -} *xstream, _xstream; - -xstream xstream_new(pool p, xstream_onNode f, void *arg); /* create a new xstream */ -int xstream_eat(xstream xs, char *buff, int len); /* parse new data for this xstream, returns last XSTREAM_* status */ - -/* convience functions */ -xmlnode xstream_header(char *namespace, char *to, char *from); -char *xstream_header_char(xmlnode x); - - -typedef struct { - unsigned long H[5]; - unsigned long W[80]; - int lenW; - unsigned long sizeHi,sizeLo; -} j_SHA_CTX; - - -void shaInit(j_SHA_CTX *ctx); -void shaUpdate(j_SHA_CTX *ctx, unsigned char *dataIn, int len); -void shaFinal(j_SHA_CTX *ctx, unsigned char hashout[20]); -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); - -/********** END OLD libxode.h BEGIN OLD jabber.h *************/ - -/* --------------------------------------------------------- */ -/* */ -/* JID structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JID_RESOURCE 1 -#define JID_USER 2 -#define JID_SERVER 4 - -typedef struct jid_struct -{ - pool p; - char* resource; - char* user; - char* server; - char* full; - struct jid_struct *next; /* for lists of jids */ -} *jid; - -jid jid_new(pool p, char *idstr); /* Creates a jabber id from the idstr */ -void jid_set(jid id, char *str, int item); /* Individually sets jid components */ -char* jid_full(jid id); /* Builds a string type=user/resource@server from the jid data */ -int jid_cmp(jid a, jid b); /* Compares two jid's, returns 0 for perfect match */ -int jid_cmpx(jid a, jid b, int parts); /* Compares just the parts specified as JID_|JID_ */ -jid jid_append(jid a, jid b); /* Appending b to a (list), no dups */ -xmlnode jid_xres(jid id); /* Returns xmlnode representation of the resource?query=string */ -xmlnode jid_nodescan(jid id, xmlnode x); /* Scans the children of the node for a matching jid attribute */ -jid jid_user(jid a); /* returns the same jid but just of the user@host part */ - - -/* --------------------------------------------------------- */ -/* */ -/* JPacket structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JPACKET_UNKNOWN 0x00 -#define JPACKET_MESSAGE 0x01 -#define JPACKET_PRESENCE 0x02 -#define JPACKET_IQ 0x04 -#define JPACKET_S10N 0x08 - -#define JPACKET__UNKNOWN 0 -#define JPACKET__NONE 1 -#define JPACKET__ERROR 2 -#define JPACKET__CHAT 3 -#define JPACKET__GROUPCHAT 4 -#define JPACKET__GET 5 -#define JPACKET__SET 6 -#define JPACKET__RESULT 7 -#define JPACKET__SUBSCRIBE 8 -#define JPACKET__SUBSCRIBED 9 -#define JPACKET__UNSUBSCRIBE 10 -#define JPACKET__UNSUBSCRIBED 11 -#define JPACKET__AVAILABLE 12 -#define JPACKET__UNAVAILABLE 13 -#define JPACKET__PROBE 14 -#define JPACKET__HEADLINE 15 -#define JPACKET__INVISIBLE 16 - -typedef struct jpacket_struct -{ - unsigned char type; - int subtype; - int flag; - void* aux1; - xmlnode x; - jid to; - jid from; - char* iqns; - xmlnode iq; - pool p; -} *jpacket, _jpacket; - -jpacket jpacket_new(xmlnode x); /* Creates a jabber packet from the xmlnode */ -jpacket jpacket_reset(jpacket p); /* Resets the jpacket values based on the xmlnode */ -int jpacket_subtype(jpacket p); /* Returns the subtype value (looks at xmlnode for it) */ - - -/* --------------------------------------------------------- */ -/* */ -/* Presence Proxy DB structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct ppdb_struct -{ - jid id; /* entry data */ - int pri; - xmlnode x; - struct ppdb_struct* user; /* linked list for user@server */ - pool p; /* db-level data */ - struct ppdb_struct* next; -} _ppdb, *ppdb; - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x); /* Inserts presence into the proxy */ -xmlnode ppdb_primary(ppdb db, jid id); /* Fetches the matching primary presence for the id */ -void ppdb_free(ppdb db); /* Frees the db and all entries */ -xmlnode ppdb_get(ppdb db, jid id); /* Called successively to return each presence xmlnode */ - /* for the id and children, returns NULL at the end */ - - -/* --------------------------------------------------------- */ -/* */ -/* Simple Jabber Rate limit functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct jlimit_struct -{ - char *key; - int start; - int points; - int maxt, maxp; - pool p; -} *jlimit, _jlimit; - -jlimit jlimit_new(int maxt, int maxp); -void jlimit_free(jlimit r); -int jlimit_check(jlimit r, char *key, int points); - - -/* #define KARMA_DEBUG */ -/* default to disable karma */ -#define KARMA_READ_MAX(k) (abs(k)*100) /* how much you are allowed to read off the sock */ -#define KARMA_INIT 5 /* internal "init" value */ -#define KARMA_HEARTBEAT 2 /* seconds to register for heartbeat */ -#define KARMA_MAX 10 /* total max karma you can have */ -#define KARMA_INC 1 /* how much to increment every KARMA_HEARTBEAT seconds */ -#define KARMA_DEC 0 /* how much to penalize for reading KARMA_READ_MAX in - KARMA_HEARTBEAT seconds */ -#define KARMA_PENALTY -5 /* where you go when you hit 0 karma */ -#define KARMA_RESTORE 5 /* where you go when you payed your penelty or INIT */ -#define KARMA_RESETMETER 0 /* Reset byte meter on restore default is falst */ - -struct karma -{ - int init; /* struct initialized */ - int reset_meter; /* reset the byte meter on restore */ - int val; /* current karma value */ - long bytes; /* total bytes read (in that time period) */ - int max; /* max karma you can have */ - int inc,dec; /* how much to increment/decrement */ - int penalty,restore; /* what penalty (<0) or restore (>0) */ - time_t last_update; /* time this was last incremented */ -}; - -struct karma *karma_new(pool p); /* creates a new karma object, with default values */ -void karma_copy(struct karma *new, struct karma *old); /* makes a copy of old in new */ -void karma_increment(struct karma *k); /* inteligently increments karma */ -void karma_decrement(struct karma *k, long bytes_read); /* inteligently decrements karma */ -int karma_check(struct karma *k,long bytes_read); /* checks to see if we have good karma */ - - - -/* --------------------------------------------------------- */ -/* */ -/* Error structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct terror_struct -{ - int code; - char msg[64]; -} terror; - -#define TERROR_BAD (terror){400,"Bad Request"} -#define TERROR_AUTH (terror){401,"Unauthorized"} -#define TERROR_PAY (terror){402,"Payment Required"} -#define TERROR_FORBIDDEN (terror){403,"Forbidden"} -#define TERROR_NOTFOUND (terror){404,"Not Found"} -#define TERROR_NOTALLOWED (terror){405,"Not Allowed"} -#define TERROR_NOTACCEPTABLE (terror){406,"Not Acceptable"} -#define TERROR_REGISTER (terror){407,"Registration Required"} -#define TERROR_REQTIMEOUT (terror){408,"Request Timeout"} -#define TERROR_CONFLICT (terror){409,"Conflict"} - -#define TERROR_INTERNAL (terror){500,"Internal Server Error"} -#define TERROR_NOTIMPL (terror){501,"Not Implemented"} -#define TERROR_EXTERNAL (terror){502,"Remote Server Error"} -#define TERROR_UNAVAIL (terror){503,"Service Unavailable"} -#define TERROR_EXTTIMEOUT (terror){504,"Remote Server Timeout"} -#define TERROR_DISCONNECTED (terror){510,"Disconnected"} - -/* --------------------------------------------------------- */ -/* */ -/* Namespace constants */ -/* */ -/* --------------------------------------------------------- */ -#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0) - -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" -#define NS_AUTH "jabber:iq:auth" -#define NS_REGISTER "jabber:iq:register" -#define NS_ROSTER "jabber:iq:roster" -#define NS_OFFLINE "jabber:x:offline" -#define NS_AGENT "jabber:iq:agent" -#define NS_AGENTS "jabber:iq:agents" -#define NS_DELAY "jabber:x:delay" -#define NS_VERSION "jabber:iq:version" -#define NS_TIME "jabber:iq:time" -#define NS_VCARD "vcard-temp" -#define NS_PRIVATE "jabber:iq:private" -#define NS_SEARCH "jabber:iq:search" -#define NS_OOB "jabber:iq:oob" -#define NS_XOOB "jabber:x:oob" -#define NS_ADMIN "jabber:iq:admin" -#define NS_FILTER "jabber:iq:filter" -#define NS_AUTH_0K "jabber:iq:auth:0k" -#define NS_BROWSE "jabber:iq:browse" -#define NS_EVENT "jabber:x:event" -#define NS_CONFERENCE "jabber:iq:conference" -#define NS_SIGNED "jabber:x:signed" -#define NS_ENCRYPTED "jabber:x:encrypted" -#define NS_GATEWAY "jabber:iq:gateway" -#define NS_LAST "jabber:iq:last" -#define NS_ENVELOPE "jabber:x:envelope" -#define NS_EXPIRE "jabber:x:expire" -#define NS_XHTML "http://www.w3.org/1999/xhtml" - -#define NS_XDBGINSERT "jabber:xdb:ginsert" -#define NS_XDBNSLIST "jabber:xdb:nslist" - - -/* --------------------------------------------------------- */ -/* */ -/* JUtil functions */ -/* */ -/* --------------------------------------------------------- */ -xmlnode jutil_presnew(int type, char *to, char *status); /* Create a skeleton presence packet */ -xmlnode jutil_iqnew(int type, char *ns); /* Create a skeleton iq packet */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body); - /* Create a skeleton message packet */ -xmlnode jutil_header(char* xmlns, char* server); /* Create a skeleton stream packet */ -int jutil_priority(xmlnode x); /* Determine priority of this packet */ -void jutil_tofrom(xmlnode x); /* Swaps to/from fields on a packet */ -xmlnode jutil_iqresult(xmlnode x); /* Generate a skeleton iq/result, given a iq/query */ -char* jutil_timestamp(void); /* Get stringified timestamp */ -void jutil_error(xmlnode x, terror E); /* Append an <error> node to x */ -void jutil_delay(xmlnode msg, char *reason); /* Append a delay packet to msg */ -char* jutil_regkey(char *key, char *seed); /* pass a seed to generate a key, pass the key again to validate (returns it) */ - - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_LIB_H */
--- a/src/protocols/jabber/libxode.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,450 +0,0 @@ -#ifndef _WIN32 -#include <syslog.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <strings.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <unistd.h> -#else -#include <winsock.h> -#endif - -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <sys/time.h> -#include <time.h> - -#include "xmlparse.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - -/* -** Arrange to use either varargs or stdargs -*/ - -#define MAXSHORTSTR 203 /* max short string length */ -#define QUAD_T unsigned long long - -#ifdef __STDC__ - -#include <stdarg.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_END va_end(ap) - -#else /* __STDC__ */ - -# include <varargs.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) -# define VA_END va_end(ap) - -#endif /* __STDC__ */ - - -#ifndef INCL_LIBXODE_H -#define INCL_LIBXODE_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_SNPRINTF -extern int ap_snprintf(char *, size_t, const char *, ...); -#define snprintf ap_snprintf -#endif - -#ifndef HAVE_VSNPRINTF -extern int ap_vsnprintf(char *, size_t, const char *, va_list ap); -#define vsnprintf ap_vsnprintf -#endif - -#define ZONE zonestr(__FILE__,__LINE__) -char *zonestr(char *file, int line); - -/* --------------------------------------------------------- */ -/* */ -/* Pool-based memory management routines */ -/* */ -/* --------------------------------------------------------- */ - -#undef POOL_DEBUG -/* - flip these, this should be a prime number for top # of pools debugging -#define POOL_DEBUG 40009 -*/ - -/* pheap - singular allocation of memory */ -struct pheap -{ - void *block; - int size, used; -}; - -/* pool_cleaner - callback type which is associated - with a pool entry; invoked when the pool entry is - free'd */ -typedef void (*pool_cleaner)(void *arg); - -/* pfree - a linked list node which stores an - allocation chunk, plus a callback */ -struct pfree -{ - pool_cleaner f; - void *arg; - struct pheap *heap; - struct pfree *next; -}; - -/* pool - base node for a pool. Maintains a linked list - of pool entries (pfree) */ -typedef struct pool_struct -{ - int size; - struct pfree *cleanup; - struct pheap *heap; -#ifdef POOL_DEBUG - char name[8], zone[32]; - int lsize; -} _pool, *pool; -#define pool_new() _pool_new(ZONE) -#define pool_heap(i) _pool_new_heap(i,ZONE) -#else -} _pool, *pool; -#define pool_heap(i) _pool_new_heap(i,NULL) -#define pool_new() _pool_new(NULL) -#endif - -pool _pool_new(char *zone); /* new pool :) */ -pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */ -void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */ -void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */ -void *pmalloco(pool p, int size); /* YAPW for zeroing the block */ -char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */ -void pool_stat(int full); /* print to stderr the changed pools and reset */ -char *pstrdupx(pool p, const char *src); /* temp stub */ -void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */ -void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */ -int pool_size(pool p); /* returns total bytes allocated in this pool */ - - - - -/* --------------------------------------------------------- */ -/* */ -/* Socket helper stuff */ -/* */ -/* --------------------------------------------------------- */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define NETSOCKET_SERVER 0 -#define NETSOCKET_CLIENT 1 -#define NETSOCKET_UDP 2 - -int make_netsocket(unsigned short port, char *host, int type); -struct in_addr *make_addr(char *host); -int set_fd_close_on_exec(int fd, int flag); - - -/* --------------------------------------------------------- */ -/* */ -/* String management routines */ -/* */ -/* --------------------------------------------------------- */ -char *j_strdup(const char *str); /* provides NULL safe strdup wrapper */ -char *j_strcat(char *dest, char *txt); /* strcpy() clone */ -int j_strcmp(const char *a, const char *b); /* provides NULL safe strcmp wrapper */ -int j_strcasecmp(const char *a, const char *b); /* provides NULL safe strcasecmp wrapper */ -int j_strncmp(const char *a, const char *b, int i); /* provides NULL safe strncmp wrapper */ -int j_strncasecmp(const char *a, const char *b, int i); /* provides NULL safe strncasecmp wrapper */ -int j_strlen(const char *a); /* provides NULL safe strlen wrapper */ -int j_atoi(const char *a, int def); /* checks for NULL and uses default instead, convienence */ -void str_b64decode(char *str); /* what it says */ - - -/* --------------------------------------------------------- */ -/* */ -/* SHA calculations */ -/* */ -/* --------------------------------------------------------- */ -#if (SIZEOF_INT == 4) -typedef unsigned int uint32; -#elif (SIZEOF_SHORT == 4) -typedef unsigned short uint32; -#else -typedef unsigned int uint32; -#endif /* HAVEUINT32 */ - -int sha_hash(int *data, int *hash); -int sha_init(int *hash); -char *shahash(char *str); /* NOT THREAD SAFE */ -void shahash_r(const char* str, char hashbuf[41]); /* USE ME */ - -int strprintsha(char *dest, int *hashval); - - -/* --------------------------------------------------------- */ -/* */ -/* Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef int (*KEYHASHFUNC)(const void *key); -typedef int (*KEYCOMPAREFUNC)(const void *key1, const void *key2); -typedef int (*TABLEWALKFUNC)(void *user_data, const void *key, void *data); - -typedef void *HASHTABLE; - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp); -void ghash_destroy(HASHTABLE tbl); -void *ghash_get(HASHTABLE tbl, const void *key); -int ghash_put(HASHTABLE tbl, const void *key, void *value); -int ghash_remove(HASHTABLE tbl, const void *key); -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data); -int str_hash_code(const char *s); - - -/* --------------------------------------------------------- */ -/* */ -/* XML escaping utils */ -/* */ -/* --------------------------------------------------------- */ -char *strescape(pool p, char *buf); /* Escape <>&'" chars */ -char *strunescape(pool p, char *buf); - - -/* --------------------------------------------------------- */ -/* */ -/* String pools (spool) functions */ -/* */ -/* --------------------------------------------------------- */ -struct spool_node -{ - char *c; - struct spool_node *next; -}; - -typedef struct spool_struct -{ - pool p; - int len; - struct spool_node *last; - struct spool_node *first; -} *spool; - -spool spool_new(pool p); /* create a string pool */ -void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */ -char *spool_print(spool s); /* return a big string */ -void spool_add(spool s, char *str); /* add a single char to the pool */ -char *spools(pool p, ...); /* wrap all the spooler stuff in one function, the happy fun ball! */ - - -/* --------------------------------------------------------- */ -/* */ -/* xmlnodes - Document Object Model */ -/* */ -/* --------------------------------------------------------- */ -#define NTYPE_TAG 0 -#define NTYPE_ATTRIB 1 -#define NTYPE_CDATA 2 - -#define NTYPE_LAST 2 -#define NTYPE_UNDEF -1 - -/* -------------------------------------------------------------------------- - Node structure. Do not use directly! Always use accessor macros - and methods! - -------------------------------------------------------------------------- */ -typedef struct xmlnode_t -{ - char* name; - unsigned short type; - char* data; - int data_sz; - int complete; - pool p; - struct xmlnode_t* parent; - struct xmlnode_t* firstchild; - struct xmlnode_t* lastchild; - struct xmlnode_t* prev; - struct xmlnode_t* next; - struct xmlnode_t* firstattrib; - struct xmlnode_t* lastattrib; -} _xmlnode, *xmlnode; - -/* Node creation routines */ -xmlnode xmlnode_wrap(xmlnode x,const char* wrapper); -xmlnode xmlnode_new_tag(const char* name); -xmlnode xmlnode_new_tag_pool(pool p, const char* name); -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name); -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size); -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node); -void xmlnode_insert_node(xmlnode parent, xmlnode node); -xmlnode xmlnode_str(char *str, int len); -xmlnode xmlnode_file(char *file); -xmlnode xmlnode_dup(xmlnode x); /* duplicate x */ -xmlnode xmlnode_dup_pool(pool p, xmlnode x); - -/* Node Memory Pool */ -pool xmlnode_pool(xmlnode node); -xmlnode _xmlnode_new(pool p, const char *name, unsigned int type); - -/* Node editing */ -void xmlnode_hide(xmlnode child); -void xmlnode_hide_attrib(xmlnode parent, const char *name); - -/* Node deletion routine, also frees the node pool! */ -void xmlnode_free(xmlnode node); - -/* Locates a child tag by name and returns it */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name); -char* xmlnode_get_tag_data(xmlnode parent, const char* name); - -/* Attribute accessors */ -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value); -char* xmlnode_get_attrib(xmlnode owner, const char* name); -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts); - -/* Bastard am I, but these are fun for internal use ;-) */ -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value); -void* xmlnode_get_vattrib(xmlnode owner, const char* name); - -/* Node traversal routines */ -xmlnode xmlnode_get_firstattrib(xmlnode parent); -xmlnode xmlnode_get_firstchild(xmlnode parent); -xmlnode xmlnode_get_lastchild(xmlnode parent); -xmlnode xmlnode_get_nextsibling(xmlnode sibling); -xmlnode xmlnode_get_prevsibling(xmlnode sibling); -xmlnode xmlnode_get_parent(xmlnode node); - -/* Node information routines */ -char* xmlnode_get_name(xmlnode node); -char* xmlnode_get_data(xmlnode node); -int xmlnode_get_datasz(xmlnode node); -int xmlnode_get_type(xmlnode node); - -int xmlnode_has_children(xmlnode node); -int xmlnode_has_attribs(xmlnode node); - -/* Node-to-string translation */ -char* xmlnode2str(xmlnode node); - -/* Node-to-terminated-string translation - -- useful for interfacing w/ scripting langs */ -char* xmlnode2tstr(xmlnode node); - -int xmlnode_cmp(xmlnode a, xmlnode b); /* compares a and b for equality */ - -int xmlnode2file(char *file, xmlnode node); /* writes node to file */ - -/* Expat callbacks */ -void expat_startElement(void* userdata, const char* name, const char** atts); -void expat_endElement(void* userdata, const char* name); -void expat_charData(void* userdata, const char* s, int len); - -/*********************** - * XSTREAM Section - ***********************/ - -#define XSTREAM_MAXNODE 1000000 -#define XSTREAM_MAXDEPTH 100 - -#define XSTREAM_ROOT 0 /* root element */ -#define XSTREAM_NODE 1 /* normal node */ -#define XSTREAM_CLOSE 2 /* closed </stream:stream> */ -#define XSTREAM_ERR 4 /* parser error */ - -typedef void (*xstream_onNode)(int type, xmlnode x, void *arg); /* xstream event handler */ - -typedef struct xstream_struct -{ - XML_Parser parser; - xmlnode node; - char *cdata; - int cdata_len; - pool p; - xstream_onNode f; - void *arg; - int status; - int depth; -} *xstream, _xstream; - -xstream xstream_new(pool p, xstream_onNode f, void *arg); /* create a new xstream */ -int xstream_eat(xstream xs, char *buff, int len); /* parse new data for this xstream, returns last XSTREAM_* status */ - -/* convience functions */ -xmlnode xstream_header(char *namespace, char *to, char *from); -char *xstream_header_char(xmlnode x); - -/* SHA.H */ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Header File - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - * Paul Kocher - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -typedef struct { - unsigned long H[5]; - unsigned long W[80]; - int lenW; - unsigned long sizeHi,sizeLo; -} SHA_CTX; - - -void shaInit(SHA_CTX *ctx); -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); - - -/* END SHA.H */ - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_LIBXODE_H */
--- a/src/protocols/jabber/log.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include "jabber.h" -#include "log.h" - -#ifdef DEBUG - -void jdebug(char *zone, const char *msgfmt, ...) -{ - va_list ap; - static char loghdr[LOGSIZE_HDR]; - static char logmsg[LOGSIZE_TAIL]; - static int size; - - /* XXX: We may want to check the sizes eventually */ - size = snprintf(loghdr, LOGSIZE_HDR, "debug/%s %s\n", zone, msgfmt); - - va_start(ap, msgfmt); - size = vsnprintf(logmsg, LOGSIZE_TAIL, loghdr, ap); - - fprintf(stderr,"%s",logmsg); - - return; -} - - -#endif /* DEBUG */
--- a/src/protocols/jabber/log.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#ifndef INCL_LOG_H -#define INCL_LOG_H - -#define LOGSIZE_HDR 1024 -#define LOGSIZE_TAIL 2048 - - -#ifdef DEBUG - void jdebug(char *zone, const char *msgfmt, ...); -#else - #define jdebug if(0) warn -#endif - - - -#endif /* INCL_LOG_H */ -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/message.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,413 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" + +#include "debug.h" +#include "html.h" +#include "notify.h" +#include "server.h" + +#include "buddy.h" +#include "chat.h" +#include "message.h" +#include "xmlnode.h" + +#define JABBER_TYPING_NOTIFY_INT 15 + +void jabber_message_free(JabberMessage *jm) +{ + if(jm->from) + g_free(jm->from); + if(jm->to) + g_free(jm->to); + if(jm->subject) + g_free(jm->subject); + if(jm->body) + g_free(jm->body); + if(jm->xhtml) + g_free(jm->xhtml); + if(jm->password) + g_free(jm->password); + + g_free(jm); +} + +void handle_chat(JabberMessage *jm) +{ + JabberID *jid = jabber_id_new(jm->from); + char *from; + + JabberBuddy *jb; + JabberBuddyResource *jbr; + + jb = jabber_buddy_find(jm->js, jm->from, TRUE); + jbr = jabber_buddy_find_resource(jb, jabber_get_resource(jm->from)); + + if(gaim_find_conversation_with_account(jm->from, jm->js->gc->account)) + from = g_strdup(jm->from); + else if(jid->node) + from = g_strdup_printf("%s@%s", jid->node, jid->domain); + else + from = g_strdup(jid->domain); + + if(!jm->xhtml && !jm->body) { + if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) + serv_got_typing(jm->js->gc, from, 0, GAIM_TYPING); + else + serv_got_typing_stopped(jm->js->gc, from); + } else { + if(jbr && jm->events & JABBER_MESSAGE_EVENT_COMPOSING) + jbr->capabilities |= JABBER_CAP_COMPOSING; + serv_got_im(jm->js->gc, from, jm->xhtml ? jm->xhtml : jm->body, 0, + jm->sent); + } + + g_free(from); + jabber_id_free(jid); +} + +void handle_groupchat(JabberMessage *jm) +{ + JabberID *jid = jabber_id_new(jm->from); + JabberChat *chat = jabber_chat_find(jm->js, jid->node, jid->domain); + + if(!chat) + return; + + if(jm->subject) + gaim_chat_set_topic(GAIM_CHAT(chat->conv), jid->resource, jm->subject); + + serv_got_chat_in(jm->js->gc, chat->id, jabber_get_resource(jm->from), + 0, jm->xhtml ? jm->xhtml : jm->body, jm->sent); + jabber_id_free(jid); +} + +void handle_groupchat_invite(JabberMessage *jm) +{ + GHashTable *components = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + JabberID *jid = jabber_id_new(jm->to); + + g_hash_table_replace(components, g_strdup("room"), jid->node); + g_hash_table_replace(components, g_strdup("server"), jid->node); + g_hash_table_replace(components, g_strdup("handle"), jm->js->user->node); + g_hash_table_replace(components, g_strdup("password"), jm->password); + + jabber_id_free(jid); + serv_got_chat_invite(jm->js->gc, jm->to, jm->from, jm->body, components); +} + +void handle_error(JabberMessage *jm) +{ + char *buf; + + if(!jm->body) + return; + + buf = g_strdup_printf(_("Message delivery to %s failed: %s"), + jm->from, jm->error); + + gaim_notify_error(jm->js->gc, _("Jabber Message Error"), buf, jm->body); + + g_free(buf); +} + +void jabber_message_parse(JabberStream *js, xmlnode *packet) +{ + JabberMessage *jm; + const char *type; + xmlnode *child; + + if(strcmp(packet->name, "message")) + return; + + jm = g_new0(JabberMessage, 1); + jm->js = js; + jm->sent = time(NULL); + + type = xmlnode_get_attrib(packet, "type"); + + if(type) { + if(!strcmp(type, "normal")) + jm->type = JABBER_MESSAGE_NORMAL; + else if(!strcmp(type, "chat")) + jm->type = JABBER_MESSAGE_CHAT; + else if(!strcmp(type, "groupchat")) + jm->type = JABBER_MESSAGE_GROUPCHAT; + else if(!strcmp(type, "headline")) + jm->type = JABBER_MESSAGE_HEADLINE; + else if(!strcmp(type, "error")) + jm->type = JABBER_MESSAGE_ERROR; + else + jm->type = JABBER_MESSAGE_OTHER; + } else { + jm->type = JABBER_MESSAGE_NORMAL; + } + + jm->from = g_strdup(xmlnode_get_attrib(packet, "from")); + jm->to = g_strdup(xmlnode_get_attrib(packet, "to")); + + for(child = packet->child; child; child = child->next) { + if(child->type != NODE_TYPE_TAG) + continue; + + if(!strcmp(child->name, "subject")) { + if(!jm->subject) + jm->subject = xmlnode_get_data(child); + } else if(!strcmp(child->name, "body")) { + if(!jm->body) + jm->body = xmlnode_get_data(child); + } else if(!strcmp(child->name, "html") && child->child) { + /* check to see if the <html> actually contains anything, + * otherwise we'll ignore it */ + char *txt = xmlnode_get_data(child); + if(!jm->xhtml && txt) + jm->xhtml = xmlnode_to_str(child); + g_free(txt); + } else if(!strcmp(child->name, "error")) { + const char *code = xmlnode_get_attrib(child, "code"); + char *code_txt = NULL; + char *text = xmlnode_get_data(child); + + if(code) + code_txt = g_strdup_printf(_(" (Code %s)"), code); + + if(!jm->error) + jm->error = g_strdup_printf("%s%s", text ? text : "", + code_txt ? code_txt : ""); + + g_free(code_txt); + g_free(text); + } else if(!strcmp(child->name, "x")) { + const char *xmlns = xmlnode_get_attrib(child, "xmlns"); + if(xmlns && !strcmp(xmlns, "jabber:x:event")) { + if(xmlnode_get_child(child, "composing")) + jm->events |= JABBER_MESSAGE_EVENT_COMPOSING; + } else if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { + const char *timestamp = xmlnode_get_attrib(child, "stamp"); + if(timestamp) + jm->sent = str_to_time(timestamp); + } else if(xmlns && !strcmp(xmlns, "jabber:x:conference") && + jm->type != JABBER_MESSAGE_GROUPCHAT_INVITE) { + const char *jid = xmlnode_get_attrib(child, "jid"); + if(jid) { + jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; + g_free(jm->to); + jm->to = g_strdup(jid); + } + } else if(xmlns && !strcmp(xmlns, + "http://jabber.org/protocol/muc#user")) { + xmlnode *invite = xmlnode_get_child(child, "invite"); + if(invite) { + xmlnode *reason, *password; + const char *jid = xmlnode_get_attrib(child, "from"); + g_free(jm->to); + jm->to = jm->from; + jm->from = g_strdup(jid); + if((reason = xmlnode_get_child(invite, "reason"))) { + g_free(jm->body); + jm->body = xmlnode_get_data(reason); + } + if((password = xmlnode_get_child(invite, "password"))) + jm->password = xmlnode_get_data(password); + + jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; + } + } + } + } + + switch(jm->type) { + case JABBER_MESSAGE_NORMAL: + case JABBER_MESSAGE_CHAT: + case JABBER_MESSAGE_HEADLINE: + handle_chat(jm); + break; + case JABBER_MESSAGE_GROUPCHAT: + handle_groupchat(jm); + break; + case JABBER_MESSAGE_GROUPCHAT_INVITE: + handle_groupchat_invite(jm); + break; + case JABBER_MESSAGE_ERROR: + handle_error(jm); + break; + case JABBER_MESSAGE_OTHER: + gaim_debug(GAIM_DEBUG_INFO, "jabber", + "Received message of unknown type: %s\n", type); + break; + } + jabber_message_free(jm); +} + +void jabber_message_send(JabberMessage *jm) +{ + xmlnode *message, *child; + const char *type = NULL; + + message = xmlnode_new("message"); + + switch(jm->type) { + case JABBER_MESSAGE_NORMAL: + type = "normal"; + break; + case JABBER_MESSAGE_CHAT: + case JABBER_MESSAGE_GROUPCHAT_INVITE: + type = "chat"; + break; + case JABBER_MESSAGE_HEADLINE: + type = "headline"; + break; + case JABBER_MESSAGE_GROUPCHAT: + type = "groupchat"; + break; + case JABBER_MESSAGE_ERROR: + type = "error"; + break; + case JABBER_MESSAGE_OTHER: + type = NULL; + break; + } + + if(type) + xmlnode_set_attrib(message, "type", type); + + xmlnode_set_attrib(message, "to", jm->to); + + if(jm->events || (!jm->body && !jm->xhtml)) { + child = xmlnode_new_child(message, "x"); + xmlnode_set_attrib(child, "xmlns", "jabber:x:event"); + if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) + xmlnode_new_child(child, "composing"); + } + + if(jm->subject) { + child = xmlnode_new_child(message, "subject"); + xmlnode_insert_data(child, jm->subject, -1); + } + + if(jm->body) { + child = xmlnode_new_child(message, "body"); + xmlnode_insert_data(child, jm->body, -1); + } + + if(jm->xhtml) { + child = xmlnode_from_str(jm->xhtml, -1); + if(child) { + xmlnode_insert_child(message, child); + } else { + gaim_debug(GAIM_DEBUG_ERROR, "jabber", + "XHTML translation/validation failed, returning: %s\n", + jm->xhtml); + } + } + + jabber_send(jm->js, message); + + xmlnode_free(message); +} + +int jabber_message_send_im(GaimConnection *gc, const char *who, const char *msg, + GaimImFlags flags) +{ + JabberMessage *jm; + JabberBuddy *jb; + JabberBuddyResource *jbr; + char *buf; + char *xhtml, *plain; + + if(!who || !msg) + return 0; + + jb = jabber_buddy_find(gc->proto_data, who, TRUE); + jbr = jabber_buddy_find_resource(jb, jabber_get_resource(who)); + + jm = g_new0(JabberMessage, 1); + jm->js = gc->proto_data; + jm->type = JABBER_MESSAGE_CHAT; + jm->events = JABBER_MESSAGE_EVENT_COMPOSING; + jm->to = g_strdup(who); + + buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body>%s</body></html>", msg); + + html_to_xhtml(buf, &xhtml, &plain); + g_free(buf); + + jm->body = plain; + if(!jbr || jbr->capabilities & JABBER_CAP_XHTML) + jm->xhtml = xhtml; + else + g_free(xhtml); + + jabber_message_send(jm); + jabber_message_free(jm); + return 1; +} + +int jabber_message_send_chat(GaimConnection *gc, int id, const char *message) +{ + JabberChat *chat; + JabberMessage *jm; + JabberStream *js = gc->proto_data; + + if(!message) + return 0; + + chat = jabber_chat_find_by_id(js, id); + + jm = g_new0(JabberMessage, 1); + jm->js = gc->proto_data; + jm->type = JABBER_MESSAGE_CHAT; + jm->to = g_strdup_printf("%s@%s", chat->room, chat->server); + + html_to_xhtml(message, NULL, &jm->body); + + jabber_message_send(jm); + jabber_message_free(jm); + return 1; +} + +int jabber_send_typing(GaimConnection *gc, const char *who, int typing) +{ + JabberMessage *jm; + JabberBuddy *jb; + JabberBuddyResource *jbr; + + jb = jabber_buddy_find(gc->proto_data, who, TRUE); + jbr = jabber_buddy_find_resource(jb, jabber_get_resource(who)); + + if(jbr && !(jbr->capabilities & JABBER_CAP_COMPOSING)) + return 0; + + jm = g_new0(JabberMessage, 1); + jm->js = gc->proto_data; + jm->type = JABBER_MESSAGE_CHAT; + jm->to = g_strdup(who); + + if(typing == GAIM_TYPING) + jm->events = JABBER_MESSAGE_EVENT_COMPOSING; + + jabber_message_send(jm); + jabber_message_free(jm); + + return JABBER_TYPING_NOTIFY_INT; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/message.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,60 @@ +/** + * @file message.h Message handlers + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_MESSAGE_H_ +#define _GAIM_JABBER_MESSAGE_H_ + +#include "jabber.h" +#include "xmlnode.h" + +typedef struct _JabberMessage { + JabberStream *js; + enum { + JABBER_MESSAGE_NORMAL, + JABBER_MESSAGE_CHAT, + JABBER_MESSAGE_GROUPCHAT, + JABBER_MESSAGE_HEADLINE, + JABBER_MESSAGE_ERROR, + JABBER_MESSAGE_GROUPCHAT_INVITE, + JABBER_MESSAGE_OTHER + } type; + time_t sent; + char *from; + char *to; + char *subject; + char *body; + char *xhtml; + char *password; + char *error; + enum { + JABBER_MESSAGE_EVENT_COMPOSING = 1 << 1 + } events; +} JabberMessage; + + +void jabber_message_parse(JabberStream *js, xmlnode *packet); +int jabber_message_send_im(GaimConnection *gc, const char *who, const char *msg, + GaimImFlags flags); +int jabber_message_send_chat(GaimConnection *gc, int id, const char *message); + +int jabber_send_typing(GaimConnection *gc, const char *who, int typing); + +#endif /* _GAIM_JABBER_MESSAGE_H_ */
--- a/src/protocols/jabber/nametab.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -static const unsigned namingBitmap[] = { -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, -0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, -0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, -0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, -0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, -0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, -0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, -0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, -0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, -0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, -0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, -0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, -0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, -0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, -0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, -0x40000000, 0xF580C900, 0x00000007, 0x02010800, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, -0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, -0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, -0x00000000, 0x00004C40, 0x00000000, 0x00000000, -0x00000007, 0x00000000, 0x00000000, 0x00000000, -0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, -0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, -0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, -0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, -0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, -0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, -0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, -0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, -0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, -0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, -0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, -0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, -0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, -0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, -0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, -0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, -0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, -0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, -}; -static const unsigned char nmstrtPages[] = { -0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, -0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const unsigned char namePages[] = { -0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, -0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/parser.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,131 @@ +/* + * gaim - Jabber XML parser stuff + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" + +#include "connection.h" + +#include "jabber.h" +#include "parser.h" +#include "xmlnode.h" + +static void +jabber_parser_element_start(GMarkupParseContext *context, + const char *element_name, const char **attrib_names, + const char **attrib_values, gpointer user_data, GError **error) +{ + JabberStream *js = user_data; + xmlnode *node; + int i; + + if(!element_name) { + return; + } else if(!strcmp(element_name, "stream:stream")) { + js->protocol_version = JABBER_PROTO_0_9; + for(i=0; attrib_names[i]; i++) { + if(!strcmp(attrib_names[i], "version") + && !strcmp(attrib_values[i], "1.0")) { + js->protocol_version = JABBER_PROTO_1_0; + } else if(!strcmp(attrib_names[i], "id")) { + if(js->stream_id) + g_free(js->stream_id); + js->stream_id = g_strdup(attrib_values[i]); + } + } + + if(js->state == JABBER_STREAM_INITIALIZING) + jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING); + } else { + + if(js->current) + node = xmlnode_new_child(js->current, element_name); + else + node = xmlnode_new(element_name); + + for(i=0; attrib_names[i]; i++) { + xmlnode_set_attrib(node, attrib_names[i], attrib_values[i]); + } + + js->current = node; + } +} + +static void +jabber_parser_element_end(GMarkupParseContext *context, + const char *element_name, gpointer user_data, GError **error) +{ + JabberStream *js = user_data; + + if(!js->current) + return; + + if(js->current->parent) { + if(!strcmp(js->current->name, element_name)) + js->current = js->current->parent; + } else { + jabber_process_packet(js, js->current); + xmlnode_free(js->current); + js->current = NULL; + } +} + +static void +jabber_parser_element_text(GMarkupParseContext *context, const char *text, + gsize text_len, gpointer user_data, GError **error) +{ + JabberStream *js = user_data; + + if(!js->current) + return; + + if(!text || !text_len) + return; + + xmlnode_insert_data(js->current, text, text_len); +} + +static GMarkupParser jabber_parser = { + jabber_parser_element_start, + jabber_parser_element_end, + jabber_parser_element_text, + NULL, + NULL +}; + +void +jabber_parser_setup(JabberStream *js) +{ + if(!js->context) + js->context = g_markup_parse_context_new(&jabber_parser, 0, js, NULL); +} + + +void jabber_parser_process(JabberStream *js, const char *buf, int len) +{ + + /* May need to check for other encodings and do the conversion here */ + + if(!g_markup_parse_context_parse(js->context, buf, len, NULL)) { + g_markup_parse_context_free(js->context); + js->context = NULL; + gaim_connection_error(js->gc, _("XML Parse error")); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/parser.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,30 @@ +/** + * @file parser.h XML parser functions + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_PARSER_H_ +#define _GAIM_JABBER_PARSER_H_ + +#include "jabber.h" + +void jabber_parser_setup(JabberStream *js); +void jabber_parser_process(JabberStream *js, const char *buf, int len); + +#endif /* _GAIM_JABBER_PARSER_H_ */
--- a/src/protocols/jabber/pool.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -#ifdef POOL_DEBUG -int pool__total = 0; -int pool__ltotal = 0; -HASHTABLE pool__disturbed = NULL; -void *_pool__malloc(size_t size) -{ - pool__total++; - return malloc(size); -} -void _pool__free(void *block) -{ - pool__total--; - free(block); -} -#else -#define _pool__malloc malloc -#define _pool__free free -#endif - - -/* make an empty pool */ -pool _pool_new(char *zone) -{ - pool p; - while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1); - p->cleanup = NULL; - p->heap = NULL; - p->size = 0; - -#ifdef POOL_DEBUG - p->lsize = -1; - p->zone[0] = '\0'; - strcat(p->zone,zone); - sprintf(p->name,"%X",p); - - if(pool__disturbed == NULL) - { - pool__disturbed = 1; /* reentrancy flag! */ - pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp); - } - if(pool__disturbed != 1) - ghash_put(pool__disturbed,p->name,p); -#endif - - return p; -} - -/* free a heap */ -void _pool_heap_free(void *arg) -{ - struct pheap *h = (struct pheap *)arg; - - _pool__free(h->block); - _pool__free(h); -} - -/* mem should always be freed last */ -void _pool_cleanup_append(pool p, struct pfree *pf) -{ - struct pfree *cur; - - if(p->cleanup == NULL) - { - p->cleanup = pf; - return; - } - - /* fast forward to end of list */ - for(cur = p->cleanup; cur->next != NULL; cur = cur->next); - - cur->next = pf; -} - -/* create a cleanup tracker */ -struct pfree *_pool_free(pool p, pool_cleaner f, void *arg) -{ - struct pfree *ret; - - /* make the storage for the tracker */ - while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1); - ret->f = f; - ret->arg = arg; - ret->next = NULL; - - return ret; -} - -/* create a heap and make sure it get's cleaned up */ -struct pheap *_pool_heap(pool p, int size) -{ - struct pheap *ret; - struct pfree *clean; - - /* make the return heap */ - while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1); - while((ret->block = _pool__malloc(size)) == NULL) sleep(1); - ret->size = size; - p->size += size; - ret->used = 0; - - /* append to the cleanup list */ - clean = _pool_free(p, _pool_heap_free, (void *)ret); - clean->heap = ret; /* for future use in finding used mem for pstrdup */ - _pool_cleanup_append(p, clean); - - return ret; -} - -pool _pool_new_heap(int size, char *zone) -{ - pool p; - p = _pool_new(zone); - p->heap = _pool_heap(p,size); - return p; -} - -void *pmalloc(pool p, int size) -{ - void *block; - - if(p == NULL) - { - fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n"); - abort(); - } - - /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */ - if(p->heap == NULL || size > (p->heap->size / 2)) - { - while((block = _pool__malloc(size)) == NULL) sleep(1); - p->size += size; - _pool_cleanup_append(p, _pool_free(p, _pool__free, block)); - return block; - } - - /* we have to preserve boundaries, long story :) */ - if(size >= 4) - while(p->heap->used&7) p->heap->used++; - - /* if we don't fit in the old heap, replace it */ - if(size > (p->heap->size - p->heap->used)) - p->heap = _pool_heap(p, p->heap->size); - - /* the current heap has room */ - block = (char *)p->heap->block + p->heap->used; - p->heap->used += size; - return block; -} - -void *pmalloc_x(pool p, int size, char c) -{ - void* result = pmalloc(p, size); - if (result != NULL) - memset(result, c, size); - return result; -} - -/* easy safety utility (for creating blank mem for structs, etc) */ -void *pmalloco(pool p, int size) -{ - void *block = pmalloc(p, size); - memset(block, 0, size); - return block; -} - -/* XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is within a block in this pool */ -char *pstrdup(pool p, const char *src) -{ - char *ret; - - if(src == NULL) - return NULL; - - ret = pmalloc(p,strlen(src) + 1); - strcpy(ret,src); - - return ret; -} - -/* when move above, this one would actually return a new block */ -char *pstrdupx(pool p, const char *src) -{ - return pstrdup(p, src); -} - -int pool_size(pool p) -{ - if(p == NULL) return 0; - - return p->size; -} - -void pool_free(pool p) -{ - struct pfree *cur, *stub; - - if(p == NULL) return; - - cur = p->cleanup; - while(cur != NULL) - { - (*cur->f)(cur->arg); - stub = cur->next; - _pool__free(cur); - cur = stub; - } - -#ifdef POOL_DEBUG - ghash_remove(pool__disturbed,p->name); -#endif - - _pool__free(p); - -} - -/* public cleanup utils, insert in a way that they are run FIFO, before mem frees */ -void pool_cleanup(pool p, pool_cleaner f, void *arg) -{ - struct pfree *clean; - - clean = _pool_free(p, f, arg); - clean->next = p->cleanup; - p->cleanup = clean; -} - -#ifdef POOL_DEBUG -void debug_log(char *zone, const char *msgfmt, ...); -int _pool_stat(void *arg, const void *key, void *data) -{ - pool p = (pool)data; - - if(p->lsize == -1) - debug_log("leak","%s: %X is a new pool",p->zone,p->name); - else if(p->size > p->lsize) - debug_log("leak","%s: %X grew %d",p->zone,p->name, p->size - p->lsize); - else if((int)arg) - debug_log("leak","%s: %X exists %d",p->zone,p->name, p->size); - p->lsize = p->size; - return 1; -} - -void pool_stat(int full) -{ - ghash_walk(pool__disturbed,_pool_stat,(void *)full); - if(pool__total != pool__ltotal) - debug_log("leak","%d\ttotal missed mallocs",pool__total); - pool__ltotal = pool__total; - return; -} -#else -void pool_stat(int full) -{ - return; -} -#endif
--- a/src/protocols/jabber/pproxy.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -/* these aren't the most efficient things in the world, a hash optimized for tiny spaces would be far better */ - -ppdb _ppdb_new(pool p, jid id) -{ - ppdb ret; - ret = pmalloc(p,sizeof(_ppdb)); - ret->p = p; - ret->pri = -1; - ret->next = NULL; - ret->user = NULL; - ret->x = NULL; - ret->id = jid_new(p,jid_full(id)); - - return ret; -} - -ppdb _ppdb_get(ppdb db, jid id) -{ - ppdb cur; - - if(db == NULL || id == NULL) return NULL; - - for(cur = db->next; cur != NULL; cur = cur->next) - if(jid_cmp(cur->id,id) == 0) return cur; - - return NULL; -} - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x) -{ - ppdb cur, curu; - pool p; - - if(id == NULL || id->server == NULL || x == NULL) - return db; - - /* new ppdb list dummy holder */ - if(db == NULL) - { - p = pool_heap(1024); - db = _ppdb_new(p,NULL); - } - - cur = _ppdb_get(db,id); - - /* just update it */ - if(cur != NULL) - { - xmlnode_free(cur->x); - cur->x = xmlnode_dup(x); - cur->pri = jutil_priority(x); - return db; - } - - /* make an entry for it */ - cur = _ppdb_new(db->p,id); - cur->x = xmlnode_dup(x); - cur->pri = jutil_priority(x); - cur->next = db->next; - db->next = cur; - - /* if this is a user's resource presence, get the the user entry */ - if(id->user != NULL && (curu = _ppdb_get(db,jid_user(id))) != cur) - { - /* no user entry, make one */ - if(curu == NULL) - { - curu = _ppdb_new(db->p,jid_user(id)); - curu->next = db->next; - db->next = curu; - } - - /* insert this resource into the user list */ - cur->user = curu->user; - curu->user = cur; - } - - return db; -} - -xmlnode ppdb_primary(ppdb db, jid id) -{ - ppdb cur, top; - - if(db == NULL || id == NULL) return NULL; - - cur = _ppdb_get(db,id); - - if(cur == NULL) return NULL; - - /* not user@host check, just return */ - if(id->user == NULL || id->resource != NULL) return cur->x; - - top = cur; - for(cur = cur->user; cur != NULL; cur = cur->user) - if(cur->pri >= top->pri) top = cur; - - if(top != NULL && top->pri >= 0) return top->x; - - return NULL; -} - -/* return the presence for the id, successive calls return all of the known resources for a user@host address */ -xmlnode ppdb_get(ppdb db, jid id) -{ - static ppdb last = NULL; - ppdb cur; - - if(db == NULL || id == NULL) return NULL; - - /* MODE: if this is NOT just user@host addy, return just the single entry */ - if(id->user == NULL || id->resource != NULL) - { - /* we were just here, return now */ - if(last != NULL) - { - last = NULL; - return NULL; - } - - last = _ppdb_get(db,id); - if(last != NULL) - return last->x; - else - return NULL; - } - - /* handle looping for user@host */ - - /* we're already in the loop */ - if(last != NULL) - { - /* this is the last entry in the list */ - if(last->user == NULL) - { - last = NULL; - return NULL; - } - - last = last->user; - return last->x; - } - - /* start a new loop */ - cur = _ppdb_get(db,id); - - if(cur == NULL) return NULL; - - last = cur->user; - if(last != NULL) - return last->x; - else - return NULL; -} - - -void ppdb_free(ppdb db) -{ - ppdb cur; - - if(db == NULL) return; - - for(cur = db; cur != NULL; cur = cur->next) - xmlnode_free(cur->x); - - pool_free(db->p); -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/presence.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,337 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" + +#include "debug.h" +#include "html.h" +#include "notify.h" +#include "request.h" +#include "server.h" + +#include "buddy.h" +#include "chat.h" +#include "presence.h" +#include "iq.h" +#include "jutil.h" +#include "xmlnode.h" + + +static void chats_send_presence_foreach(gpointer key, gpointer val, + gpointer user_data) +{ + JabberChat *chat = val; + xmlnode *presence = user_data; + char *chat_jid = key; + + xmlnode_set_attrib(presence, "to", chat_jid); + jabber_send(chat->js, presence); +} + + +void jabber_presence_send(GaimConnection *gc, const char *state, + const char *msg) +{ + JabberStream *js = gc->proto_data; + xmlnode *presence; + char *stripped = NULL; + + if(msg) { + html_to_xhtml(msg, NULL, &stripped); + } else { + stripped = g_strdup(""); + } + + gc->away = stripped; + + presence = jabber_presence_create(state, msg); + jabber_send(js, presence); + g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence); + xmlnode_free(presence); +} + +xmlnode *jabber_presence_create(const char *state, const char *msg) +{ + xmlnode *show, *status, *presence; + + + presence = xmlnode_new("presence"); + + if(state) { + const char *show_string = NULL; + if(!strcmp(state, _("Chatty"))) + show_string = "chat"; + else if(!strcmp(state, _("Away")) || + (msg && !strcmp(state, GAIM_AWAY_CUSTOM))) + show_string = "away"; + else if(!strcmp(state, _("Extended Away"))) + show_string = "xa"; + else if(!strcmp(state, _("Do Not Disturb"))) + show_string = "dnd"; + else if(!strcmp(state, _("Invisible"))) { + xmlnode_set_attrib(presence, "type", "invisible"); + } + + if(show_string) { + show = xmlnode_new_child(presence, "show"); + xmlnode_insert_data(show, show_string, -1); + } + } + + if(msg && *msg) { + status = xmlnode_new_child(presence, "status"); + xmlnode_insert_data(status, msg, -1); + } + + return presence; +} + +struct _jabber_add_permit { + GaimConnection *gc; + char *who; +}; + +static void authorize_add_cb(struct _jabber_add_permit *jap) +{ + if(g_list_find(gaim_connections_get_all(), jap->gc)) { + jabber_presence_subscription_set(jap->gc->proto_data, jap->who, + "subscribed"); + + if(!gaim_find_buddy(jap->gc->account, jap->who)) + show_got_added(jap->gc, NULL, jap->who, NULL, NULL); + } + + g_free(jap->who); + g_free(jap); +} + +static void deny_add_cb(struct _jabber_add_permit *jap) +{ + if(g_list_find(gaim_connections_get_all(), jap->gc)) { + jabber_presence_subscription_set(jap->gc->proto_data, jap->who, + "unsubscribed"); + + if(!gaim_find_buddy(jap->gc->account, jap->who)) + show_got_added(jap->gc, NULL, jap->who, NULL, NULL); + } + + g_free(jap->who); + g_free(jap); +} + +void jabber_presence_parse(JabberStream *js, xmlnode *packet) +{ + const char *from = xmlnode_get_attrib(packet, "from"); + const char *type = xmlnode_get_attrib(packet, "type"); + char *status = NULL; + int priority = 0; + JabberID *jid; + JabberChat *chat; + JabberBuddy *jb; + JabberBuddyResource *jbr; + GaimBuddy *b; + char *buddy_name; + int state = 0; + xmlnode *y; + gboolean muc = FALSE; + + jb = jabber_buddy_find(js, from, TRUE); + + if(jb->error_msg) { + g_free(jb->error_msg); + jb->error_msg = NULL; + } + + if(type && !strcasecmp(type, "error")) { + state = JABBER_STATE_ERROR; + if((y = xmlnode_get_child(packet, "error")) != NULL) { + char *txt = xmlnode_get_data(y); + jb->error_msg = g_strdup_printf(_("%s (Code %s)"), + txt, xmlnode_get_attrib(y, "code")); + g_free(txt); + } else { + jb->error_msg = g_strdup(_("Unknown Error in presence")); + } + } else if(type && !strcasecmp(type, "subscribe")) { + struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); + char *msg = g_strdup_printf(_("The user %s wants to add you to their buddy list."), from); + jap->gc = js->gc; + jap->who = g_strdup(from); + + gaim_request_action(js->gc, NULL, msg, NULL, 0, jap, 2, + _("Authorize"), G_CALLBACK(authorize_add_cb), + _("Deny"), G_CALLBACK(deny_add_cb)); + g_free(msg); + } else if(type && (!strcmp(type, "subscribed") || + !strcmp(type, "unsubscribed"))) { + /* we've been allowed to see their presence, but we don't care */ + return; + } else { + if((y = xmlnode_get_child(packet, "show"))) { + char *show = xmlnode_get_data(y); + if(!show) { + state = 0; + } else if(!strcasecmp(show, "away")) { + state = JABBER_STATE_AWAY; + } else if(!strcasecmp(show, "chat")) { + state = JABBER_STATE_CHAT; + } else if(!strcasecmp(show, "xa")) { + state = JABBER_STATE_XA; + } else if(!strcasecmp(show, "dnd")) { + state = JABBER_STATE_DND; + } + g_free(show); + } else { + state = 0; + } + } + + for(y = packet->child; y; y = y->next) { + if(y->type != NODE_TYPE_TAG) + continue; + + if(!strcmp(y->name, "status")) { + status = xmlnode_get_data(y); + } else if(!strcmp(y->name, "priority")) { + char *p = xmlnode_get_data(y); + if(p) { + priority = atoi(p); + g_free(p); + } + } else if(!strcmp(y->name, "x")) { + const char *xmlns = xmlnode_get_attrib(y, "xmlns"); + if(xmlns && !strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { + /* this is where we'd normally get the "op" status of the + * user, but since we don't have a good way to show that yet + * we'll ignore it */ + muc = TRUE; + } + } + } + + jid = jabber_id_new(from); + + if((chat = jabber_chat_find(js, jid->node, jid->domain))) { + static int i = 0; + char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); + + if(state == JABBER_STATE_ERROR) { + const char *code = NULL; + char *text = NULL; + char *buf; + xmlnode *error = xmlnode_get_child(packet, "error"); + if(error) { + /* I should make my own messages so they can be + * translated, but i'm tired */ + code = xmlnode_get_attrib(error, "code"); + text = xmlnode_get_data(error); + } + + if(!code) + code = ""; + if(!text) + text = g_strdup(_("Unable to join chat")); + + buf = g_strdup_printf("Error %s joining chat %s: %s", + code, from, text); + gaim_notify_error(js->gc, _("Error"), _("Error"), buf); + g_free(text); + g_free(buf); + + jabber_chat_destroy(chat); + return; + } + + + if(!chat->conv) { + chat->id = i++; + chat->muc = muc; + chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); + } + + if(type && !strcasecmp(type, "unavailable")) { + if(!strcmp(jid->resource, chat->nick)) { + serv_got_chat_left(js->gc, chat->id); + jabber_chat_destroy(chat); + } else { + gaim_chat_remove_user(GAIM_CHAT(chat->conv), jid->resource, + NULL); + } + } else { + if(!jabber_chat_find_buddy(chat->conv, jid->resource)) + gaim_chat_add_user(GAIM_CHAT(chat->conv), jid->resource, + NULL); + } + g_free(room_jid); + } else { + if(!(jb->subscription & JABBER_SUB_TO)) { + gaim_debug(GAIM_DEBUG_INFO, "jabber", + "got unexpected presence from %s, ignoring\n", from); + jabber_id_free(jid); + return; + } + + buddy_name = g_strdup_printf("%s@%s", jid->node, jid->domain); + if((b = gaim_find_buddy(js->gc->account, buddy_name)) == NULL) { + jabber_id_free(jid); + g_free(buddy_name); + return; + } + + if(state == JABBER_STATE_ERROR || + (type && !strcasecmp(type, "unavailable"))) + jabber_buddy_remove_resource(jb, jid->resource); + else + jabber_buddy_track_resource(jb, jid->resource, priority, state, + status); + + jbr = jabber_buddy_find_resource(jb, jid->resource); + + if(jbr) + serv_got_update(js->gc, buddy_name, 1, 0, b->signon, b->idle, + jbr->state); + else + serv_got_update(js->gc, buddy_name, 0, 0, 0, 0, 0); +#if 0 + iq = jabber_iq_new_query(js, JABBER_IQ_GET, + "http://jabber.org/protocol/disco#items"); + query = xmlnode_get_child(iq->node, "query"); + xmlnode_set_attrib(query, "node", + "http://jabber.org/protocol/avatar"); + xmlnode_set_attrib(iq->node, "to", buddy_name); + jabber_iq_send(iq); +#endif + + g_free(buddy_name); + } + g_free(status); + jabber_id_free(jid); +} + +void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type) +{ + xmlnode *presence = xmlnode_new("presence"); + + xmlnode_set_attrib(presence, "to", who); + xmlnode_set_attrib(presence, "type", type); + + jabber_send(js, presence); + xmlnode_free(presence); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/presence.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,41 @@ +/** + * @file presence.h Presence + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_PRESENCE_H_ +#define _GAIM_JABBER_PRESENCE_H_ + +#include "jabber.h" +#include "xmlnode.h" + +#define JABBER_STATE_AWAY (0x02 | UC_UNAVAILABLE) +#define JABBER_STATE_CHAT (0x04) +#define JABBER_STATE_XA (0x08 | UC_UNAVAILABLE) +#define JABBER_STATE_DND (0x10 | UC_UNAVAILABLE) +#define JABBER_STATE_ERROR (0x20 | UC_UNAVAILABLE) + +void jabber_presence_send(GaimConnection *gc, const char *state, + const char *msg); +xmlnode *jabber_presence_create(const char *state, const char *msg); +void jabber_presence_parse(JabberStream *js, xmlnode *packet); +void jabber_presence_subscription_set(JabberStream *js, const char *who, + const char *type); + +#endif /* _GAIM_JABBER_PRESENCE_H_ */
--- a/src/protocols/jabber/rate.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -jlimit jlimit_new(int maxt, int maxp) -{ - pool p; - jlimit r; - - p = pool_new(); - r = pmalloc(p,sizeof(_jlimit)); - r->key = NULL; - r->start = r->points = 0; - r->maxt = maxt; - r->maxp = maxp; - r->p = p; - - return r; -} - -void jlimit_free(jlimit r) -{ - if(r != NULL) - { - if(r->key != NULL) free(r->key); - pool_free(r->p); - } -} - -int jlimit_check(jlimit r, char *key, int points) -{ - int now = time(NULL); - - if(r == NULL) return 0; - - /* make sure we didn't go over the time frame or get a null/new key */ - if((now - r->start) > r->maxt || key == NULL || j_strcmp(key,r->key) != 0) - { /* start a new key */ - free(r->key); - if(key != NULL) - /* We use strdup instead of pstrdup since r->key needs to be free'd before - and more often than the rest of the rlimit structure */ - r->key = strdup(key); - else - r->key = NULL; - r->start = now; - r->points = 0; - } - - r->points += points; - - /* if we're within the time frame and over the point limit */ - if(r->points > r->maxp && (now - r->start) < r->maxt) - { - return 1; /* we don't reset the rate here, so that it remains rated until the time runs out */ - } - - return 0; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/roster.c Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,311 @@ +/* + * gaim - Jabber Protocol Plugin + * + * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "internal.h" +#include "debug.h" +#include "server.h" + +#include "buddy.h" +#include "presence.h" +#include "roster.h" +#include "iq.h" + +#include <string.h> + + +void jabber_roster_request(JabberStream *js) +{ + JabberIq *iq; + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster"); + + jabber_iq_send(iq); +} + +static void remove_gaim_buddies(JabberStream *js, const char *jid) +{ + GSList *buddies, *l; + + buddies = gaim_find_buddies(js->gc->account, jid); + + for(l = buddies; l; l = l->next) + gaim_blist_remove_buddy(l->data); + + g_slist_free(buddies); +} + +static void add_gaim_buddies_in_groups(JabberStream *js, const char *jid, + const char *alias, GSList *groups) +{ + GSList *buddies, *g2, *l; + int present =0, idle=0, signon=0, state=0; + + buddies = gaim_find_buddies(js->gc->account, jid); + + g2 = groups; + + if(!groups) { + if(!buddies) + g2 = g_slist_append(g2, g_strdup(_("Buddies"))); + else + return; + } + + if(buddies) { + present = ((GaimBuddy*)buddies->data)->present; + signon = ((GaimBuddy*)buddies->data)->signon; + idle = ((GaimBuddy*)buddies->data)->idle; + state = ((GaimBuddy*)buddies->data)->uc; + } + + while(buddies) { + GaimBuddy *b = buddies->data; + GaimGroup *g = gaim_find_buddys_group(b); + + buddies = g_slist_remove(buddies, b); + + if((l = g_slist_find_custom(g2, g->name, (GCompareFunc)strcmp))) { + if(alias && (!b->alias || strcmp(b->alias, alias))) + gaim_blist_alias_buddy(b, alias); + g_free(l->data); + g2 = g_slist_delete_link(g2, l); + } else { + gaim_blist_remove_buddy(b); + } + } + + while(g2) { + GaimBuddy *b = gaim_buddy_new(js->gc->account, jid, alias); + GaimGroup *g = gaim_find_group(g2->data); + + if(!g) { + g = gaim_group_new(g2->data); + gaim_blist_add_group(g, NULL); + } + + b->present = present; + b->signon = signon; + b->idle = idle; + b->uc = state; + + gaim_blist_add_buddy(b, NULL, g, NULL); + g_free(g2->data); + g2 = g_slist_delete_link(g2, g2); + } + + g_slist_free(buddies); +} + +void jabber_roster_parse(JabberStream *js, xmlnode *packet) +{ + xmlnode *query, *item, *group; + const char *from = xmlnode_get_attrib(packet, "from"); + if(from && strcmp(gaim_account_get_username(js->gc->account), from)) + return; + + query = xmlnode_get_child(packet, "query"); + if(!query) + return; + + js->roster_parsed = TRUE; + + for(item = query->child; item; item = item->next) + { + const char *jid, *name, *subscription, *ask; + JabberBuddy *jb; + + if(item->type != NODE_TYPE_TAG || strcmp(item->name, "item")) + continue; + + subscription = xmlnode_get_attrib(item, "subscription"); + jid = xmlnode_get_attrib(item, "jid"); + name = xmlnode_get_attrib(item, "name"); + ask = xmlnode_get_attrib(item, "ask"); + + jb = jabber_buddy_find(js, jid, TRUE); + + if(!strcmp(subscription, "to")) + jb->subscription = JABBER_SUB_TO; + else if(!strcmp(subscription, "from")) + jb->subscription = JABBER_SUB_FROM; + else if(!strcmp(subscription, "both")) + jb->subscription = JABBER_SUB_BOTH; + else + jb->subscription = JABBER_SUB_NONE; + + if(ask && !strcmp(ask, "subscribe")) + jb->subscription |= JABBER_SUB_PENDING; + else + jb->subscription &= ~JABBER_SUB_PENDING; + + if(jb->subscription == JABBER_SUB_NONE) { + jb = jabber_buddy_find(js, jid, FALSE); + if(jb) + jb->subscription = JABBER_SUB_NONE; + remove_gaim_buddies(js, jid); + } else { + GSList *groups = NULL; + + for(group = item->child; group; group = group->next) { + if(group->type != NODE_TYPE_TAG || strcmp(group->name, "group")) + continue; + groups = g_slist_append(groups, + xmlnode_get_data(group)); + } + add_gaim_buddies_in_groups(js, jid, name, groups); + } + } + + gaim_blist_save(); +} + +static void jabber_roster_update(JabberStream *js, const char *name, + GSList *grps) +{ + GaimBuddy *b; + GaimGroup *g; + GSList *groups = NULL, *l; + JabberIq *iq; + xmlnode *query, *item, *group; + + if(grps) { + groups = grps; + } else { + GSList *buddies = gaim_find_buddies(js->gc->account, name); + if(!buddies) + return; + while(buddies) { + b = buddies->data; + g = gaim_find_buddys_group(b); + groups = g_slist_append(groups, g->name); + buddies = g_slist_remove(buddies, b); + } + } + + b = gaim_find_buddy(js->gc->account, name); + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + + xmlnode_set_attrib(item, "jid", name); + + if(b->alias) + xmlnode_set_attrib(item, "name", b->alias); + + for(l = groups; l; l = l->next) { + group = xmlnode_new_child(item, "group"); + xmlnode_insert_data(group, l->data, -1); + } + + if(!grps) + g_slist_free(groups); + + jabber_iq_send(iq); +} + +void jabber_roster_add_buddy(GaimConnection *gc, const char *name, + GaimGroup *grp) +{ + JabberStream *js = gc->proto_data; + char *who; + GSList *buddies; + JabberBuddy *jb; + + if(!js->roster_parsed) + return; + + who = jabber_get_bare_jid(name); + + buddies = gaim_find_buddies(gc->account, who); + + jabber_roster_update(js, who, NULL); + + jb = jabber_buddy_find(js, name, FALSE); + if(!jb || !(jb->subscription & JABBER_SUB_TO)) + jabber_presence_subscription_set(js, who, "subscribe"); + g_free(who); +} + +void jabber_roster_alias_change(GaimConnection *gc, const char *name, const char *alias) +{ + jabber_roster_update(gc->proto_data, name, NULL); +} + +void jabber_roster_group_change(GaimConnection *gc, const char *name, + const char *old_group, const char *new_group) +{ + GSList *buddies, *groups = NULL; + GaimBuddy *b; + GaimGroup *g; + + if(!old_group || !new_group || !strcmp(old_group, new_group)) + return; + + buddies = gaim_find_buddies(gc->account, name); + while(buddies) { + b = buddies->data; + g = gaim_find_buddys_group(b); + if(!strcmp(g->name, old_group)) + groups = g_slist_append(groups, (char*)new_group); /* ick */ + else + groups = g_slist_append(groups, g->name); + buddies = g_slist_remove(buddies, b); + } + jabber_roster_update(gc->proto_data, name, groups); + g_slist_free(groups); +} + +void jabber_roster_group_rename(GaimConnection *gc, const char *old_group, + const char *new_group, GList *members) +{ + GList *l; + if(old_group && new_group && strcmp(old_group, new_group)) { + for(l = members; l; l = l->next) { + jabber_roster_group_change(gc, l->data, old_group, new_group); + } + } +} + +void jabber_roster_remove_buddy(GaimConnection *gc, const char *name, const char *group) { + GSList *buddies = gaim_find_buddies(gc->account, name); + GSList *groups = NULL; + GaimGroup *g = gaim_find_group(group); + GaimBuddy *b = gaim_find_buddy_in_group(gc->account, name, g); + + buddies = g_slist_remove(buddies, b); + if(g_slist_length(buddies)) { + while(buddies) { + b = buddies->data; + g = gaim_find_buddys_group(b); + groups = g_slist_append(groups, g->name); + buddies = g_slist_remove(buddies, b); + } + jabber_roster_update(gc->proto_data, name, groups); + } else { + jabber_presence_subscription_set(gc->proto_data, name, "unsubscribe"); + } + + if(buddies) + g_slist_free(buddies); + if(groups) + g_slist_free(groups); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/roster.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,42 @@ +/** + * @file roster.h Roster manipulation + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_JABBER_ROSTER_H_ +#define _GAIM_JABBER_ROSTER_H_ + +#include "jabber.h" + +void jabber_roster_request(JabberStream *js); + +void jabber_roster_parse(JabberStream *js, xmlnode *packet); + +void jabber_roster_add_buddy(GaimConnection *gc, const char *name, + GaimGroup *grp); +void jabber_roster_alias_change(GaimConnection *gc, const char *name, + const char *alias); +void jabber_roster_group_change(GaimConnection *gc, const char *name, + const char *old_group, const char *new_group); +void jabber_roster_group_rename(GaimConnection *gc, const char *old_group, + const char *new_group, GList *members); +void jabber_roster_remove_buddy(GaimConnection *gc, const char *name, + const char *group); + +#endif /* _GAIM_JABBER_ROSTER_H_ */
--- a/src/protocols/jabber/sha.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - */ - -#include "lib.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -static void shaHashBlock(j_SHA_CTX *ctx); - -void shaInit(j_SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301L; - ctx->H[1] = 0xefcdab89L; - ctx->H[2] = 0x98badcfeL; - ctx->H[3] = 0x10325476L; - ctx->H[4] = 0xc3d2e1f0L; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void shaUpdate(j_SHA_CTX *ctx, unsigned char *dataIn, int len) { - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (unsigned long)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void shaFinal(j_SHA_CTX *ctx, unsigned char hashout[20]) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - shaUpdate(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - shaUpdate(ctx, &pad0x00, 1); - shaUpdate(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - shaInit(ctx); -} - - -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { - j_SHA_CTX ctx; - - shaInit(&ctx); - shaUpdate(&ctx, dataIn, len); - shaFinal(&ctx, hashout); -} - - -#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL) - -static void shaHashBlock(j_SHA_CTX *ctx) { - int t; - unsigned long A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -/*---------------------------------------------------------------------------- - * - * This code added by Thomas "temas" Muldowney for Jabber compatability - * - *---------------------------------------------------------------------------*/ -char *shahash(char *str) -{ - static char final[41]; - char *pos; - unsigned char hashval[20]; - int x; - - if(!str || strlen(str) == 0) - return NULL; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = final; - for(x=0;x<20;x++) - { - snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - return (char *)final; -} - -void shahash_r(const char* str, char hashbuf[41]) -{ - int x; - char *pos; - unsigned char hashval[20]; - - if(!str || strlen(str) == 0) - return; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = hashbuf; - for(x=0;x<20;x++) - { - snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - - return; -}
--- a/src/protocols/jabber/snprintf.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,932 +0,0 @@ -/* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the Apache Group - * for use in the Apache HTTP server project (http://www.apache.org/)." - * - * 4. The names "Apache Server" and "Apache Group" must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 5. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the Apache Group - * for use in the Apache HTTP server project (http://www.apache.org/)." - * - * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Group and was originally based - * on public domain software written at the National Center for - * Supercomputing Applications, University of Illinois, Urbana-Champaign. - * For more information on the Apache Group and the Apache HTTP server - * project, please see <http://www.apache.org/>. - * - * This code is based on, and used with the permission of, the - * SIO stdio-replacement strx_* functions by Panos Tsirigotis - * <panos@alumni.cs.colorado.edu> for xinetd. - */ - -#include "lib.h" - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> - - -#ifdef HAVE_GCVT - -#define ap_ecvt ecvt -#define ap_fcvt fcvt -#define ap_gcvt gcvt - -#else - -/* -* cvt.c - IEEE floating point formatting routines for FreeBSD -* from GNU libc-4.6.27 -*/ - -/* -* ap_ecvt converts to decimal -* the number of digits is specified by ndigit -* decpt is set to the position of the decimal point -* sign is set to 0 for positive, 1 for negative -*/ - -#define NDIG 80 - -static char * -ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag) -{ - register int r2; - double fi, fj; - register char *p, *p1; - static char buf[NDIG]; - - if (ndigits >= NDIG - 1) - ndigits = NDIG - 2; - r2 = 0; - *sign = 0; - p = &buf[0]; - if (arg < 0) { - *sign = 1; - arg = -arg; - } - arg = modf(arg, &fi); - p1 = &buf[NDIG]; - /* - * Do integer part - */ - if (fi != 0) { - p1 = &buf[NDIG]; - while (fi != 0) { - fj = modf(fi / 10, &fi); - *--p1 = (int) ((fj + .03) * 10) + '0'; - r2++; - } - while (p1 < &buf[NDIG]) - *p++ = *p1++; - } else if (arg > 0) { - while ((fj = arg * 10) < 1) { - arg = fj; - r2--; - } - } - p1 = &buf[ndigits]; - if (eflag == 0) - p1 += r2; - *decpt = r2; - if (p1 < &buf[0]) { - buf[0] = '\0'; - return (buf); - } - while (p <= p1 && p < &buf[NDIG]) { - arg *= 10; - arg = modf(arg, &fj); - *p++ = (int) fj + '0'; - } - if (p1 >= &buf[NDIG]) { - buf[NDIG - 1] = '\0'; - return (buf); - } - p = p1; - *p1 += 5; - while (*p1 > '9') { - *p1 = '0'; - if (p1 > buf) - ++ * --p1; - else { - *p1 = '1'; - (*decpt)++; - if (eflag == 0) { - if (p > buf) - *p = '0'; - p++; - } - } - } - *p = '\0'; - return (buf); -} - -static char * -ap_ecvt(double arg, int ndigits, int *decpt, int *sign) -{ - return (ap_cvt(arg, ndigits, decpt, sign, 1)); -} - -static char * -ap_fcvt(double arg, int ndigits, int *decpt, int *sign) -{ - return (ap_cvt(arg, ndigits, decpt, sign, 0)); -} - -/* -* ap_gcvt - Floating output conversion to -* minimal length string -*/ - -static char * -ap_gcvt(double number, int ndigit, char *buf) -{ - int sign, decpt; - register char *p1, *p2; - int i; - - p1 = ap_ecvt(number, ndigit, &decpt, &sign); - p2 = buf; - if (sign) - *p2++ = '-'; - for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) - ndigit--; - if ((decpt >= 0 && decpt - ndigit > 4) - || (decpt < 0 && decpt < -3)) { /* use E-style */ - decpt--; - *p2++ = *p1++; - *p2++ = '.'; - for (i = 1; i < ndigit; i++) - *p2++ = *p1++; - *p2++ = 'e'; - if (decpt < 0) { - decpt = -decpt; - *p2++ = '-'; - } else - *p2++ = '+'; - if (decpt / 100 > 0) - *p2++ = decpt / 100 + '0'; - if (decpt / 10 > 0) - *p2++ = (decpt % 100) / 10 + '0'; - *p2++ = decpt % 10 + '0'; - } else { - if (decpt <= 0) { - if (*p1 != '0') - *p2++ = '.'; - while (decpt < 0) { - decpt++; - *p2++ = '0'; - } - } - for (i = 1; i <= ndigit; i++) { - *p2++ = *p1++; - if (i == decpt) - *p2++ = '.'; - } - if (ndigit < decpt) { - while (ndigit++ < decpt) - *p2++ = '0'; - *p2++ = '.'; - } - } - if (p2[-1] == '.') - p2--; - *p2 = '\0'; - return (buf); -} - -#endif /* HAVE_CVT */ - -typedef enum { - NO = 0, YES = 1 -} boolean_e; - -#define FALSE 0 -#define TRUE 1 -#define NUL '\0' -#define INT_NULL ((int *)0) -#define WIDE_INT long - -typedef WIDE_INT wide_int; -typedef unsigned WIDE_INT u_wide_int; -typedef int bool_int; - -#define S_NULL "(null)" -#define S_NULL_LEN 6 - -#define FLOAT_DIGITS 6 -#define EXPONENT_LENGTH 10 - -/* - * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions - * - * XXX: this is a magic number; do not decrease it - */ -#define NUM_BUF_SIZE 512 - - -/* - * Descriptor for buffer area - */ -struct buf_area { - char *buf_end; - char *nextb; /* pointer to next byte to read/write */ -}; - -typedef struct buf_area buffy; - -/* - * The INS_CHAR macro inserts a character in the buffer and writes - * the buffer back to disk if necessary - * It uses the char pointers sp and bep: - * sp points to the next available character in the buffer - * bep points to the end-of-buffer+1 - * While using this macro, note that the nextb pointer is NOT updated. - * - * NOTE: Evaluation of the c argument should not have any side-effects - */ -#define INS_CHAR( c, sp, bep, cc ) \ - { \ - if ( sp < bep ) \ - { \ - *sp++ = c ; \ - cc++ ; \ - } \ - } - -#define NUM( c ) ( c - '0' ) - -#define STR_TO_DEC( str, num ) \ - num = NUM( *str++ ) ; \ - while ( isdigit((int)*str ) ) \ - { \ - num *= 10 ; \ - num += NUM( *str++ ) ; \ - } - -/* - * This macro does zero padding so that the precision - * requirement is satisfied. The padding is done by - * adding '0's to the left of the string that is going - * to be printed. - */ -#define FIX_PRECISION( adjust, precision, s, s_len ) \ - if ( adjust ) \ - while ( s_len < precision ) \ - { \ - *--s = '0' ; \ - s_len++ ; \ - } - -/* - * Macro that does padding. The padding is done by printing - * the character ch. - */ -#define PAD( width, len, ch ) do \ - { \ - INS_CHAR( ch, sp, bep, cc ) ; \ - width-- ; \ - } \ - while ( width > len ) - -/* - * Prefix the character ch to the string str - * Increase length - * Set the has_prefix flag - */ -#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES - - -/* - * Convert num to its decimal format. - * Return value: - * - a pointer to a string containing the number (no sign) - * - len contains the length of the string - * - is_negative is set to TRUE or FALSE depending on the sign - * of the number (always set to FALSE if is_unsigned is TRUE) - * - * The caller provides a buffer for the string: that is the buf_end argument - * which is a pointer to the END of the buffer + 1 (i.e. if the buffer - * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) - */ -static char * -conv_10(register wide_int num, register bool_int is_unsigned, - register bool_int * is_negative, char *buf_end, register int *len) -{ - register char *p = buf_end; - register u_wide_int magnitude; - - if (is_unsigned) { - magnitude = (u_wide_int) num; - *is_negative = FALSE; - } else { - *is_negative = (num < 0); - - /* - * On a 2's complement machine, negating the most negative integer - * results in a number that cannot be represented as a signed integer. - * Here is what we do to obtain the number's magnitude: - * a. add 1 to the number - * b. negate it (becomes positive) - * c. convert it to unsigned - * d. add 1 - */ - if (*is_negative) { - wide_int t = num + 1; - - magnitude = ((u_wide_int) - t) + 1; - } else - magnitude = (u_wide_int) num; - } - - /* - * We use a do-while loop so that we write at least 1 digit - */ - do { - register u_wide_int new_magnitude = magnitude / 10; - - *--p = magnitude - new_magnitude * 10 + '0'; - magnitude = new_magnitude; - } - while (magnitude); - - *len = buf_end - p; - return (p); -} - - - -/* - * Convert a floating point number to a string formats 'f', 'e' or 'E'. - * The result is placed in buf, and len denotes the length of the string - * The sign is returned in the is_negative argument (and is not placed - * in buf). - */ -static char * -conv_fp(register char format, register double num, - boolean_e add_dp, int precision, bool_int * is_negative, char *buf, int *len) -{ - register char *s = buf; - register char *p; - int decimal_point; - - if (format == 'f') - p = ap_fcvt(num, precision, &decimal_point, is_negative); - else /* either e or E format */ - p = ap_ecvt(num, precision + 1, &decimal_point, is_negative); - - /* - * Check for Infinity and NaN - */ - if (isalpha((int)*p)) { - *len = strlen(strcpy(buf, p)); - *is_negative = FALSE; - return (buf); - } - if (format == 'f') { - if (decimal_point <= 0) { - *s++ = '0'; - if (precision > 0) { - *s++ = '.'; - while (decimal_point++ < 0) - *s++ = '0'; - } else if (add_dp) { - *s++ = '.'; - } - } else { - while (decimal_point-- > 0) { - *s++ = *p++; - } - if (precision > 0 || add_dp) { - *s++ = '.'; - } - } - } else { - *s++ = *p++; - if (precision > 0 || add_dp) - *s++ = '.'; - } - - /* - * copy the rest of p, the NUL is NOT copied - */ - while (*p) - *s++ = *p++; - - if (format != 'f') { - char temp[EXPONENT_LENGTH]; /* for exponent conversion */ - int t_len; - bool_int exponent_is_negative; - - *s++ = format; /* either e or E */ - decimal_point--; - if (decimal_point != 0) { - p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, - &temp[EXPONENT_LENGTH], &t_len); - *s++ = exponent_is_negative ? '-' : '+'; - - /* - * Make sure the exponent has at least 2 digits - */ - if (t_len == 1) - *s++ = '0'; - while (t_len--) - *s++ = *p++; - } else { - *s++ = '+'; - *s++ = '0'; - *s++ = '0'; - } - } - *len = s - buf; - return (buf); -} - - -/* - * Convert num to a base X number where X is a power of 2. nbits determines X. - * For example, if nbits is 3, we do base 8 conversion - * Return value: - * a pointer to a string containing the number - * - * The caller provides a buffer for the string: that is the buf_end argument - * which is a pointer to the END of the buffer + 1 (i.e. if the buffer - * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) - */ -static char * -conv_p2(register u_wide_int num, register int nbits, - char format, char *buf_end, register int *len) -{ - register int mask = (1 << nbits) - 1; - register char *p = buf_end; - static char low_digits[] = "0123456789abcdef"; - static char upper_digits[] = "0123456789ABCDEF"; - register char *digits = (format == 'X') ? upper_digits : low_digits; - - do { - *--p = digits[num & mask]; - num >>= nbits; - } - while (num); - - *len = buf_end - p; - return (p); -} - - -/* - * Do format conversion placing the output in buffer - */ -static int format_converter(register buffy * odp, const char *fmt, - va_list ap) -{ - register char *sp; - register char *bep; - register int cc = 0; - register int i; - - register char *s = NULL; - char *q; - int s_len; - - register int min_width = 0; - int precision = 0; - enum { - LEFT, RIGHT - } adjust; - char pad_char; - char prefix_char; - - double fp_num; - wide_int i_num = (wide_int) 0; - u_wide_int ui_num; - - char num_buf[NUM_BUF_SIZE]; - char char_buf[2]; /* for printing %% and %<unknown> */ - - /* - * Flag variables - */ - boolean_e is_long; - boolean_e alternate_form; - boolean_e print_sign; - boolean_e print_blank; - boolean_e adjust_precision; - boolean_e adjust_width; - bool_int is_negative; - - sp = odp->nextb; - bep = odp->buf_end; - - while (*fmt) { - if (*fmt != '%') { - INS_CHAR(*fmt, sp, bep, cc); - } else { - /* - * Default variable settings - */ - adjust = RIGHT; - alternate_form = print_sign = print_blank = NO; - pad_char = ' '; - prefix_char = NUL; - - fmt++; - - /* - * Try to avoid checking for flags, width or precision - */ - if (isascii((int)*fmt) && !islower((int)*fmt)) { - /* - * Recognize flags: -, #, BLANK, + - */ - for (;; fmt++) { - if (*fmt == '-') - adjust = LEFT; - else if (*fmt == '+') - print_sign = YES; - else if (*fmt == '#') - alternate_form = YES; - else if (*fmt == ' ') - print_blank = YES; - else if (*fmt == '0') - pad_char = '0'; - else - break; - } - - /* - * Check if a width was specified - */ - if (isdigit((int)*fmt)) { - STR_TO_DEC(fmt, min_width); - adjust_width = YES; - } else if (*fmt == '*') { - min_width = va_arg(ap, int); - fmt++; - adjust_width = YES; - if (min_width < 0) { - adjust = LEFT; - min_width = -min_width; - } - } else - adjust_width = NO; - - /* - * Check if a precision was specified - * - * XXX: an unreasonable amount of precision may be specified - * resulting in overflow of num_buf. Currently we - * ignore this possibility. - */ - if (*fmt == '.') { - adjust_precision = YES; - fmt++; - if (isdigit((int)*fmt)) { - STR_TO_DEC(fmt, precision); - } else if (*fmt == '*') { - precision = va_arg(ap, int); - fmt++; - if (precision < 0) - precision = 0; - } else - precision = 0; - } else - adjust_precision = NO; - } else - adjust_precision = adjust_width = NO; - - /* - * Modifier check - */ - if (*fmt == 'l') { - is_long = YES; - fmt++; - } else - is_long = NO; - - /* - * Argument extraction and printing. - * First we determine the argument type. - * Then, we convert the argument to a string. - * On exit from the switch, s points to the string that - * must be printed, s_len has the length of the string - * The precision requirements, if any, are reflected in s_len. - * - * NOTE: pad_char may be set to '0' because of the 0 flag. - * It is reset to ' ' by non-numeric formats - */ - switch (*fmt) { - case 'u': - if (is_long) - i_num = va_arg(ap, u_wide_int); - else - i_num = (wide_int) va_arg(ap, unsigned int); - /* - * The rest also applies to other integer formats, so fall - * into that case. - */ - case 'd': - case 'i': - /* - * Get the arg if we haven't already. - */ - if ((*fmt) != 'u') { - if (is_long) - i_num = va_arg(ap, wide_int); - else - i_num = (wide_int) va_arg(ap, int); - }; - s = conv_10(i_num, (*fmt) == 'u', &is_negative, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - - if (*fmt != 'u') { - if (is_negative) - prefix_char = '-'; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - } - break; - - - case 'o': - if (is_long) - ui_num = va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); - s = conv_p2(ui_num, 3, *fmt, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - if (alternate_form && *s != '0') { - *--s = '0'; - s_len++; - } - break; - - - case 'x': - case 'X': - if (is_long) - ui_num = (u_wide_int) va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); - s = conv_p2(ui_num, 4, *fmt, - &num_buf[NUM_BUF_SIZE], &s_len); - FIX_PRECISION(adjust_precision, precision, s, s_len); - if (alternate_form && i_num != 0) { - *--s = *fmt; /* 'x' or 'X' */ - *--s = '0'; - s_len += 2; - } - break; - - - case 's': - s = va_arg(ap, char *); - if (s != NULL) { - s_len = strlen(s); - if (adjust_precision && precision < s_len) - s_len = precision; - } else { - s = S_NULL; - s_len = S_NULL_LEN; - } - pad_char = ' '; - break; - - - case 'f': - case 'e': - case 'E': - fp_num = va_arg(ap, double); - - s = conv_fp(*fmt, fp_num, alternate_form, - (adjust_precision == NO) ? FLOAT_DIGITS : precision, - &is_negative, &num_buf[1], &s_len); - if (is_negative) - prefix_char = '-'; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - break; - - - case 'g': - case 'G': - if (adjust_precision == NO) - precision = FLOAT_DIGITS; - else if (precision == 0) - precision = 1; - /* - * * We use &num_buf[ 1 ], so that we have room for the sign - */ - s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1]); - if (*s == '-') - prefix_char = *s++; - else if (print_sign) - prefix_char = '+'; - else if (print_blank) - prefix_char = ' '; - - s_len = strlen(s); - - if (alternate_form && (q = strchr(s, '.')) == NULL) - s[s_len++] = '.'; - if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) - *q = 'E'; - break; - - - case 'c': - char_buf[0] = (char) (va_arg(ap, int)); - s = &char_buf[0]; - s_len = 1; - pad_char = ' '; - break; - - - case '%': - char_buf[0] = '%'; - s = &char_buf[0]; - s_len = 1; - pad_char = ' '; - break; - - - case 'n': - *(va_arg(ap, int *)) = cc; - break; - - /* - * Always extract the argument as a "char *" pointer. We - * should be using "void *" but there are still machines - * that don't understand it. - * If the pointer size is equal to the size of an unsigned - * integer we convert the pointer to a hex number, otherwise - * we print "%p" to indicate that we don't handle "%p". - */ - case 'p': - ui_num = (u_wide_int) va_arg(ap, char *); - - if (sizeof(char *) <= sizeof(u_wide_int)) - s = conv_p2(ui_num, 4, 'x', - &num_buf[NUM_BUF_SIZE], &s_len); - else { - s = "%p"; - s_len = 2; - } - pad_char = ' '; - break; - - - case NUL: - /* - * The last character of the format string was %. - * We ignore it. - */ - continue; - - - /* - * The default case is for unrecognized %'s. - * We print %<char> to help the user identify what - * option is not understood. - * This is also useful in case the user wants to pass - * the output of format_converter to another function - * that understands some other %<char> (like syslog). - * Note that we can't point s inside fmt because the - * unknown <char> could be preceded by width etc. - */ - default: - char_buf[0] = '%'; - char_buf[1] = *fmt; - s = char_buf; - s_len = 2; - pad_char = ' '; - break; - } - - if (prefix_char != NUL) { - *--s = prefix_char; - s_len++; - } - if (adjust_width && adjust == RIGHT && min_width > s_len) { - if (pad_char == '0' && prefix_char != NUL) { - INS_CHAR(*s, sp, bep, cc) - s++; - s_len--; - min_width--; - } - PAD(min_width, s_len, pad_char); - } - /* - * Print the string s. - */ - for (i = s_len; i != 0; i--) { - INS_CHAR(*s, sp, bep, cc); - s++; - } - - if (adjust_width && adjust == LEFT && min_width > s_len) - PAD(min_width, s_len, pad_char); - } - fmt++; - } - odp->nextb = sp; - return (cc); -} - - -/* - * This is the general purpose conversion function. - */ -static void strx_printv(int *ccp, char *buf, size_t len, const char *format, - va_list ap) -{ - buffy od; - int cc; - - /* - * First initialize the descriptor - * Notice that if no length is given, we initialize buf_end to the - * highest possible address. - */ - od.buf_end = len ? &buf[len] : (char *) ~0; - od.nextb = buf; - - /* - * Do the conversion - */ - cc = format_converter(&od, format, ap); - if (len == 0 || od.nextb <= od.buf_end) - *(od.nextb) = '\0'; - if (ccp) - *ccp = cc; -} - - -int ap_snprintf(char *buf, size_t len, const char *format,...) -{ - int cc; - va_list ap; - - va_start(ap, format); - strx_printv(&cc, buf, (len - 1), format, ap); - va_end(ap); - return (cc); -} - - -int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap) -{ - int cc; - - strx_printv(&cc, buf, (len - 1), format, ap); - return (cc); -} - -#endif /* HAVE_SNPRINTF */
--- a/src/protocols/jabber/socket.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -/* socket.c - * - * Simple wrapper to make socket creation easy. - * type = NETSOCKET_SERVER is local listening socket - * type = NETSOCKET_CLIENT is connection socket - * type = NETSOCKET_UDP is a UDP connection socket - */ - -int make_netsocket(unsigned short port, char *host, int type) -{ - int s, flag = 1; - struct sockaddr_in sa; - struct in_addr *saddr; - int socket_type; - - /* is this a UDP socket or a TCP socket? */ - socket_type = (type == NETSOCKET_UDP)?SOCK_DGRAM:SOCK_STREAM; - - bzero((void *)&sa,sizeof(struct sockaddr_in)); - - if((s = socket(AF_INET,socket_type,0)) < 0) - return(-1); - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)) < 0) - return(-1); - - saddr = make_addr(host); - if(saddr == NULL && type != NETSOCKET_UDP) - return(-1); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - - if(type == NETSOCKET_SERVER) - { - /* bind to specific address if specified */ - if(host != NULL) - sa.sin_addr.s_addr = saddr->s_addr; - - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_CLIENT) - { - sa.sin_addr.s_addr = saddr->s_addr; - if(connect(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - } - if(type == NETSOCKET_UDP) - { - /* bind to all addresses for now */ - if(bind(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - - /* if specified, use a default recipient for read/write */ - if(host != NULL && saddr != NULL) - { - sa.sin_addr.s_addr = saddr->s_addr; - if(connect(s,(struct sockaddr*)&sa,sizeof sa) < 0) - { - close(s); - return(-1); - } - } - } - - - return(s); -} - - -struct in_addr *make_addr(char *host) -{ - struct hostent *hp; - static struct in_addr addr; - char myname[MAXHOSTNAMELEN + 1]; - - if(host == NULL || strlen(host) == 0) - { - gethostname(myname,MAXHOSTNAMELEN); - hp = gethostbyname(myname); - if(hp != NULL) - { - return (struct in_addr *) *hp->h_addr_list; - } - }else{ - addr.s_addr = inet_addr(host); - if(addr.s_addr != -1) - { - return &addr; - } - hp = gethostbyname(host); - if(hp != NULL) - { - return (struct in_addr *) *hp->h_addr_list; - } - } - return NULL; -} - -#ifndef _WIN32 -/* Sets a file descriptor to close on exec. "flag" is 1 to close on exec, 0 to - * leave open across exec. - * -- EJB 7/31/2000 - */ -int set_fd_close_on_exec(int fd, int flag) -{ - int oldflags = fcntl(fd,F_GETFL); - int newflags; - - if(flag) - newflags = oldflags | FD_CLOEXEC; - else - newflags = oldflags & (~FD_CLOEXEC); - - if(newflags==oldflags) - return 0; - return fcntl(fd,F_SETFL,(long)newflags); -} -#endif -
--- a/src/protocols/jabber/str.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -char *j_strdup(const char *str) -{ - if(str == NULL) - return NULL; - else - return strdup(str); -} - -char *j_strcat(char *dest, char *txt) -{ - if(!txt) return(dest); - - while(*txt) - *dest++ = *txt++; - *dest = '\0'; - - return(dest); -} - -int j_strcmp(const char *a, const char *b) -{ - if(a == NULL || b == NULL) - return -1; - - while(*a == *b && *a != '\0' && *b != '\0'){ a++; b++; } - - if(*a == *b) return 0; - - return -1; -} - -int j_strcasecmp(const char *a, const char *b) -{ - if(a == NULL || b == NULL) - return -1; - else - return strcasecmp(a, b); -} - -int j_strncmp(const char *a, const char *b, int i) -{ - if(a == NULL || b == NULL) - return -1; - else - return strncmp(a, b, i); -} - -int j_strncasecmp(const char *a, const char *b, int i) -{ - if(a == NULL || b == NULL) - return -1; - else - return strncasecmp(a, b, i); -} - -int j_strlen(const char *a) -{ - if(a == NULL) - return 0; - else - return strlen(a); -} - -int j_atoi(const char *a, int def) -{ - if(a == NULL) - return def; - else - return atoi(a); -} - -spool spool_new(pool p) -{ - spool s; - - s = pmalloc(p, sizeof(struct spool_struct)); - s->p = p; - s->len = 0; - s->last = NULL; - s->first = NULL; - return s; -} - -void spool_add(spool s, char *str) -{ - struct spool_node *sn; - int len; - - if(str == NULL) - return; - - len = strlen(str); - if(len == 0) - return; - - sn = pmalloc(s->p, sizeof(struct spool_node)); - sn->c = pstrdup(s->p, str); - sn->next = NULL; - - s->len += len; - if(s->last != NULL) - s->last->next = sn; - s->last = sn; - if(s->first == NULL) - s->first = sn; -} - -void spooler(spool s, ...) -{ - va_list ap; - char *arg = NULL; - - if(s == NULL) - return; - - va_start(ap, s); - - /* loop till we hit our end flag, the first arg */ - while(1) - { - arg = va_arg(ap,char *); - if((spool)arg == s) - break; - else - spool_add(s, arg); - } - - va_end(ap); -} - -char *spool_print(spool s) -{ - char *ret,*tmp; - struct spool_node *next; - - if(s == NULL || s->len == 0 || s->first == NULL) - return NULL; - - ret = pmalloc(s->p, s->len + 1); - *ret = '\0'; - - next = s->first; - tmp = ret; - while(next != NULL) - { - tmp = j_strcat(tmp,next->c); - next = next->next; - } - - return ret; -} - -/* convenience :) */ -char *spools(pool p, ...) -{ - va_list ap; - spool s; - char *arg = NULL; - - if(p == NULL) - return NULL; - - s = spool_new(p); - - va_start(ap, p); - - /* loop till we hit our end flag, the first arg */ - while(1) - { - arg = va_arg(ap,char *); - if((pool)arg == p) - break; - else - spool_add(s, arg); - } - - va_end(ap); - - return spool_print(s); -} - - -char *strunescape(pool p, char *buf) -{ - int i,j=0; - char *temp; - - if (p == NULL || buf == NULL) return(NULL); - - if (strchr(buf,'&') == NULL) return(buf); - - temp = pmalloc(p,strlen(buf)+1); - - if (temp == NULL) return(NULL); - - for(i=0;i<strlen(buf);i++) - { - if (buf[i]=='&') - { - if (strncmp(&buf[i],"&",5)==0) - { - temp[j] = '&'; - i += 4; - } else if (strncmp(&buf[i],""",6)==0) { - temp[j] = '\"'; - i += 5; - } else if (strncmp(&buf[i],"'",6)==0) { - temp[j] = '\''; - i += 5; - } else if (strncmp(&buf[i],"<",4)==0) { - temp[j] = '<'; - i += 3; - } else if (strncmp(&buf[i],">",4)==0) { - temp[j] = '>'; - i += 3; - } - } else { - temp[j]=buf[i]; - } - j++; - } - temp[j]='\0'; - return(temp); -} - - -char *strescape(pool p, char *buf) -{ - int i,j,oldlen,newlen; - char *temp; - - if (p == NULL || buf == NULL) return(NULL); - - oldlen = newlen = strlen(buf); - for(i=0;i<oldlen;i++) - { - switch(buf[i]) - { - case '&': - newlen+=5; - break; - case '\'': - newlen+=6; - break; - case '\"': - newlen+=6; - break; - case '<': - newlen+=4; - break; - case '>': - newlen+=4; - break; - } - } - - if(oldlen == newlen) return buf; - - temp = pmalloc(p,newlen+1); - - if (temp==NULL) return(NULL); - - for(i=j=0;i<oldlen;i++) - { - switch(buf[i]) - { - case '&': - memcpy(&temp[j],"&",5); - j += 5; - break; - case '\'': - memcpy(&temp[j],"'",6); - j += 6; - break; - case '\"': - memcpy(&temp[j],""",6); - j += 6; - break; - case '<': - memcpy(&temp[j],"<",4); - j += 4; - break; - case '>': - memcpy(&temp[j],">",4); - j += 4; - break; - default: - temp[j++] = buf[i]; - } - } - temp[j] = '\0'; - return temp; -} - -char *zonestr(char *file, int line) -{ - static char buff[64]; - int i; - - i = snprintf(buff,63,"%s:%d",file,line); - buff[i] = '\0'; - - return buff; -} - -void str_b64decode(char* str) -{ - char *cur; - int d, dlast, phase; - unsigned char c; - static int table[256] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ - 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ - 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ - -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ - 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ - }; - - d = dlast = phase = 0; - for (cur = str; *cur != '\0'; ++cur ) - { - d = table[(int)*cur]; - if(d != -1) - { - switch(phase) - { - case 0: - ++phase; - break; - case 1: - c = ((dlast << 2) | ((d & 0x30) >> 4)); - *str++ = c; - ++phase; - break; - case 2: - c = (((dlast & 0xf) << 4) | ((d & 0x3c) >> 2)); - *str++ = c; - ++phase; - break; - case 3: - c = (((dlast & 0x03 ) << 6) | d); - *str++ = c; - phase = 0; - break; - } - dlast = d; - } - } - *str = '\0'; -}
--- a/src/protocols/jabber/utf8tab.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, -/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
--- a/src/protocols/jabber/xhash.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - - -/* Generates a hash code for a string. - * This function uses the ELF hashing algorithm as reprinted in - * Andrew Binstock, "Hashing Rehashed," Dr. Dobb's Journal, April 1996. - */ -int _xhasher(const char *s) -{ - /* ELF hash uses unsigned chars and unsigned arithmetic for portability */ - const unsigned char *name = (const unsigned char *)s; - unsigned long h = 0, g; - - while (*name) - { /* do some fancy bitwanking on the string */ - h = (h << 4) + (unsigned long)(*name++); - if ((g = (h & 0xF0000000UL))!=0) - h ^= (g >> 24); - h &= ~g; - - } - - return (int)h; -} - - -xhn _xhash_node_new(xht h, int index) -{ - xhn n; - int i = index % h->prime; - - /* get existing empty one */ - for(n = &h->zen[i]; n != NULL; n = n->next) - if(n->key == NULL) - return n; - - /* overflowing, new one! */ - n = pmalloco(h->p, sizeof(_xhn)); - n->next = h->zen[i].next; - h->zen[i].next = n; - return n; -} - - -xhn _xhash_node_get(xht h, const char *key, int index) -{ - xhn n; - int i = index % h->prime; - for(n = &h->zen[i]; n != NULL; n = n->next) - if(j_strcmp(key, n->key) == 0) - return n; - return NULL; -} - - -xht xhash_new(int prime) -{ - xht xnew; - pool p; - -/* log_debug(ZONE,"creating new hash table of size %d",prime); */ - - p = pool_heap(sizeof(_xhn)*prime + sizeof(_xht)); - xnew = pmalloco(p, sizeof(_xht)); - xnew->prime = prime; - xnew->p = p; - xnew->zen = pmalloco(p, sizeof(_xhn)*prime); /* array of xhn size of prime */ - return xnew; -} - - -void xhash_put(xht h, const char *key, void *val) -{ - int index; - xhn n; - - if(h == NULL || key == NULL) - return; - - index = _xhasher(key); - - /* if existing key, replace it */ - if((n = _xhash_node_get(h, key, index)) != NULL) - { -/* log_debug(ZONE,"replacing %s with new val %X",key,val); */ - - n->key = key; - n->val = val; - return; - } - -/* log_debug(ZONE,"saving %s val %X",key,val); */ - - /* new node */ - n = _xhash_node_new(h, index); - n->key = key; - n->val = val; -} - - -void *xhash_get(xht h, const char *key) -{ - xhn n; - - if(h == NULL || key == NULL || (n = _xhash_node_get(h, key, _xhasher(key))) == NULL) - { -/* log_debug(ZONE,"failed lookup of %s",key); */ - return NULL; - } - -/* log_debug(ZONE,"found %s returning %X",key,n->val); */ - return n->val; -} - - -void xhash_zap(xht h, const char *key) -{ - xhn n; - - if(h == NULL || key == NULL || (n = _xhash_node_get(h, key, _xhasher(key))) == NULL) - return; - -/* log_debug(ZONE,"zapping %s",key); */ - - /* kill an entry by zeroing out the key */ - n->key = NULL; -} - - -void xhash_free(xht h) -{ -/* log_debug(ZONE,"hash free %X",h); */ - - if(h != NULL) - pool_free(h->p); -} - -void xhash_walk(xht h, xhash_walker w, void *arg) -{ - int i; - xhn n; - - if(h == NULL || w == NULL) - return; - -/* log_debug(ZONE,"walking %X",h); */ - - for(i = 0; i < h->prime; i++) - for(n = &h->zen[i]; n != NULL; n = n->next) - if(n->key != NULL && n->val != NULL) - (*w)(h, n->key, n->val, arg); -} -
--- a/src/protocols/jabber/xmldef.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include <string.h> - -#ifdef XML_WINLIB - -#define WIN32_LEAN_AND_MEAN -#define STRICT -#include <windows.h> - -#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x)) -#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y)) -#define free(x) HeapFree(GetProcessHeap(), 0, (x)) -#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y) -#define abort() /* as nothing */ - -#else /* not XML_WINLIB */ - -#include <stdlib.h> - -#endif /* not XML_WINLIB */ - -/* This file can be used for any definitions needed in -particular environments. */ - -#ifdef MOZILLA - -#include "nspr.h" -#define malloc(x) PR_Malloc(x) -#define realloc(x, y) PR_Realloc((x), (y)) -#define calloc(x, y) PR_Calloc((x),(y)) -#define free(x) PR_Free(x) -#define int int32 - -#endif /* MOZILLA */
--- a/src/protocols/jabber/xmlnode.c Mon Sep 29 13:00:55 2003 +0000 +++ b/src/protocols/jabber/xmlnode.c Mon Sep 29 15:23:19 2003 +0000 @@ -1,846 +1,372 @@ -/* -------------------------------------------------------------------------- - * - * License +/** + * @file xmlnode.c XML DOM functions * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. + * gaim * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ -#include "lib.h" - -/* Internal routines */ -xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) -{ - xmlnode result = NULL; - if (type > NTYPE_LAST) - return NULL; +/* A lot of this code at least resembles the code in libxode, but since + * libxode uses memory pools that we simply have no need for, I decided to + * write my own stuff. Also, re-writing this lets me be as lightweight + * as I want to be. Thank you libxode for giving me a good starting point */ - if (type != NTYPE_CDATA && name == NULL) - return NULL; +#include "internal.h" - if (p == NULL) - { - p = pool_heap(1*1024); - } - - /* Allocate & zero memory */ - result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); +#include <string.h> +#include <glib.h> - /* Initialize fields */ - if (type != NTYPE_CDATA) - result->name = pstrdup(p,name); - result->type = type; - result->p = p; - return result; -} +#include "xmlnode.h" -static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type) +static xmlnode* +new_node(const char *name, NodeType type) { - xmlnode result; + xmlnode *node = g_new0(xmlnode, 1); + if(name) + node->name = g_strdup(name); + node->type = type; - result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); - if (result != NULL) - { - /* Setup sibling pointers */ - result->prev = lastsibling; - lastsibling->next = result; - } - return result; + return node; } -static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) +xmlnode* +xmlnode_new(const char *name) { - xmlnode result; - - if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL; + g_return_val_if_fail(name != NULL, NULL); - /* If parent->firstchild is NULL, simply create a new node for the first child */ - if (parent->firstchild == NULL) - { - result = _xmlnode_new(parent->p, name, type); - parent->firstchild = result; - } - /* Otherwise, append this to the lastchild */ - else - { - result= _xmlnode_append_sibling(parent->lastchild, name, type); - } - result->parent = parent; - parent->lastchild = result; - return result; - + return new_node(name, NODE_TYPE_TAG); } -static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) +xmlnode *xmlnode_new_child(xmlnode *parent, const char *name) { - xmlnode current; + xmlnode *node; - /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with - the specified name */ - current = firstsibling; - while (current != NULL) - { - if ((current->type == type) && (j_strcmp(current->name, name) == 0)) - return current; - else - current = current->next; - } - return NULL; + g_return_val_if_fail(parent != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + node = new_node(name, NODE_TYPE_TAG); + + xmlnode_insert_child(parent, node); + + return node; } -void _xmlnode_merge(xmlnode data) +void +xmlnode_insert_child(xmlnode *parent, xmlnode *child) { - xmlnode cur; - char *merge, *scur; - int imerge; + g_return_if_fail(parent != NULL); + g_return_if_fail(child != NULL); - /* get total size of all merged cdata */ - imerge = 0; - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - imerge += cur->data_sz; + child->parent = parent; - /* copy in current data and then spin through all of them and merge */ - scur = merge = pmalloc(data->p,imerge + 1); - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - { - memcpy(scur,cur->data,cur->data_sz); - scur += cur->data_sz; - } - *scur = '\0'; - - /* this effectively hides all of the merged-in chunks */ - data->next = cur; - if(cur == NULL) - data->parent->lastchild = data; - else - cur->prev = data; - - /* reset data */ - data->data = merge; - data->data_sz = imerge; - + if(parent->child) { + xmlnode *x; + for(x = parent->child; x->next; x = x->next); + x->next = child; + } else { + parent->child = child; + } } -static void _xmlnode_hide_sibling(xmlnode child) +void +xmlnode_insert_data(xmlnode *parent, const char *data, size_t size) { - if(child == NULL) - return; - - if(child->prev != NULL) - child->prev->next = child->next; - if(child->next != NULL) - child->next->prev = child->prev; -} - -void _xmlnode_tag2str(spool s, xmlnode node, int flag) -{ - xmlnode tmp; + xmlnode *node; + size_t real_size; - if(flag==0 || flag==1) - { - spooler(s,"<",xmlnode_get_name(node),s); - tmp = xmlnode_get_firstattrib(node); - while(tmp) { - spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); - tmp = xmlnode_get_nextsibling(tmp); - } - if(flag==0) - spool_add(s,"/>"); - else - spool_add(s,">"); - } - else - { - spooler(s,"</",xmlnode_get_name(node),">",s); - } + g_return_if_fail(parent != NULL); + g_return_if_fail(data != NULL); + g_return_if_fail(size != 0); + + real_size = size == -1 ? strlen(data) : size; + + node = new_node(NULL, NODE_TYPE_DATA); + + node->data = g_memdup(data, real_size); + node->data_sz = real_size; + + xmlnode_insert_child(parent, node); } -spool _xmlnode2spool(xmlnode node) +void +xmlnode_remove_attrib(xmlnode *node, const char *attr) { - spool s; - int level=0,dir=0; - xmlnode tmp; + xmlnode *attr_node, *sibling = NULL; - if(!node || xmlnode_get_type(node)!=NTYPE_TAG) - return NULL; - - s = spool_new(xmlnode_pool(node)); - if(!s) return(NULL); + g_return_if_fail(node != NULL); + g_return_if_fail(attr != NULL); - while(1) - { - if(dir==0) - { - if(xmlnode_get_type(node) == NTYPE_TAG) - { - if(xmlnode_has_children(node)) - { - _xmlnode_tag2str(s,node,1); - node = xmlnode_get_firstchild(node); - level++; - continue; - }else{ - _xmlnode_tag2str(s,node,0); - } - }else{ - spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); - } - } - - tmp = xmlnode_get_nextsibling(node); - if(!tmp) - { - node = xmlnode_get_parent(node); - level--; - if(level>=0) _xmlnode_tag2str(s,node,2); - if(level<1) break; - dir = 1; - }else{ - node = tmp; - dir = 0; - } - } - - return s; + for(attr_node = node->child; attr_node; attr_node = attr_node->next) + { + if(attr_node->type == NODE_TYPE_ATTRIB && + !strcmp(attr_node->name, attr)) { + if(node->child == attr_node) { + node->child = attr_node->next; + } else { + sibling->next = attr_node->next; + } + xmlnode_free(attr_node); + return; + } + sibling = attr_node; + } } - -/* External routines */ - +void +xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value) +{ + xmlnode *attrib_node; -/* - * xmlnode_new_tag -- create a tag node - * Automatically creates a memory pool for the node. - * - * parameters - * name -- name of the tag - * - * returns - * a pointer to the tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_new_tag(const char* name) -{ - return _xmlnode_new(NULL, name, NTYPE_TAG); + g_return_if_fail(node != NULL); + g_return_if_fail(attr != NULL); + g_return_if_fail(value != NULL); + + xmlnode_remove_attrib(node, attr); + + attrib_node = new_node(attr, NODE_TYPE_ATTRIB); + + attrib_node->data = g_strdup(value); + + xmlnode_insert_child(node, attrib_node); } - -/* - * xmlnode_new_tag_pool -- create a tag node within given pool - * - * parameters - * p -- previously created memory pool - * name -- name of the tag - * - * returns - * a pointer to the tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_new_tag_pool(pool p, const char* name) +const char* +xmlnode_get_attrib(xmlnode *node, const char *attr) { - return _xmlnode_new(p, name, NTYPE_TAG); -} + xmlnode *x; + g_return_val_if_fail(node != NULL, NULL); -/* - * xmlnode_insert_tag -- append a child tag to a tag - * - * parameters - * parent -- pointer to the parent tag - * name -- name of the child tag - * - * returns - * a pointer to the child tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name) -{ - return _xmlnode_insert(parent, name, NTYPE_TAG); + for(x = node->child; x; x = x->next) { + if(x->type == NODE_TYPE_ATTRIB && !strcmp(attr, x->name)) { + return x->data; + } + } + + return NULL; } - -/* - * xmlnode_insert_cdata -- append character data to a tag - * - * parameters - * parent -- parent tag - * CDATA -- character data - * size -- size of CDATA - * or -1 for null-terminated CDATA strings - * - * returns - * a pointer to the child CDATA node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size) +void xmlnode_free(xmlnode *node) { - xmlnode result; + xmlnode *x, *y; - if(CDATA == NULL || parent == NULL) - return NULL; - - if(size == -1) - size = strlen(CDATA); + g_return_if_fail(node != NULL); - result = _xmlnode_insert(parent, NULL, NTYPE_CDATA); - if (result != NULL) - { - result->data = (char*)pmalloc(result->p, size + 1); - memcpy(result->data, CDATA, size); - result->data[size] = '\0'; - result->data_sz = size; - } + x = node->child; + while(x) { + y = x->next; + xmlnode_free(x); + x = y; + } - return result; + if(node->name) + g_free(node->name); + if(node->data) + g_free(node->data); + g_free(node); } +xmlnode* +xmlnode_get_child(xmlnode *parent, const char *name) +{ + xmlnode *x, *ret = NULL; + char **names; + char *parent_name, *child_name; -/* - * xmlnode_get_tag -- find given tag in an xmlnode tree - * - * parameters - * parent -- pointer to the parent tag - * name -- "name" for the child tag of that name - * "name/name" for a sub child (recurses) - * "?attrib" to match the first tag with that attrib defined - * "?attrib=value" to match the first tag with that attrib and value - * "=cdata" to match the cdata contents of the child - * or any combination: "name/name/?attrib", "name=cdata", etc - * - * results - * a pointer to the tag matching search criteria - * or NULL if search was unsuccessfull - */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name) -{ - char *str, *slash, *qmark, *equals; - xmlnode step, ret; + g_return_val_if_fail(parent != NULL, NULL); + + names = g_strsplit(name, "/", 2); + parent_name = names[0]; + child_name = names[1]; - - if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; - - if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) - return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); - - str = strdup(name); - slash = strstr(str, "/"); - qmark = strstr(str, "?"); - equals = strstr(str, "="); + for(x = parent->child; x; x = x->next) { + if(x->type == NODE_TYPE_TAG && name && !strcmp(parent_name, x->name)) { + ret = x; + break; + } + } - if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) - { /* of type =cdata */ + if(child_name && ret) + ret = xmlnode_get_child(x, child_name); - *equals = '\0'; - equals++; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; + g_strfreev(names); + return ret; +} - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(j_strcmp(xmlnode_get_data(step),equals) != 0) - continue; +char * +xmlnode_get_data(xmlnode *node) +{ + GString *str; + char *ret; + xmlnode *c; - break; - } + g_return_val_if_fail(node != NULL, NULL); + + str = g_string_new(""); - free(str); - return step; - } - - - if(qmark != NULL && (slash == NULL || qmark < slash)) - { /* of type ?attrib */ + for(c = node->child; c; c = c->next) { + if(c->type == NODE_TYPE_DATA) + str = g_string_append_len(str, c->data, c->data_sz); + } - *qmark = '\0'; - qmark++; - if(equals != NULL) - { - *equals = '\0'; - equals++; - } + ret = str->str; + g_string_free(str, FALSE); - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; + return ret; +} - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(xmlnode_get_attrib(step,qmark) == NULL) - continue; +char *xmlnode_to_str(xmlnode *node) +{ + char *ret; + GString *text = g_string_new(""); + xmlnode *c; + char *node_name, *esc, *esc2; + gboolean need_end = FALSE; - if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) - continue; - - break; - } - - free(str); - return step; - } + node_name = g_markup_escape_text(node->name, -1); + g_string_append_printf(text, "<%s", node_name); - *slash = '\0'; - ++slash; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) continue; - - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - ret = xmlnode_get_tag(step, slash); - if(ret != NULL) - { - free(str); - return ret; - } - } - - free(str); - return NULL; -} - - -/* return the cdata from any tag */ -char *xmlnode_get_tag_data(xmlnode parent, const char *name) -{ - xmlnode tag; - - tag = xmlnode_get_tag(parent, name); - if(tag == NULL) return NULL; - - return xmlnode_get_data(tag); -} - - -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value) -{ - xmlnode attrib; - - if(owner == NULL || name == NULL || value == NULL) return; + for(c = node->child; c; c = c->next) + { + if(c->type == NODE_TYPE_ATTRIB) { + esc = g_markup_escape_text(c->name, -1); + esc2 = g_markup_escape_text(c->data, -1); + g_string_append_printf(text, " %s='%s'", esc, esc2); + g_free(esc); + g_free(esc2); + } else if(c->type == NODE_TYPE_TAG || c->type == NODE_TYPE_DATA) { + need_end = TRUE; + } + } - /* If there are no existing attributs, allocate a new one to start - the list */ - if (owner->firstattrib == NULL) - { - attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB); - owner->firstattrib = attrib; - owner->lastattrib = attrib; - } - else - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - { - attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB); - owner->lastattrib = attrib; - } - } - /* Update the value of the attribute */ - attrib->data_sz = strlen(value); - attrib->data = pstrdup(owner->p, value); - -} - -char* xmlnode_get_attrib(xmlnode owner, const char* name) -{ - xmlnode attrib; - - if (owner != NULL && owner->firstattrib != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib != NULL) - return (char*)attrib->data; - } - return NULL; -} - -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value) -{ - xmlnode attrib; - - if (owner != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib == NULL) - { - xmlnode_put_attrib(owner, name, ""); - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - } - if (attrib != NULL) - attrib->firstchild = (xmlnode)value; - } -} - -void* xmlnode_get_vattrib(xmlnode owner, const char* name) -{ - xmlnode attrib; + if(need_end) { + text = g_string_append_c(text, '>'); - if (owner != NULL && owner->firstattrib != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib != NULL) - return (void*)attrib->firstchild; - } - return NULL; -} - -xmlnode xmlnode_get_firstattrib(xmlnode parent) -{ - if (parent != NULL) - return parent->firstattrib; - return NULL; -} - -xmlnode xmlnode_get_firstchild(xmlnode parent) -{ - if (parent != NULL) - return parent->firstchild; - return NULL; -} - -xmlnode xmlnode_get_lastchild(xmlnode parent) -{ - if (parent != NULL) - return parent->lastchild; - return NULL; -} - -xmlnode xmlnode_get_nextsibling(xmlnode sibling) -{ - if (sibling != NULL) - return sibling->next; - return NULL; -} - -xmlnode xmlnode_get_prevsibling(xmlnode sibling) -{ - if (sibling != NULL) - return sibling->prev; - return NULL; -} - -xmlnode xmlnode_get_parent(xmlnode node) -{ - if (node != NULL) - return node->parent; - return NULL; -} + for(c = node->child; c; c = c->next) + { + if(c->type == NODE_TYPE_TAG) { + esc = xmlnode_to_str(c); + g_string_append_printf(text, "%s", esc); + g_free(esc); + } else if(c->type == NODE_TYPE_DATA) { + esc = g_markup_escape_text(c->data, c->data_sz); + g_string_append_printf(text, "%s", esc); + g_free(esc); + } + } -char* xmlnode_get_name(xmlnode node) -{ - if (node != NULL) - return node->name; - return NULL; -} - -char* xmlnode_get_data(xmlnode node) -{ - if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */ - for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node)) - if(xmlnode_get_type(node) == NTYPE_CDATA) break; - - if(node == NULL) return NULL; - - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - - return node->data; -} - -int xmlnode_get_datasz(xmlnode node) -{ - if(xmlnode_get_type(node) != NTYPE_CDATA) return 0; + g_string_append_printf(text, "</%s>", node_name); + } else { + g_string_append_printf(text, "/>"); + } - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - return node->data_sz; -} - -int xmlnode_get_type(xmlnode node) -{ - if (node != NULL) - return node->type; - return NTYPE_UNDEF; -} + g_free(node_name); -int xmlnode_has_children(xmlnode node) -{ - if ((node != NULL) && (node->firstchild != NULL)) - return 1; - return 0; -} - -int xmlnode_has_attribs(xmlnode node) -{ - if ((node != NULL) && (node->firstattrib != NULL)) - return 1; - return 0; -} - -pool xmlnode_pool(xmlnode node) -{ - if (node != NULL) - return node->p; - return (pool)NULL; + ret = text->str; + g_string_free(text, FALSE); + return ret; } -void xmlnode_hide(xmlnode child) -{ - xmlnode parent; +struct _xmlnode_parser_data { + xmlnode *current; +}; - if(child == NULL || child->parent == NULL) - return; - - parent = child->parent; +static void +xmlnode_parser_element_start(GMarkupParseContext *context, + const char *element_name, const char **attrib_names, + const char **attrib_values, gpointer user_data, GError **error) +{ + struct _xmlnode_parser_data *xpd = user_data; + xmlnode *node; + int i; - /* first fix up at the child level */ - _xmlnode_hide_sibling(child); + if(!element_name) { + return; + } else { + if(xpd->current) + node = xmlnode_new_child(xpd->current, element_name); + else + node = xmlnode_new(element_name); - /* next fix up at the parent level */ - if(parent->firstchild == child) - parent->firstchild = child->next; - if(parent->lastchild == child) - parent->lastchild = child->prev; + for(i=0; attrib_names[i]; i++) + xmlnode_set_attrib(node, attrib_names[i], attrib_values[i]); + + xpd->current = node; + } } -void xmlnode_hide_attrib(xmlnode parent, const char *name) +static void +xmlnode_parser_element_end(GMarkupParseContext *context, + const char *element_name, gpointer user_data, GError **error) { - xmlnode attrib; - - if(parent == NULL || parent->firstattrib == NULL || name == NULL) - return; + struct _xmlnode_parser_data *xpd = user_data; - attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - return; + if(!element_name || !xpd->current) + return; - /* first fix up at the child level */ - _xmlnode_hide_sibling(attrib); - - /* next fix up at the parent level */ - if(parent->firstattrib == attrib) - parent->firstattrib = attrib->next; - if(parent->lastattrib == attrib) - parent->lastattrib = attrib->prev; + if(xpd->current->parent) { + if(!strcmp(xpd->current->name, element_name)) + xpd->current = xpd->current->parent; + } } - +static void +xmlnode_parser_element_text(GMarkupParseContext *context, const char *text, + gsize text_len, gpointer user_data, GError **error) +{ + struct _xmlnode_parser_data *xpd = user_data; -/* - * xmlnode2str -- convert given xmlnode tree into a string - * - * parameters - * node -- pointer to the xmlnode structure - * - * results - * a pointer to the created string - * or NULL if it was unsuccessfull - */ -char *xmlnode2str(xmlnode node) -{ - return spool_print(_xmlnode2spool(node)); + if(!xpd->current) + return; + + if(!text || !text_len) + return; + + xmlnode_insert_data(xpd->current, text, text_len); } -/* - * xmlnode2tstr -- convert given xmlnode tree into a newline terminated string - * - * parameters - * node -- pointer to the xmlnode structure - * - * results - * a pointer to the created string - * or NULL if it was unsuccessfull - */ -char* xmlnode2tstr(xmlnode node) -{ - spool s = _xmlnode2spool(node); - if (s != NULL) - spool_add(s, "\n"); - return spool_print(s); -} +static GMarkupParser xmlnode_parser = { + xmlnode_parser_element_start, + xmlnode_parser_element_end, + xmlnode_parser_element_text, + NULL, + NULL +}; -/* loop through both a and b comparing everything, attribs, cdata, children, etc */ -int xmlnode_cmp(xmlnode a, xmlnode b) +xmlnode *xmlnode_from_str(const char *str, size_t size) { - int ret = 0; - - while(1) - { - if(a == NULL && b == NULL) - return 0; - - if(a == NULL || b == NULL) - return -1; - - if(xmlnode_get_type(a) != xmlnode_get_type(b)) - return -1; + struct _xmlnode_parser_data *xpd = g_new0(struct _xmlnode_parser_data, 1); + xmlnode *ret; + GMarkupParseContext *context; + size_t real_size = size == -1 ? strlen(str) : size; - switch(xmlnode_get_type(a)) - { - case NTYPE_ATTRIB: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - break; - case NTYPE_TAG: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); - if(ret != 0) - return -1; - break; - case NTYPE_CDATA: - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - } - a = xmlnode_get_nextsibling(a); - b = xmlnode_get_nextsibling(b); - } -} - - -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node) -{ - xmlnode child; - - child = xmlnode_insert_tag(parent, xmlnode_get_name(node)); - if (xmlnode_has_attribs(node)) - xmlnode_insert_node(child, xmlnode_get_firstattrib(node)); - if (xmlnode_has_children(node)) - xmlnode_insert_node(child, xmlnode_get_firstchild(node)); - - return child; -} - -/* places copy of node and node's siblings in parent */ -void xmlnode_insert_node(xmlnode parent, xmlnode node) -{ - if(node == NULL || parent == NULL) - return; + context = g_markup_parse_context_new(&xmlnode_parser, 0, xpd, NULL); - while(node != NULL) - { - switch(xmlnode_get_type(node)) - { - case NTYPE_ATTRIB: - xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node)); - break; - case NTYPE_TAG: - xmlnode_insert_tag_node(parent, node); - break; - case NTYPE_CDATA: - xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node)); - } - node = xmlnode_get_nextsibling(node); - } -} - - -/* produce full duplicate of x with a new pool, x must be a tag! */ -xmlnode xmlnode_dup(xmlnode x) -{ - xmlnode x2; - - if(x == NULL) - return NULL; - - x2 = xmlnode_new_tag(xmlnode_get_name(x)); - - if (xmlnode_has_attribs(x)) - xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); - if (xmlnode_has_children(x)) - xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); - - return x2; -} + if(!g_markup_parse_context_parse(context, str, real_size, NULL)) { + while(xpd->current && xpd->current->parent) + xpd->current = xpd->current->parent; + xmlnode_free(xpd->current); + xpd->current = NULL; + } + g_markup_parse_context_free(context); -xmlnode xmlnode_dup_pool(pool p, xmlnode x) -{ - xmlnode x2; - - if(x == NULL) - return NULL; - - x2 = xmlnode_new_tag_pool(p, xmlnode_get_name(x)); - - if (xmlnode_has_attribs(x)) - xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); - if (xmlnode_has_children(x)) - xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); - - return x2; + ret = xpd->current; + g_free(xpd); + return ret; } - -xmlnode xmlnode_wrap(xmlnode x,const char *wrapper) -{ - xmlnode wrap; - if(x==NULL||wrapper==NULL) return NULL; - wrap=xmlnode_new_tag_pool(xmlnode_pool(x),wrapper); - if(wrap==NULL) return NULL; - wrap->firstchild=x; - wrap->lastchild=x; - x->parent=wrap; - return wrap; -} - -void xmlnode_free(xmlnode node) -{ - if(node == NULL) - return; - - pool_free(node->p); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/jabber/xmlnode.h Mon Sep 29 15:23:19 2003 +0000 @@ -0,0 +1,57 @@ +/** + * @file xmlnode.h XML DOM functions + * + * gaim + * + * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_XMLNODE_H_ +#define _GAIM_XMLNODE_H_ + +typedef enum _NodeType +{ + NODE_TYPE_TAG, + NODE_TYPE_ATTRIB, + NODE_TYPE_DATA +} NodeType; + +typedef struct _xmlnode +{ + char *name; + NodeType type; + char *data; + size_t data_sz; + struct _xmlnode *parent; + struct _xmlnode *child; + struct _xmlnode *next; +} xmlnode; + +xmlnode *xmlnode_new(const char *name); +xmlnode *xmlnode_new_child(xmlnode *parent, const char *name); +void xmlnode_insert_child(xmlnode *parent, xmlnode *child); +xmlnode *xmlnode_get_child(xmlnode *parent, const char *name); +void xmlnode_insert_data(xmlnode *parent, const char *data, size_t size); +char *xmlnode_get_data(xmlnode *node); +void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value); +const char *xmlnode_get_attrib(xmlnode *node, const char *attr); +void xmlnode_remove_attrib(xmlnode *node, const char *attr); +char *xmlnode_to_str(xmlnode *node); +xmlnode *xmlnode_from_str(const char *str, size_t size); + +void xmlnode_free(xmlnode *node); + +#endif /* _GAIM_XMLNODE_H_ */
--- a/src/protocols/jabber/xmlparse.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3232 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmlparse.h" - -#ifdef XML_UNICODE -#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX -#define XmlConvert XmlUtf16Convert -#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS -#define XmlEncode XmlUtf16Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) -typedef unsigned short ICHAR; -#else -#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX -#define XmlConvert XmlUtf8Convert -#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS -#define XmlEncode XmlUtf8Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) -typedef char ICHAR; -#endif - - -#ifndef XML_NS - -#define XmlInitEncodingNS XmlInitEncoding -#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding -#undef XmlGetInternalEncodingNS -#define XmlGetInternalEncodingNS XmlGetInternalEncoding -#define XmlParseXmlDeclNS XmlParseXmlDecl - -#endif - - -#ifdef XML_UNICODE_WCHAR_T -#define XML_T(x) L ## x -#else -#define XML_T(x) x -#endif - -/* Round up n to be a multiple of sz, where sz is a power of 2. */ -#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) - -#include "xmltok.h" -#include "xmlrole.h" -#include "hashtable.h" - -#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ -#define INIT_DATA_BUF_SIZE 1024 -#define INIT_ATTS_SIZE 16 -#define INIT_BLOCK_SIZE 1024 -#define INIT_BUFFER_SIZE 1024 - -#define EXPAND_SPARE 24 - -typedef struct binding { - struct prefix *prefix; - struct binding *nextTagBinding; - struct binding *prevPrefixBinding; - const struct attribute_id *attId; - XML_Char *uri; - int uriLen; - int uriAlloc; -} BINDING; - -typedef struct prefix { - const XML_Char *name; - BINDING *binding; -} PREFIX; - -typedef struct { - const XML_Char *str; - const XML_Char *localPart; - int uriLen; -} TAG_NAME; - -typedef struct tag { - struct tag *parent; - const char *rawName; - int rawNameLength; - TAG_NAME name; - char *buf; - char *bufEnd; - BINDING *bindings; -} TAG; - -typedef struct { - const XML_Char *name; - const XML_Char *textPtr; - int textLen; - const XML_Char *systemId; - const XML_Char *base; - const XML_Char *publicId; - const XML_Char *notation; - char open; -} ENTITY; - -typedef struct block { - struct block *next; - int size; - XML_Char s[1]; -} BLOCK; - -typedef struct { - BLOCK *blocks; - BLOCK *freeBlocks; - const XML_Char *end; - XML_Char *ptr; - XML_Char *start; -} STRING_POOL; - -/* The XML_Char before the name is used to determine whether -an attribute has been specified. */ -typedef struct attribute_id { - XML_Char *name; - PREFIX *prefix; - char maybeTokenized; - char xmlns; -} ATTRIBUTE_ID; - -typedef struct { - const ATTRIBUTE_ID *id; - char isCdata; - const XML_Char *value; -} DEFAULT_ATTRIBUTE; - -typedef struct { - const XML_Char *name; - PREFIX *prefix; - int nDefaultAtts; - int allocDefaultAtts; - DEFAULT_ATTRIBUTE *defaultAtts; -} ELEMENT_TYPE; - -typedef struct { - HASH_TABLE generalEntities; - HASH_TABLE elementTypes; - HASH_TABLE attributeIds; - HASH_TABLE prefixes; - STRING_POOL pool; - int complete; - int standalone; - const XML_Char *base; - PREFIX defaultPrefix; -} DTD; - -typedef struct open_internal_entity { - const char *internalEventPtr; - const char *internalEventEndPtr; - struct open_internal_entity *next; - ENTITY *entity; -} OPEN_INTERNAL_ENTITY; - -typedef enum XML_Error Processor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr); - -static Processor prologProcessor; -static Processor prologInitProcessor; -static Processor contentProcessor; -static Processor cdataSectionProcessor; -static Processor epilogProcessor; -static Processor externalEntityInitProcessor; -static Processor externalEntityInitProcessor2; -static Processor externalEntityInitProcessor3; -static Processor externalEntityContentProcessor; - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); -static enum XML_Error -initializeEncoding(XML_Parser parser); -static enum XML_Error -doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, - const char *start, const char *end, const char **endPtr); -static enum XML_Error -doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, - TAG_NAME *tagNamePtr, BINDING **bindingsPtr); -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue); -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); -static enum XML_Error -storeEntityValue(XML_Parser parser, const char *start, const char *end); -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); - -static const XML_Char *getContext(XML_Parser parser); -static int setContext(XML_Parser parser, const XML_Char *context); -static void normalizePublicId(XML_Char *s); -static int dtdInit(DTD *); -static void dtdDestroy(DTD *); -static int dtdCopy(DTD *newDtd, const DTD *oldDtd); -static void poolInit(STRING_POOL *); -static void poolClear(STRING_POOL *); -static void poolDestroy(STRING_POOL *); -static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static int poolGrow(STRING_POOL *pool); -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s); -static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); - -#define poolStart(pool) ((pool)->start) -#define poolEnd(pool) ((pool)->ptr) -#define poolLength(pool) ((pool)->ptr - (pool)->start) -#define poolChop(pool) ((void)--(pool->ptr)) -#define poolLastChar(pool) (((pool)->ptr)[-1]) -#define poolDiscard(pool) ((pool)->ptr = (pool)->start) -#define poolFinish(pool) ((pool)->start = (pool)->ptr) -#define poolAppendChar(pool, c) \ - (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ - ? 0 \ - : ((*((pool)->ptr)++ = c), 1)) - -typedef struct { - /* The first member must be userData so that the XML_GetUserData macro works. */ - void *m_userData; - void *m_handlerArg; - char *m_buffer; - /* first character to be parsed */ - const char *m_bufferPtr; - /* past last character to be parsed */ - char *m_bufferEnd; - /* allocated end of buffer */ - const char *m_bufferLim; - long m_parseEndByteIndex; - const char *m_parseEndPtr; - XML_Char *m_dataBuf; - XML_Char *m_dataBufEnd; - XML_StartElementHandler m_startElementHandler; - XML_EndElementHandler m_endElementHandler; - XML_CharacterDataHandler m_characterDataHandler; - XML_ProcessingInstructionHandler m_processingInstructionHandler; - XML_CommentHandler m_commentHandler; - XML_StartCdataSectionHandler m_startCdataSectionHandler; - XML_EndCdataSectionHandler m_endCdataSectionHandler; - XML_DefaultHandler m_defaultHandler; - XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; - XML_NotationDeclHandler m_notationDeclHandler; - XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; - XML_NotStandaloneHandler m_notStandaloneHandler; - XML_ExternalEntityRefHandler m_externalEntityRefHandler; - void *m_externalEntityRefHandlerArg; - XML_UnknownEncodingHandler m_unknownEncodingHandler; - const ENCODING *m_encoding; - INIT_ENCODING m_initEncoding; - const XML_Char *m_protocolEncodingName; - int m_ns; - void *m_unknownEncodingMem; - void *m_unknownEncodingData; - void *m_unknownEncodingHandlerData; - void (*m_unknownEncodingRelease)(void *); - PROLOG_STATE m_prologState; - Processor *m_processor; - enum XML_Error m_errorCode; - const char *m_eventPtr; - const char *m_eventEndPtr; - const char *m_positionPtr; - OPEN_INTERNAL_ENTITY *m_openInternalEntities; - int m_defaultExpandInternalEntities; - int m_tagLevel; - ENTITY *m_declEntity; - const XML_Char *m_declNotationName; - const XML_Char *m_declNotationPublicId; - ELEMENT_TYPE *m_declElementType; - ATTRIBUTE_ID *m_declAttributeId; - char m_declAttributeIsCdata; - DTD m_dtd; - TAG *m_tagStack; - TAG *m_freeTagList; - BINDING *m_inheritedBindings; - BINDING *m_freeBindingList; - int m_attsSize; - int m_nSpecifiedAtts; - ATTRIBUTE *m_atts; - POSITION m_position; - STRING_POOL m_tempPool; - STRING_POOL m_temp2Pool; - char *m_groupConnector; - unsigned m_groupSize; - int m_hadExternalDoctype; - XML_Char m_namespaceSeparator; -} Parser; - -#define userData (((Parser *)parser)->m_userData) -#define handlerArg (((Parser *)parser)->m_handlerArg) -#define startElementHandler (((Parser *)parser)->m_startElementHandler) -#define endElementHandler (((Parser *)parser)->m_endElementHandler) -#define characterDataHandler (((Parser *)parser)->m_characterDataHandler) -#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) -#define commentHandler (((Parser *)parser)->m_commentHandler) -#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) -#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) -#define defaultHandler (((Parser *)parser)->m_defaultHandler) -#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) -#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) -#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) -#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) -#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) -#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) -#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) -#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) -#define encoding (((Parser *)parser)->m_encoding) -#define initEncoding (((Parser *)parser)->m_initEncoding) -#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) -#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) -#define unknownEncodingHandlerData \ - (((Parser *)parser)->m_unknownEncodingHandlerData) -#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) -#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) -#define ns (((Parser *)parser)->m_ns) -#define prologState (((Parser *)parser)->m_prologState) -#define processor (((Parser *)parser)->m_processor) -#define errorCode (((Parser *)parser)->m_errorCode) -#define eventPtr (((Parser *)parser)->m_eventPtr) -#define eventEndPtr (((Parser *)parser)->m_eventEndPtr) -#define positionPtr (((Parser *)parser)->m_positionPtr) -#define position (((Parser *)parser)->m_position) -#define openInternalEntities (((Parser *)parser)->m_openInternalEntities) -#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) -#define tagLevel (((Parser *)parser)->m_tagLevel) -#define buffer (((Parser *)parser)->m_buffer) -#define bufferPtr (((Parser *)parser)->m_bufferPtr) -#define bufferEnd (((Parser *)parser)->m_bufferEnd) -#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) -#define parseEndPtr (((Parser *)parser)->m_parseEndPtr) -#define bufferLim (((Parser *)parser)->m_bufferLim) -#define dataBuf (((Parser *)parser)->m_dataBuf) -#define dataBufEnd (((Parser *)parser)->m_dataBufEnd) -#define dtd (((Parser *)parser)->m_dtd) -#define declEntity (((Parser *)parser)->m_declEntity) -#define declNotationName (((Parser *)parser)->m_declNotationName) -#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) -#define declElementType (((Parser *)parser)->m_declElementType) -#define declAttributeId (((Parser *)parser)->m_declAttributeId) -#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) -#define freeTagList (((Parser *)parser)->m_freeTagList) -#define freeBindingList (((Parser *)parser)->m_freeBindingList) -#define inheritedBindings (((Parser *)parser)->m_inheritedBindings) -#define tagStack (((Parser *)parser)->m_tagStack) -#define atts (((Parser *)parser)->m_atts) -#define attsSize (((Parser *)parser)->m_attsSize) -#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) -#define tempPool (((Parser *)parser)->m_tempPool) -#define temp2Pool (((Parser *)parser)->m_temp2Pool) -#define groupConnector (((Parser *)parser)->m_groupConnector) -#define groupSize (((Parser *)parser)->m_groupSize) -#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) -#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) - -#ifdef _MSC_VER -#ifdef _DEBUG -Parser *asParser(XML_Parser parser) -{ - return parser; -} -#endif -#endif - -XML_Parser XML_ParserCreate(const XML_Char *encodingName) -{ - XML_Parser parser = malloc(sizeof(Parser)); - if (!parser) - return parser; - processor = prologInitProcessor; - XmlPrologStateInit(&prologState); - userData = 0; - handlerArg = 0; - startElementHandler = 0; - endElementHandler = 0; - characterDataHandler = 0; - processingInstructionHandler = 0; - commentHandler = 0; - startCdataSectionHandler = 0; - endCdataSectionHandler = 0; - defaultHandler = 0; - unparsedEntityDeclHandler = 0; - notationDeclHandler = 0; - startNamespaceDeclHandler = 0; - endNamespaceDeclHandler = 0; - notStandaloneHandler = 0; - externalEntityRefHandler = 0; - externalEntityRefHandlerArg = parser; - unknownEncodingHandler = 0; - buffer = 0; - bufferPtr = 0; - bufferEnd = 0; - parseEndByteIndex = 0; - parseEndPtr = 0; - bufferLim = 0; - declElementType = 0; - declAttributeId = 0; - declEntity = 0; - declNotationName = 0; - declNotationPublicId = 0; - memset(&position, 0, sizeof(POSITION)); - errorCode = XML_ERROR_NONE; - eventPtr = 0; - eventEndPtr = 0; - positionPtr = 0; - openInternalEntities = 0; - tagLevel = 0; - tagStack = 0; - freeTagList = 0; - freeBindingList = 0; - inheritedBindings = 0; - attsSize = INIT_ATTS_SIZE; - atts = malloc(attsSize * sizeof(ATTRIBUTE)); - nSpecifiedAtts = 0; - dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); - groupSize = 0; - groupConnector = 0; - hadExternalDoctype = 0; - unknownEncodingMem = 0; - unknownEncodingRelease = 0; - unknownEncodingData = 0; - unknownEncodingHandlerData = 0; - namespaceSeparator = '!'; - ns = 0; - poolInit(&tempPool); - poolInit(&temp2Pool); - protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0; - if (!dtdInit(&dtd) || !atts || !dataBuf - || (encodingName && !protocolEncodingName)) { - XML_ParserFree(parser); - return 0; - } - dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; - XmlInitEncoding(&initEncoding, &encoding, 0); - return parser; -} - -XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) -{ - static - const XML_Char implicitContext[] = { - XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='), - XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'), - XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'), - XML_T('.'), XML_T('w'), XML_T('3'), - XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'), - XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'), - XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'), - XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'), - XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'), - XML_T('\0') - }; - - XML_Parser parser = XML_ParserCreate(encodingName); - if (parser) { - XmlInitEncodingNS(&initEncoding, &encoding, 0); - ns = 1; - namespaceSeparator = nsSep; - } - if (!setContext(parser, implicitContext)) { - XML_ParserFree(parser); - return 0; - } - return parser; -} - -int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (!encodingName) - protocolEncodingName = 0; - else { - protocolEncodingName = poolCopyString(&tempPool, encodingName); - if (!protocolEncodingName) - return 0; - } - return 1; -} - -XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser, - const XML_Char *context, - const XML_Char *encodingName) -{ - XML_Parser parser = oldParser; - DTD *oldDtd = &dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; - - parser = (ns - ? XML_ParserCreateNS(encodingName, namespaceSeparator) - : XML_ParserCreate(encodingName)); - if (!parser) - return 0; - startElementHandler = oldStartElementHandler; - endElementHandler = oldEndElementHandler; - characterDataHandler = oldCharacterDataHandler; - processingInstructionHandler = oldProcessingInstructionHandler; - commentHandler = oldCommentHandler; - startCdataSectionHandler = oldStartCdataSectionHandler; - endCdataSectionHandler = oldEndCdataSectionHandler; - defaultHandler = oldDefaultHandler; - startNamespaceDeclHandler = oldStartNamespaceDeclHandler; - endNamespaceDeclHandler = oldEndNamespaceDeclHandler; - notStandaloneHandler = oldNotStandaloneHandler; - externalEntityRefHandler = oldExternalEntityRefHandler; - unknownEncodingHandler = oldUnknownEncodingHandler; - userData = oldUserData; - if (oldUserData == oldHandlerArg) - handlerArg = userData; - else - handlerArg = parser; - if (oldExternalEntityRefHandlerArg != oldParser) - externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; - defaultExpandInternalEntities = oldDefaultExpandInternalEntities; - if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) { - XML_ParserFree(parser); - return 0; - } - processor = externalEntityInitProcessor; - return parser; -} - -static -void destroyBindings(BINDING *bindings) -{ - for (;;) { - BINDING *b = bindings; - if (!b) - break; - bindings = b->nextTagBinding; - free(b->uri); - free(b); - } -} - -void XML_ParserFree(XML_Parser parser) -{ - for (;;) { - TAG *p; - if (tagStack == 0) { - if (freeTagList == 0) - break; - tagStack = freeTagList; - freeTagList = 0; - } - p = tagStack; - tagStack = tagStack->parent; - free(p->buf); - destroyBindings(p->bindings); - free(p); - } - destroyBindings(freeBindingList); - destroyBindings(inheritedBindings); - poolDestroy(&tempPool); - poolDestroy(&temp2Pool); - dtdDestroy(&dtd); - free((void *)atts); - free(groupConnector); - free(buffer); - free(dataBuf); - free(unknownEncodingMem); - if (unknownEncodingRelease) - unknownEncodingRelease(unknownEncodingData); - free(parser); -} - -void XML_UseParserAsHandlerArg(XML_Parser parser) -{ - handlerArg = parser; -} - -void XML_SetUserData(XML_Parser parser, void *p) -{ - if (handlerArg == userData) - handlerArg = userData = p; - else - userData = p; -} - -int XML_SetBase(XML_Parser parser, const XML_Char *p) -{ - if (p) { - p = poolCopyString(&dtd.pool, p); - if (!p) - return 0; - dtd.base = p; - } - else - dtd.base = 0; - return 1; -} - -const XML_Char *XML_GetBase(XML_Parser parser) -{ - return dtd.base; -} - -int XML_GetSpecifiedAttributeCount(XML_Parser parser) -{ - return nSpecifiedAtts; -} - -void XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end) -{ - startElementHandler = start; - endElementHandler = end; -} - -void XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler) -{ - characterDataHandler = handler; -} - -void XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler) -{ - processingInstructionHandler = handler; -} - -void XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler) -{ - commentHandler = handler; -} - -void XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end) -{ - startCdataSectionHandler = start; - endCdataSectionHandler = end; -} - -void XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler) -{ - defaultHandler = handler; - defaultExpandInternalEntities = 0; -} - -void XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler) -{ - defaultHandler = handler; - defaultExpandInternalEntities = 1; -} - -void XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler) -{ - unparsedEntityDeclHandler = handler; -} - -void XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler) -{ - notationDeclHandler = handler; -} - -void XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end) -{ - startNamespaceDeclHandler = start; - endNamespaceDeclHandler = end; -} - -void XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler) -{ - notStandaloneHandler = handler; -} - -void XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler) -{ - externalEntityRefHandler = handler; -} - -void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) -{ - if (arg) - externalEntityRefHandlerArg = arg; - else - externalEntityRefHandlerArg = parser; -} - -void XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *data) -{ - unknownEncodingHandler = handler; - unknownEncodingHandlerData = data; -} - -int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) -{ - if (len == 0) { - if (!isFinal) - return 1; - positionPtr = bufferPtr; - errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - else if (bufferPtr == bufferEnd) { - const char *end; - int nLeftOver; - parseEndByteIndex += len; - positionPtr = s; - if (isFinal) { - errorCode = processor(parser, s, parseEndPtr = s + len, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - errorCode = processor(parser, s, parseEndPtr = s + len, &end); - if (errorCode != XML_ERROR_NONE) { - eventEndPtr = eventPtr; - return 0; - } - XmlUpdatePosition(encoding, positionPtr, end, &position); - nLeftOver = s + len - end; - if (nLeftOver) { - if (buffer == 0 || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2); - if (!buffer) { - errorCode = XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = 0; - return 0; - } - bufferLim = buffer + len * 2; - } - memcpy(buffer, end, nLeftOver); - bufferPtr = buffer; - bufferEnd = buffer + nLeftOver; - } - return 1; - } - else { - memcpy(XML_GetBuffer(parser, len), s, len); - return XML_ParseBuffer(parser, len, isFinal); - } -} - -int XML_ParseBuffer(XML_Parser parser, int len, int isFinal) -{ - const char *start = bufferPtr; - positionPtr = start; - bufferEnd += len; - parseEndByteIndex += len; - errorCode = processor(parser, start, parseEndPtr = bufferEnd, - isFinal ? (const char **)0 : &bufferPtr); - if (errorCode == XML_ERROR_NONE) { - if (!isFinal) - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - return 1; - } - else { - eventEndPtr = eventPtr; - return 0; - } -} - -void *XML_GetBuffer(XML_Parser parser, int len) -{ - if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ - int neededSize = len + (bufferEnd - bufferPtr); - if (neededSize <= bufferLim - buffer) { - memmove(buffer, bufferPtr, bufferEnd - bufferPtr); - bufferEnd = buffer + (bufferEnd - bufferPtr); - bufferPtr = buffer; - } - else { - char *newBuf; - int bufferSize = bufferLim - bufferPtr; - if (bufferSize == 0) - bufferSize = INIT_BUFFER_SIZE; - do { - bufferSize *= 2; - } while (bufferSize < neededSize); - newBuf = malloc(bufferSize); - if (newBuf == 0) { - errorCode = XML_ERROR_NO_MEMORY; - return 0; - } - bufferLim = newBuf + bufferSize; - if (bufferPtr) { - memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); - free(buffer); - } - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; - } - } - return bufferEnd; -} - -enum XML_Error XML_GetErrorCode(XML_Parser parser) -{ - return errorCode; -} - -long XML_GetCurrentByteIndex(XML_Parser parser) -{ - if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); - return -1; -} - -int XML_GetCurrentByteCount(XML_Parser parser) -{ - if (eventEndPtr && eventPtr) - return eventEndPtr - eventPtr; - return 0; -} - -int XML_GetCurrentLineNumber(XML_Parser parser) -{ - if (eventPtr) { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.lineNumber + 1; -} - -int XML_GetCurrentColumnNumber(XML_Parser parser) -{ - if (eventPtr) { - XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); - positionPtr = eventPtr; - } - return position.columnNumber; -} - -void XML_DefaultCurrent(XML_Parser parser) -{ - if (defaultHandler) { - if (openInternalEntities) - reportDefault(parser, - ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(), - openInternalEntities->internalEventPtr, - openInternalEntities->internalEventEndPtr); - else - reportDefault(parser, encoding, eventPtr, eventEndPtr); - } -} - -const XML_LChar *XML_ErrorString(int code) -{ - static const XML_LChar *message[] = { - 0, - XML_T("out of memory"), - XML_T("syntax error"), - XML_T("no element found"), - XML_T("not well-formed"), - XML_T("unclosed token"), - XML_T("unclosed token"), - XML_T("mismatched tag"), - XML_T("duplicate attribute"), - XML_T("junk after document element"), - XML_T("illegal parameter entity reference"), - XML_T("undefined entity"), - XML_T("recursive entity reference"), - XML_T("asynchronous entity"), - XML_T("reference to invalid character number"), - XML_T("reference to binary entity"), - XML_T("reference to external entity in attribute"), - XML_T("xml processing instruction not at start of external entity"), - XML_T("unknown encoding"), - XML_T("encoding specified in XML declaration is incorrect"), - XML_T("unclosed CDATA section"), - XML_T("error in processing external entity reference"), - XML_T("document is not standalone") - }; - if (code > 0 && code < sizeof(message)/sizeof(message[0])) - return message[code]; - return 0; -} - -static -enum XML_Error contentProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - return doContent(parser, 0, encoding, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = externalEntityInitProcessor2; - return externalEntityInitProcessor2(parser, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor2(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - const char *next; - int tok = XmlContentTok(encoding, start, end, &next); - switch (tok) { - case XML_TOK_BOM: - start = next; - break; - case XML_TOK_PARTIAL: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_PARTIAL_CHAR; - } - processor = externalEntityInitProcessor3; - return externalEntityInitProcessor3(parser, start, end, endPtr); -} - -static -enum XML_Error externalEntityInitProcessor3(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - const char *next; - int tok = XmlContentTok(encoding, start, end, &next); - switch (tok) { - case XML_TOK_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 1, start, next); - if (result != XML_ERROR_NONE) - return result; - start = next; - } - break; - case XML_TOK_PARTIAL: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (endPtr) { - *endPtr = start; - return XML_ERROR_NONE; - } - eventPtr = start; - return XML_ERROR_PARTIAL_CHAR; - } - processor = externalEntityContentProcessor; - tagLevel = 1; - return doContent(parser, 1, encoding, start, end, endPtr); -} - -static -enum XML_Error externalEntityContentProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - return doContent(parser, 1, encoding, start, end, endPtr); -} - -static enum XML_Error -doContent(XML_Parser parser, - int startTagLevel, - const ENCODING *enc, - const char *s, - const char *end, - const char **nextPtr) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - for (;;) { - const char *next = s; /* XmlContentTok doesn't always set the last arg */ - int tok = XmlContentTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - *eventEndPP = end; - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) - return XML_ERROR_NO_ELEMENTS; - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (startTagLevel > 0) { - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - } - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (characterDataHandler) - characterDataHandler(handlerArg, &ch, 1); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - name = poolStoreString(&dtd.pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&dtd.pool); - if (!entity) { - if (dtd.complete || dtd.standalone) - return XML_ERROR_UNDEFINED_ENTITY; - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - if (entity->open) - return XML_ERROR_RECURSIVE_ENTITY_REF; - if (entity->notation) - return XML_ERROR_BINARY_ENTITY_REF; - if (entity) { - if (entity->textPtr) { - enum XML_Error result; - OPEN_INTERNAL_ENTITY openEntity; - if (defaultHandler && !defaultExpandInternalEntities) { - reportDefault(parser, enc, s, next); - break; - } - entity->open = 1; - openEntity.next = openInternalEntities; - openInternalEntities = &openEntity; - openEntity.entity = entity; - openEntity.internalEventPtr = 0; - openEntity.internalEventEndPtr = 0; - result = doContent(parser, - tagLevel, - internalEnc, - (char *)entity->textPtr, - (char *)(entity->textPtr + entity->textLen), - 0); - entity->open = 0; - openInternalEntities = openEntity.next; - if (result) - return result; - } - else if (externalEntityRefHandler) { - const XML_Char *context; - entity->open = 1; - context = getContext(parser); - entity->open = 0; - if (!context) - return XML_ERROR_NO_MEMORY; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - context, - dtd.base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - poolDiscard(&tempPool); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_START_TAG_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_START_TAG_NO_ATTS: - { - TAG *tag; - if (freeTagList) { - tag = freeTagList; - freeTagList = freeTagList->parent; - } - else { - tag = malloc(sizeof(TAG)); - if (!tag) - return XML_ERROR_NO_MEMORY; - tag->buf = malloc(INIT_TAG_BUF_SIZE); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; - } - tag->bindings = 0; - tag->parent = tagStack; - tagStack = tag; - tag->name.localPart = 0; - tag->rawName = s + enc->minBytesPerChar; - tag->rawNameLength = XmlNameLength(enc, tag->rawName); - if (nextPtr) { - /* Need to guarantee that: - tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */ - if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { - int bufSize = tag->rawNameLength * 4; - bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - } - memcpy(tag->buf, tag->rawName, tag->rawNameLength); - tag->rawName = tag->buf; - } - ++tagLevel; - if (startElementHandler) { - enum XML_Error result; - XML_Char *toPtr; - for (;;) { - const char *rawNameEnd = tag->rawName + tag->rawNameLength; - const char *fromPtr = tag->rawName; - int bufSize; - if (nextPtr) - toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char))); - else - toPtr = (XML_Char *)tag->buf; - tag->name.str = toPtr; - XmlConvert(enc, - &fromPtr, rawNameEnd, - (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - if (fromPtr == rawNameEnd) - break; - bufSize = (tag->bufEnd - tag->buf) << 1; - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - if (nextPtr) - tag->rawName = tag->buf; - } - *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); - if (result) - return result; - startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); - poolClear(&tempPool); - } - else { - tag->name.str = 0; - if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_EMPTY_ELEMENT_NO_ATTS: - if (startElementHandler || endElementHandler) { - const char *rawName = s + enc->minBytesPerChar; - enum XML_Error result; - BINDING *bindings = 0; - TAG_NAME name; - name.str = poolStoreString(&tempPool, enc, rawName, - rawName + XmlNameLength(enc, rawName)); - if (!name.str) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); - if (result) - return result; - poolFinish(&tempPool); - if (startElementHandler) - startElementHandler(handlerArg, name.str, (const XML_Char **)atts); - if (endElementHandler) { - if (startElementHandler) - *eventPP = *eventEndPP; - endElementHandler(handlerArg, name.str); - } - poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - break; - case XML_TOK_END_TAG: - if (tagLevel == startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - else { - int len; - const char *rawName; - TAG *tag = tagStack; - tagStack = tag->parent; - tag->parent = freeTagList; - freeTagList = tag; - rawName = s + enc->minBytesPerChar*2; - len = XmlNameLength(enc, rawName); - if (len != tag->rawNameLength - || memcmp(tag->rawName, rawName, len) != 0) { - *eventPP = rawName; - return XML_ERROR_TAG_MISMATCH; - } - --tagLevel; - if (endElementHandler && tag->name.str) { - if (tag->name.localPart) { - XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen; - const XML_Char *from = tag->name.localPart; - while ((*to++ = *from++) != 0) - ; - } - endElementHandler(handlerArg, tag->name.str); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - while (tag->bindings) { - BINDING *b = tag->bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - tag->bindings = tag->bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - } - break; - case XML_TOK_CHAR_REF: - { - int n = XmlCharRefNumber(enc, s); - if (n < 0) - return XML_ERROR_BAD_CHAR_REF; - if (characterDataHandler) { - XML_Char buf[XML_ENCODE_MAX]; - characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_CDATA_SECT_OPEN: - { - enum XML_Error result; - if (startCdataSectionHandler) - startCdataSectionHandler(handlerArg); -#if 0 - /* Suppose you doing a transformation on a document that involves - changing only the character data. You set up a defaultHandler - and a characterDataHandler. The defaultHandler simply copies - characters through. The characterDataHandler does the transformation - and writes the characters out escaping them as necessary. This case - will fail to work if we leave out the following two lines (because & - and < inside CDATA sections will be incorrectly escaped). - - However, now we have a start/endCdataSectionHandler, so it seems - easier to let the user deal with this. */ - - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr); - if (!next) { - processor = cdataSectionProcessor; - return result; - } - } - break; - case XML_TOK_TRAILING_RSQB: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)end - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) { - *eventPP = end; - return XML_ERROR_NO_ELEMENTS; - } - if (tagLevel != startTagLevel) { - *eventPP = end; - return XML_ERROR_ASYNC_ENTITY; - } - return XML_ERROR_NONE; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - default: - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - *eventPP = s = next; - } - /* not reached */ -} - -/* If tagNamePtr is non-null, build a real list of attributes, -otherwise just check the attributes for well-formedness. */ - -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, - const char *s, TAG_NAME *tagNamePtr, - BINDING **bindingsPtr) -{ - ELEMENT_TYPE *elementType = 0; - int nDefaultAtts = 0; - const XML_Char **appAtts; - int attIndex = 0; - int i; - int n; - int nPrefixes = 0; - BINDING *binding; - const XML_Char *localPart; - - if (tagNamePtr) { - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0); - if (!elementType) { - tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); - if (!tagNamePtr->str) - return XML_ERROR_NO_MEMORY; - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); - if (!elementType) - return XML_ERROR_NO_MEMORY; - if (ns && !setElementTypePrefix(parser, elementType)) - return XML_ERROR_NO_MEMORY; - } - nDefaultAtts = elementType->nDefaultAtts; - } - n = XmlGetAttributes(enc, s, attsSize, atts); - if (n + nDefaultAtts > attsSize) { - int oldAttsSize = attsSize; - attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE)); - if (!atts) - return XML_ERROR_NO_MEMORY; - if (n > oldAttsSize) - XmlGetAttributes(enc, s, n, atts); - } - appAtts = (const XML_Char **)atts; - for (i = 0; i < n; i++) { - ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, - atts[i].name - + XmlNameLength(enc, atts[i].name)); - if (!attId) - return XML_ERROR_NO_MEMORY; - if ((attId->name)[-1]) { - if (enc == encoding) - eventPtr = atts[i].name; - return XML_ERROR_DUPLICATE_ATTRIBUTE; - } - (attId->name)[-1] = 1; - appAtts[attIndex++] = attId->name; - if (!atts[i].normalized) { - enum XML_Error result; - int isCdata = 1; - - if (attId->maybeTokenized) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - if (attId == elementType->defaultAtts[j].id) { - isCdata = elementType->defaultAtts[j].isCdata; - break; - } - } - } - - result = storeAttributeValue(parser, enc, isCdata, - atts[i].valuePtr, atts[i].valueEnd, - &tempPool); - if (result) - return result; - if (tagNamePtr) { - appAtts[attIndex] = poolStart(&tempPool); - poolFinish(&tempPool); - } - else - poolDiscard(&tempPool); - } - else if (tagNamePtr) { - appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); - if (appAtts[attIndex] == 0) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - if (attId->prefix && tagNamePtr) { - if (attId->xmlns) { - if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr)) - return XML_ERROR_NO_MEMORY; - --attIndex; - } - else { - attIndex++; - nPrefixes++; - (attId->name)[-1] = 2; - } - } - else - attIndex++; - } - nSpecifiedAtts = attIndex; - if (tagNamePtr) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; - if (!(da->id->name)[-1] && da->value) { - if (da->id->prefix) { - if (da->id->xmlns) { - if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr)) - return XML_ERROR_NO_MEMORY; - } - else { - (da->id->name)[-1] = 2; - nPrefixes++; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - else { - (da->id->name)[-1] = 1; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - } - appAtts[attIndex] = 0; - } - i = 0; - if (nPrefixes) { - for (; i < attIndex; i += 2) { - if (appAtts[i][-1] == 2) { - ATTRIBUTE_ID *id; - ((XML_Char *)(appAtts[i]))[-1] = 0; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); - if (id->prefix->binding) { - int j; - const BINDING *b = id->prefix->binding; - const XML_Char *s = appAtts[i]; - for (j = 0; j < b->uriLen; j++) { - if (!poolAppendChar(&tempPool, b->uri[j])) - return XML_ERROR_NO_MEMORY; - } - while (*s++ != ':') - ; - do { - if (!poolAppendChar(&tempPool, *s)) - return XML_ERROR_NO_MEMORY; - } while (*s++); - appAtts[i] = poolStart(&tempPool); - poolFinish(&tempPool); - } - if (!--nPrefixes) - break; - } - else - ((XML_Char *)(appAtts[i]))[-1] = 0; - } - } - for (; i < attIndex; i += 2) - ((XML_Char *)(appAtts[i]))[-1] = 0; - if (!tagNamePtr) - return XML_ERROR_NONE; - for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) - binding->attId->name[-1] = 0; - if (elementType->prefix) { - binding = elementType->prefix->binding; - if (!binding) - return XML_ERROR_NONE; - localPart = tagNamePtr->str; - while (*localPart++ != XML_T(':')) - ; - } - else if (dtd.defaultPrefix.binding) { - binding = dtd.defaultPrefix.binding; - localPart = tagNamePtr->str; - } - else - return XML_ERROR_NONE; - tagNamePtr->localPart = localPart; - tagNamePtr->uriLen = binding->uriLen; - i = binding->uriLen; - do { - if (i == binding->uriAlloc) { - binding->uri = realloc(binding->uri, binding->uriAlloc *= 2); - if (!binding->uri) - return XML_ERROR_NO_MEMORY; - } - binding->uri[i++] = *localPart; - } while (*localPart++); - tagNamePtr->str = binding->uri; - return XML_ERROR_NONE; -} - -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) -{ - BINDING *b; - int len; - for (len = 0; uri[len]; len++) - ; - if (namespaceSeparator) - len++; - if (freeBindingList) { - b = freeBindingList; - if (len > b->uriAlloc) { - b->uri = realloc(b->uri, len + EXPAND_SPARE); - if (!b->uri) - return 0; - b->uriAlloc = len + EXPAND_SPARE; - } - freeBindingList = b->nextTagBinding; - } - else { - b = malloc(sizeof(BINDING)); - if (!b) - return 0; - b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE); - if (!b->uri) { - free(b); - return 0; - } - b->uriAlloc = len; - } - b->uriLen = len; - memcpy(b->uri, uri, len * sizeof(XML_Char)); - if (namespaceSeparator) - b->uri[len - 1] = namespaceSeparator; - b->prefix = prefix; - b->attId = attId; - b->prevPrefixBinding = prefix->binding; - if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) - prefix->binding = 0; - else - prefix->binding = b; - b->nextTagBinding = *bindingsPtr; - *bindingsPtr = b; - if (startNamespaceDeclHandler) - startNamespaceDeclHandler(handlerArg, prefix->name, - prefix->binding ? uri : 0); - return 1; -} - -/* The idea here is to avoid using stack for each CDATA section when -the whole file is parsed with one call. */ - -static -enum XML_Error cdataSectionProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); - if (start) { - processor = contentProcessor; - return contentProcessor(parser, start, end, endPtr); - } - return result; -} - -/* startPtr gets set to non-null is the section is closed, and to null if -the section is not yet closed. */ - -static -enum XML_Error doCdataSection(XML_Parser parser, - const ENCODING *enc, - const char **startPtr, - const char *end, - const char **nextPtr) -{ - const char *s = *startPtr; - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - *eventPP = s; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - *startPtr = 0; - for (;;) { - const char *next; - int tok = XmlCdataSectionTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_CDATA_SECT_CLOSE: - if (endCdataSectionHandler) - endCdataSectionHandler(handlerArg); -#if 0 - /* see comment under XML_TOK_CDATA_SECT_OPEN */ - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - *startPtr = next; - return XML_ERROR_NONE; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = next; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_PARTIAL: - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_CDATA_SECTION; - default: - abort(); - } - *eventPP = s = next; - } - /* not reached */ -} - -static enum XML_Error -initializeEncoding(XML_Parser parser) -{ - const char *s; -#ifdef XML_UNICODE - char encodingBuf[128]; - if (!protocolEncodingName) - s = 0; - else { - int i; - for (i = 0; protocolEncodingName[i]; i++) { - if (i == sizeof(encodingBuf) - 1 - || protocolEncodingName[i] >= 0x80 - || protocolEncodingName[i] < 0) { - encodingBuf[0] = '\0'; - break; - } - encodingBuf[i] = (char)protocolEncodingName[i]; - } - encodingBuf[i] = '\0'; - s = encodingBuf; - } -#else -s = protocolEncodingName; -#endif - if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) - return XML_ERROR_NONE; - return handleUnknownEncoding(parser, protocolEncodingName); -} - -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, - const char *s, const char *next) -{ - const char *encodingName = 0; - const ENCODING *newEncoding = 0; - const char *version; - int standalone = -1; - if (!(ns - ? XmlParseXmlDeclNS - : XmlParseXmlDecl)(isGeneralTextEntity, - encoding, - s, - next, - &eventPtr, - &version, - &encodingName, - &newEncoding, - &standalone)) - return XML_ERROR_SYNTAX; - if (!isGeneralTextEntity && standalone == 1) - dtd.standalone = 1; - if (defaultHandler) - reportDefault(parser, encoding, s, next); - if (!protocolEncodingName) { - if (newEncoding) { - if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { - eventPtr = encodingName; - return XML_ERROR_INCORRECT_ENCODING; - } - encoding = newEncoding; - } - else if (encodingName) { - enum XML_Error result; - const XML_Char *s = poolStoreString(&tempPool, - encoding, - encodingName, - encodingName - + XmlNameLength(encoding, encodingName)); - if (!s) - return XML_ERROR_NO_MEMORY; - result = handleUnknownEncoding(parser, s); - poolDiscard(&tempPool); - if (result == XML_ERROR_UNKNOWN_ENCODING) - eventPtr = encodingName; - return result; - } - } - return XML_ERROR_NONE; -} - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (unknownEncodingHandler) { - XML_Encoding info; - int i; - for (i = 0; i < 256; i++) - info.map[i] = -1; - info.convert = 0; - info.data = 0; - info.release = 0; - if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { - ENCODING *enc; - unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding()); - if (!unknownEncodingMem) { - if (info.release) - info.release(info.data); - return XML_ERROR_NO_MEMORY; - } - enc = (ns - ? XmlInitUnknownEncodingNS - : XmlInitUnknownEncoding)(unknownEncodingMem, - info.map, - info.convert, - info.data); - if (enc) { - unknownEncodingData = info.data; - unknownEncodingRelease = info.release; - encoding = enc; - return XML_ERROR_NONE; - } - } - if (info.release) - info.release(info.data); - } - return XML_ERROR_UNKNOWN_ENCODING; -} - -static enum XML_Error -prologInitProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = prologProcessor; - return prologProcessor(parser, s, end, nextPtr); -} - -static enum XML_Error -prologProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) { - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_NONE: - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_TRAILING_CR: - eventPtr = s + encoding->minBytesPerChar; - return XML_ERROR_NO_ELEMENTS; - default: - abort(); - } - } - switch (XmlTokenRole(&prologState, tok, s, next, encoding)) { - case XML_ROLE_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 0, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_DOCTYPE_SYSTEM_ID: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - hadExternalDoctype = 1; - break; - case XML_ROLE_DOCTYPE_PUBLIC_ID: - case XML_ROLE_ENTITY_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declEntity) { - XML_Char *tem = poolStoreString(&dtd.pool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declEntity->publicId = tem; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_INSTANCE_START: - processor = contentProcessor; - if (hadExternalDoctype) - dtd.complete = 0; - return contentProcessor(parser, s, end, nextPtr); - case XML_ROLE_ATTLIST_ELEMENT_NAME: - { - const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); - if (!declElementType) - return XML_ERROR_NO_MEMORY; - if (declElementType->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!setElementTypePrefix(parser, declElementType)) - return XML_ERROR_NO_MEMORY; - } - break; - } - case XML_ROLE_ATTRIBUTE_NAME: - declAttributeId = getAttributeId(parser, encoding, s, next); - if (!declAttributeId) - return XML_ERROR_NO_MEMORY; - declAttributeIsCdata = 0; - break; - case XML_ROLE_ATTRIBUTE_TYPE_CDATA: - declAttributeIsCdata = 1; - break; - case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: - case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0)) - return XML_ERROR_NO_MEMORY; - break; - case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: - case XML_ROLE_FIXED_ATTRIBUTE_VALUE: - { - const XML_Char *attVal; - enum XML_Error result - = storeAttributeValue(parser, encoding, declAttributeIsCdata, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar, - &dtd.pool); - if (result) - return result; - attVal = poolStart(&dtd.pool); - poolFinish(&dtd.pool); - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal)) - return XML_ERROR_NO_MEMORY; - break; - } - case XML_ROLE_ENTITY_VALUE: - { - enum XML_Error result = storeEntityValue(parser, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_ENTITY_SYSTEM_ID: - if (declEntity) { - declEntity->systemId = poolStoreString(&dtd.pool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!declEntity->systemId) - return XML_ERROR_NO_MEMORY; - declEntity->base = dtd.base; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_ENTITY_NOTATION_NAME: - if (declEntity) { - declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next); - if (!declEntity->notation) - return XML_ERROR_NO_MEMORY; - poolFinish(&dtd.pool); - if (unparsedEntityDeclHandler) { - eventPtr = eventEndPtr = s; - unparsedEntityDeclHandler(handlerArg, - declEntity->name, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - declEntity->notation); - } - - } - break; - case XML_ROLE_GENERAL_ENTITY_NAME: - { - const XML_Char *name; - if (XmlPredefinedEntityName(encoding, s, next)) { - declEntity = 0; - break; - } - name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - if (dtd.complete) { - declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - if (declEntity->name != name) { - poolDiscard(&dtd.pool); - declEntity = 0; - } - else - poolFinish(&dtd.pool); - } - else { - poolDiscard(&dtd.pool); - declEntity = 0; - } - } - break; - case XML_ROLE_PARAM_ENTITY_NAME: - declEntity = 0; - break; - case XML_ROLE_NOTATION_NAME: - declNotationPublicId = 0; - declNotationName = 0; - if (notationDeclHandler) { - declNotationName = poolStoreString(&tempPool, encoding, s, next); - if (!declNotationName) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declNotationName) { - XML_Char *tem = poolStoreString(&tempPool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declNotationPublicId = tem; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_SYSTEM_ID: - if (declNotationName && notationDeclHandler) { - const XML_Char *systemId - = poolStoreString(&tempPool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!systemId) - return XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - systemId, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_NOTATION_NO_SYSTEM_ID: - if (declNotationPublicId && notationDeclHandler) { - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - 0, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_ERROR: - eventPtr = s; - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - return XML_ERROR_PARAM_ENTITY_REF; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - default: - return XML_ERROR_SYNTAX; - } - case XML_ROLE_GROUP_OPEN: - if (prologState.level >= groupSize) { - if (groupSize) - groupConnector = realloc(groupConnector, groupSize *= 2); - else - groupConnector = malloc(groupSize = 32); - if (!groupConnector) - return XML_ERROR_NO_MEMORY; - } - groupConnector[prologState.level] = 0; - break; - case XML_ROLE_GROUP_SEQUENCE: - if (groupConnector[prologState.level] == '|') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = ','; - break; - case XML_ROLE_GROUP_CHOICE: - if (groupConnector[prologState.level] == ',') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = '|'; - break; - case XML_ROLE_PARAM_ENTITY_REF: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - dtd.complete = 0; - break; - case XML_ROLE_NONE: - switch (tok) { - case XML_TOK_PI: - eventPtr = s; - eventEndPtr = next; - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - eventPtr = s; - eventEndPtr = next; - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - } - break; - } - if (defaultHandler) { - switch (tok) { - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - case XML_TOK_XML_DECL: - break; - default: - eventPtr = s; - eventEndPtr = next; - reportDefault(parser, encoding, s, next); - } - } - s = next; - } - /* not reached */ -} - -static -enum XML_Error epilogProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - processor = epilogProcessor; - eventPtr = s; - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - eventEndPtr = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (defaultHandler) { - eventEndPtr = end; - reportDefault(parser, encoding, s, end); - } - /* fall through */ - case XML_TOK_NONE: - if (nextPtr) - *nextPtr = end; - return XML_ERROR_NONE; - case XML_TOK_PROLOG_S: - if (defaultHandler) - reportDefault(parser, encoding, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - default: - return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; - } - eventPtr = s = next; - } -} - -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); - if (result) - return result; - if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) - poolChop(pool); - if (!poolAppendChar(pool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - return XML_ERROR_NONE; -} - -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - for (;;) { - const char *next; - int tok = XmlAttributeValueTok(enc, ptr, end, &next); - switch (tok) { - case XML_TOK_NONE: - return XML_ERROR_NONE; - case XML_TOK_INVALID: - if (enc == encoding) - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(enc, ptr); - if (n < 0) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - if (!isCdata - && n == 0x20 /* space */ - && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (!poolAppendChar(pool, buf[i])) - return XML_ERROR_NO_MEMORY; - } - } - break; - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, enc, ptr, next)) - return XML_ERROR_NO_MEMORY; - break; - break; - case XML_TOK_TRAILING_CR: - next = ptr + enc->minBytesPerChar; - /* fall through */ - case XML_TOK_ATTRIBUTE_VALUE_S: - case XML_TOK_DATA_NEWLINE: - if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - if (!poolAppendChar(pool, 0x20)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (!poolAppendChar(pool, ch)) - return XML_ERROR_NO_MEMORY; - break; - } - name = poolStoreString(&temp2Pool, enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&temp2Pool); - if (!entity) { - if (dtd.complete) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_UNDEFINED_ENTITY; - } - } - else if (entity->open) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_RECURSIVE_ENTITY_REF; - } - else if (entity->notation) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BINARY_ENTITY_REF; - } - else if (!entity->textPtr) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; - } - else { - enum XML_Error result; - const XML_Char *textEnd = entity->textPtr + entity->textLen; - entity->open = 1; - result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); - entity->open = 0; - if (result) - return result; - } - } - break; - default: - abort(); - } - ptr = next; - } - /* not reached */ -} - -static -enum XML_Error storeEntityValue(XML_Parser parser, - const char *entityTextPtr, - const char *entityTextEnd) -{ - const ENCODING *internalEnc; - STRING_POOL *pool = &(dtd.pool); - entityTextPtr += encoding->minBytesPerChar; - entityTextEnd -= encoding->minBytesPerChar; - internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - for (;;) { - const char *next; - int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next); - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - eventPtr = entityTextPtr; - return XML_ERROR_SYNTAX; - case XML_TOK_NONE: - if (declEntity) { - declEntity->textPtr = pool->start; - declEntity->textLen = pool->ptr - pool->start; - poolFinish(pool); - } - else - poolDiscard(pool); - return XML_ERROR_NONE; - case XML_TOK_ENTITY_REF: - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, encoding, entityTextPtr, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_TRAILING_CR: - next = entityTextPtr + encoding->minBytesPerChar; - /* fall through */ - case XML_TOK_DATA_NEWLINE: - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = 0xA; - break; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(encoding, entityTextPtr); - if (n < 0) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = buf[i]; - } - } - break; - case XML_TOK_PARTIAL: - eventPtr = entityTextPtr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - default: - abort(); - } - entityTextPtr = next; - } - /* not reached */ -} - -static void -normalizeLines(XML_Char *s) -{ - XML_Char *p; - for (;; s++) { - if (*s == XML_T('\0')) - return; - if (*s == 0xD) - break; - } - p = s; - do { - if (*s == 0xD) { - *p++ = 0xA; - if (*++s == 0xA) - s++; - } - else - *p++ = *s++; - } while (*s); - *p = XML_T('\0'); -} - -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - const XML_Char *target; - XML_Char *data; - const char *tem; - if (!processingInstructionHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - start += enc->minBytesPerChar * 2; - tem = start + XmlNameLength(enc, start); - target = poolStoreString(&tempPool, enc, start, tem); - if (!target) - return 0; - poolFinish(&tempPool); - data = poolStoreString(&tempPool, enc, - XmlSkipS(enc, tem), - end - enc->minBytesPerChar*2); - if (!data) - return 0; - normalizeLines(data); - processingInstructionHandler(handlerArg, target, data); - poolClear(&tempPool); - return 1; -} - -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - XML_Char *data; - if (!commentHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - data = poolStoreString(&tempPool, - enc, - start + enc->minBytesPerChar * 4, - end - enc->minBytesPerChar * 3); - if (!data) - return 0; - normalizeLines(data); - commentHandler(handlerArg, data); - poolClear(&tempPool); - return 1; -} - -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) -{ - if (MUST_CONVERT(enc, s)) { - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - do { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - *eventPP = s; - } while (s != end); - } - else - defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); -} - - -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value) -{ - DEFAULT_ATTRIBUTE *att; - if (type->nDefaultAtts == type->allocDefaultAtts) { - if (type->allocDefaultAtts == 0) { - type->allocDefaultAtts = 8; - type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - else { - type->allocDefaultAtts *= 2; - type->defaultAtts = realloc(type->defaultAtts, - type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - if (!type->defaultAtts) - return 0; - } - att = type->defaultAtts + type->nDefaultAtts; - att->id = attId; - att->value = value; - att->isCdata = isCdata; - if (!isCdata) - attId->maybeTokenized = 1; - type->nDefaultAtts += 1; - return 1; -} - -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) -{ - const XML_Char *name; - for (name = elementType->name; *name; name++) { - if (*name == XML_T(':')) { - PREFIX *prefix; - const XML_Char *s; - for (s = elementType->name; s != name; s++) { - if (!poolAppendChar(&dtd.pool, *s)) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - elementType->prefix = prefix; - - } - } - return 1; -} - -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - ATTRIBUTE_ID *id; - const XML_Char *name; - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - name = poolStoreString(&dtd.pool, enc, start, end); - if (!name) - return 0; - ++name; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); - if (!id) - return 0; - if (id->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!ns) - ; - else if (name[0] == 'x' - && name[1] == 'm' - && name[2] == 'l' - && name[3] == 'n' - && name[4] == 's' - && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { - if (name[5] == '\0') - id->prefix = &dtd.defaultPrefix; - else - id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); - id->xmlns = 1; - } - else { - int i; - for (i = 0; name[i]; i++) { - if (name[i] == XML_T(':')) { - int j; - for (j = 0; j < i; j++) { - if (!poolAppendChar(&dtd.pool, name[j])) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (id->prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - break; - } - } - } - } - return id; -} - -#define CONTEXT_SEP XML_T('\f') - -static -const XML_Char *getContext(XML_Parser parser) -{ - HASH_TABLE_ITER iter; - int needSep = 0; - - if (dtd.defaultPrefix.binding) { - int i; - int len; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = dtd.defaultPrefix.binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) - return 0; - needSep = 1; - } - - hashTableIterInit(&iter, &(dtd.prefixes)); - for (;;) { - int i; - int len; - const XML_Char *s; - PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); - if (!prefix) - break; - if (!prefix->binding) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = prefix->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = prefix->binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) - return 0; - needSep = 1; - } - - - hashTableIterInit(&iter, &(dtd.generalEntities)); - for (;;) { - const XML_Char *s; - ENTITY *e = (ENTITY *)hashTableIterNext(&iter); - if (!e) - break; - if (!e->open) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = e->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - needSep = 1; - } - - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - return tempPool.start; -} - -static -int setContext(XML_Parser parser, const XML_Char *context) -{ - const XML_Char *s = context; - - while (*context != XML_T('\0')) { - if (*s == CONTEXT_SEP || *s == XML_T('\0')) { - ENTITY *e; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0); - if (e) - e->open = 1; - if (*s != XML_T('\0')) - s++; - context = s; - poolDiscard(&tempPool); - } - else if (*s == '=') { - PREFIX *prefix; - if (poolLength(&tempPool) == 0) - prefix = &dtd.defaultPrefix; - else { - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&tempPool)) - poolFinish(&tempPool); - else - poolDiscard(&tempPool); - } - for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) - if (!poolAppendChar(&tempPool, *context)) - return 0; - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings)) - return 0; - poolDiscard(&tempPool); - if (*context != XML_T('\0')) - ++context; - s = context; - } - else { - if (!poolAppendChar(&tempPool, *s)) - return 0; - s++; - } - } - return 1; -} - - -static -void normalizePublicId(XML_Char *publicId) -{ - XML_Char *p = publicId; - XML_Char *s; - for (s = publicId; *s; s++) { - switch (*s) { - case 0x20: - case 0xD: - case 0xA: - if (p != publicId && p[-1] != 0x20) - *p++ = 0x20; - break; - default: - *p++ = *s; - } - } - if (p != publicId && p[-1] == 0x20) - --p; - *p = XML_T('\0'); -} - -static int dtdInit(DTD *p) -{ - poolInit(&(p->pool)); - hashTableInit(&(p->generalEntities)); - hashTableInit(&(p->elementTypes)); - hashTableInit(&(p->attributeIds)); - hashTableInit(&(p->prefixes)); - p->complete = 1; - p->standalone = 0; - p->base = 0; - p->defaultPrefix.name = 0; - p->defaultPrefix.binding = 0; - return 1; -} - -static void dtdDestroy(DTD *p) -{ - HASH_TABLE_ITER iter; - hashTableIterInit(&iter, &(p->elementTypes)); - for (;;) { - ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!e) - break; - if (e->allocDefaultAtts != 0) - free(e->defaultAtts); - } - hashTableDestroy(&(p->generalEntities)); - hashTableDestroy(&(p->elementTypes)); - hashTableDestroy(&(p->attributeIds)); - hashTableDestroy(&(p->prefixes)); - poolDestroy(&(p->pool)); -} - -/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise. -The new DTD has already been initialized. */ - -static int dtdCopy(DTD *newDtd, const DTD *oldDtd) -{ - HASH_TABLE_ITER iter; - - if (oldDtd->base) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldDtd->base); - if (!tem) - return 0; - newDtd->base = tem; - } - - /* Copy the prefix table. */ - - hashTableIterInit(&iter, &(oldDtd->prefixes)); - for (;;) { - const XML_Char *name; - const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); - if (!oldP) - break; - name = poolCopyString(&(newDtd->pool), oldP->name); - if (!name) - return 0; - if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) - return 0; - } - - hashTableIterInit(&iter, &(oldDtd->attributeIds)); - - /* Copy the attribute id table. */ - - for (;;) { - ATTRIBUTE_ID *newA; - const XML_Char *name; - const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); - - if (!oldA) - break; - /* Remember to allocate the scratch byte before the name. */ - if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) - return 0; - name = poolCopyString(&(newDtd->pool), oldA->name); - if (!name) - return 0; - ++name; - newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); - if (!newA) - return 0; - newA->maybeTokenized = oldA->maybeTokenized; - if (oldA->prefix) { - newA->xmlns = oldA->xmlns; - if (oldA->prefix == &oldDtd->defaultPrefix) - newA->prefix = &newDtd->defaultPrefix; - else - newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0); - } - } - - /* Copy the element type table. */ - - hashTableIterInit(&iter, &(oldDtd->elementTypes)); - - for (;;) { - int i; - ELEMENT_TYPE *newE; - const XML_Char *name; - const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(&(newDtd->pool), oldE->name); - if (!name) - return 0; - newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); - if (!newE) - return 0; - if (oldE->nDefaultAtts) { - newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); - if (!newE->defaultAtts) - return 0; - } - newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; - if (oldE->prefix) - newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0); - for (i = 0; i < newE->nDefaultAtts; i++) { - newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); - newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; - if (oldE->defaultAtts[i].value) { - newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); - if (!newE->defaultAtts[i].value) - return 0; - } - else - newE->defaultAtts[i].value = 0; - } - } - - /* Copy the entity table. */ - - hashTableIterInit(&iter, &(oldDtd->generalEntities)); - - for (;;) { - ENTITY *newE; - const XML_Char *name; - const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); - if (!oldE) - break; - name = poolCopyString(&(newDtd->pool), oldE->name); - if (!name) - return 0; - newE = (ENTITY *)lookup(&(newDtd->generalEntities), name, sizeof(ENTITY)); - if (!newE) - return 0; - if (oldE->systemId) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->systemId); - if (!tem) - return 0; - newE->systemId = tem; - if (oldE->base) { - if (oldE->base == oldDtd->base) - newE->base = newDtd->base; - tem = poolCopyString(&(newDtd->pool), oldE->base); - if (!tem) - return 0; - newE->base = tem; - } - } - else { - const XML_Char *tem = poolCopyStringN(&(newDtd->pool), oldE->textPtr, oldE->textLen); - if (!tem) - return 0; - newE->textPtr = tem; - newE->textLen = oldE->textLen; - } - if (oldE->notation) { - const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->notation); - if (!tem) - return 0; - newE->notation = tem; - } - } - - newDtd->complete = oldDtd->complete; - newDtd->standalone = oldDtd->standalone; - return 1; -} - -static -void poolInit(STRING_POOL *pool) -{ - pool->blocks = 0; - pool->freeBlocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolClear(STRING_POOL *pool) -{ - if (!pool->freeBlocks) - pool->freeBlocks = pool->blocks; - else { - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - p->next = pool->freeBlocks; - pool->freeBlocks = p; - p = tem; - } - } - pool->blocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolDestroy(STRING_POOL *pool) -{ - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - free(p); - p = tem; - } - pool->blocks = 0; - p = pool->freeBlocks; - while (p) { - BLOCK *tem = p->next; - free(p); - p = tem; - } - pool->freeBlocks = 0; - pool->ptr = 0; - pool->start = 0; - pool->end = 0; -} - -static -XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!pool->ptr && !poolGrow(pool)) - return 0; - for (;;) { - XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); - if (ptr == end) - break; - if (!poolGrow(pool)) - return 0; - } - return pool->start; -} - -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) -{ - do { - if (!poolAppendChar(pool, *s)) - return 0; - } while (*s++); - s = pool->start; - poolFinish(pool); - return s; -} - -static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) -{ - if (!pool->ptr && !poolGrow(pool)) - return 0; - for (; n > 0; --n, s++) { - if (!poolAppendChar(pool, *s)) - return 0; - - } - s = pool->start; - poolFinish(pool); - return s; -} - -static -XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!poolAppend(pool, enc, ptr, end)) - return 0; - if (pool->ptr == pool->end && !poolGrow(pool)) - return 0; - *(pool->ptr)++ = 0; - return pool->start; -} - -static -int poolGrow(STRING_POOL *pool) -{ - if (pool->freeBlocks) { - if (pool->start == 0) { - pool->blocks = pool->freeBlocks; - pool->freeBlocks = pool->freeBlocks->next; - pool->blocks->next = 0; - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - pool->ptr = pool->start; - return 1; - } - if (pool->end - pool->start < pool->freeBlocks->size) { - BLOCK *tem = pool->freeBlocks->next; - pool->freeBlocks->next = pool->blocks; - pool->blocks = pool->freeBlocks; - pool->freeBlocks = tem; - memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - return 1; - } - } - if (pool->blocks && pool->start == pool->blocks->s) { - int blockSize = (pool->end - pool->start)*2; - pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!pool->blocks) - return 0; - pool->blocks->size = blockSize; - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + blockSize; - } - else { - BLOCK *tem; - int blockSize = pool->end - pool->start; - if (blockSize < INIT_BLOCK_SIZE) - blockSize = INIT_BLOCK_SIZE; - else - blockSize *= 2; - tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!tem) - return 0; - tem->size = blockSize; - tem->next = pool->blocks; - pool->blocks = tem; - memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); - pool->ptr = tem->s + (pool->ptr - pool->start); - pool->start = tem->s; - pool->end = tem->s + blockSize; - } - return 1; -}
--- a/src/protocols/jabber/xmlparse.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlParse_INCLUDED -#define XmlParse_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLPARSEAPI -#define XMLPARSEAPI /* as nothing */ -#endif - -typedef void *XML_Parser; - -#ifdef XML_UNICODE_WCHAR_T - -/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t -uses Unicode. */ -/* Information is UTF-16 encoded as wchar_ts */ - -#ifndef XML_UNICODE -#define XML_UNICODE -#endif - -#include <stddef.h> -typedef wchar_t XML_Char; -typedef wchar_t XML_LChar; - -#else /* not XML_UNICODE_WCHAR_T */ - -#ifdef XML_UNICODE - -/* Information is UTF-16 encoded as unsigned shorts */ -typedef unsigned short XML_Char; -typedef char XML_LChar; - -#else /* not XML_UNICODE */ - -/* Information is UTF-8 encoded. */ -typedef char XML_Char; -typedef char XML_LChar; - -#endif /* not XML_UNICODE */ - -#endif /* not XML_UNICODE_WCHAR_T */ - - -/* Constructs a new parser; encoding is the encoding specified by the external -protocol or null if there is none specified. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreate(const XML_Char *encoding); - -/* Constructs a new parser and namespace processor. Element type names -and attribute names that belong to a namespace will be expanded; -unprefixed attribute names are never expanded; unprefixed element type -names are expanded only if there is a default namespace. The expanded -name is the concatenation of the namespace URI, the namespace separator character, -and the local part of the name. If the namespace separator is '\0' then -the namespace URI and the local part will be concatenated without any -separator. When a namespace is not declared, the name and prefix will be -passed through without expansion. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); - - -/* atts is array of name/value pairs, terminated by 0; - names and values are 0 terminated. */ - -typedef void (*XML_StartElementHandler)(void *userData, - const XML_Char *name, - const XML_Char **atts); - -typedef void (*XML_EndElementHandler)(void *userData, - const XML_Char *name); - -/* s is not 0 terminated. */ -typedef void (*XML_CharacterDataHandler)(void *userData, - const XML_Char *s, - int len); - -/* target and data are 0 terminated */ -typedef void (*XML_ProcessingInstructionHandler)(void *userData, - const XML_Char *target, - const XML_Char *data); - -/* data is 0 terminated */ -typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); - -typedef void (*XML_StartCdataSectionHandler)(void *userData); -typedef void (*XML_EndCdataSectionHandler)(void *userData); - -/* This is called for any characters in the XML document for -which there is no applicable handler. This includes both -characters that are part of markup which is of a kind that is -not reported (comments, markup declarations), or characters -that are part of a construct which could be reported but -for which no handler has been supplied. The characters are passed -exactly as they were in the XML document except that -they will be encoded in UTF-8. Line boundaries are not normalized. -Note that a byte order mark character is not passed to the default handler. -There are no guarantees about how characters are divided between calls -to the default handler: for example, a comment might be split between -multiple calls. */ - -typedef void (*XML_DefaultHandler)(void *userData, - const XML_Char *s, - int len); - -/* This is called for a declaration of an unparsed (NDATA) -entity. The base argument is whatever was set by XML_SetBase. -The entityName, systemId and notationName arguments will never be null. -The other arguments may be. */ - -typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); - -/* This is called for a declaration of notation. -The base argument is whatever was set by XML_SetBase. -The notationName will never be null. The other arguments can be. */ - -typedef void (*XML_NotationDeclHandler)(void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* When namespace processing is enabled, these are called once for -each namespace declaration. The call to the start and end element -handlers occur between the calls to the start and end namespace -declaration handlers. For an xmlns attribute, prefix will be null. -For an xmlns="" attribute, uri will be null. */ - -typedef void (*XML_StartNamespaceDeclHandler)(void *userData, - const XML_Char *prefix, - const XML_Char *uri); - -typedef void (*XML_EndNamespaceDeclHandler)(void *userData, - const XML_Char *prefix); - -/* This is called if the document is not standalone (it has an -external subset or a reference to a parameter entity, but does not -have standalone="yes"). If this handler returns 0, then processing -will not continue, and the parser will return a -XML_ERROR_NOT_STANDALONE error. */ - -typedef int (*XML_NotStandaloneHandler)(void *userData); - -/* This is called for a reference to an external parsed general entity. -The referenced entity is not automatically parsed. -The application can parse it immediately or later using -XML_ExternalEntityParserCreate. -The parser argument is the parser parsing the entity containing the reference; -it can be passed as the parser argument to XML_ExternalEntityParserCreate. -The systemId argument is the system identifier as specified in the entity declaration; -it will not be null. -The base argument is the system identifier that should be used as the base for -resolving systemId if systemId was relative; this is set by XML_SetBase; -it may be null. -The publicId argument is the public identifier as specified in the entity declaration, -or null if none was specified; the whitespace in the public identifier -will have been normalized as required by the XML spec. -The context argument specifies the parsing context in the format -expected by the context argument to -XML_ExternalEntityParserCreate; context is valid only until the handler -returns, so if the referenced entity is to be parsed later, it must be copied. -The handler should return 0 if processing should not continue because of -a fatal error in the handling of the external entity. -In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING -error. -Note that unlike other handlers the first argument is the parser, not userData. */ - -typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* This structure is filled in by the XML_UnknownEncodingHandler -to provide information to the parser about encodings that are unknown -to the parser. -The map[b] member gives information about byte sequences -whose first byte is b. -If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. -If map[b] is -1, then the byte sequence is malformed. -If map[b] is -n, where n >= 2, then b is the first byte of an n-byte -sequence that encodes a single Unicode scalar value. -The data member will be passed as the first argument to the convert function. -The convert function is used to convert multibyte sequences; -s will point to a n-byte sequence where map[(unsigned char)*s] == -n. -The convert function must return the Unicode scalar value -represented by this byte sequence or -1 if the byte sequence is malformed. -The convert function may be null if the encoding is a single-byte encoding, -that is if map[b] >= -1 for all bytes b. -When the parser is finished with the encoding, then if release is not null, -it will call release passing it the data member; -once release has been called, the convert function will not be called again. - -Expat places certain restrictions on the encodings that are supported -using this mechanism. - -1. Every ASCII character that can appear in a well-formed XML document, -other than the characters - - $@\^`{}~ - -must be represented by a single byte, and that byte must be the -same byte that represents that character in ASCII. - -2. No character may require more than 4 bytes to encode. - -3. All characters encoded must have Unicode scalar values <= 0xFFFF, -(ie characters that would be encoded by surrogates in UTF-16 -are not allowed). Note that this restriction doesn't apply to -the built-in support for UTF-8 and UTF-16. - -4. No Unicode character may be encoded by more than one distinct sequence -of bytes. */ - -typedef struct { - int map[256]; - void *data; - int (*convert)(void *data, const char *s); - void (*release)(void *data); -} XML_Encoding; - -/* This is called for an encoding that is unknown to the parser. -The encodingHandlerData argument is that which was passed as the -second argument to XML_SetUnknownEncodingHandler. -The name argument gives the name of the encoding as specified in -the encoding declaration. -If the callback can provide information about the encoding, -it must fill in the XML_Encoding structure, and return 1. -Otherwise it must return 0. -If info does not describe a suitable encoding, -then the parser will return an XML_UNKNOWN_ENCODING error. */ - -typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info); - -void XMLPARSEAPI -XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end); - -void XMLPARSEAPI -XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler); - -void XMLPARSEAPI -XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler); -void XMLPARSEAPI -XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler); - -void XMLPARSEAPI -XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end); - -/* This sets the default handler and also inhibits expansion of internal entities. -The entity reference will be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler); - -/* This sets the default handler but does not inhibit expansion of internal entities. -The entity reference will not be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler); - -void XMLPARSEAPI -XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler); - -void XMLPARSEAPI -XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler); - -void XMLPARSEAPI -XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end); - -void XMLPARSEAPI -XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler); - -void XMLPARSEAPI -XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler); - -/* If a non-null value for arg is specified here, then it will be passed -as the first argument to the external entity ref handler instead -of the parser object. */ -void XMLPARSEAPI -XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); - -void XMLPARSEAPI -XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *encodingHandlerData); - -/* This can be called within a handler for a start element, end element, -processing instruction or character data. It causes the corresponding -markup to be passed to the default handler. */ -void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser); - -/* This value is passed as the userData argument to callbacks. */ -void XMLPARSEAPI -XML_SetUserData(XML_Parser parser, void *userData); - -/* Returns the last value set by XML_SetUserData or null. */ -#define XML_GetUserData(parser) (*(void **)(parser)) - -/* This is equivalent to supplying an encoding argument -to XML_CreateParser. It must not be called after XML_Parse -or XML_ParseBuffer. */ - -int XMLPARSEAPI -XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); - -/* If this function is called, then the parser will be passed -as the first argument to callbacks instead of userData. -The userData will still be accessible using XML_GetUserData. */ - -void XMLPARSEAPI -XML_UseParserAsHandlerArg(XML_Parser parser); - -/* Sets the base to be used for resolving relative URIs in system identifiers in -declarations. Resolving relative identifiers is left to the application: -this value will be passed through as the base argument to the -XML_ExternalEntityRefHandler, XML_NotationDeclHandler -and XML_UnparsedEntityDeclHandler. The base argument will be copied. -Returns zero if out of memory, non-zero otherwise. */ - -int XMLPARSEAPI -XML_SetBase(XML_Parser parser, const XML_Char *base); - -const XML_Char XMLPARSEAPI * -XML_GetBase(XML_Parser parser); - -/* Returns the number of the attributes passed in last call to the -XML_StartElementHandler that were specified in the start-tag rather -than defaulted. */ - -int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser); - -/* Parses some input. Returns 0 if a fatal error is detected. -The last call to XML_Parse must have isFinal true; -len may be zero for this call (or any other). */ -int XMLPARSEAPI -XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); - -void XMLPARSEAPI * -XML_GetBuffer(XML_Parser parser, int len); - -int XMLPARSEAPI -XML_ParseBuffer(XML_Parser parser, int len, int isFinal); - -/* Creates an XML_Parser object that can parse an external general entity; -context is a '\0'-terminated string specifying the parse context; -encoding is a '\0'-terminated string giving the name of the externally specified encoding, -or null if there is no externally specified encoding. -The context string consists of a sequence of tokens separated by formfeeds (\f); -a token consisting of a name specifies that the general entity of the name -is open; a token of the form prefix=uri specifies the namespace for a particular -prefix; a token of the form =uri specifies the default namespace. -This can be called at any point after the first call to an ExternalEntityRefHandler -so longer as the parser has not yet been freed. -The new parser is completely independent and may safely be used in a separate thread. -The handlers and userData are initialized from the parser argument. -Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ -XML_Parser XMLPARSEAPI -XML_ExternalEntityParserCreate(XML_Parser parser, - const XML_Char *context, - const XML_Char *encoding); - -enum XML_Error { - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE -}; - -/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode -returns information about the error. */ - -enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser); - -/* These functions return information about the current parse location. -They may be called when XML_Parse or XML_ParseBuffer return 0; -in this case the location is the location of the character at which -the error was detected. -They may also be called from any other callback called to report -some parse event; in this the location is the location of the first -of the sequence of characters that generated the event. */ - -int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser); -int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser); -long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser); - -/* Return the number of bytes in the current event. -Returns 0 if the event is in an internal entity. */ - -int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser); - -/* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex - -/* Frees memory used by the parser. */ -void XMLPARSEAPI -XML_ParserFree(XML_Parser parser); - -/* Returns a string describing the error. */ -const XML_LChar XMLPARSEAPI *XML_ErrorString(int code); - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlParse_INCLUDED */
--- a/src/protocols/jabber/xmlrole.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1104 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmlrole.h" - -/* Doesn't check: - - that ,| are not mixed in a model group - content of literals - -*/ - -#ifndef MIN_BYTES_PER_CHAR -#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) -#endif - -typedef int PROLOG_HANDLER(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - -static PROLOG_HANDLER -prolog0, prolog1, prolog2, -doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, -internalSubset, -entity0, entity1, entity2, entity3, entity4, entity5, entity6, -entity7, entity8, entity9, -notation0, notation1, notation2, notation3, notation4, -attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, -attlist7, attlist8, attlist9, -element0, element1, element2, element3, element4, element5, element6, -element7, -declClose, -error; - -static -int syntaxError(PROLOG_STATE *); - -static -int prolog0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_XML_DECL: - state->handler = prolog1; - return XML_ROLE_XML_DECL; - case XML_TOK_PI: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_COMMENT: - state->handler = prolog1; - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int doctype0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = doctype1; - return XML_ROLE_DOCTYPE_NAME; - } - return syntaxError(state); -} - -static -int doctype1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = doctype3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = doctype2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int doctype2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype3; - return XML_ROLE_DOCTYPE_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int doctype3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype4; - return XML_ROLE_DOCTYPE_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int doctype4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int doctype5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int internalSubset(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ENTITY")) { - state->handler = entity0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ATTLIST")) { - state->handler = attlist0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ELEMENT")) { - state->handler = element0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "NOTATION")) { - state->handler = notation0; - return XML_ROLE_NONE; - } - break; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_PARAM_ENTITY_REF: - return XML_ROLE_PARAM_ENTITY_REF; - case XML_TOK_CLOSE_BRACKET: - state->handler = doctype5; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int entity0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PERCENT: - state->handler = entity1; - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity2; - return XML_ROLE_GENERAL_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity7; - return XML_ROLE_PARAM_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity4; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity3; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity4; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - - -static -int entity4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity5; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int entity5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "NDATA")) { - state->handler = entity6; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int entity6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = declClose; - return XML_ROLE_ENTITY_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int entity7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity9; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity8; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity9; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int entity9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = notation1; - return XML_ROLE_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int notation1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = notation3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = notation2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int notation2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = notation4; - return XML_ROLE_NOTATION_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int notation3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NOTATION_NO_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int attlist0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist1; - return XML_ROLE_ATTLIST_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int attlist1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist2; - return XML_ROLE_ATTRIBUTE_NAME; - } - return syntaxError(state); -} - -static -int attlist2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - { - static const char *types[] = { - "CDATA", - "ID", - "IDREF", - "IDREFS", - "ENTITY", - "ENTITIES", - "NMTOKEN", - "NMTOKENS", - }; - int i; - for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) - if (XmlNameMatchesAscii(enc, ptr, types[i])) { - state->handler = attlist8; - return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; - } - } - if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) { - state->handler = attlist5; - return XML_ROLE_NONE; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NMTOKEN: - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist4; - return XML_ROLE_ATTRIBUTE_ENUM_VALUE; - } - return syntaxError(state); -} - -static -int attlist4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - - -static -int attlist6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = attlist7; - return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; - } - return syntaxError(state); -} - -static -int attlist7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -/* default value */ -static -int attlist8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "IMPLIED")) { - state->handler = attlist1; - return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "REQUIRED")) { - state->handler = attlist1; - return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "FIXED")) { - state->handler = attlist9; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int attlist9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_FIXED_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int element0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element1; - return XML_ROLE_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int element1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_EMPTY; - } - if (XmlNameMatchesAscii(enc, ptr, "ANY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_ANY; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = element2; - state->level = 1; - return XML_ROLE_GROUP_OPEN; - } - return syntaxError(state); -} - -static -int element2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "PCDATA")) { - state->handler = element3; - return XML_ROLE_CONTENT_PCDATA; - } - break; - case XML_TOK_OPEN_PAREN: - state->level = 2; - state->handler = element6; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element5; - return XML_ROLE_CONTENT_ELEMENT; - } - return syntaxError(state); -} - -static -int element5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->level += 1; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_CLOSE_PAREN_QUESTION: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_OPT; - case XML_TOK_CLOSE_PAREN_PLUS: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_PLUS; - case XML_TOK_COMMA: - state->handler = element6; - return XML_ROLE_GROUP_SEQUENCE; - case XML_TOK_OR: - state->handler = element6; - return XML_ROLE_GROUP_CHOICE; - } - return syntaxError(state); -} - -static -int declClose(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -#if 0 - -static -int ignore(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return 0; - default: - return XML_ROLE_NONE; - } - return syntaxError(state); -} -#endif - -static -int error(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - return XML_ROLE_NONE; -} - -static -int syntaxError(PROLOG_STATE *state) -{ - state->handler = error; - return XML_ROLE_ERROR; -} - -void XmlPrologStateInit(PROLOG_STATE *state) -{ - state->handler = prolog0; -}
--- a/src/protocols/jabber/xmlrole.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 - -#include "xmltok.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - XML_ROLE_ERROR = -1, - XML_ROLE_NONE = 0, - XML_ROLE_XML_DECL, - XML_ROLE_INSTANCE_START, - XML_ROLE_DOCTYPE_NAME, - XML_ROLE_DOCTYPE_SYSTEM_ID, - XML_ROLE_DOCTYPE_PUBLIC_ID, - XML_ROLE_DOCTYPE_CLOSE, - XML_ROLE_GENERAL_ENTITY_NAME, - XML_ROLE_PARAM_ENTITY_NAME, - XML_ROLE_ENTITY_VALUE, - XML_ROLE_ENTITY_SYSTEM_ID, - XML_ROLE_ENTITY_PUBLIC_ID, - XML_ROLE_ENTITY_NOTATION_NAME, - XML_ROLE_NOTATION_NAME, - XML_ROLE_NOTATION_SYSTEM_ID, - XML_ROLE_NOTATION_NO_SYSTEM_ID, - XML_ROLE_NOTATION_PUBLIC_ID, - XML_ROLE_ATTRIBUTE_NAME, - XML_ROLE_ATTRIBUTE_TYPE_CDATA, - XML_ROLE_ATTRIBUTE_TYPE_ID, - XML_ROLE_ATTRIBUTE_TYPE_IDREF, - XML_ROLE_ATTRIBUTE_TYPE_IDREFS, - XML_ROLE_ATTRIBUTE_TYPE_ENTITY, - XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, - XML_ROLE_ATTRIBUTE_ENUM_VALUE, - XML_ROLE_ATTRIBUTE_NOTATION_VALUE, - XML_ROLE_ATTLIST_ELEMENT_NAME, - XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, - XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, - XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, - XML_ROLE_FIXED_ATTRIBUTE_VALUE, - XML_ROLE_ELEMENT_NAME, - XML_ROLE_CONTENT_ANY, - XML_ROLE_CONTENT_EMPTY, - XML_ROLE_CONTENT_PCDATA, - XML_ROLE_GROUP_OPEN, - XML_ROLE_GROUP_CLOSE, - XML_ROLE_GROUP_CLOSE_REP, - XML_ROLE_GROUP_CLOSE_OPT, - XML_ROLE_GROUP_CLOSE_PLUS, - XML_ROLE_GROUP_CHOICE, - XML_ROLE_GROUP_SEQUENCE, - XML_ROLE_CONTENT_ELEMENT, - XML_ROLE_CONTENT_ELEMENT_REP, - XML_ROLE_CONTENT_ELEMENT_OPT, - XML_ROLE_CONTENT_ELEMENT_PLUS, - XML_ROLE_PARAM_ENTITY_REF -}; - -typedef struct prolog_state { - int (*handler)(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - unsigned level; -} PROLOG_STATE; - -void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *); - -#define XmlTokenRole(state, tok, ptr, end, enc) \ - (((state)->handler)(state, tok, ptr, end, enc)) - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlRole_INCLUDED */
--- a/src/protocols/jabber/xmltok.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1518 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmltok.h" -#include "nametab.h" - -#define VTABLE1 \ - { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \ - { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ - PREFIX(sameName), \ - PREFIX(nameMatchesAscii), \ - PREFIX(nameLength), \ - PREFIX(skipS), \ - PREFIX(getAtts), \ - PREFIX(charRefNumber), \ - PREFIX(predefinedEntityName), \ - PREFIX(updatePosition), \ - PREFIX(isPublicId) - -#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) - -#define UCS2_GET_NAMING(pages, hi, lo) \ - (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) - -/* A 2 byte UTF-8 representation splits the characters 11 bits -between the bottom 5 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING2(pages, byte) \ - (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ - + ((((byte)[0]) & 3) << 1) \ - + ((((byte)[1]) >> 5) & 1)] \ - & (1 << (((byte)[1]) & 0x1F))) - -/* A 3 byte UTF-8 representation splits the characters 16 bits -between the bottom 4, 6 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING3(pages, byte) \ - (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ - + ((((byte)[1]) >> 2) & 0xF)] \ - << 3) \ - + ((((byte)[1]) & 3) << 1) \ - + ((((byte)[2]) >> 5) & 1)] \ - & (1 << (((byte)[2]) & 0x1F))) - -#define UTF8_GET_NAMING(pages, p, n) \ - ((n) == 2 \ - ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ - : ((n) == 3 \ - ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ - : 0)) - -#define UTF8_INVALID3(p) \ - ((*p) == 0xED \ - ? (((p)[1] & 0x20) != 0) \ - : ((*p) == 0xEF \ - ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ - : 0)) - -#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) - -static -int isNever(const ENCODING *enc, const char *p) -{ - return 0; -} - -static -int utf8_isName2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); -} - -static -int utf8_isName3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); -} - -#define utf8_isName4 isNever - -static -int utf8_isNmstrt2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); -} - -static -int utf8_isNmstrt3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); -} - -#define utf8_isNmstrt4 isNever - -#define utf8_isInvalid2 isNever - -static -int utf8_isInvalid3(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID3((const unsigned char *)p); -} - -static -int utf8_isInvalid4(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID4((const unsigned char *)p); -} - -struct normal_encoding { - ENCODING enc; - unsigned char type[256]; -#ifdef XML_MIN_SIZE - int (*byteType)(const ENCODING *, const char *); - int (*isNameMin)(const ENCODING *, const char *); - int (*isNmstrtMin)(const ENCODING *, const char *); - int (*byteToAscii)(const ENCODING *, const char *); - int (*charMatches)(const ENCODING *, const char *, int); -#endif /* XML_MIN_SIZE */ - int (*isName2)(const ENCODING *, const char *); - int (*isName3)(const ENCODING *, const char *); - int (*isName4)(const ENCODING *, const char *); - int (*isNmstrt2)(const ENCODING *, const char *); - int (*isNmstrt3)(const ENCODING *, const char *); - int (*isNmstrt4)(const ENCODING *, const char *); - int (*isInvalid2)(const ENCODING *, const char *); - int (*isInvalid3)(const ENCODING *, const char *); - int (*isInvalid4)(const ENCODING *, const char *); -}; - -#ifdef XML_MIN_SIZE - -#define STANDARD_VTABLE(E) \ - E ## byteType, \ - E ## isNameMin, \ - E ## isNmstrtMin, \ - E ## byteToAscii, \ - E ## charMatches, - -#else - -#define STANDARD_VTABLE(E) /* as nothing */ - -#endif - -#define NORMAL_VTABLE(E) \ - E ## isName2, \ - E ## isName3, \ - E ## isName4, \ - E ## isNmstrt2, \ - E ## isNmstrt3, \ - E ## isNmstrt4, \ - E ## isInvalid2, \ - E ## isInvalid3, \ - E ## isInvalid4 - -static int checkCharRefNumber(int); - -#include "xmltok_impl.h" - -#ifdef XML_MIN_SIZE -#define sb_isNameMin isNever -#define sb_isNmstrtMin isNever -#endif - -#ifdef XML_MIN_SIZE -#define MINBPC(enc) ((enc)->minBytesPerChar) -#else -/* minimum bytes per character */ -#define MINBPC(enc) 1 -#endif - -#define SB_BYTE_TYPE(enc, p) \ - (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) - -#ifdef XML_MIN_SIZE -static -int sb_byteType(const ENCODING *enc, const char *p) -{ - return SB_BYTE_TYPE(enc, p); -} -#define BYTE_TYPE(enc, p) \ - (((const struct normal_encoding *)(enc))->byteType(enc, p)) -#else -#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) -#endif - -#ifdef XML_MIN_SIZE -#define BYTE_TO_ASCII(enc, p) \ - (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) -static -int sb_byteToAscii(const ENCODING *enc, const char *p) -{ - return *p; -} -#else -#define BYTE_TO_ASCII(enc, p) (*p) -#endif - -#define IS_NAME_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) -#define IS_NMSTRT_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) -#define IS_INVALID_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) - -#ifdef XML_MIN_SIZE -#define IS_NAME_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) -#else -#define IS_NAME_CHAR_MINBPC(enc, p) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) -#endif - -#ifdef XML_MIN_SIZE -#define CHAR_MATCHES(enc, p, c) \ - (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) -static -int sb_charMatches(const ENCODING *enc, const char *p, int c) -{ - return *p == c; -} -#else -/* c is an ASCII character */ -#define CHAR_MATCHES(enc, p, c) (*(p) == c) -#endif - -#define PREFIX(ident) normal_ ## ident -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ - UTF8_cval1 = 0x00, - UTF8_cval2 = 0xc0, - UTF8_cval3 = 0xe0, - UTF8_cval4 = 0xf0 -}; - -static -void utf8_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char *to; - const char *from; - if (fromLim - *fromP > toLim - *toP) { - /* Avoid copying partial characters. */ - for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) - if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) - break; - } - for (to = *toP, from = *fromP; from != fromLim; from++, to++) - *to = *from; - *fromP = from; - *toP = to; -} - -static -void utf8_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - unsigned short *to = *toP; - const char *from = *fromP; - while (from != fromLim && to != toLim) { - switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { - case BT_LEAD2: - *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); - from += 2; - break; - case BT_LEAD3: - *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); - from += 3; - break; - case BT_LEAD4: - { - unsigned long n; - if (to + 1 == toLim) - break; - n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); - n -= 0x10000; - to[0] = (unsigned short)((n >> 10) | 0xD800); - to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); - to += 2; - from += 4; - } - break; - default: - *to++ = *from++; - break; - } - } - *fromP = from; - *toP = to; -} - -#ifdef XML_NS -static const struct normal_encoding utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; -#endif - -static const struct normal_encoding utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#ifdef XML_NS - -static const struct normal_encoding internal_utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "iasciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#endif - -static const struct normal_encoding internal_utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -static -void latin1_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - for (;;) { - unsigned char c; - if (*fromP == fromLim) - break; - c = (unsigned char)**fromP; - if (c & 0x80) { - if (toLim - *toP < 2) - break; - *(*toP)++ = ((c >> 6) | UTF8_cval2); - *(*toP)++ = ((c & 0x3f) | 0x80); - (*fromP)++; - } - else { - if (*toP == toLim) - break; - *(*toP)++ = *(*fromP)++; - } - } -} - -static -void latin1_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = (unsigned char)*(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding latin1_encoding_ns = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding latin1_encoding = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -static -void ascii_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = *(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding ascii_encoding_ns = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding ascii_encoding = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -static int unicode_byte_type(char hi, char lo) -{ - switch ((unsigned char)hi) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: - return BT_LEAD4; -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return BT_TRAIL; - case 0xFF: - switch ((unsigned char)lo) { - case 0xFF: - case 0xFE: - return BT_NONXML; - } - break; - } - return BT_NONASCII; -} - -#define DEFINE_UTF16_TO_UTF8(E) \ -static \ -void E ## toUtf8(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - char **toP, const char *toLim) \ -{ \ - const char *from; \ - for (from = *fromP; from != fromLim; from += 2) { \ - int plane; \ - unsigned char lo2; \ - unsigned char lo = GET_LO(from); \ - unsigned char hi = GET_HI(from); \ - switch (hi) { \ - case 0: \ - if (lo < 0x80) { \ - if (*toP == toLim) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = lo; \ - break; \ - } \ - /* fall through */ \ - case 0x1: case 0x2: case 0x3: \ - case 0x4: case 0x5: case 0x6: case 0x7: \ - if (toLim - *toP < 2) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - default: \ - if (toLim - *toP < 3) { \ - *fromP = from; \ - return; \ - } \ - /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ - *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ - *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ - if (toLim - *toP < 4) { \ - *fromP = from; \ - return; \ - } \ - plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ - *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ - *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ - from += 2; \ - lo2 = GET_LO(from); \ - *(*toP)++ = (((lo & 0x3) << 4) \ - | ((GET_HI(from) & 0x3) << 2) \ - | (lo2 >> 6) \ - | 0x80); \ - *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ - break; \ - } \ - } \ - *fromP = from; \ -} - -#define DEFINE_UTF16_TO_UTF16(E) \ -static \ -void E ## toUtf16(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - unsigned short **toP, const unsigned short *toLim) \ -{ \ - /* Avoid copying first half only of surrogate */ \ - if (fromLim - *fromP > ((toLim - *toP) << 1) \ - && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ - fromLim -= 2; \ - for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ - *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ -} - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) -#define GET_LO(ptr) ((unsigned char)(ptr)[0]) -#define GET_HI(ptr) ((unsigned char)(ptr)[1]) - -DEFINE_UTF16_TO_UTF8(little2_) -DEFINE_UTF16_TO_UTF16(little2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) -#define GET_LO(ptr) ((unsigned char)(ptr)[1]) -#define GET_HI(ptr) ((unsigned char)(ptr)[0]) - -DEFINE_UTF16_TO_UTF8(big2_) -DEFINE_UTF16_TO_UTF16(big2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define LITTLE2_BYTE_TYPE(enc, p) \ - ((p)[1] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ - : unicode_byte_type((p)[1], (p)[0])) -#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) -#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) -#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) -#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) - -#ifdef XML_MIN_SIZE - -static -int little2_byteType(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TYPE(enc, p); -} - -static -int little2_byteToAscii(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TO_ASCII(enc, p); -} - -static -int little2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return LITTLE2_CHAR_MATCHES(enc, p, c); -} - -static -int little2_isNameMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int little2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) little2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding little2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding little2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#if XML_BYTE_ORDER != 21 - -#ifdef XML_NS - -static const struct normal_encoding internal_little2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding internal_little2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - - -#define BIG2_BYTE_TYPE(enc, p) \ - ((p)[0] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ - : unicode_byte_type((p)[0], (p)[1])) -#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) -#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) -#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) -#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) - -#ifdef XML_MIN_SIZE - -static -int big2_byteType(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TYPE(enc, p); -} - -static -int big2_byteToAscii(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TO_ASCII(enc, p); -} - -static -int big2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return BIG2_CHAR_MATCHES(enc, p, c); -} - -static -int big2_isNameMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int big2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) big2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding big2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding big2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#if XML_BYTE_ORDER != 12 - -#ifdef XML_NS - -static const struct normal_encoding internal_big2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding internal_big2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -#undef PREFIX - -static -int streqci(const char *s1, const char *s2) -{ - for (;;) { - char c1 = *s1++; - char c2 = *s2++; - if ('a' <= c1 && c1 <= 'z') - c1 += 'A' - 'a'; - if ('a' <= c2 && c2 <= 'z') - c2 += 'A' - 'a'; - if (c1 != c2) - return 0; - if (!c1) - break; - } - return 1; -} - -static -void initUpdatePosition(const ENCODING *enc, const char *ptr, - const char *end, POSITION *pos) -{ - normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); -} - -static -int toAscii(const ENCODING *enc, const char *ptr, const char *end) -{ - char buf[1]; - char *p = buf; - XmlUtf8Convert(enc, &ptr, end, &p, p + 1); - if (p == buf) - return -1; - else - return buf[0]; -} - -static -int isSpace(int c) -{ - switch (c) { - case 0x20: - case 0xD: - case 0xA: - case 0x9: - return 1; - } - return 0; -} - -/* Return 1 if there's just optional white space -or there's an S followed by name=val. */ -static -int parsePseudoAttribute(const ENCODING *enc, - const char *ptr, - const char *end, - const char **namePtr, - const char **valPtr, - const char **nextTokPtr) -{ - int c; - char open; - if (ptr == end) { - *namePtr = 0; - return 1; - } - if (!isSpace(toAscii(enc, ptr, end))) { - *nextTokPtr = ptr; - return 0; - } - do { - ptr += enc->minBytesPerChar; - } while (isSpace(toAscii(enc, ptr, end))); - if (ptr == end) { - *namePtr = 0; - return 1; - } - *namePtr = ptr; - for (;;) { - c = toAscii(enc, ptr, end); - if (c == -1) { - *nextTokPtr = ptr; - return 0; - } - if (c == '=') - break; - if (isSpace(c)) { - do { - ptr += enc->minBytesPerChar; - } while (isSpace(c = toAscii(enc, ptr, end))); - if (c != '=') { - *nextTokPtr = ptr; - return 0; - } - break; - } - ptr += enc->minBytesPerChar; - } - if (ptr == *namePtr) { - *nextTokPtr = ptr; - return 0; - } - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - while (isSpace(c)) { - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - } - if (c != '"' && c != '\'') { - *nextTokPtr = ptr; - return 0; - } - open = c; - ptr += enc->minBytesPerChar; - *valPtr = ptr; - for (;; ptr += enc->minBytesPerChar) { - c = toAscii(enc, ptr, end); - if (c == open) - break; - if (!('a' <= c && c <= 'z') - && !('A' <= c && c <= 'Z') - && !('0' <= c && c <= '9') - && c != '.' - && c != '-' - && c != '_') { - *nextTokPtr = ptr; - return 0; - } - } - *nextTokPtr = ptr + enc->minBytesPerChar; - return 1; -} - -static -int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, - const char *, - const char *), - int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - const char *val = 0; - const char *name = 0; - ptr += 5 * enc->minBytesPerChar; - end -= 2 * enc->minBytesPerChar; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) { - *badPtr = ptr; - return 0; - } - if (!XmlNameMatchesAscii(enc, name, "version")) { - if (!isGeneralTextEntity) { - *badPtr = name; - return 0; - } - } - else { - if (versionPtr) - *versionPtr = val; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) { - if (isGeneralTextEntity) { - /* a TextDecl must have an EncodingDecl */ - *badPtr = ptr; - return 0; - } - return 1; - } - } - if (XmlNameMatchesAscii(enc, name, "encoding")) { - int c = toAscii(enc, val, end); - if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) { - *badPtr = val; - return 0; - } - if (encodingName) - *encodingName = val; - if (encoding) - *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) - return 1; - } - if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) { - *badPtr = name; - return 0; - } - if (XmlNameMatchesAscii(enc, val, "yes")) { - if (standalone) - *standalone = 1; - } - else if (XmlNameMatchesAscii(enc, val, "no")) { - if (standalone) - *standalone = 0; - } - else { - *badPtr = val; - return 0; - } - while (isSpace(toAscii(enc, ptr, end))) - ptr += enc->minBytesPerChar; - if (ptr != end) { - *badPtr = ptr; - return 0; - } - return 1; -} - -static -int checkCharRefNumber(int result) -{ - switch (result >> 8) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return -1; - case 0: - if (latin1_encoding.type[result] == BT_NONXML) - return -1; - break; - case 0xFF: - if (result == 0xFFFE || result == 0xFFFF) - return -1; - break; - } - return result; -} - -int XmlUtf8Encode(int c, char *buf) -{ - enum { - /* minN is minimum legal resulting value for N byte sequence */ - min2 = 0x80, - min3 = 0x800, - min4 = 0x10000 - }; - - if (c < 0) - return 0; - if (c < min2) { - buf[0] = (c | UTF8_cval1); - return 1; - } - if (c < min3) { - buf[0] = ((c >> 6) | UTF8_cval2); - buf[1] = ((c & 0x3f) | 0x80); - return 2; - } - if (c < min4) { - buf[0] = ((c >> 12) | UTF8_cval3); - buf[1] = (((c >> 6) & 0x3f) | 0x80); - buf[2] = ((c & 0x3f) | 0x80); - return 3; - } - if (c < 0x110000) { - buf[0] = ((c >> 18) | UTF8_cval4); - buf[1] = (((c >> 12) & 0x3f) | 0x80); - buf[2] = (((c >> 6) & 0x3f) | 0x80); - buf[3] = ((c & 0x3f) | 0x80); - return 4; - } - return 0; -} - -int XmlUtf16Encode(int charNum, unsigned short *buf) -{ - if (charNum < 0) - return 0; - if (charNum < 0x10000) { - buf[0] = charNum; - return 1; - } - if (charNum < 0x110000) { - charNum -= 0x10000; - buf[0] = (charNum >> 10) + 0xD800; - buf[1] = (charNum & 0x3FF) + 0xDC00; - return 2; - } - return 0; -} - -struct unknown_encoding { - struct normal_encoding normal; - int (*convert)(void *userData, const char *p); - void *userData; - unsigned short utf16[256]; - char utf8[256][4]; -}; - -int XmlSizeOfUnknownEncoding() -{ - return sizeof(struct unknown_encoding); -} - -static -int unknown_isName(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); -} - -static -int unknown_isNmstrt(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); -} - -static -int unknown_isInvalid(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; -} - -static -void unknown_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char buf[XML_UTF8_ENCODE_MAX]; - for (;;) { - const char *utf8; - int n; - if (*fromP == fromLim) - break; - utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; - n = *utf8++; - if (n == 0) { - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - n = XmlUtf8Encode(c, buf); - if (n > toLim - *toP) - break; - utf8 = buf; - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else { - if (n > toLim - *toP) - break; - (*fromP)++; - } - do { - *(*toP)++ = *utf8++; - } while (--n != 0); - } -} - -static -void unknown_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) { - unsigned short c - = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; - if (c == 0) { - c = (unsigned short)((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else - (*fromP)++; - *(*toP)++ = c; - } -} - -ENCODING * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - int i; - struct unknown_encoding *e = mem; - for (i = 0; i < sizeof(struct normal_encoding); i++) - ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; - for (i = 0; i < 128; i++) - if (latin1_encoding.type[i] != BT_OTHER - && latin1_encoding.type[i] != BT_NONXML - && table[i] != i) - return 0; - for (i = 0; i < 256; i++) { - int c = table[i]; - if (c == -1) { - e->normal.type[i] = BT_MALFORM; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else if (c < 0) { - if (c < -4) - return 0; - e->normal.type[i] = BT_LEAD2 - (c + 2); - e->utf8[i][0] = 0; - e->utf16[i] = 0; - } - else if (c < 0x80) { - if (latin1_encoding.type[c] != BT_OTHER - && latin1_encoding.type[c] != BT_NONXML - && c != i) - return 0; - e->normal.type[i] = latin1_encoding.type[c]; - e->utf8[i][0] = 1; - e->utf8[i][1] = (char)c; - e->utf16[i] = c == 0 ? 0xFFFF : c; - } - else if (checkCharRefNumber(c) < 0) { - e->normal.type[i] = BT_NONXML; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else { - if (c > 0xFFFF) - return 0; - if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NMSTRT; - else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NAME; - else - e->normal.type[i] = BT_OTHER; - e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); - e->utf16[i] = c; - } - } - e->userData = userData; - e->convert = convert; - if (convert) { - e->normal.isName2 = unknown_isName; - e->normal.isName3 = unknown_isName; - e->normal.isName4 = unknown_isName; - e->normal.isNmstrt2 = unknown_isNmstrt; - e->normal.isNmstrt3 = unknown_isNmstrt; - e->normal.isNmstrt4 = unknown_isNmstrt; - e->normal.isInvalid2 = unknown_isInvalid; - e->normal.isInvalid3 = unknown_isInvalid; - e->normal.isInvalid4 = unknown_isInvalid; - } - e->normal.enc.utf8Convert = unknown_toUtf8; - e->normal.enc.utf16Convert = unknown_toUtf16; - return &(e->normal.enc); -} - -/* If this enumeration is changed, getEncodingIndex and encodings -must also be changed. */ -enum { - UNKNOWN_ENC = -1, - ISO_8859_1_ENC = 0, - US_ASCII_ENC, - UTF_8_ENC, - UTF_16_ENC, - UTF_16BE_ENC, - UTF_16LE_ENC, - /* must match encodingNames up to here */ - NO_ENC -}; - -static -int getEncodingIndex(const char *name) -{ - static const char *encodingNames[] = { - "ISO-8859-1", - "US-ASCII", - "UTF-8", - "UTF-16", - "UTF-16BE" - "UTF-16LE", - }; - int i; - if (name == 0) - return NO_ENC; - for (i = 0; i < sizeof(encodingNames)/sizeof(encodingNames[0]); i++) - if (streqci(name, encodingNames[i])) - return i; - return UNKNOWN_ENC; -} - -/* For binary compatibility, we store the index of the encoding specified -at initialization in the isUtf16 member. */ - -#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16) - -/* This is what detects the encoding. -encodingTable maps from encoding indices to encodings; -INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; -state is XML_CONTENT_STATE if we're parsing an external text entity, -and XML_PROLOG_STATE otherwise. -*/ - - -static -int initScan(const ENCODING **encodingTable, - const INIT_ENCODING *enc, - int state, - const char *ptr, - const char *end, - const char **nextTokPtr) -{ - const ENCODING **encPtr; - - if (ptr == end) - return XML_TOK_NONE; - encPtr = enc->encPtr; - if (ptr + 1 == end) { - /* only a single byte available for auto-detection */ - /* a well-formed document entity must have more than one byte */ - if (state != XML_CONTENT_STATE) - return XML_TOK_PARTIAL; - /* so we're parsing an external text entity... */ - /* if UTF-16 was externally specified, then we need at least 2 bytes */ - switch (INIT_ENC_INDEX(enc)) { - case UTF_16_ENC: - case UTF_16LE_ENC: - case UTF_16BE_ENC: - return XML_TOK_PARTIAL; - } - switch ((unsigned char)*ptr) { - case 0xFE: - case 0xFF: - case 0xEF: /* possibly first byte of UTF-8 BOM */ - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - /* fall through */ - case 0x00: - case 0x3C: - return XML_TOK_PARTIAL; - } - } - else { - switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { - case 0xFEFF: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XML_TOK_BOM; - /* 00 3C is handled in the default case */ - case 0x3C00: - if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC - || INIT_ENC_INDEX(enc) == UTF_16_ENC) - && state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - case 0xFFFE: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XML_TOK_BOM; - case 0xEFBB: - /* Maybe a UTF-8 BOM (EF BB BF) */ - /* If there's an explicitly specified (external) encoding - of ISO-8859-1 or some flavour of UTF-16 - and this is an external text entity, - don't look for the BOM, - because it might be a legal data. */ - if (state == XML_CONTENT_STATE) { - int e = INIT_ENC_INDEX(enc); - if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) - break; - } - if (ptr + 2 == end) - return XML_TOK_PARTIAL; - if ((unsigned char)ptr[2] == 0xBF) { - *encPtr = encodingTable[UTF_8_ENC]; - return XML_TOK_BOM; - } - break; - default: - if (ptr[0] == '\0') { - /* 0 isn't a legal data character. Furthermore a document entity can only - start with ASCII characters. So the only way this can fail to be big-endian - UTF-16 if it it's an external parsed general entity that's labelled as - UTF-16LE. */ - if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) - break; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - else if (ptr[1] == '\0') { - /* We could recover here in the case: - - parsing an external entity - - second byte is 0 - - no externally specified encoding - - no encoding declaration - by assuming UTF-16LE. But we don't, because this would mean when - presented just with a single byte, we couldn't reliably determine - whether we needed further bytes. */ - if (state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - break; - } - } - *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); -} - - -#define NS(x) x -#define ns(x) x -#include "xmltok_ns.c" -#undef NS -#undef ns - -#ifdef XML_NS - -#define NS(x) x ## NS -#define ns(x) x ## _ns - -#include "xmltok_ns.c" - -#undef NS -#undef ns - -ENCODING * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); - if (enc) - ((struct normal_encoding *)enc)->type[':'] = BT_COLON; - return enc; -} - -#endif /* XML_NS */
--- a/src/protocols/jabber/xmltok.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLTOKAPI -#define XMLTOKAPI /* as nothing */ -#endif - -/* The following token may be returned by XmlContentTok */ -#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of - illegal ]]> sequence */ -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_NONE -4 /* The string to be scanned is empty */ -#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; - might be part of CRLF sequence */ -#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ -#define XML_TOK_PARTIAL -1 /* only part of a token */ -#define XML_TOK_INVALID 0 - -/* The following tokens are returned by XmlContentTok; some are also - returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ - -#define XML_TOK_START_TAG_WITH_ATTS 1 -#define XML_TOK_START_TAG_NO_ATTS 2 -#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ -#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 -#define XML_TOK_END_TAG 5 -#define XML_TOK_DATA_CHARS 6 -#define XML_TOK_DATA_NEWLINE 7 -#define XML_TOK_CDATA_SECT_OPEN 8 -#define XML_TOK_ENTITY_REF 9 -#define XML_TOK_CHAR_REF 10 /* numeric character reference */ - -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_PI 11 /* processing instruction */ -#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ -#define XML_TOK_COMMENT 13 -#define XML_TOK_BOM 14 /* Byte order mark */ - -/* The following tokens are returned only by XmlPrologTok */ -#define XML_TOK_PROLOG_S 15 -#define XML_TOK_DECL_OPEN 16 /* <!foo */ -#define XML_TOK_DECL_CLOSE 17 /* > */ -#define XML_TOK_NAME 18 -#define XML_TOK_NMTOKEN 19 -#define XML_TOK_POUND_NAME 20 /* #name */ -#define XML_TOK_OR 21 /* | */ -#define XML_TOK_PERCENT 22 -#define XML_TOK_OPEN_PAREN 23 -#define XML_TOK_CLOSE_PAREN 24 -#define XML_TOK_OPEN_BRACKET 25 -#define XML_TOK_CLOSE_BRACKET 26 -#define XML_TOK_LITERAL 27 -#define XML_TOK_PARAM_ENTITY_REF 28 -#define XML_TOK_INSTANCE_START 29 - -/* The following occur only in element type declarations */ -#define XML_TOK_NAME_QUESTION 30 /* name? */ -#define XML_TOK_NAME_ASTERISK 31 /* name* */ -#define XML_TOK_NAME_PLUS 32 /* name+ */ -#define XML_TOK_COND_SECT_OPEN 33 /* <![ */ -#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */ -#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ -#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ -#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ -#define XML_TOK_COMMA 38 - -/* The following token is returned only by XmlAttributeValueTok */ -#define XML_TOK_ATTRIBUTE_VALUE_S 39 - -/* The following token is returned only by XmlCdataSectionTok */ -#define XML_TOK_CDATA_SECT_CLOSE 40 - -/* With namespace processing this is returned by XmlPrologTok - for a name with a colon. */ -#define XML_TOK_PREFIXED_NAME 41 - -#define XML_N_STATES 3 -#define XML_PROLOG_STATE 0 -#define XML_CONTENT_STATE 1 -#define XML_CDATA_SECTION_STATE 2 - -#define XML_N_LITERAL_TYPES 2 -#define XML_ATTRIBUTE_VALUE_LITERAL 0 -#define XML_ENTITY_VALUE_LITERAL 1 - -/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ -#define XML_UTF8_ENCODE_MAX 4 -/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ -#define XML_UTF16_ENCODE_MAX 2 - -typedef struct position { - /* first line and first column are 0 not 1 */ - unsigned long lineNumber; - unsigned long columnNumber; -} POSITION; - -typedef struct { - const char *name; - const char *valuePtr; - const char *valueEnd; - char normalized; -} ATTRIBUTE; - -struct encoding; -typedef struct encoding ENCODING; - -struct encoding { - int (*scanners[XML_N_STATES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*sameName)(const ENCODING *, - const char *, const char *); - int (*nameMatchesAscii)(const ENCODING *, - const char *, const char *); - int (*nameLength)(const ENCODING *, const char *); - const char *(*skipS)(const ENCODING *, const char *); - int (*getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts); - int (*charRefNumber)(const ENCODING *enc, const char *ptr); - int (*predefinedEntityName)(const ENCODING *, const char *, const char *); - void (*updatePosition)(const ENCODING *, - const char *ptr, - const char *end, - POSITION *); - int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr); - void (*utf8Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - char **toP, - const char *toLim); - void (*utf16Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - unsigned short **toP, - const unsigned short *toLim); - int minBytesPerChar; - char isUtf8; - char isUtf16; -}; - -/* -Scan the string starting at ptr until the end of the next complete token, -but do not scan past eptr. Return an integer giving the type of token. - -Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. - -Return XML_TOK_PARTIAL when the string does not contain a complete token; -nextTokPtr will not be set. - -Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr -will be set to point to the character which made the token invalid. - -Otherwise the string starts with a valid token; nextTokPtr will be set to point -to the character following the end of that token. - -Each data character counts as a single token, but adjacent data characters -may be returned together. Similarly for characters in the prolog outside -literals, comments and processing instructions. -*/ - - -#define XmlTok(enc, state, ptr, end, nextTokPtr) \ - (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) - -#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) - -#define XmlContentTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) - -#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) - -/* This is used for performing a 2nd-level tokenization on -the content of a literal that has already been returned by XmlTok. */ - -#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ - (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) - -#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) - -#define XmlNameMatchesAscii(enc, ptr1, ptr2) \ - (((enc)->nameMatchesAscii)(enc, ptr1, ptr2)) - -#define XmlNameLength(enc, ptr) \ - (((enc)->nameLength)(enc, ptr)) - -#define XmlSkipS(enc, ptr) \ - (((enc)->skipS)(enc, ptr)) - -#define XmlGetAttributes(enc, ptr, attsMax, atts) \ - (((enc)->getAtts)(enc, ptr, attsMax, atts)) - -#define XmlCharRefNumber(enc, ptr) \ - (((enc)->charRefNumber)(enc, ptr)) - -#define XmlPredefinedEntityName(enc, ptr, end) \ - (((enc)->predefinedEntityName)(enc, ptr, end)) - -#define XmlUpdatePosition(enc, ptr, end, pos) \ - (((enc)->updatePosition)(enc, ptr, end, pos)) - -#define XmlIsPublicId(enc, ptr, end, badPtr) \ - (((enc)->isPublicId)(enc, ptr, end, badPtr)) - -#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) - -#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) - -typedef struct { - ENCODING initEnc; - const ENCODING **encPtr; -} INIT_ENCODING; - -int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); - -int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(); -int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf); -int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf); - -int XMLTOKAPI XmlSizeOfUnknownEncoding(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); - -int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); -int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); -#ifdef __cplusplus -} -#endif - -#endif /* not XmlTok_INCLUDED */
--- a/src/protocols/jabber/xmltok_impl.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1737 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#ifndef IS_INVALID_CHAR -#define IS_INVALID_CHAR(enc, ptr, n) (0) -#endif - -#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_INVALID_CHAR(enc, ptr, n)) { \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define INVALID_CASES(ptr, nextTokPtr) \ - INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ - case BT_NONXML: \ - case BT_MALFORM: \ - case BT_TRAIL: \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; - -#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NAME_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - case BT_DIGIT: \ - case BT_NAME: \ - case BT_MINUS: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) - -#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) - -#ifndef PREFIX -#define PREFIX(ident) ident -#endif - -/* ptr points to character following "<!-" */ - -static -int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - if (!CHAR_MATCHES(enc, ptr, '-')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) - case BT_MINUS: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '-')) { - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMENT; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "<!" */ - -static -int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COND_SECT_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_PERCNT: - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - /* don't allow <!ENTITY% foo "whatever"> */ - switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { -case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* fall through */ -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DECL_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) -{ - int upper = 0; - *tokPtr = XML_TOK_PI; - if (end - ptr != MINBPC(enc)*3) - return 1; - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'x': - break; - case 'X': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'm': - break; - case 'M': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - break; - case 'L': - upper = 1; - break; - default: - return 1; - } - if (upper) - return 0; - *tokPtr = XML_TOK_XML_DECL; - return 1; -} - -/* ptr points to character following "<?" */ - -static -int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int tok; - const char *target = ptr; - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_CR: case BT_LF: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUEST: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; - case BT_QUEST: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - - -static -int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int i; - /* CDATA[ */ - if (end - ptr < 6 * MINBPC(enc)) - return XML_TOK_PARTIAL; - for (i = 0; i < 6; i++, ptr += MINBPC(enc)) { - if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - *nextTokPtr = ptr; - return XML_TOK_CDATA_SECT_OPEN; -} - -static -int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CDATA_SECT_CLOSE; - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - case BT_RSQB: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "</" */ - -static -int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_CR: case BT_LF: - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_CR: case BT_LF: - break; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -#ifdef XML_NS - case BT_COLON: - /* no need to check qname syntax here, since end-tag must match exactly */ - ptr += MINBPC(enc); - break; -#endif - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&#X" */ - -static -int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&#" */ - -static -int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - if (CHAR_MATCHES(enc, ptr, 'x')) - return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&" */ - -static -int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_NUM: - return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following first character of attribute name */ - -static -int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ -#ifdef XML_NS - int hadColon = 0; -#endif - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -#ifdef XML_NS - case BT_COLON: - if (hadColon) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; -#endif -case BT_S: case BT_CR: case BT_LF: - for (;;) { - int t; - - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == BT_EQUALS) - break; - switch (t) { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_EQUALS: - { - int open; -#ifdef XML_NS - hadColon = 0; -#endif - for (;;) { - - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - open = BYTE_TYPE(enc, ptr); - if (open == BT_QUOT || open == BT_APOS) - break; - switch (open) { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - ptr += MINBPC(enc); - /* in attribute value */ - for (;;) { - int t; - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == open) - break; - switch (t) { - INVALID_CASES(ptr, nextTokPtr) - case BT_AMP: - { - int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr); - if (tok <= 0) { - if (tok == XML_TOK_INVALID) - *nextTokPtr = ptr; - return tok; - } - break; - } - case BT_LT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - default: - ptr += MINBPC(enc); - break; - } - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: - case BT_CR: - case BT_LF: - break; - case BT_SOL: - goto sol; - case BT_GT: - goto gt; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* ptr points to closing quote */ - for (;;) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_S: case BT_CR: case BT_LF: - continue; - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_WITH_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_WITH_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; - } - break; - } - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "<" */ - -static -int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ -#ifdef XML_NS - int hadColon; -#endif - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_EXCL: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr); - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_SOL: - return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } -#ifdef XML_NS - hadColon = 0; -#endif - /* we have a start-tag */ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -#ifdef XML_NS - case BT_COLON: - if (hadColon) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; -#endif -case BT_S: case BT_CR: case BT_LF: - { - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_GT: - goto gt; - case BT_SOL: - goto sol; - case BT_S: case BT_CR: case BT_LF: - ptr += MINBPC(enc); - continue; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr); - } - return XML_TOK_PARTIAL; - } - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_NO_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_NO_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_LT: - return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_AMP: - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_RSQB: - if (ptr + MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) { - ptr += MINBPC(enc); - break; - } - if (ptr + 2*MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) { - ptr += MINBPC(enc); - break; - } - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_AMP: - case BT_LT: - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "%" */ - -static -int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_PERCENT; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_PARAM_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_CR: case BT_LF: case BT_S: -case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: - *nextTokPtr = ptr; - return XML_TOK_POUND_NAME; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanLit)(int open, const ENCODING *enc, - const char *ptr, const char *end, - const char **nextTokPtr) -{ - while (ptr != end) { - int t = BYTE_TYPE(enc, ptr); - switch (t) { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUOT: - case BT_APOS: - ptr += MINBPC(enc); - if (t != open) - break; - if (ptr == end) - return XML_TOK_PARTIAL; - *nextTokPtr = ptr; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_CR: case BT_LF: - case BT_GT: case BT_PERCNT: case BT_LSQB: - return XML_TOK_LITERAL; - default: - return XML_TOK_INVALID; - } - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int tok; - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_QUOT: - return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_APOS: - return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LT: - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_EXCL: - return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_NMSTRT: - case BT_HEX: - case BT_NONASCII: - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - *nextTokPtr = ptr - MINBPC(enc); - return XML_TOK_INSTANCE_START; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - case BT_CR: - if (ptr + MINBPC(enc) == end) - return XML_TOK_TRAILING_CR; - /* fall through */ -case BT_S: case BT_LF: - for (;;) { - ptr += MINBPC(enc); - if (ptr == end) - break; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_LF: - break; - case BT_CR: - /* don't split CR/LF pair */ - if (ptr + MINBPC(enc) != end) - break; - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - } - } - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - case BT_PERCNT: - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_COMMA: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMA; - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_BRACKET; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ']')) { - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) { - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_COND_SECT_CLOSE; - } - } - *nextTokPtr = ptr; - return XML_TOK_CLOSE_BRACKET; - case BT_LPAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_PAREN; - case BT_RPAR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_AST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_ASTERISK; - case BT_QUEST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_QUESTION; - case BT_PLUS: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_PLUS; -case BT_CR: case BT_LF: case BT_S: -case BT_GT: case BT_COMMA: case BT_VERBAR: - case BT_RPAR: - *nextTokPtr = ptr; - return XML_TOK_CLOSE_PAREN; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_VERBAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OR; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DECL_CLOSE; - case BT_NUM: - return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NAME; \ - break; \ - } \ - if (IS_NAME_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NMTOKEN; \ - break; \ - } \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NMSTRT: - case BT_HEX: - tok = XML_TOK_NAME; - ptr += MINBPC(enc); - break; - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: -#ifdef XML_NS - case BT_COLON: -#endif - tok = XML_TOK_NMTOKEN; - ptr += MINBPC(enc); - break; - case BT_NONASCII: - if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NAME; - break; - } - if (IS_NAME_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NMTOKEN; - break; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_GT: case BT_RPAR: case BT_COMMA: -case BT_VERBAR: case BT_LSQB: case BT_PERCNT: -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return tok; -#ifdef XML_NS - case BT_COLON: - ptr += MINBPC(enc); - switch (tok) { - case XML_TOK_NAME: - if (ptr == end) - return XML_TOK_PARTIAL; - tok = XML_TOK_PREFIXED_NAME; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - default: - tok = XML_TOK_NMTOKEN; - break; - } - break; - case XML_TOK_PREFIXED_NAME: - tok = XML_TOK_NMTOKEN; - break; - } - break; -#endif - case BT_PLUS: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_PLUS; - case BT_AST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_ASTERISK; - case BT_QUEST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_QUESTION; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LT: - /* this is for inside entity references */ - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_S: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ATTRIBUTE_VALUE_S; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_PERCNT: - if (ptr == start) - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr) -{ - ptr += MINBPC(enc); - end -= MINBPC(enc); - for (; ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - case BT_MINUS: - case BT_APOS: - case BT_LPAR: - case BT_RPAR: - case BT_PLUS: - case BT_COMMA: - case BT_SOL: - case BT_EQUALS: - case BT_QUEST: - case BT_CR: - case BT_LF: - case BT_SEMI: - case BT_EXCL: - case BT_AST: - case BT_PERCNT: - case BT_NUM: -#ifdef XML_NS - case BT_COLON: -#endif - break; - case BT_S: - if (CHAR_MATCHES(enc, ptr, '\t')) { - *badPtr = ptr; - return 0; - } - break; - case BT_NAME: - case BT_NMSTRT: - if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) - break; - default: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 0x24: /* $ */ - case 0x40: /* @ */ - break; - default: - *badPtr = ptr; - return 0; - } - break; - } - } - return 1; -} - -/* This must only be called for a well-formed start-tag or empty element tag. -Returns the number of attributes. Pointers to the first attsMax attributes -are stored in atts. */ - -static -int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts) -{ - enum { other, inName, inValue } state = inName; - int nAtts = 0; - int open = 0; - - for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { -#define START_NAME \ - if (state == other) { \ - if (nAtts < attsMax) { \ - atts[nAtts].name = ptr; \ - atts[nAtts].normalized = 1; \ - } \ - state = inName; \ - } -#define LEAD_CASE(n) \ - case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: - case BT_HEX: - START_NAME - break; -#undef START_NAME - case BT_QUOT: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_QUOT; - } - else if (open == BT_QUOT) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_APOS: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_APOS; - } - else if (open == BT_APOS) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_AMP: - if (nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_S: - if (state == inName) - state = other; - else if (state == inValue - && nAtts < attsMax - && atts[nAtts].normalized - && (ptr == atts[nAtts].valuePtr - || BYTE_TO_ASCII(enc, ptr) != ' ' - || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' ' - || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) - atts[nAtts].normalized = 0; - break; - case BT_CR: case BT_LF: - /* This case ensures that the first attribute name is counted - Apart from that we could just change state on the quote. */ - if (state == inName) - state = other; - else if (state == inValue && nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_GT: - case BT_SOL: - if (state != inValue) - return nAtts; - break; - default: - break; - } - } - /* not reached */ -} - -static -int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) -{ - int result = 0; - /* skip &# */ - ptr += 2*MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'x')) { - for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - switch (c) { -case '0': case '1': case '2': case '3': case '4': -case '5': case '6': case '7': case '8': case '9': - result <<= 4; - result |= (c - '0'); - break; -case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - result <<= 4; - result += 10 + (c - 'A'); - break; -case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - result <<= 4; - result += 10 + (c - 'a'); - break; - } - if (result >= 0x110000) - return -1; - } - } - else { - for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - result *= 10; - result += (c - '0'); - if (result >= 0x110000) - return -1; - } - } - return checkCharRefNumber(result); -} - -static -int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) -{ - switch ((end - ptr)/MINBPC(enc)) { - case 2: - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) { - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - return '<'; - case 'g': - return '>'; - } - } - break; - case 3: - if (CHAR_MATCHES(enc, ptr, 'a')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'm')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) - return '&'; - } - } - break; - case 4: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'q': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'u')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 't')) - return '"'; - } - } - break; - case 'a': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 's')) - return '\''; - } - } - break; - } - } - return 0; -} - -static -int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr1)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (*ptr1++ != *ptr2++) \ - return 0; - LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) -#undef LEAD_CASE - /* fall through */ - if (*ptr1++ != *ptr2++) - return 0; - break; - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 1) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 2) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 3) { - if (*ptr2++ != *ptr1++) - return 0; - } - } - } - break; - default: - if (MINBPC(enc) == 1 && *ptr1 == *ptr2) - return 1; - switch (BYTE_TYPE(enc, ptr2)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } - } - } - /* not reached */ -} - -static -int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { - if (!CHAR_MATCHES(enc, ptr1, *ptr2)) - return 0; - } - switch (BYTE_TYPE(enc, ptr1)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } -} - -static -int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) -{ - const char *start = ptr; - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - ptr += MINBPC(enc); - break; - default: - return ptr - start; - } - } -} - -static -const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_LF: - case BT_CR: - case BT_S: - ptr += MINBPC(enc); - break; - default: - return ptr; - } - } -} - -static -void PREFIX(updatePosition)(const ENCODING *enc, - const char *ptr, - const char *end, - POSITION *pos) -{ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_LF: - pos->columnNumber = (unsigned)-1; - pos->lineNumber++; - ptr += MINBPC(enc); - break; - case BT_CR: - pos->lineNumber++; - ptr += MINBPC(enc); - if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - pos->columnNumber = (unsigned)-1; - break; - default: - ptr += MINBPC(enc); - break; - } - pos->columnNumber++; - } -} - -#undef DO_LEAD_CASE -#undef MULTIBYTE_CASES -#undef INVALID_CASES -#undef CHECK_NAME_CASE -#undef CHECK_NAME_CASES -#undef CHECK_NMSTRT_CASE -#undef CHECK_NMSTRT_CASES
--- a/src/protocols/jabber/xmltok_impl.h Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -enum { - BT_NONXML, - BT_MALFORM, - BT_LT, - BT_AMP, - BT_RSQB, - BT_LEAD2, - BT_LEAD3, - BT_LEAD4, - BT_TRAIL, - BT_CR, - BT_LF, - BT_GT, - BT_QUOT, - BT_APOS, - BT_EQUALS, - BT_QUEST, - BT_EXCL, - BT_SOL, - BT_SEMI, - BT_NUM, - BT_LSQB, - BT_S, - BT_NMSTRT, - BT_COLON, - BT_HEX, - BT_DIGIT, - BT_NAME, - BT_MINUS, - BT_OTHER, /* known not to be a name or name start character */ - BT_NONASCII, /* might be a name or name start character */ - BT_PERCNT, - BT_LPAR, - BT_RPAR, - BT_AST, - BT_PLUS, - BT_COMMA, - BT_VERBAR -}; - -#include <stddef.h>
--- a/src/protocols/jabber/xmltok_ns.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -const ENCODING *NS(XmlGetUtf8InternalEncoding)() -{ - return &ns(internal_utf8_encoding).enc; -} - -const ENCODING *NS(XmlGetUtf16InternalEncoding)() -{ -#if XML_BYTE_ORDER == 12 - return &ns(internal_little2_encoding).enc; -#elif XML_BYTE_ORDER == 21 -return &ns(internal_big2_encoding).enc; -#else -const short n = 1; - return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc; -#endif -} - -static -const ENCODING *NS(encodings)[] = { - &ns(latin1_encoding).enc, - &ns(ascii_encoding).enc, - &ns(utf8_encoding).enc, - &ns(big2_encoding).enc, - &ns(big2_encoding).enc, - &ns(little2_encoding).enc, - &ns(utf8_encoding).enc /* NO_ENC */ -}; - -static -int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); -} - -static -int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); -} - -int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) -{ - int i = getEncodingIndex(name); - if (i == UNKNOWN_ENC) - return 0; - INIT_ENC_INDEX(p) = (char)i; - p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); - p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); - p->initEnc.updatePosition = initUpdatePosition; - p->encPtr = encPtr; - *encPtr = &(p->initEnc); - return 1; -} - -static -const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) -{ -#define ENCODING_MAX 128 - char buf[ENCODING_MAX]; - char *p = buf; - int i; - XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); - if (ptr != end) - return 0; - *p = 0; - if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2) - return enc; - i = getEncodingIndex(buf); - if (i == UNKNOWN_ENC) - return 0; - return NS(encodings)[i]; -} - -int NS(XmlParseXmlDecl)(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - return doParseXmlDecl(NS(findEncoding), - isGeneralTextEntity, - enc, - ptr, - end, - badPtr, - versionPtr, - encodingName, - encoding, - standalone); -}
--- a/src/protocols/jabber/xstream.c Mon Sep 29 13:00:55 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" - -/* xstream is a way to have a consistent method of handling incoming XML Stream based events... it doesn't handle the generation of an XML Stream, but provides some facilities to help do that */ - -/******* internal expat callbacks *********/ -void _xstream_startElement(xstream xs, const char* name, const char** atts) -{ - pool p; - - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - if(xs->node == NULL) - { - p = pool_heap(5*1024); /* 5k, typically 1-2k each plus copy of self and workspace */ - xs->node = xmlnode_new_tag_pool(p,name); - xmlnode_put_expat_attribs(xs->node, atts); - - if(xs->status == XSTREAM_ROOT) - { - xs->status = XSTREAM_NODE; /* flag status that we're processing nodes now */ - (xs->f)(XSTREAM_ROOT, xs->node, xs->arg); /* send the root, f must free all nodes */ - xs->node = NULL; - } - }else{ - xs->node = xmlnode_insert_tag(xs->node, name); - xmlnode_put_expat_attribs(xs->node, atts); - } - - /* depth check */ - xs->depth++; - if(xs->depth > XSTREAM_MAXDEPTH) - xs->status = XSTREAM_ERR; -} - - -void _xstream_endElement(xstream xs, const char* name) -{ - xmlnode parent; - - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - /* if it's already NULL we've received </stream>, tell the app and we're outta here */ - if(xs->node == NULL) - { - xs->status = XSTREAM_CLOSE; - (xs->f)(XSTREAM_CLOSE, NULL, xs->arg); - }else{ - parent = xmlnode_get_parent(xs->node); - - /* we are the top-most node, feed to the app who is responsible to delete it */ - if(parent == NULL) - (xs->f)(XSTREAM_NODE, xs->node, xs->arg); - - xs->node = parent; - } - xs->depth--; -} - - -void _xstream_charData(xstream xs, const char *str, int len) -{ - /* if xstream is bad, get outa here */ - if(xs->status > XSTREAM_NODE) return; - - if(xs->node == NULL) - { - /* we must be in the root of the stream where CDATA is irrelevant */ - return; - } - - xmlnode_insert_cdata(xs->node, str, len); -} - - -void _xstream_cleanup(void *arg) -{ - xstream xs = (xstream)arg; - - xmlnode_free(xs->node); /* cleanup anything left over */ - XML_ParserFree(xs->parser); -} - - -/* creates a new xstream with given pool, xstream will be cleaned up w/ pool */ -xstream xstream_new(pool p, xstream_onNode f, void *arg) -{ - xstream newx; - - if(p == NULL || f == NULL) - { - fprintf(stderr,"Fatal Programming Error: xstream_new() was improperly called with NULL.\n"); - return NULL; - } - - newx = pmalloco(p, sizeof(_xstream)); - newx->p = p; - newx->f = f; - newx->arg = arg; - - /* create expat parser and ensure cleanup */ - newx->parser = XML_ParserCreate(NULL); - XML_SetUserData(newx->parser, (void *)newx); - XML_SetElementHandler(newx->parser, (void *)_xstream_startElement, (void *)_xstream_endElement); - XML_SetCharacterDataHandler(newx->parser, (void *)_xstream_charData); - pool_cleanup(p, _xstream_cleanup, (void *)newx); - - return newx; -} - -/* attempts to parse the buff onto this stream firing events to the handler, returns the last known status */ -int xstream_eat(xstream xs, char *buff, int len) -{ - char *err = NULL; - xmlnode xerr; - static char maxerr[] = "maximum node size reached"; - static char deeperr[] = "maximum node depth reached"; - - if(xs == NULL) - { - fprintf(stderr,"Fatal Programming Error: xstream_eat() was improperly called with NULL.\n"); - return XSTREAM_ERR; - } - - if(len == 0 || buff == NULL) - return xs->status; - - if(len == -1) /* easy for hand-fed eat calls */ - len = strlen(buff); - - if(!XML_Parse(xs->parser, buff, len, 0)) - { - err = (char *)XML_ErrorString(XML_GetErrorCode(xs->parser)); - xs->status = XSTREAM_ERR; - }else if(pool_size(xmlnode_pool(xs->node)) > XSTREAM_MAXNODE || xs->cdata_len > XSTREAM_MAXNODE){ - err = maxerr; - xs->status = XSTREAM_ERR; - }else if(xs->status == XSTREAM_ERR){ /* set within expat handlers */ - err = deeperr; - } - - /* fire parsing error event, make a node containing the error string */ - if(xs->status == XSTREAM_ERR) - { - xerr = xmlnode_new_tag("error"); - xmlnode_insert_cdata(xerr,err,-1); - (xs->f)(XSTREAM_ERR, xerr, xs->arg); - } - - return xs->status; -} - - -/* STREAM CREATION UTILITIES */ - -/* give a standard template xmlnode to work from */ -xmlnode xstream_header(char *namespace, char *to, char *from) -{ - xmlnode x; - char id[10]; - - sprintf(id,"%X",(int)time(NULL)); - - x = xmlnode_new_tag("stream:stream"); - xmlnode_put_attrib(x, "xmlns:stream", "http://etherx.jabber.org/streams"); - xmlnode_put_attrib(x, "id", id); - if(namespace != NULL) - xmlnode_put_attrib(x, "xmlns", namespace); - if(to != NULL) - xmlnode_put_attrib(x, "to", to); - if(from != NULL) - xmlnode_put_attrib(x, "from", from); - - return x; -} - -/* trim the xmlnode to only the opening header :) [NO CHILDREN ALLOWED] */ -char *xstream_header_char(xmlnode x) -{ - spool s; - char *fixr, *head; - - if(xmlnode_has_children(x)) - { - fprintf(stderr,"Fatal Programming Error: xstream_header_char() was sent a header with children!\n"); - return NULL; - } - - s = spool_new(xmlnode_pool(x)); - spooler(s,"<?xml version='1.0'?>",xmlnode2str(x),s); - head = spool_print(s); - fixr = strstr(head,"/>"); - *fixr = '>'; - ++fixr; - *fixr = '\0'; - - return head; -} -