# HG changeset patch # User tailor@frmp8452 # Date 1120167571 0 # Node ID b3b2332715fb2a25a3b5e4e7f635457dbd0531a6 Tailorization of /trunk Import of the upstream sources from Repository: file:///tmp/svn-mcabber Module: /trunk Revision: 15 diff -r 000000000000 -r b3b2332715fb .hgignore --- /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$ diff -r 000000000000 -r b3b2332715fb mcabber/ACKNOWLEDGEMENT --- /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) diff -r 000000000000 -r b3b2332715fb mcabber/COPYING --- /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. + + + Copyright (C) + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -r 000000000000 -r b3b2332715fb mcabber/Changelog --- /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. + diff -r 000000000000 -r b3b2332715fb mcabber/Makefile --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/README --- /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 ;-) + diff -r 000000000000 -r b3b2332715fb mcabber/TODO --- /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!!! :-) diff -r 000000000000 -r b3b2332715fb mcabber/buddies.c --- /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 +#include +#include +#include +#include +#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, "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()); +} diff -r 000000000000 -r b3b2332715fb mcabber/buddies.h --- /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 +#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 diff -r 000000000000 -r b3b2332715fb mcabber/cabberrc.example --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/harddefines.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/lang.c --- /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 +#include +#include +#include +#include + + +#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; +} diff -r 000000000000 -r b3b2332715fb mcabber/lang.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/lang/POSIX.txt --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/lang/es_ES.txt --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/list.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/main.c --- /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 +#include +#include +#include +#include +#include + +#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; +} diff -r 000000000000 -r b3b2332715fb mcabber/parsecfg.c --- /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 +#include +#include +#include +#include + + +#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; +} diff -r 000000000000 -r b3b2332715fb mcabber/parsecfg.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/screen.c --- /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 +#include +#include +#include +#include +#include +#include + +#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; +} diff -r 000000000000 -r b3b2332715fb mcabber/screen.h --- /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 + +#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 diff -r 000000000000 -r b3b2332715fb mcabber/server.c --- /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 +#include +#include +#include +#include +#include + +#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, ""); + strcat(stringtosend, "\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, ""); + strcat(stringtosend, ""); + strcat(stringtosend, ""); + strcat(stringtosend, user); + strcat(stringtosend, ""); + strcat(stringtosend, pass); + strcat(stringtosend, ""); + strcat(stringtosend, resource); + strcat(stringtosend, "\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, ""); + strcat(stringtosend, ""); + strcat(stringtosend, ""); + strcat(stringtosend, user); + strcat(stringtosend, ""); + strcat(stringtosend, pass); + strcat(stringtosend, ""); + strcat(stringtosend, "\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, "%s", 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, "\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, + "%s", + 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, "m = SM_MESSAGE; + } else if (!strncmp(buffer, "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, ""); + strcat(buffer, " "); + strcat(buffer, " "); + 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, ""); + strcat(buffer, "I would like to add you!"); + 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, ""); + 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, ""); + strcat(buffer, ""); + + sk_send(sock, buffer); + free(buffer); + + buffer = sk_recv(sock); + ut_WriteLog("[SubscriptionRemove]: %s\n", buffer); + free(buffer); +} diff -r 000000000000 -r b3b2332715fb mcabber/server.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/socket.c --- /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 +#include +#include +#include +#include +#include "utils.h" + +#include "socket.h" +#include + +/* 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; +} diff -r 000000000000 -r b3b2332715fb mcabber/socket.h --- /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 + +int sk_conn(struct sockaddr *name); +int sk_send(int sock, char *buffer); +char *sk_recv(int sock); + +#endif diff -r 000000000000 -r b3b2332715fb mcabber/utf8.c --- /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 +#include + +#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; +} diff -r 000000000000 -r b3b2332715fb mcabber/utf8.h --- /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 diff -r 000000000000 -r b3b2332715fb mcabber/utils.c --- /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 +#include +#include +#include +#include +#include + +/* 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 + */ +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, "", 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); +} diff -r 000000000000 -r b3b2332715fb mcabber/utils.h --- /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 + +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