Tailorization of /trunk
Import of the upstream sources from
Repository: file:///tmp/svn-mcabber
Module: /trunk
Revision: 15
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,9 @@
+(^|/)\.svn($|/)
+(^|/)\_darcs($|/)
+(^|/)CVS($|/)
+(^|/)\.cdv($|/)
+(^|/)MT($|/)
+(^|/)\.hg($|/)
+(^|/)\.bzr($|/)
+^tailor.log$
+^tailor.info$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/ACKNOWLEDGEMENT Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,16 @@
+Special Thanks to:
+ Daniel Borca (http://www.geocities.com/dborca).
+ Many of the new code is his own work!!!
+ Thanks Daniel!!!
+
+Thanks to:
+ Abrililla (???)
+ Gabber (http://gabber.sourceforge.net)
+ Manolo Romero (cobreti@mundivia.es)
+ NexusX (nexusx666@ajmacias.com)
+ Pablo2000 (josepablosc@wanadoo.es)
+ Pras (???)
+ Ted (ted@php.net)
+ Thomas Fischer (th.fischer@gmx.net)
+ _Yed_ (#linux at irc-hispano)
+ ZJoyKiller (#linux at irc-hispano)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/COPYING Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/Changelog Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,46 @@
+--[cabber 0.5.0-test1]--
+ - unification of lists in list.h
+ - changed UI... now is multiwindow and have popups!!!
+ - roster is now capable of add/delete buddies (very primitive and buggy!)
+ - improved many routines. Thanks to Daniel Borca.
+ - Added i18n function to translate cabber to others languages
+ - TODO: management of buddies away status...
+
+--[cabber 0.4.0-test5]--
+ - many bugs fixed: (roster, utf8...)
+
+--[cabber 0.4.0-test4]--
+ - added UTF8 encoding/decoding (yes, it have bugs...)
+ - added default color for make cabber transparent (Johannes WeiBl)
+ - fixed cursor position.
+
+--[cabber 0.4.0-test3]--
+ - rewritten routine "receivedata" at socket.c (bug #1: Johannes WeiBl)
+ - ignored left and rigth keys until i implement input line editor.
+ - colors are stored in $HOME/.cabberrc
+ - see cabberrc.example ;-)
+
+--[cabber 0.4.0-test2]--
+ - not public.
+
+--[cabber 0.4.0-test1]--
+ - many routines has been rewritten again d8-)
+
+ * use of lists instead of stacks for store data
+ - stack.c is not needed anymore, i use list.c instead.
+ - added a ugly routine for sort list (improve it!!)
+
+ * socket module has been rewritten and improved:
+ - O_NONBLOCK eliminated
+
+ * module parse.c has been rewritten: now is more effective.
+
+ * the XML parser is now more effective (i hope!)
+
+ * contact list:
+ - it have scroll bar now, (manoleT have a large list of contacts ;-)
+ - now contacts are sorted alphabetically.
+
+ * a lot of new bugs... sorry, but my main pc is broken. This version
+ of cabber has been made in my laptop.
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/Makefile Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,80 @@
+#
+# mcabber Makefile
+#
+
+
+#
+# Available options:
+#
+# Environment variables:
+# CPU optimize for the given processor.
+# default = pentium
+# DEBUG=1 disable optimizations and build for debug
+# default = no
+#
+# Targets:
+# all: build executable
+# clean: remove object files
+# realclean: remove all generated files
+# install: build & install
+# dep: create dependencies
+#
+
+
+.PHONY: all clean realclean install
+# dep
+
+CPU ?= i386
+JCLIENT = mcabber
+
+CC = gcc
+CFLAGS = -Wall -W -pedantic
+LD = gcc
+LDLIBS = -lncurses -lpanel
+
+ifeq ($(DEBUG),1)
+CFLAGS += -O0 -g -DDEBUG=1
+else
+CFLAGS += -O2 -mcpu=$(CPU)
+LDFLAGS = -s
+endif
+
+CP = cp -f
+
+SOURCES = \
+ main.c \
+ screen.c \
+ utils.c \
+ buddies.c \
+ parsecfg.c \
+ server.c \
+ socket.c \
+ lang.c \
+ utf8.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+all: $(JCLIENT)
+
+$(JCLIENT): $(OBJECTS)
+ $(LD) -o $@ $(LDFLAGS) $^ $(LDLIBS)
+
+clean:
+ -$(RM) *~
+ -$(RM) $(JCLIENT)
+ -$(RM) $(OBJECTS)
+# -$(RM) depend
+
+realclean: clean
+ -$(RM) $(JCLIENT)
+
+install: all
+ $(CP) $(JCLIENT) /usr/bin/$(JCLIENT)
+
+#dep: $(SOURCES)
+# makedepend -f- -Ylydialog -- $(CFLAGS) -- $(SOURCES) > depend
+
+#-include depend
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/README Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,17 @@
+Well, the documentation is missing yet, but...
+
+!!!!!! SEE mcabberrc.example !!!!!!
+
+configfile:
+ The configfile will be placed in $HOME/.mcabberrc
+ and it will be:
+
+ username = username
+ password = yourpassword
+ server = serveryou.use
+ resource = yourresourcenameOFFICE
+ passtype = plain (or sha1)
+
+
+That's all folks! (by the moment ;-)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/TODO Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,7 @@
+A "few" things :-)
+
+ * write XML code to add/delete buddies (the code is primitive)
+ * add control over delete buddies
+ * ...
+ * ...
+ * and many many things!!! :-)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/buddies.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,366 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ncurses.h>
+#include <panel.h>
+#include "screen.h"
+#include "buddies.h"
+
+#include "lang.h"
+#include "utils.h"
+#include "server.h"
+#include "list.h"
+#include "harddefines.h"
+
+/* global vars for BUDDIES.C */
+int buddySelected = 1; /* Hold the selected Buddy */
+int buddyOffset = 0; /* Hold the roster offset */
+
+static LIST_HEAD(buddy_list);
+static LIST_HEAD(sorted_buddies);
+#define buddy_entry(n) list_entry(n, buddy_entry_t, list)
+
+
+void bud_SetBuddyStatus(char *jidfrom, int status)
+{
+ struct list_head *pos, *n;
+ buddy_entry_t *tmp;
+ int changed = 0;
+ char *buffer = (char *) malloc(4096);
+
+ list_for_each_safe(pos, n, &buddy_list) {
+ tmp = buddy_entry(pos);
+ if (!strcmp(tmp->jid, jidfrom)) {
+ if (tmp->flags != status) {
+ tmp->flags = status;
+ changed = 1;
+ }
+ break;
+ }
+ }
+ if (changed) {
+ bud_DrawRoster(scr_GetRosterWindow());
+ switch (status) {
+ case FLAG_BUDDY_DISCONNECTED:
+ sprintf(buffer, "--> %s %s!", jidfrom, i18n("disconected"));
+ break;
+
+ case FLAG_BUDDY_CONNECTED:
+ sprintf(buffer, "--> %s %s!", jidfrom, i18n("connected"));
+ break;
+ }
+ scr_WriteInWindow(i18n("status window"), buffer, TRUE);
+ }
+ free(buffer);
+}
+
+int compara(buddy_entry_t * t1, buddy_entry_t * t2)
+{
+ const char *s1 =
+ (const char *) (STR_EMPTY(t1->name) ? t1->jid : t1->name);
+ const char *s2 =
+ (const char *) (STR_EMPTY(t2->name) ? t2->jid : t2->name);
+ return strcasecmp(s1, s2);
+}
+
+void bud_SortRoster(void)
+{
+ buddy_entry_t *indice, *tmp;
+ struct list_head *pos, *n;
+
+ while (!list_empty(&buddy_list)) {
+ indice = NULL;
+ tmp = NULL;
+ list_for_each_safe(pos, n, &buddy_list) {
+ if (!indice) {
+ indice = buddy_entry(pos);
+ tmp = buddy_entry(pos);
+ } else {
+ tmp = buddy_entry(pos);
+ if (compara(indice, tmp) > 0) {
+ indice = tmp;
+ }
+ }
+ }
+ list_move_tail(&indice->list, &sorted_buddies);
+ }
+ list_splice(&sorted_buddies, &buddy_list);
+}
+
+void bud_ParseBuddies(char *roster)
+{
+ buddy_entry_t *tmp = NULL;
+ char *aux;
+ char *p, *str;
+
+ ut_WriteLog("[roster]: %s\n\n", roster);
+
+ while ((aux = ut_strrstr(roster, "<item")) != NULL) {
+ char *jid = getattr(aux, "jid='");
+ char *name = getattr(aux, "name='");
+ char *group = gettag(aux, "group='");
+
+ *aux = '\0';
+
+ tmp = (buddy_entry_t *) calloc(1, sizeof(buddy_entry_t));
+
+ tmp->flags = FLAG_BUDDY_DISCONNECTED;
+
+ if (strncmp(jid, "UNK", 3)) {
+ char *res = strstr(jid, "/");
+ if (res)
+ *res = '\0';
+
+ tmp->jid = (char *) malloc(strlen(jid) + 1);
+ strcpy(tmp->jid, jid);
+ free(jid);
+ }
+
+ if (strncmp(name, "UNK", 3)) {
+ tmp->name = (char *) calloc(1, strlen(name) + 1);
+ strcpy(tmp->name, name);
+ free(name);
+ } else {
+ tmp->name = (char *) calloc(1, strlen(tmp->jid) + 1);
+ str = strdup(tmp->jid);
+ p = strstr(str, "@");
+ if (p) {
+ *p = '\0';
+ }
+ strncpy(tmp->name, str, 18);
+ free(str);
+ }
+
+ if (strncmp(group, "UNK", 3)) {
+ tmp->group = (char *) malloc(strlen(group) + 1);
+ strcpy(tmp->group, group);
+ free(group);
+ }
+
+ if (!strncmp(tmp->jid, "msn.", 4)) {
+ sprintf(tmp->name, "%c MSN %c", 254, 254);
+ }
+
+ if (!STR_EMPTY(tmp->jid)) {
+ list_add_tail(&tmp->list, &buddy_list);
+ } else {
+ if (tmp->jid)
+ free(tmp->jid);
+ if (tmp->name)
+ free(tmp->name);
+ if (tmp->group)
+ free(tmp->group);
+ free(tmp);
+ }
+ }
+ free(roster);
+
+ bud_SortRoster();
+}
+
+/* Desc: Initialize buddy list
+ *
+ * In : none
+ * Out: none
+ *
+ * Note: none
+ */
+void bud_InitBuddies(int sock)
+{
+ char *roster;
+ roster = srv_getroster(sock);
+ bud_ParseBuddies(roster);
+}
+
+/* Desc: Destroy (and free) buddy list
+ *
+ * In : none
+ * Out: none
+ *
+ * Note: none
+ */
+void bud_TerminateBuddies(void)
+{
+}
+
+/* Desc: Count elements in buddy list
+ *
+ * In : none
+ * Out: number of buddies
+ *
+ * Note: none
+ */
+int bud_BuddyCount(void)
+{
+ int i = 0;
+ struct list_head *pos, *n;
+
+ list_for_each_safe(pos, n, &buddy_list) {
+ i++;
+ }
+ return i;
+}
+
+/* Desc: Draw the roster in roster window
+ *
+ * In : roster window
+ * Out: none
+ *
+ * Note: none
+ */
+void bud_DrawRoster(WINDOW * win)
+{
+ buddy_entry_t *tmp = NULL;
+ struct list_head *pos, *nn;
+ int i = 1;
+ int n;
+ int maxx, maxy;
+ int fakeOffset = buddyOffset;
+
+ keypad(win, TRUE);
+ getmaxyx(win, maxy, maxx);
+
+
+ /* cleanup of roster window */
+ wattrset(win, COLOR_PAIR(COLOR_GENERAL));
+ for (i = 1; i < maxy - 1; i++) {
+ mvwprintw(win, i, 1, "");
+ for (n = 2; n < maxx; n++)
+ waddch(win, ' ');
+ }
+
+ i = 1;
+ list_for_each_safe(pos, nn, &buddy_list) {
+
+ if (fakeOffset > 0) {
+ fakeOffset--;
+ continue;
+ }
+
+ tmp = buddy_entry(pos);
+
+ if ((tmp->flags && FLAG_BUDDY_CONNECTED) == 1) {
+ if (i == (buddySelected - buddyOffset))
+ wattrset(win, COLOR_PAIR(COLOR_BD_CONSEL));
+ else
+ wattrset(win, COLOR_PAIR(COLOR_BD_CON));
+ } else {
+ if (i == (buddySelected - buddyOffset))
+ wattrset(win, COLOR_PAIR(COLOR_BD_DESSEL));
+ else
+ wattrset(win, COLOR_PAIR(COLOR_BD_DES));
+ }
+ mvwprintw(win, i, 1, "");
+ for (n = 2; n < maxx; n++)
+ waddch(win, ' ');
+ mvwprintw(win, i, (maxx - strlen(tmp->name)) / 2, "%s", tmp->name);
+ i++;
+ if (i >= maxy - 1)
+ break;
+ }
+ update_panels();
+ doupdate();
+}
+
+/* Desc: Change selected buddy (one position down)
+ *
+ * In : none
+ * Out: none
+ *
+ * Note: none
+ */
+void bud_RosterDown(void)
+{
+ int x, y;
+ getmaxyx(scr_GetRosterWindow(), y, x);
+ y -= 2;
+
+ if (buddySelected < bud_BuddyCount()) {
+ buddySelected++;
+ if (buddySelected > y)
+ buddyOffset++;
+ bud_DrawRoster(scr_GetRosterWindow());
+ }
+}
+
+/* Desc: Change selected buddy (one position up)
+ *
+ * In : none
+ * Out: none
+ *
+ * Note: none
+ */
+void bud_RosterUp(void)
+{
+ if (buddySelected > 1) {
+ buddySelected--;
+ if (buddySelected - buddyOffset < 1)
+ buddyOffset--;
+ bud_DrawRoster(scr_GetRosterWindow());
+ }
+}
+
+/* Desc: Retrieve info for selected buddy
+ *
+ * In : none
+ * Out: (buddy_entry_t *) of selected buddy
+ *
+ * Note: none
+ */
+buddy_entry_t *bud_SelectedInfo(void)
+{
+ struct list_head *pos, *n;
+ buddy_entry_t *tmp = NULL;
+
+ int i = 0;
+
+ list_for_each_safe(pos, n, &buddy_list) {
+ tmp = buddy_entry(pos);
+ if (i == buddySelected - 1) {
+ return tmp;
+ }
+ i++;
+ }
+ return NULL;
+}
+
+void bud_AddBuddy(int sock)
+{
+ char *buffer = (char *) calloc(1, 1024);
+ char *buffer2 = (char *) calloc(1, 1024);
+ char *p, *str;
+ buddy_entry_t *tmp;
+
+ ut_CenterMessage(i18n("write jid here"), 60, buffer2);
+ scr_CreatePopup(i18n("Add jid"), buffer2, 60, 1, buffer);
+
+ if (!STR_EMPTY(buffer)) {
+ tmp = (buddy_entry_t *) calloc(1, sizeof(buddy_entry_t));
+ tmp->jid = (char *) malloc(strlen(buffer) + 1);
+ strcpy(tmp->jid, buffer);
+ tmp->name = (char *) malloc(strlen(buffer) + 1);
+
+ str = strdup(buffer);
+ p = strstr(str, "@");
+ if (p) {
+ *p = '\0';
+ }
+ strcpy(tmp->name, str);
+ free(str);
+
+ list_add_tail(&tmp->list, &buddy_list);
+ buddySelected = 1;
+ bud_DrawRoster(scr_GetRosterWindow());
+ srv_AddBuddy(sock, tmp->jid);
+ }
+ free(buffer);
+}
+
+void bud_DeleteBuddy(int sock)
+{
+ buddy_entry_t *tmp = bud_SelectedInfo();
+ srv_DelBuddy(sock, tmp->jid);
+ list_del(&tmp->list);
+ buddySelected = 1;
+ bud_DrawRoster(scr_GetRosterWindow());
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/buddies.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,29 @@
+#ifndef __BUDDIES_H__
+#define __BUDDIES_H__ 1
+
+#include <ncurses.h>
+#include "list.h"
+
+/* Definición de tipos */
+typedef struct _buddy_entry_t {
+ char *jid;
+ char *name;
+ char *group;
+ char *resource;
+ int flags;
+ struct list_head list;
+} buddy_entry_t;
+
+void bud_DrawRoster(WINDOW * win);
+void bud_RosterDown(void);
+void bud_RosterUp(void);
+void bud_InitBuddies(int sock);
+void bud_TerminateBuddies(void);
+int bud_BuddyCount(void);
+void bud_SetBuddyStatus(char *jidfrom, int status);
+void bud_ParseBuddies(char *roster);
+void bud_AddBuddy(int sock);
+void bud_DeleteBuddy(int sock);
+buddy_entry_t *bud_SelectedInfo(void);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/cabberrc.example Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,18 @@
+username = yourusername
+password = yourpassword
+server = your.jabber.server
+port = 5222
+resource = yourresource
+passtype = plain
+
+
+#now, the colors
+#color are: black, red, green, yellow, blue, magenta, cyan, white
+color_background = blue
+color_backselected = cyan
+color_borderlines = white
+color_jidonlineselected = black
+color_jidonline = green
+color_jidofflineselected = red
+color_jidoffline = red
+color_text = white
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/harddefines.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,15 @@
+#ifndef __AJMACIAS__
+#define __AJMACIAS__ 0xWIN!
+
+#define VERSION "MCabber v0.6.0-dev -- based on http://cabber.sourceforge.net"
+#define EMAIL "Email: bmikael [at] lists [dot] lilotux [dot] net"
+
+#define STR_EMPTY(s) ((s)[0] == '\0')
+
+#define FLAG_BUDDY_DISCONNECTED 0x00
+#define FLAG_BUDDY_CONNECTED 0x01
+#define FLAG_BUDDY_AWAY 0x02
+#define FLAG_BUDDY_XAWAY 0x04
+#define FLAG_BUDDY_HASMESSAGE 0x08
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/lang.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+
+#include "utils.h"
+
+char Lang[100];
+
+void lng_InitLanguage(void)
+{
+ FILE *fp;
+ memset(Lang, 0, 100);
+ sprintf(Lang, "./lang/%s.txt", getenv("LANG"));
+/* strcpy(Lang, "./lang/");
+ strcat(Lang, getenv("LANG"));
+ strcat(Lang, ".txt");
+*/
+ if ((fp = fopen(Lang, "r")) == NULL) {
+ /* reverting to default */
+ ut_WriteLog("Reverting language to default: POSIX\n");
+ strcpy(Lang, "./lang/POSIX.txt");
+ } else {
+ fclose(fp);
+ ut_WriteLog("Setting language to %s\n", getenv("LANG"));
+ }
+}
+
+char *i18n(char *text)
+{
+ /* hack */
+ char *buf = (char *) malloc(1024);
+ static char result[1024];
+ FILE *fp;
+ char *line;
+ char *value;
+ int found = 0;
+
+ memset(result, 0, 1024);
+
+ if ((fp = fopen(Lang, "r")) != NULL) {
+ while ((fgets(buf, 1024, fp) != NULL) && (!found)) {
+ line = buf;
+
+ while (isspace((int) *line))
+ line++;
+
+ while ((strlen(line) > 0)
+ && isspace((int) line[strlen(line) - 1]))
+ line[strlen(line) - 1] = '\0';
+
+ if ((*line == '\n') || (*line == '\0') || (*line == '#'))
+ continue;
+
+ if ((strchr(line, '=') != NULL)) {
+ value = strchr(line, '=');
+ *value = '\0';
+ value++;
+
+ while (isspace((int) *value))
+ value++;
+
+ while ((strlen(line) > 0)
+ && isspace((int) line[strlen(line) - 1]))
+ line[strlen(line) - 1] = '\0';
+
+ if (!strcasecmp(line, text)) {
+ strcpy(result, value);
+ found = 1;
+ }
+ continue;
+ }
+ /* fprintf(stderr, "CFG: orphaned line \"%s\"\n", line); */
+ }
+ fclose(fp);
+ }
+
+ if (!found) {
+ strcpy(result, text);
+ }
+
+ free(buf);
+ return result;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/lang.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,7 @@
+#ifndef __LANG_H__
+#define __LANG_H__ 1
+
+void lng_InitLanguage(void);
+char *i18n(char *text);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/lang/POSIX.txt Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,21 @@
+#########################
+# text for help message #
+#########################
+#note the same lenght of lines, sorry!
+
+add contact = Add contact............
+delete contact = Delete contact.........
+view buddy window = Show buddy Window......
+send message = Send Message...........
+#########################
+
+exit = Exit
+help = Help
+Press any key = Press any key...
+roster = Contacts
+status window = Status Window
+write your message here = Write your message here
+write jid here = Write jid here
+
+conected = connected
+disconnected = disconnected
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/lang/es_ES.txt Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,21 @@
+#########################
+# text for help message #
+#########################
+#note the same lenght of lines, sorry!
+
+add contact = Añadir contacto........
+delete contact = Borrar contacto........
+view buddy window = Ver ventana contacto...
+send message = Enviar mensaje.........
+#########################
+
+exit = Salir
+help = Ayuda
+Press any key = Pulsa una tecla
+roster = Contactos
+status window = Ventana de estado
+write your message here = Escriba aquí su mensaje!
+write jid here = Escriba aquí el jid que desea añadir?
+
+connected = conectado
+disconnected = desconectado
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/list.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,213 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void
+__list_add(struct list_head *new,
+ struct list_head *prev, struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void
+list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = (void *) 0;
+ entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void
+list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void
+list_move_tail(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void
+__list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void
+list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void
+list_splice_init(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/main.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,291 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <termios.h>
+
+#include "utils.h"
+#include "screen.h"
+#include "buddies.h"
+#include "parsecfg.h"
+#include "lang.h"
+#include "server.h"
+#include "harddefines.h"
+#include "socket.h"
+
+int sock;
+
+void sig_handler(int signum)
+{
+ switch (signum) {
+ case SIGALRM:
+ sk_send(sock, " ");
+ break;
+
+ case SIGTERM:
+ bud_TerminateBuddies();
+ scr_TerminateCurses();
+ srv_setpresence(sock, "unavailable");
+ close(sock);
+ printf("Killed by SIGTERM\nBye!\n");
+ exit(EXIT_SUCCESS);
+ break;
+
+ }
+ signal(SIGALRM, sig_handler);
+}
+
+ssize_t my_getpass (char **passstr, size_t *n)
+{
+ struct termios orig, new;
+ int nread;
+
+ /* Turn echoing off and fail if we can't. */
+ if (tcgetattr(fileno (stdin), &orig) != 0)
+ return -1;
+ new = orig;
+ new.c_lflag &= ~ECHO;
+ if (tcsetattr(fileno (stdin), TCSAFLUSH, &new) != 0)
+ return -1;
+
+ /* Read the password. */
+ nread = getline(passstr, n, stdin);
+
+ /* Restore terminal. */
+ (void) tcsetattr(fileno (stdin), TCSAFLUSH, &orig);
+
+ return nread;
+}
+
+void credits(void)
+{
+ printf(VERSION "\n");
+ printf(EMAIL "\n");
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ char configFile[4096];
+ char *buffer;
+ char *secbuffer;
+ char *username, *password, *resource;
+ char *servername;
+ char *idsession;
+ char *portstring;
+ int key;
+ unsigned int port;
+ unsigned int ping;
+
+
+ credits();
+
+ /* SET THIS >0 TO ENABLE LOG */
+ ut_InitDebug(1);
+
+ lng_InitLanguage();
+
+ ut_WriteLog("Setting signals handlers...\n");
+ signal(SIGTERM, sig_handler);
+ signal(SIGALRM, sig_handler);
+
+
+ sprintf(configFile, "%s/.mcabberrc", getenv("HOME"));
+
+ /* Proceso opciones de usuario */
+ while (1) {
+ int c = getopt(argc, argv, "hf:");
+ if (c == -1) {
+ break;
+ } else
+ switch (c) {
+ case 'h':
+ printf("Usage: %s [-f mcabberrc_file]\n\n", argv[0]);
+ printf("Thanks to AjMacias for cabber!\n\n");
+ return 0;
+ case 'f':
+ strncpy(configFile, optarg, 1024);
+ break;
+ }
+ }
+
+ ut_WriteLog("Setting config file: %s\n", configFile);
+
+
+ /* Parsing config file... */
+ ut_WriteLog("Parsing config file...\n");
+ cfg_file(configFile);
+
+ servername = cfg_read("server");
+ username = cfg_read("username");
+ password = cfg_read("password");
+ resource = cfg_read("resource");
+
+ if (!servername) {
+ printf("Server name has not been specified in the config file!\n");
+ return -1;
+ }
+ if (!username) {
+ printf("User name has not been specified in the config file!\n");
+ return -1;
+ }
+ if (!password) {
+ char *p;
+ size_t passsize = 64;
+ printf("Please enter password: ");
+ my_getpass(&password, &passsize);
+ printf("\n");
+ for (p = password; *p; p++);
+ for ( ; p > password ; p--)
+ if (*p == '\n' || *p == '\r') *p = 0;
+ }
+
+ /* Initialize N-Curses */
+ ut_WriteLog("Initializing N-Curses...\n");
+ scr_InitCurses();
+
+ /* Connect to server */
+ portstring = cfg_read("port");
+ port = (portstring != NULL) ? atoi(portstring) : -1;
+
+ ut_WriteLog("Connecting to server: %s:%d\n", servername, port);
+ if ((sock = srv_connect(servername, port)) < 0) {
+ ut_WriteLog("\terror!!!\n");
+ fprintf(stderr, "Error connecting to (%s)\n", servername);
+ scr_TerminateCurses();
+ return -2;
+ }
+
+ ut_WriteLog("Sending login string...\n");
+ if ((idsession = srv_login(sock, servername, username, password,
+ resource)) == NULL) {
+
+ ut_WriteLog("\terror!!!\n");
+ fprintf(stderr, "Error sending login string...\n");
+ scr_TerminateCurses();
+ return -3;
+ }
+ ut_WriteLog("Connected to %s: %s\n", servername, idsession);
+ free(idsession);
+
+ ut_WriteLog("Requesting roster...\n");
+ bud_InitBuddies(sock);
+
+ ut_WriteLog("Sending presence...\n");
+ srv_setpresence(sock, "Online!");
+
+
+ ut_WriteLog("Drawing main window...\n");
+ scr_DrawMainWindow();
+
+ ping = 15;
+ if (cfg_read("pinginterval"))
+ ping = atoi(cfg_read("pinginterval"));
+
+ ut_WriteLog("Ping interval stablished: %d secs\n", ping);
+
+ ut_WriteLog("Entering into main loop...\n\n");
+ ut_WriteLog("Ready to send/receive messages...\n");
+ key = 0;
+ while (key != 'x') {
+ int x;
+ alarm(ping);
+ x = check_io(sock, 0);
+ if ((x & 1) == 1) {
+ srv_msg *incoming = readserver(sock);
+
+ switch (incoming->m) {
+ case SM_PRESENCE:
+ bud_SetBuddyStatus(incoming->from, incoming->connected);
+ break;
+
+ case SM_MESSAGE:
+ scr_WriteIncomingMessage(incoming->from, incoming->body);
+ free(incoming->body);
+ free(incoming->from);
+ break;
+
+ case SM_UNHANDLED:
+ break;
+ }
+ free(incoming);
+ }
+ if ((x & 2) == 2) {
+ keypad(scr_GetRosterWindow(), TRUE);
+ key = scr_Getch();
+ switch (key) {
+ case KEY_IC:
+ bud_AddBuddy(sock);
+ break;
+ case KEY_DC:
+ bud_DeleteBuddy(sock);
+ break;
+ case KEY_DOWN:
+ bud_RosterDown();
+ break;
+ case KEY_UP:
+ bud_RosterUp();
+ break;
+
+ case 0x19a:
+ endwin();
+ printf("\nRedimensionado no implementado\n");
+ printf("Reinicie Cabber.\n\n\n");
+ exit(EXIT_FAILURE);
+ break;
+
+ case KEY_NPAGE:
+ for (i = 0; i < 10; i++)
+ bud_RosterDown();
+ break;
+
+ case KEY_PPAGE:
+ for (i = 0; i < 10; i++)
+ bud_RosterUp();
+ break;
+
+ case 'z':
+ case KEY_F(1):
+ buffer = (char *) calloc(1, 4096);
+ secbuffer = (char *) calloc(1, 4096);
+
+ sprintf(secbuffer, "INS = %s ", i18n("Add contact"));
+ i = strlen(secbuffer);
+ strcpy(buffer, secbuffer);
+ sprintf(secbuffer, "DEL = %s ", i18n("Delete contact"));
+ strcat(buffer, secbuffer);
+ sprintf(secbuffer, "SPACE = %s ", i18n("View buddy window"));
+ strcat(buffer, secbuffer);
+ sprintf(secbuffer, "INTRO = %s ", i18n("Send message"));
+ strcat(buffer, secbuffer);
+ sprintf(secbuffer, "ESC = %s ", i18n("Exit"));
+ strcat(buffer, secbuffer);
+
+ scr_CreatePopup(i18n("help"), buffer, i, 0, NULL);
+ free(buffer);
+ free(secbuffer);
+ break;
+
+ case '\n':
+ scr_WriteMessage(sock);
+ break;
+
+ case ' ':
+ scr_ShowBuddyWindow();
+ break;
+ }
+ }
+ }
+
+ bud_TerminateBuddies();
+ scr_TerminateCurses();
+
+ srv_setpresence(sock, "unavailable");
+
+ close(sock);
+
+ printf("\n\nHave a nice day!\nBye!\n");
+
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/parsecfg.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+
+
+#include "list.h"
+
+/* Definicion de tipos */
+#define MAX_LENGHT_INPUT 1024
+#define cfg_entry(n) list_entry(n, cfg_entry_t, list)
+
+typedef struct _cfg_entry_t {
+ char *key;
+ char *value;
+ struct list_head list;
+} cfg_entry_t;
+
+static LIST_HEAD(cfg_list);
+
+
+void push_in_list(char *key, char *value)
+{
+ cfg_entry_t *new_entry = calloc(1, sizeof(cfg_entry_t));
+
+ new_entry->key = (char *) calloc(1, strlen(key) + 1);
+ new_entry->value = (char *) calloc(1, strlen(value) + 1);
+
+ strcpy(new_entry->key, key);
+ strcpy(new_entry->value, value);
+
+ list_add(&new_entry->list, &cfg_list);
+}
+
+int cfg_file(char *filename)
+{
+ FILE *fp;
+ char *buf;
+ char *line;
+ char *value;
+
+ buf = malloc(255);
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ perror("fopen (parsecfg.c:46)");
+ exit(EXIT_FAILURE);
+ }
+
+ while (fgets(buf, 255, fp) != NULL) {
+ line = buf;
+
+ while (isspace((int) *line))
+ line++;
+
+ while ((strlen(line) > 0)
+ && isspace((int) line[strlen(line) - 1]))
+ line[strlen(line) - 1] = '\0';
+
+ if ((*line == '\n') || (*line == '\0') || (*line == '#'))
+ continue;
+
+ if ((strchr(line, '=') != NULL)) {
+ value = strchr(line, '=');
+ *value = '\0';
+ value++;
+
+ while (isspace((int) *value))
+ value++;
+
+ while ((strlen(line) > 0)
+ && isspace((int) line[strlen(line) - 1]))
+ line[strlen(line) - 1] = '\0';
+
+ push_in_list(line, value);
+ continue;
+ }
+ fprintf(stderr, "CFG: orphaned line \"%s\"\n", line);
+ }
+ return 1;
+}
+
+char *cfg_read(char *key)
+{
+ struct list_head *n, *pos;
+ cfg_entry_t *search_entry = NULL;
+
+ list_for_each_safe(pos, n, &cfg_list) {
+ search_entry = cfg_entry(pos);
+ if (search_entry->key) {
+ if (!strcasecmp(search_entry->key, key)) {
+ return search_entry->value;
+ }
+ }
+ }
+ return NULL;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/parsecfg.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,7 @@
+#ifndef __PARSECFG_H__
+#define __PARSECFG_H__ 1
+
+int cfg_file(char *filename);
+char *cfg_read(char *key);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/screen.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,546 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ncurses.h>
+#include <panel.h>
+#include <time.h>
+#include <ctype.h>
+
+#include "screen.h"
+#include "utils.h"
+#include "buddies.h"
+#include "parsecfg.h"
+#include "lang.h"
+#include "server.h"
+
+#include "list.h"
+
+/* Definicion de tipos */
+#define window_entry(n) list_entry(n, window_entry_t, list)
+
+typedef struct _window_entry_t {
+ WINDOW *win;
+ PANEL *panel;
+ char *name;
+ int nlines;
+ char **texto;
+ struct list_head list;
+} window_entry_t;
+
+LIST_HEAD(window_list);
+
+/* Variables globales a SCREEN.C */
+WINDOW *rosterWnd, *chatWnd;
+PANEL *rosterPanel, *chatPanel;
+int maxY, maxX;
+window_entry_t *ventanaActual;
+
+
+/* Funciones */
+
+int scr_WindowHeight(WINDOW * win)
+{
+ int x, y;
+ getmaxyx(win, y, x);
+ return x;
+}
+
+void
+scr_draw_box(WINDOW * win, int y, int x, int height, int width, int Color,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset(win, COLOR_PAIR(Color));
+ for (i = 0; i < height; i++) {
+ wmove(win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch(win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch(win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch(win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch(win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch(win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch(win, box | ACS_HLINE);
+ else if (!j)
+ waddch(win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch(win, box | ACS_VLINE);
+ else
+ waddch(win, box | ' ');
+ }
+}
+
+int FindColor(char *name)
+{
+ if (!strcmp(name, "default"))
+ return -1;
+ if (!strcmp(name, "black"))
+ return COLOR_BLACK;
+ if (!strcmp(name, "red"))
+ return COLOR_RED;
+ if (!strcmp(name, "green"))
+ return COLOR_GREEN;
+ if (!strcmp(name, "yellow"))
+ return COLOR_YELLOW;
+ if (!strcmp(name, "blue"))
+ return COLOR_BLUE;
+ if (!strcmp(name, "magenta"))
+ return COLOR_MAGENTA;
+ if (!strcmp(name, "cyan"))
+ return COLOR_CYAN;
+ if (!strcmp(name, "white"))
+ return COLOR_WHITE;
+
+ return -1;
+}
+
+void ParseColors(void)
+{
+ char *colors[11] = {
+ "", "",
+ "borderlines",
+ "jidonlineselected",
+ "jidonline",
+ "jidofflineselected",
+ "jidoffline",
+ "text",
+ NULL
+ };
+
+ char *tmp = malloc(1024);
+ char *color1;
+ char *background = cfg_read("color_background");
+ char *backselected = cfg_read("color_backselected");
+ int i = 0;
+
+ while (colors[i]) {
+ sprintf(tmp, "color_%s", colors[i]);
+ color1 = cfg_read(tmp);
+
+ switch (i + 1) {
+ case 1:
+ init_pair(1, COLOR_BLACK, COLOR_WHITE);
+ break;
+ case 2:
+ init_pair(2, COLOR_WHITE, COLOR_BLACK);
+ break;
+ case 3:
+ init_pair(3, FindColor(color1), FindColor(background));
+ break;
+ case 4:
+ init_pair(4, FindColor(color1), FindColor(backselected));
+ break;
+ case 5:
+ init_pair(5, FindColor(color1), FindColor(background));
+ break;
+ case 6:
+ init_pair(6, FindColor(color1), FindColor(backselected));
+ break;
+ case 7:
+ init_pair(7, FindColor(color1), FindColor(background));
+ break;
+ case 8:
+ init_pair(8, FindColor(color1), FindColor(background));
+ break;
+ }
+ i++;
+ }
+}
+
+
+window_entry_t *scr_CreatePanel(char *title, int x, int y, int lines,
+ int cols)
+{
+ window_entry_t *tmp = calloc(1, sizeof(window_entry_t));
+
+ tmp->win = newwin(lines, cols, y, x);
+ tmp->panel = new_panel(tmp->win);
+ tmp->name = (char *) calloc(1, 1024);
+ strncpy(tmp->name, title, 1024);
+ scr_draw_box(tmp->win, 0, 0, lines, cols, COLOR_GENERAL, 0, 0);
+ mvwprintw(tmp->win, 0, (cols - (2 + strlen(title))) / 2, " %s ", title);
+
+ list_add_tail(&tmp->list, &window_list);
+ update_panels();
+
+ return tmp;
+}
+
+
+void
+scr_CreatePopup(char *title, char *texto, int corte, int type,
+ char *returnstring)
+{
+ WINDOW *popupWin;
+ PANEL *popupPanel;
+
+ int lineas = 0;
+ int cols = 0;
+
+ char **submsgs;
+ int n = 0;
+ int i;
+
+ char *instr = (char *) calloc(1, 1024);
+
+ /* fprintf(stderr, "\r\n%d", lineas); */
+
+ submsgs = ut_SplitMessage(texto, &n, corte);
+
+ switch (type) {
+ case 1:
+ case 0:
+ lineas = n + 4;
+ break;
+ }
+
+ cols = corte + 3;
+ popupWin = newwin(lineas, cols, (maxY - lineas) / 2, (maxX - cols) / 2);
+ popupPanel = new_panel(popupWin);
+
+ /*ATENCION!!! Colorear el popup ??
+ / box (popupWin, 0, 0); */
+ scr_draw_box(popupWin, 0, 0, lineas, cols, COLOR_POPUP, 0, 0);
+ mvwprintw(popupWin, 0, (cols - (2 + strlen(title))) / 2, " %s ", title);
+
+ for (i = 0; i < n; i++)
+ mvwprintw(popupWin, i + 1, 2, "%s", submsgs[i]);
+
+
+ for (i = 0; i < n; i++)
+ free(submsgs[i]);
+ free(submsgs);
+
+ switch (type) {
+ case 0:
+ mvwprintw(popupWin, n + 2,
+ (cols - (2 + strlen(i18n("Press any key")))) / 2,
+ i18n("Press any key"));
+ update_panels();
+ doupdate();
+ getch();
+ break;
+ case 1:
+ {
+ char ch;
+ int scroll = 0;
+ int input_x = 0;
+
+ wmove(popupWin, 3, 1);
+ wrefresh(popupWin);
+ keypad(popupWin, TRUE);
+ while ((ch = getch()) != '\n') {
+ switch (ch) {
+ case 0x09:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_RIGHT:
+ case KEY_LEFT:
+ break;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ /* wattrset (popupWin, 0); */
+ if (!input_x) {
+ scroll = scroll < cols - 3 ? 0 : scroll - (cols - 3);
+ wmove(popupWin, 3, 1);
+ for (i = 0; i < cols; i++)
+ waddch
+ (popupWin,
+ instr
+ [scroll
+ + input_x + i] ? instr[scroll + input_x + i] : ' ');
+ input_x = strlen(instr) - scroll;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch(popupWin, 3, input_x + 1, ' ');
+ wmove(popupWin, 3, input_x + 1);
+ wrefresh(popupWin);
+ }
+ default:
+ if ( /*ch<0x100 && */ isprint(ch) || ch == 'ñ'
+ || ch == 'Ñ') {
+ if (scroll + input_x < 1024) {
+ instr[scroll + input_x] = ch;
+ instr[scroll + input_x + 1] = '\0';
+ if (input_x == cols - 3) {
+ scroll++;
+ wmove(popupWin, 3, 1);
+ for (i = 0; i < cols - 3; i++)
+ waddch(popupWin, instr[scroll + i]);
+ } else {
+ wmove(popupWin, 3, 1 + input_x++);
+ waddch(popupWin, ch);
+ }
+ wrefresh(popupWin);
+ } else {
+ flash();
+ }
+ }
+ }
+ }
+ }
+ if (returnstring != NULL)
+ strcpy(returnstring, instr);
+ break;
+ }
+
+ del_panel(popupPanel);
+ delwin(popupWin);
+ update_panels();
+ doupdate();
+ free(instr);
+ keypad(rosterWnd, TRUE);
+}
+
+
+
+void scr_RoolWindow(void)
+{
+}
+
+window_entry_t *scr_SearchWindow(char *nombreVentana)
+{
+ struct list_head *pos, *n;
+ window_entry_t *search_entry = NULL;
+
+ list_for_each_safe(pos, n, &window_list) {
+ search_entry = window_entry(pos);
+ if (search_entry->name) {
+ if (!strcasecmp(search_entry->name, nombreVentana)) {
+ return search_entry;
+ }
+ }
+ }
+ return NULL;
+}
+
+void scr_ShowWindow(char *nombreVentana)
+{
+ int n, width, i;
+ window_entry_t *tmp = scr_SearchWindow(nombreVentana);
+ if (tmp != NULL) {
+ top_panel(tmp->panel);
+ width = scr_WindowHeight(tmp->win);
+ for (n = 0; n < tmp->nlines; n++) {
+ mvwprintw(tmp->win, n + 1, 1, "");
+ for (i = 0; i < width - 2; i++)
+ waddch(tmp->win, ' ');
+ mvwprintw(tmp->win, n + 1, 1, "%s", tmp->texto[n]);
+ }
+ move(maxY - 2, maxX - 1);
+ update_panels();
+ doupdate();
+ }
+}
+
+void scr_ShowBuddyWindow(void)
+{
+ buddy_entry_t *tmp = bud_SelectedInfo();
+ if (tmp->jid != NULL)
+ scr_ShowWindow(tmp->jid);
+}
+
+
+void scr_WriteInWindow(char *nombreVentana, char *texto, int TimeStamp)
+{
+ time_t ahora;
+ int n;
+ int i;
+ int width;
+ window_entry_t *tmp;
+
+ tmp = scr_SearchWindow(nombreVentana);
+ if (tmp == NULL) {
+ tmp = scr_CreatePanel(nombreVentana, 20, 0, maxY-1, maxX - 20);
+ tmp->texto = (char **) calloc(maxY * 3, sizeof(char *));
+ for (n = 0; n < (maxY-1) * 3; n++)
+ tmp->texto[n] = (char *) calloc(1, 1024);
+
+ if (TimeStamp) {
+ ahora = time(NULL);
+ strftime(tmp->texto[tmp->nlines], 1024, "[%H:%M] ",
+ localtime(&ahora));
+ strcat(tmp->texto[tmp->nlines], texto);
+ } else {
+ sprintf(tmp->texto[tmp->nlines], " %s", texto);
+ }
+ tmp->nlines++;
+ } else {
+ if (tmp->nlines < maxY - 3) {
+ if (TimeStamp) {
+ ahora = time(NULL);
+ strftime(tmp->texto[tmp->nlines], 1024,
+ "[%H:%M] ", localtime(&ahora));
+ strcat(tmp->texto[tmp->nlines], texto);
+ } else {
+ sprintf(tmp->texto[tmp->nlines], " %s", texto);
+ }
+ tmp->nlines++;
+ } else {
+ for (n = 0; n < tmp->nlines; n++) {
+ memset(tmp->texto[n], 0, 1024);
+ strncpy(tmp->texto[n], tmp->texto[n + 1], 1024);
+ }
+ if (TimeStamp) {
+ ahora = time(NULL);
+ strftime(tmp->texto[tmp->nlines - 1], 1024,
+ "[%H:%M] ", localtime(&ahora));
+ strcat(tmp->texto[tmp->nlines - 1], texto);
+ } else {
+ sprintf(tmp->texto[tmp->nlines - 1], " %s", texto);
+ }
+ }
+ }
+
+ top_panel(tmp->panel);
+ width = scr_WindowHeight(tmp->win);
+ for (n = 0; n < tmp->nlines; n++) {
+ mvwprintw(tmp->win, n + 1, 1, "");
+ for (i = 0; i < width - 2; i++)
+ waddch(tmp->win, ' ');
+ mvwprintw(tmp->win, n + 1, 1, "%s", tmp->texto[n]);
+ }
+
+ update_panels();
+ doupdate();
+}
+
+void scr_InitCurses(void)
+{
+ initscr();
+ noecho();
+ raw();
+ start_color();
+ use_default_colors();
+
+ ParseColors();
+
+ getmaxyx(stdscr, maxY, maxX);
+
+ return;
+}
+
+void scr_DrawMainWindow(void)
+{
+ /* Dibujamos los paneles principales */
+ rosterWnd = newwin(maxY-1, 20, 0, 0);
+ rosterPanel = new_panel(rosterWnd);
+ scr_draw_box(rosterWnd, 0, 0, maxY-1, 20, COLOR_GENERAL, 0, 0);
+ mvwprintw(rosterWnd, 0, (20 - strlen(i18n("Roster"))) / 2,
+ i18n("Roster"));
+
+ chatWnd = newwin(maxY-1, maxX - 20, 0, 20);
+ chatPanel = new_panel(chatWnd);
+ scr_draw_box(chatWnd, 0, 0, maxY-1, maxX - 20, COLOR_GENERAL, 0, 0);
+ mvwprintw(chatWnd, 0,
+ ((maxX - 20) - strlen(i18n("Status Window"))) / 2,
+ i18n("Status Window"));
+
+ bud_DrawRoster(rosterWnd);
+
+ update_panels();
+ doupdate();
+ return;
+}
+
+void scr_TerminateCurses(void)
+{
+ clear();
+ refresh();
+ endwin();
+ return;
+}
+
+void scr_WriteIncomingMessage(char *jidfrom, char *text)
+{
+ char **submsgs;
+ int n, i;
+ char *buffer = (char *) malloc(5 + strlen(text));
+
+ sprintf(buffer, "<<< %s", text);
+
+ submsgs =
+ ut_SplitMessage(buffer, &n, maxX - scr_WindowHeight(rosterWnd) - 20);
+
+ for (i = 0; i < n; i++) {
+ if (i == 0)
+ scr_WriteInWindow(jidfrom, submsgs[i], TRUE);
+ else
+ scr_WriteInWindow(jidfrom, submsgs[i], FALSE);
+ }
+
+ for (i = 0; i < n; i++)
+ free(submsgs[i]);
+
+ free(submsgs);
+ free(buffer);
+
+}
+
+void scr_WriteMessage(int sock)
+{
+ char **submsgs;
+ int n, i;
+ char *buffer = (char *) calloc(1, 1024);
+ char *buffer2 = (char *) calloc(1, 1024);
+ buddy_entry_t *tmp = bud_SelectedInfo();
+
+ scr_ShowWindow(tmp->jid);
+
+ ut_CenterMessage(i18n("write your message here"), 60, buffer2);
+
+ scr_CreatePopup(tmp->jid, buffer2, 60, 1, buffer);
+
+ if (strlen(buffer)) {
+ sprintf(buffer2, ">>> %s", buffer);
+
+ submsgs =
+ ut_SplitMessage(buffer2, &n,
+ maxX - scr_WindowHeight(rosterWnd) - 20);
+ for (i = 0; i < n; i++) {
+ if (i == 0)
+ scr_WriteInWindow(tmp->jid, submsgs[i], TRUE);
+ else
+ scr_WriteInWindow(tmp->jid, submsgs[i], FALSE);
+ }
+
+ for (i = 0; i < n; i++)
+ free(submsgs[i]);
+ free(submsgs);
+
+ move(maxY - 2, maxX - 1);
+ refresh();
+ sprintf(buffer2, "%s@%s/%s", cfg_read("username"),
+ cfg_read("server"), cfg_read("resource"));
+ srv_sendtext(sock, tmp->jid, buffer, buffer2);
+ }
+ free(buffer);
+ free(buffer2);
+}
+
+int scr_Getch(void)
+{
+ int ch;
+ keypad(rosterWnd, TRUE);
+ ch = wgetch(rosterWnd);
+ return ch;
+}
+
+WINDOW *scr_GetRosterWindow(void)
+{
+ return rosterWnd;
+}
+
+WINDOW *scr_GetStatusWindow(void)
+{
+ return chatWnd;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/screen.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,30 @@
+#ifndef __SCREEN_H__
+#define __SCREEN_H__ 1
+
+#include <ncurses.h>
+
+#define COLOR_POPUP 1
+#define COLOR_GENERAL 3
+#define COLOR_BD_CONSEL 4
+#define COLOR_BD_CON 5
+#define COLOR_BD_DESSEL 6
+#define COLOR_BD_DES 7
+
+void scr_InitCurses(void);
+void scr_DrawMainWindow(void);
+void scr_TerminateCurses(void);
+void scr_CreatePopup(char *title, char *texto, int corte, int type,
+ char *returnstring);
+void scr_WriteInWindow(char *nombreVentana, char *texto, int TimeStamp);
+void scr_WriteMessage(int sock);
+void scr_WriteIncomingMessage(char *jidfrom, char *text);
+void scr_RoolWindow(void);
+void scr_ShowBuddyWindow(void);
+
+WINDOW *scr_GetRosterWindow(void);
+WINDOW *scr_GetStatusWindow(void);
+
+int scr_Getch(void);
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/server.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,459 @@
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/poll.h>
+
+#include "list.h"
+#include "parsecfg.h"
+#include "screen.h"
+#include "socket.h"
+#include "utf8.h"
+#include "server.h"
+#include "harddefines.h"
+#include "utils.h"
+#include "buddies.h"
+
+#define JABBERPORT 5222
+
+
+/* Desc: poll data from server
+ *
+ * In : socket
+ * Out : pending buffer (or NULL if no incoming data)
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_poll(int sock)
+{
+ struct pollfd sock_p;
+ sock_p.fd = sock;
+ sock_p.events = POLLIN | POLLPRI;
+ sock_p.revents = 0;
+ poll(&sock_p, 1, 0);
+
+ if (sock_p.revents) {
+ return sk_recv(sock);
+ }
+
+ return NULL;
+}
+
+
+/* Desc: resolve host
+ *
+ * In : hostname
+ * Out : 32bit address (or 0 if error)
+ *
+ * Note: -
+ */
+static u_long srv_resolve(const char *host)
+{
+ long i;
+ struct hostent *he;
+
+ if ((i = inet_addr(host)) == -1) {
+ if (!(he = gethostbyname(host)))
+ return 0;
+ else
+ return (*(u_long *) he->h_addr);
+ }
+
+ return i;
+}
+
+
+/* Desc: connect to jabber server
+ *
+ * In : config
+ * Out : socket (or -1 on error)
+ *
+ * Note: if port is -1, the default Jabber port will be used
+ */
+int srv_connect(const char *server, unsigned int port)
+{
+ struct sockaddr_in name;
+ int sock;
+
+ if (server == NULL) {
+ fprintf(stderr, "You must supply a server name\n\r");
+ return -1;
+ }
+
+ if (port == -1U) {
+ port = JABBERPORT;
+ }
+
+ name.sin_family = AF_INET;
+ name.sin_port = htons(port);
+
+ if (!(name.sin_addr.s_addr = srv_resolve(server))) {
+ fprintf(stderr, "Cant resolve \"%s\"\n", server);
+ return -1;
+ }
+
+ if ((sock = sk_conn((struct sockaddr *) &name)) < 0) {
+ fprintf(stderr, "Cant connect to \"%s:%u\"\n", server, port);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/* Desc: login into jabber server
+ *
+ * In : socket, servername, user, password, resource
+ * Out : idsession
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_login(int sock, const char *server, const char *user,
+ const char *pass, const char *resource)
+{
+ char *stringtosend = malloc(2048);
+ char *response, *aux;
+ char *idsession = malloc(128);
+ int pos = 0;
+
+ memset(stringtosend, 0, 2048);
+ strcpy(stringtosend, "<?xml version='1.0' encoding='UTF-8' ?>");
+ strcat(stringtosend, "<stream:stream to='");
+ strcat(stringtosend, server);
+ strcat(stringtosend, "' xmlns='jabber:client' xmlns:stream='");
+ strcat(stringtosend, "http://etherx.jabber.org/streams'>\n");
+
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:132)");
+ return NULL;
+ }
+ response = sk_recv(sock);
+ if (strstr(response, "error")) {
+ /* fprintf(stderr, "Response not valid:\n%s\n\n", response); */
+ scr_CreatePopup("Error",
+ "El servidor no esta respondiendo correctamente",
+ 60, 0, NULL);
+ return NULL;
+ }
+ aux = response;
+ while (strncmp(aux, "id", 2))
+ aux++;
+ pos = 0;
+ aux += 4;
+ while (strncmp(aux, "'", 1)) {
+ aux++;
+ pos++;
+ }
+ aux -= pos;
+ strncpy(idsession, aux, pos);
+
+ free(response);
+
+ strcpy(stringtosend, "<iq type='set' id='1000'>");
+ strcat(stringtosend, "<query xmlns='jabber:iq:auth'>");
+ strcat(stringtosend, "<username>");
+ strcat(stringtosend, user);
+ strcat(stringtosend, "</username><password>");
+ strcat(stringtosend, pass);
+ strcat(stringtosend, "</password><resource>");
+ strcat(stringtosend, resource);
+ strcat(stringtosend, "</resource></query></iq>\n");
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:167)");
+ return NULL;
+ }
+ response = sk_recv(sock);
+ if (strstr(response, "error")) {
+/* fprintf(stderr, "Response not valid:\n%s\n\n", response);*/
+ scr_CreatePopup("Error",
+ "Cuenta no creada o contraseña incorrecta", 60, 0,
+ NULL);
+ scr_CreatePopup("Info", "Intentando crear la cuenta...", 60, 0, NULL);
+
+
+ strcpy(stringtosend, "<iq type='set' id='reg' to='");
+ strcat(stringtosend, server);
+ strcat(stringtosend, "'>");
+ strcat(stringtosend, "<query xmlns='jabber:iq:register'>");
+ strcat(stringtosend, "<username>");
+ strcat(stringtosend, user);
+ strcat(stringtosend, "</username><password>");
+ strcat(stringtosend, pass);
+ strcat(stringtosend, "</password>");
+ strcat(stringtosend, "</query></iq>\n");
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:167)");
+ return NULL;
+ }
+
+ response = sk_recv(sock);
+ scr_TerminateCurses();
+ printf("Reinicie cabber!\n\n");
+ return NULL;
+ }
+ free(response);
+ free(stringtosend);
+
+ return idsession;
+}
+
+
+/* Desc: broadcast presence
+ *
+ * In : socket, presence string
+ * Out : ?
+ *
+ * Note: see `sk_send' for output values
+ */
+int srv_setpresence(int sock, const char *type)
+{
+ int rv;
+ char *str = malloc(1024);
+
+ sprintf(str, "<presence><status>%s</status></presence>", type);
+ if (!(rv = sk_send(sock, str))) {
+ perror("senddata (server.c:199)");
+ }
+ free(str);
+
+ return rv;
+}
+
+
+/* Desc: request roster
+ *
+ * In : socket
+ * Out : roster string
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_getroster(int sock)
+{
+ char *str = malloc(1024);
+
+ strcpy(str, "<iq type='get' id='1001'><query xmlns='");
+ strcat(str, "jabber:iq:roster'/></iq>\n");
+ if (!sk_send(sock, str)) {
+ perror("senddata (server.c:222)");
+ return NULL;
+ }
+ free(str);
+
+ return sk_recv(sock);
+}
+
+
+/* Desc: send text to buddy
+ *
+ * In : socket, destination jid, text, source jid
+ * Out : 0 = ok
+ *
+ * Note: -
+ */
+int
+srv_sendtext(int sock, const char *to, const char *text, const char *from)
+{
+ char *stringtosend = malloc(2048);
+ char *utf8inputline = utf8_encode(text);
+
+ sprintf(stringtosend,
+ "<message from='%s' to='%s' type='chat'><body>%s</body></message>",
+ from, to, utf8inputline);
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:247)");
+ return -1;
+ }
+
+ free(stringtosend);
+ free(utf8inputline);
+ return 0;
+}
+
+int check_io(int fd1, int fd2)
+{
+ int n = 0, i;
+ fd_set fds;
+ int io_pending = 0;
+
+ i = fd1;
+ if (fd2 > fd1)
+ i = fd2;
+
+ FD_ZERO(&fds);
+ if (fd1 >= 0)
+ FD_SET(fd1, &fds);
+ else
+ fd1 = 0;
+ if (fd2 >= 0)
+ FD_SET(fd2, &fds);
+ else
+ fd2 = 0;
+
+ if (fd2 == 0 && io_pending)
+ n = 2;
+ else if (select(i + 1, &fds, NULL, NULL, NULL) > 0)
+ n = 1 * (FD_ISSET(fd1, &fds) > 0) + 2 * (FD_ISSET(fd2, &fds) > 0);
+
+ return (n);
+}
+
+/* Desc: read data from server
+ *
+ * In : socket
+ * Out : ptr to newly allocated srv_msg struct
+ *
+ * Note: returns NULL if no input from server
+ */
+srv_msg *readserver(int sock)
+{
+ char *buffer = sk_recv(sock);
+
+ if (buffer != NULL) {
+ srv_msg *msg = calloc(1, sizeof(srv_msg));
+ char *to = getattr(buffer, "to='");
+ char *from = getattr(buffer, "from='");
+ char *id = getattr(buffer, "id='");
+ char *type = getattr(buffer, "type='");
+ char *body = gettag(buffer, "body");
+ char *status = gettag(buffer, "status");
+ char *show = gettag(buffer, "show");
+ char *line = (char *) malloc(1024);
+ memset(line, 0, 1024);
+
+ /* scan for buffer */
+ if (!strncmp(buffer, "<message", 8)) { /* manage messages */
+ msg->m = SM_MESSAGE;
+ } else if (!strncmp(buffer, "<presence", 9)) { /* manage presences */
+ msg->m = SM_PRESENCE;
+ if (!strncmp(type, "UNK", 3)) { /* assume online */
+ msg->connected = FLAG_BUDDY_CONNECTED;
+ } else if (!strncmp(type, "unavailable", 11)) { /* offline */
+ msg->connected = 0;
+ }
+ } else {
+ msg->m = SM_UNHANDLED;
+ }
+
+ /* write the parsed buffer */
+ switch (msg->m) {
+ case SM_MESSAGE:
+ {
+ char *aux = strstr(from, "/");
+ if (aux)
+ *aux = '\0';
+ msg->from = from;
+ msg->body = utf8_decode(body);
+ ut_WriteLog("+OK [%s]\n", buffer);
+ }
+ break;
+
+ case SM_PRESENCE:
+ {
+ char *aux = strstr(from, "/");
+ if (aux)
+ *aux = '\0';
+ msg->from = from;
+ }
+ break;
+
+ case SM_UNHANDLED:
+ ut_WriteLog("BAD [%s]\n", buffer);
+ break;
+
+ }
+ free(line);
+ if (strncmp(to, "UNK", 3))
+ free(to);
+ if (strncmp(from, "UNK", 3) && (msg->m != SM_MESSAGE)
+ && (msg->m != SM_PRESENCE))
+ free(from);
+ if (strncmp(id, "UNK", 3))
+ free(id);
+ if (strncmp(type, "UNK", 3))
+ free(type);
+ if (strncmp(body, "UNK", 3))
+ free(body);
+ if (strncmp(status, "UNK", 3))
+ free(status);
+ if (strncmp(show, "UNK", 3))
+ free(show);
+ free(buffer);
+
+ return msg;
+ }
+
+ return NULL;
+}
+
+void srv_AddBuddy(int sock, char *jidname)
+{
+ char *buffer = (char *) malloc(1024);
+ char *p, *str;
+ int i;
+
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<iq type='set'>");
+ strcat(buffer, " <query xmlns='jabber:iq:roster'>");
+ strcat(buffer, " <item");
+ strcat(buffer, " jid='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' name='");
+
+ str = strdup(jidname);
+ p = strstr(str, "@");
+ if (p)
+ *p = '\0';
+ strcat(buffer, str);
+ strcat(buffer, "'/></query></iq>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ for (i = 0; i < 2; i++) {
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+ }
+
+ buffer = (char *) malloc(1024);
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<presence to='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' type='subscribe'>");
+ strcat(buffer, "<status>I would like to add you!</status></presence>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+
+ buffer = (char *) malloc(1024);
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<presence to='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' type='subscribed'/>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+}
+
+void srv_DelBuddy(int sock, char *jidname)
+{
+ char *buffer = (char *) malloc(1024);
+
+ strcpy(buffer, "<iq type='set'><query xmlns='jabber:iq:roster'>");
+ strcat(buffer, "<item jid='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' subscription='remove'/></query></iq>");
+
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[SubscriptionRemove]: %s\n", buffer);
+ free(buffer);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/server.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,29 @@
+#ifndef __SERVER_H__
+#define __SERVER_H__ 1
+
+typedef enum {
+ SM_MESSAGE,
+ SM_PRESENCE,
+ SM_UNHANDLED
+} SRV_MSGTYPE;
+
+typedef struct {
+ SRV_MSGTYPE m; /* message type: see above! */
+ int connected; /* meaningful only with SM_PRESENCE */
+ char *from; /* sender */
+ char *body; /* meaningful only with SM_MESSAGE */
+} srv_msg;
+
+char *srv_poll(int sock);
+int srv_connect(const char *server, unsigned int port);
+char *srv_login(int sock, const char *server, const char *user,
+ const char *pass, const char *resource);
+int srv_setpresence(int sock, const char *type);
+char *srv_getroster(int sock);
+int srv_sendtext(int sock, const char *to, const char *text,
+ const char *from);
+int check_io(int fd1, int fd2);
+srv_msg *readserver(int sock);
+void srv_DelBuddy(int sock, char *jidname);
+void srv_AddBuddy(int sock, char *jidname);
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/socket.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include "utils.h"
+
+#include "socket.h"
+#include <signal.h>
+
+/* Desc: create socket connection
+ *
+ * In : servername, port
+ * Out : socket (or -1 on error)
+ *
+ * Note: -
+ */
+int sk_conn(struct sockaddr *name)
+{
+ int sock;
+
+ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("socket (socket.c:23)");
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *) name, sizeof(struct sockaddr)) < 0) {
+ perror("connect (socket.c:29)");
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/* Desc: send data through socket
+ *
+ * In : socket, buffer to send
+ * Out : 0 = fail, 1 = pass
+ *
+ * Note: -
+ */
+int sk_send(int sock, char *buffer)
+{
+ if ((send(sock, buffer, strlen(buffer), 0)) == -1)
+ return 0;
+ else
+ return 1;
+}
+
+/* Desc: receive data through socket
+ *
+ * In : socket
+ * Out : received buffer
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *sk_recv(int sock)
+{
+ int i = 1;
+ int tambuffer = 128;
+ char mtag[16];
+
+ char *buffer = malloc(tambuffer);
+ char *retval = malloc(tambuffer + 1);
+
+ memset(retval, 0, tambuffer);
+ memset(buffer, 0, tambuffer + 1);
+
+ while (1) {
+ char *p1;
+ recv(sock, buffer, tambuffer, 0);
+
+ if (i == 1) {
+ char *p2;
+ strcpy(retval, buffer);
+ p1 = retval+1;
+ p2 = mtag;
+ while (('a' <= *p1) && (*p1 <= 'z') && (p2-mtag < 14))
+ *p2++ = *p1++;
+ *p2++ = '>'; *p2++ = 0;
+ //fprintf(stderr, "TAG=\"%s\"\n", mtag);
+ } else {
+ retval = realloc(retval, (tambuffer * i) + 1);
+ strncat(retval, buffer, tambuffer + 1);
+ }
+ i++;
+ p1 = retval + strlen(retval) - strlen(mtag);
+ //fprintf(stderr, "buffer:[%s]\n", buffer);
+ //fprintf(stderr, "End RET=[%s]\n", p1);
+ if (!strcmp(p1, mtag))
+ break;
+ for (p1 = retval; *p1 && (*p1 != '>'); p1++);
+ if ((*p1 == '>') && (*(p1-1) == '/'))
+ break;
+ memset(buffer, 0, tambuffer);
+ }
+ free(buffer);
+ ut_WriteLog("Received:%s\n", retval);
+ return retval;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/socket.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,10 @@
+#ifndef __SOCKET_H__
+#define __SOCKET_H__ 1
+
+#include <sys/socket.h>
+
+int sk_conn(struct sockaddr *name);
+int sk_send(int sock, char *buffer);
+char *sk_recv(int sock);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/utf8.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,58 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "utf8.h"
+
+
+/* Desc: convert UTF8 -> ASCII
+ *
+ * In : UTF8 string
+ * Out : ASCII string
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *utf8_decode(const char *src)
+{
+ char *ret = calloc(1, strlen(src) + 1);
+ char *aux = ret;
+
+ while (*src) {
+ unsigned char lead = *src++;
+ if ((lead & 0xe0) == 0xc0) {
+ unsigned char ch2 = *src++;
+ *aux = ((lead & 0x1f) << 6) | (ch2 & 0x3f);
+ } else {
+ *aux = lead;
+ }
+ aux++;
+ }
+
+ return ret;
+}
+
+
+/* Desc: convert ASCII -> UTF8
+ *
+ * In : ASCII string
+ * Out : UTF8 string
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *utf8_encode(const char *src)
+{
+ char *ret = calloc(1, (strlen(src) * 2) + 1);
+ char *aux = ret;
+
+ while (*src) {
+ unsigned char ch = *src++;
+ if (ch < 0x80) {
+ *aux = ch;
+ } else { /* if (ch < 0x800) { */
+ *aux++ = 0xc0 | (ch >> 6 & 0x1f);
+ *aux = 0xc0 | (0x80 | (ch & 0x3f));
+ }
+ aux++;
+ }
+
+ return ret;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/utf8.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,7 @@
+#ifndef __UTF8_H__
+#define __UTF8_H__ 1
+
+char *utf8_decode(const char *src);
+char *utf8_encode(const char *src);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/utils.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,191 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ncurses.h>
+#include <stdarg.h>
+#include <time.h>
+
+/* Variables globales a UTILS.C */
+int DebugEnabled = 0;
+
+void ut_InitDebug(int level)
+{
+ FILE *fp = fopen("/tmp/mcabberlog", "w");
+
+ DebugEnabled = level;
+ fprintf(fp, "Debug inicializado...\n"
+ "-----------------------------------\n");
+ fclose(fp);
+}
+
+void ut_WriteLog(const char *fmt, ...)
+{
+ FILE *fp = NULL;
+ time_t ahora;
+ va_list ap;
+ char *buffer = NULL;
+
+ if (DebugEnabled) {
+ fp = fopen("/tmp/mcabberlog", "a+");
+ buffer = (char *) calloc(1, 8192);
+
+ ahora = time(NULL);
+ strftime(buffer, 1024, "[%H:%M:%S] ", localtime(&ahora));
+ fprintf(fp, "%s", buffer);
+
+ va_start(ap, fmt);
+ vfprintf(fp, fmt, ap);
+ va_end(ap);
+
+ free(buffer);
+ fclose(fp);
+ }
+}
+
+char **ut_SplitMessage(char *mensaje, int *nsubmsgs, unsigned int maxlong)
+{
+ /* BUGs: recorta la palabra si la longitud maxlong es menor que la palabra
+ // maxlong = 4
+ // mensaje = "peaso bug!"
+ // submsgs[0] = "peas"
+ // submsgs[1] = "bug!"
+ // por lo demas, rula de arte. De todos modos, podrias verificarla ???
+ */
+ char *running;
+ char *aux;
+ char *aux2;
+ char **submsgs;
+ char *buffer = (char *) malloc(strlen(mensaje) * 2);
+ int i = 0;
+
+ submsgs = (char **) malloc(50 * sizeof(char *)); /* limitamos, a priori, el maximo de lineas devueltas... */
+
+ running = strdup(mensaje); /* duplicamos mensaje */
+ aux2 = strdup(mensaje); /* hacemos otra copia */
+ while (strlen(aux2) > maxlong) { /* mintras quede texto... */
+ memset(buffer, 0, strlen(mensaje) * 2); /* borramos el buffer */
+ running[maxlong] = '\0'; /* cortamos la cadena a la maxima longitud */
+ aux = rindex(running, ' '); /* posicion del ultimo blanco */
+ if (aux != NULL) /* hay blanco! */
+ strncpy(buffer, running, strlen(running) - strlen(aux));
+ else
+ strcpy(buffer, running); /* se supone que esto es pa evitar el bug explicado arriba, pero no rula */
+
+ submsgs[i] = (char *) malloc(strlen(buffer) + 1); /*reservamos memoria */
+ strcpy(submsgs[i], buffer); /*copiamos el buffer de arriba */
+ i++; /*aumentamos numero de mensajillos */
+ aux2 += strlen(buffer) + 1; /*eliminamos texto particionado */
+ sprintf(running, "%s", aux2); /*y lo copiamos de nuevo a la string de "curro" */
+ }
+ /* la ultima parte del mensaje, si la hay ;-) */
+ if (strlen(aux2) > 0) {
+ submsgs[i] = (char *) malloc(strlen(aux2) + 1);
+ strcpy(submsgs[i], aux2);
+ i++;
+ }
+ (*nsubmsgs) = i;
+ free(buffer);
+ return submsgs;
+}
+
+/* Desc: get the rightmost substring
+ *
+ * In : string, match
+ * Out : ptr to substring (or NULL if not found)
+ *
+ * Note: this one has no namespace, cos it belongs to <string.h>
+ */
+char *ut_strrstr(const char *s1, const char *s2)
+{
+ int l = strlen(s2);
+
+ if (l) {
+ const char *s = strchr(s1, '\0') - l;
+ while (s >= s1) {
+ if (*s == *s2) {
+ int _l = l - 1;
+ const char *_s = s + 1, *_s2 = s2 + 1;
+ while (_l) {
+ if (*_s++ != *_s2++) {
+ break;
+ }
+ _l--;
+ }
+ if (!_l) {
+ return (char *) s;
+ }
+ }
+ s--;
+ }
+ }
+
+ return NULL;
+}
+
+char *gettag(char *buffer, char *what)
+{
+ char *aux;
+ char *aux2;
+ char *result = (char *) malloc(1024);
+ char *tmp = (char *) malloc(1024);
+ memset(result, 0, 1024);
+ memset(tmp, 0, 1024);
+
+ sprintf(tmp, "<%s>", what);
+ aux = strstr(buffer, tmp);
+ if (aux) {
+ aux += strlen(tmp);
+ sprintf(tmp, "</%s>", what);
+ aux2 = strstr(aux, tmp);
+ if (aux2) {
+ strncpy(result, aux, strlen(aux) - strlen(aux2));
+ free(tmp);
+ return result;
+ }
+ }
+ free(tmp);
+ free(result);
+ return "UNKtag";
+}
+
+
+char *getattr(char *buffer, char *what)
+{
+ char *aux;
+ char *aux2;
+ char *result = (char *) malloc(1024);
+ memset(result, 0, 1024);
+
+ aux = strstr(buffer, what);
+ if (aux) {
+ aux += strlen(what);
+ aux2 = strstr(aux, "'");
+ if (aux2) {
+ strncpy(result, aux, strlen(aux) - strlen(aux2));
+ return result;
+ }
+ }
+ free(result);
+ return "UNKattr";
+}
+
+void ut_CenterMessage(char *text, int width, char *output)
+{
+ char *blank;
+ int ntest, nn;
+
+ memset(output, 0, strlen(output));
+
+ ntest = (width - strlen(text)) / 2;
+ blank = (char *) malloc(ntest + 1);
+
+ for (nn = 0; nn < ntest; nn++)
+ blank[nn] = ' ';
+ blank[ntest] = '\0';
+
+ strcpy(output, blank);
+ strcat(output, text);
+ strcat(output, blank);
+
+ free(blank);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/utils.h Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,16 @@
+#ifndef __UTILS_H__
+#define __UTILS_H__ 1
+
+#include <ncurses.h>
+
+char **ut_SplitMessage(char *mensaje, int *nsubmsgs, unsigned int maxlong);
+void ut_InitDebug(int level);
+void ut_WriteLog(const char *fmt, ...);
+char *ut_strrstr(const char *s1, const char *s2);
+char *getattr(char *buffer, char *what);
+char *gettag(char *buffer, char *what);
+void ut_CenterMessage(char *text, int width, char *output);
+
+
+
+#endif