Changes in / [051372c:41d415b]
- Files:
-
- 35 added
- 15 deleted
- 70 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r051372c r41d415b 10 10 11 11 # Program variables 12 objects = account.o bitlbee.o chat.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o13 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) 13 headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h 14 14 subdirs = lib protocols 15 15 … … 82 82 install-dev: 83 83 mkdir -p $(DESTDIR)$(INCLUDEDIR) 84 install -m 0644 $(headers) $(DESTDIR)$(INCLUDEDIR) 84 install -m 0644 config.h $(DESTDIR)$(INCLUDEDIR) 85 for i in $(headers); do install -m 0644 $(SRCDIR)$$i $(DESTDIR)$(INCLUDEDIR); done 85 86 mkdir -p $(DESTDIR)$(PCDIR) 86 87 install -m 0644 bitlbee.pc $(DESTDIR)$(PCDIR) … … 93 94 install-etc: 94 95 mkdir -p $(DESTDIR)$(ETCDIR) 95 install -m 0644 motd.txt $(DESTDIR)$(ETCDIR)/motd.txt96 install -m 0644 bitlbee.conf $(DESTDIR)$(ETCDIR)/bitlbee.conf96 install -m 0644 $(SRCDIR)motd.txt $(DESTDIR)$(ETCDIR)/motd.txt 97 install -m 0644 $(SRCDIR)bitlbee.conf $(DESTDIR)$(ETCDIR)/bitlbee.conf 97 98 98 99 uninstall-etc: … … 110 111 @$(MAKE) -C $@ $(MAKECMDGOALS) 111 112 112 $(objects): %.o: %.c113 $(objects): %.o: $(SRCDIR)%.c 113 114 @echo '*' Compiling $< 114 115 @$(CC) -c $(CFLAGS) $< -o $@ -
bitlbee.c
r051372c r41d415b 121 121 } 122 122 123 global.listen_watch_source_id = b_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL );123 global.listen_watch_source_id = b_input_add( global.listen_socket, B_EV_IO_READ, bitlbee_io_new_client, NULL ); 124 124 125 125 #ifndef _WIN32 … … 321 321 child->pid = client_pid; 322 322 child->ipc_fd = fds[0]; 323 child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );323 child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); 324 324 child_list = g_slist_append( child_list, child ); 325 325 … … 349 349 /* We can store the IPC fd there now. */ 350 350 global.listen_socket = fds[1]; 351 global.listen_watch_source_id = b_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );351 global.listen_watch_source_id = b_input_add( fds[1], B_EV_IO_READ, ipc_child_read, irc ); 352 352 353 353 close( fds[0] ); -
bitlbee.h
r051372c r41d415b 43 43 44 44 #if HAVE_CONFIG_H 45 #include "config.h"45 #include <config.h> 46 46 #endif 47 47 … … 126 126 #define CONF_FILE_DEF ETCDIR "bitlbee.conf" 127 127 128 #include "bee.h" 128 129 #include "irc.h" 129 130 #include "storage.h" … … 160 161 gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); 161 162 162 void root_command_string( irc_t *irc, user_t *u, char *command, int flags);163 void root_command_string( irc_t *irc, char *command ); 163 164 void root_command( irc_t *irc, char *command[] ); 164 165 gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); -
conf.c
r051372c r41d415b 63 63 conf->ping_timeout = 300; 64 64 conf->user = NULL; 65 conf->ft_max_size = SIZE_MAX; 66 conf->ft_max_kbps = G_MAXUINT; 67 conf->ft_listen = NULL; 65 68 conf->protocols = NULL; 66 69 proxytype = 0; … … 315 318 conf->user = g_strdup( ini->value ); 316 319 } 320 else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 ) 321 { 322 size_t ft_max_size; 323 if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 ) 324 { 325 fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); 326 return 0; 327 } 328 conf->ft_max_size = ft_max_size; 329 } 330 else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 ) 331 { 332 if( sscanf( ini->value, "%d", &i ) != 1 ) 333 { 334 fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); 335 return 0; 336 } 337 conf->ft_max_kbps = i; 338 } 339 else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 ) 340 { 341 g_free( conf->ft_listen ); 342 conf->ft_listen = g_strdup( ini->value ); 343 } 317 344 else if( g_strcasecmp( ini->key, "protocols" ) == 0 ) 318 345 { … … 349 376 if( g_strcasecmp( ini->section, "defaults" ) == 0 ) 350 377 { 351 set_t *s = set_find( &irc-> set, ini->key );378 set_t *s = set_find( &irc->b->set, ini->key ); 352 379 353 380 if( s ) -
conf.h
r051372c r41d415b 50 50 int ping_timeout; 51 51 char *user; 52 size_t ft_max_size; 53 int ft_max_kbps; 54 char *ft_listen; 52 55 char **protocols; 53 56 } conf_t; -
configure
r051372c r41d415b 27 27 yahoo=1 28 28 twitter=1 29 twitter=1 30 purple=0 29 31 30 32 debug=0 … … 67 69 --oscar=0/1 Disable/enable Oscar part (ICQ, AIM) $oscar 68 70 --yahoo=0/1 Disable/enable Yahoo part $yahoo 69 --twitter=0/1 Disable/enable Twitter part $twitter 71 --twitter=0/1 Disable/enable Twitter part $twitter 72 73 --purple=0/1 Disable/enable libpurple support $purple 70 74 71 75 --debug=0/1 Disable/enable debugging $debug … … 121 125 EOF 122 126 127 srcdir="$(dirname $0)" 128 if [ "$srcdir" != "." ]; then 129 echo 130 echo "configure script run from a different directory. Will create some symlinks..." 131 if [ ! -e Makefile -o -L Makefile ]; then 132 COPYDIRS="doc lib protocols tests utils" 133 mkdir -p $(cd "$srcdir"; find $COPYDIRS -type d) 134 find . -name Makefile -type l -print0 | xargs -0 rm 2> /dev/null 135 dst="$PWD" 136 cd "$srcdir" 137 for i in $(find . -name Makefile -type f); do 138 ln -s "$PWD${i#.}" "$dst/$i"; 139 done 140 cd "$dst" 141 rm -rf .bzr 142 fi 143 144 echo "SRCDIR=$srcdir/" >> Makefile.settings 145 CFLAGS="$CFLAGS -I${dst}" 146 else 147 srcdir=$PWD 148 fi 149 123 150 cat<<EOF>config.h 124 151 /* BitlBee settings, generated by configure … … 158 185 159 186 echo CFLAGS=$CFLAGS >> Makefile.settings 160 echo CFLAGS+=-I `pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings187 echo CFLAGS+=-I${srcdir} -I${srcdir}/lib -I${srcdir}/protocols -I. >> Makefile.settings 161 188 162 189 echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings … … 398 425 fi 399 426 400 STORAGES=" textxml"427 STORAGES="xml" 401 428 402 429 if [ "$ldap" = "auto" ]; then … … 508 535 protoobjs='' 509 536 537 if [ "$purple" = 0 ]; then 538 echo '#undef WITH_PURPLE' >> config.h 539 else 540 if ! $PKG_CONFIG purple; then 541 echo 542 echo 'Cannot find libpurple development libraries, aborting. (Install libpurple-dev?)' 543 exit 1 544 fi 545 echo '#define WITH_PURPLE' >> config.h 546 cat<<EOF>>Makefile.settings 547 EFLAGS += $($PKG_CONFIG purple --libs) 548 PURPLE_CFLAGS += $($PKG_CONFIG purple --cflags) 549 EOF 550 protocols=$protocols'purple ' 551 protoobjs=$protoobjs'purple_mod.o ' 552 553 # Having both libpurple and native IM modules in one binary may 554 # do strange things. Let's not do that. 555 msn=0 556 jabber=0 557 oscar=0 558 yahoo=0 559 twitter=0 560 561 if [ "$events" = "libevent" ]; then 562 echo 563 echo 'Warning: Some libpurple modules (including msn-pecan) do their event handling' 564 echo 'outside libpurple, talking to GLib directly. At least for now the combination' 565 echo 'libpurple + libevent is *not* recommended!' 566 fi 567 fi 568 510 569 if [ "$msn" = 0 ]; then 511 570 echo '#undef WITH_MSN' >> config.h -
debian/bitlbee.init
-
Property
mode
changed from
100755
to100644
-
Property
mode
changed from
-
debian/changelog
r051372c r41d415b 1 bitlbee (1.3-0) unstable; urgency=low 2 3 * Setting some bogus version number, fix that later. 4 * Now using debhelper to improve maintainability. 5 * Added a bitlbee-libpurple package, and split off docs and stuff into 6 bitlbee-common. 7 8 -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 05 Jun 2010 15:16:38 +0100 9 1 10 bitlbee (1.2.7-1) unstable; urgency=high 2 11 -
debian/control
r051372c r41d415b 4 4 Maintainer: Wilmer van der Gaast <wilmer@gaast.net> 5 5 Uploaders: Jelmer Vernooij <jelmer@samba.org> 6 Standards-Version: 3.8. 07 Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf6 Standards-Version: 3.8.4 7 Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), po-debconf, libpurple-dev, debhelper (>= 6) 8 8 Homepage: http://www.bitlbee.org/ 9 9 Vcs-Bzr: http://code.bitlbee.org/bitlbee/ … … 12 12 Package: bitlbee 13 13 Architecture: any 14 Depends: ${shlibs:Depends}, adduser, net-tools, ${debconf-depends}, debianutils (>= 1.16) 15 Description: An IRC to other chat networks gateway 14 Depends: ${shlibs:Depends}, adduser, debianutils (>= 1.16), bitlbee-common (= ${bee:Version}) 15 Conflicts: bitlbee-libpurple 16 Replaces: bitlbee-libpurple 17 Description: An IRC to other chat networks gateway (default version) 16 18 This program can be used as an IRC server which forwards everything you 17 19 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and 18 20 Twitter. 19 21 22 Package: bitlbee-libpurple 23 Architecture: any 24 Depends: ${shlibs:Depends}, adduser, debianutils (>= 1.16), bitlbee-common (= ${bee:Version}) 25 Conflicts: bitlbee 26 Replaces: bitlbee 27 Description: An IRC to other chat networks gateway (using libpurple) 28 This program can be used as an IRC server which forwards everything you 29 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and 30 Twitter. 31 . 32 This package contains a version of BitlBee that uses the libpurple instant 33 messaging library instead of built-in code, which adds support for more IM 34 protocols (all protocols supported by Pidgin/Finch) and features (like file 35 transfers), at the price of being less lightweight. 36 . 37 This variant may not be very suitable for BitlBee instances used by many 38 (tens or hundreds) of clients. 39 40 Package: bitlbee-common 41 Architecture: all 42 Depends: ${misc:Depends}, net-tools 43 Replaces: bitlbee 44 Description: An IRC to other chat networks gateway (common files/docs) 45 This program can be used as an IRC server which forwards everything you 46 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and 47 Twitter. 48 . 49 This package contains common files (mostly documentation) for bitlbee and 50 bitlbee-libpurple. 51 20 52 Package: bitlbee-dev 21 53 Architecture: all 22 Depends: bitlbee (>= ${source:Version}), bitlbee (<< ${source:Version}.1~)23 Description: An IRC to other chat networks gateway 54 Depends: ${misc:Depends}, bitlbee (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~) 55 Description: An IRC to other chat networks gateway (dev files) 24 56 This program can be used as an IRC server which forwards everything you 25 57 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and -
debian/patches/bitlbee.conf.diff
r051372c r41d415b 1 --- debian/bitlbee/etc/bitlbee/bitlbee.conf 2009-06-01 00:20:24.000000000 +01002 +++ debian/bitlbee/etc/bitlbee/bitlbee.conf 2009-06-07 21:16:19.000000000 +01001 --- bitlbee.conf 2009-06-01 00:20:24.000000000 +0100 2 +++ bitlbee.conf 2009-06-07 21:16:19.000000000 +0100 3 3 @@ -23,13 +23,18 @@ 4 4 ## If BitlBee is started by root as a daemon, it can drop root privileges, -
debian/po/POTFILES.in
r051372c r41d415b 1 [type: gettext/rfc822deb] templates1 [type: gettext/rfc822deb] bitlbee-common.templates -
debian/rules
r051372c r41d415b 1 1 #!/usr/bin/make -f 2 # 3 # Finally switching to debhelper. 4 # 5 # Not using debhelper was an exercise suggested to me by my AM (Gergely 6 # Nagy). It was educating at the time but I finally decided that the 7 # exercise is over now. 8 # 2 9 10 BITLBEE_CONFIGURE_FLAGS ?= 3 11 DEBUG ?= 0 4 12 5 ifdef BITLBEE_VERSION 6 BITLBEE_FORCE_VERSION=1 7 else 13 ifndef BITLBEE_VERSION 8 14 # Want to use the full package version number instead of just the release. 9 BITLBEE_VERSION ?= "$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')" 10 export BITLBEE_VERSION 15 BITLBEE_CONFIGURE_VERSION ?= BITLBEE_VERSION=\"$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')\" 11 16 endif 12 17 13 build-arch: build-arch-stamp 14 build-arch-stamp: 15 [ -d debian ] 16 ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent 17 $(MAKE) 18 # $(MAKE) -C doc/ all 19 touch build-arch-stamp 18 build: build-stamp 19 build-stamp: 20 dh_testdir 21 22 mkdir -p debian/build-native 23 ROOT=$$PWD; cd debian/build-native; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(BITLBEE_CONFIGURE_FLAGS) 24 $(MAKE) -C debian/build-native 25 26 mkdir -p debian/build-libpurple 27 ROOT=$$PWD; cd debian/build-libpurple; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --purple=1 $(BITLBEE_CONFIGURE_FLAGS) 28 $(MAKE) -C debian/build-libpurple 29 30 $(MAKE) -C doc 31 32 touch build-stamp 20 33 21 34 clean: 22 [ "`whoami`" = "root" -a -d debian ] 23 rm -rf build-arch-stamp debian/bitlbee debian/*.substvars debian/files debian/bitlbee-dev 35 dh_testdir 36 dh_testroot 37 rm -f build-stamp 38 39 rm -rf build-arch-stamp debian/build-* 24 40 $(MAKE) distclean 25 # -$(MAKE) -C doc/ clean26 27 41 28 install-arch: build-arch 29 [ "`whoami`" = "root" -a -d debian ] 30 mkdir -p debian/bitlbee/DEBIAN/ 31 $(MAKE) install install-etc DESTDIR=`pwd`/debian/bitlbee 42 dh_clean 32 43 33 mkdir -p debian/bitlbee/usr/share/doc/bitlbee/ 34 cp doc/user-guide/user-guide.txt debian/bitlbee/usr/share/doc/bitlbee/ 35 cp doc/user-guide/user-guide.html debian/bitlbee/usr/share/doc/bitlbee/ 44 install: build 45 dh_testdir 46 dh_testroot 47 dh_clean -k 48 dh_installdirs 36 49 37 install-indep: install-arch 38 [ "`whoami`" = "root" -a -d debian ] 39 mkdir -p debian/bitlbee-dev/DEBIAN/ 40 $(MAKE) install-dev DESTDIR=`pwd`/debian/bitlbee-dev 50 $(MAKE) -C debian/build-native install install-etc DESTDIR=`pwd`/debian/bitlbee 51 $(MAKE) -C debian/build-libpurple install install-etc DESTDIR=`pwd`/debian/bitlbee-libpurple 52 $(MAKE) -C debian/build-native install-dev DESTDIR=`pwd`/debian/bitlbee-dev 41 53 42 mkdir -p debian/bitlbee-dev/usr/share/doc/bitlbee-dev/ 54 patch debian/bitlbee/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff 55 patch debian/bitlbee-libpurple/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff 43 56 44 binary-arch: build-arch install-arch 45 [ "`whoami`" = "root" -a -d debian ] 57 mkdir -p debian/bitlbee-common/usr 58 mv debian/bitlbee/usr/share debian/bitlbee-common/usr 59 rm -rf debian/bitlbee-libpurple/usr/share 46 60 47 chmod 755 debian/post* debian/pre* debian/config debian/bitlbee.init 61 binary-common: 62 dh_testdir 63 dh_testroot 48 64 49 mkdir -p debian/bitlbee/usr/share/doc/bitlbee/examples/ debian/bitlbee/etc/init.d/ 50 -cp doc/RELEASE-SPEECH* debian/bitlbee/usr/share/doc/bitlbee/ && gzip -9 debian/bitlbee/usr/share/doc/bitlbee/RELEASE-SPEECH* 51 cp doc/CREDITS doc/AUTHORS doc/README doc/FAQ debian/README.Debian debian/bitlbee/usr/share/doc/bitlbee/ 52 cp debian/changelog debian/bitlbee/usr/share/doc/bitlbee/changelog.Debian 53 cp debian/copyright debian/bitlbee/usr/share/doc/bitlbee/copyright 54 cp doc/CHANGES debian/bitlbee/usr/share/doc/bitlbee/changelog 55 cp utils/* debian/bitlbee/usr/share/doc/bitlbee/examples/ 56 cp debian/bitlbee.init debian/bitlbee/etc/init.d/bitlbee 57 patch -p0 < debian/patches/bitlbee.conf.diff 58 cd debian/bitlbee/usr/share/; \ 59 gzip -9 doc/bitlbee/changelog.Debian doc/bitlbee/changelog doc/bitlbee/user-guide.txt \ 60 doc/bitlbee/examples/* man/man8/bitlbee.8 man/man5/bitlbee.conf.5 61 62 chown -R root:root debian/bitlbee/ 63 find debian/bitlbee/usr/share/ -type d -exec chmod 755 {} \; 64 find debian/bitlbee/usr/share/ -type f -exec chmod 644 {} \; 65 66 cp debian/prerm debian/bitlbee/DEBIAN/ 67 cp debian/postinst debian/bitlbee/DEBIAN/ 68 cp debian/postrm debian/bitlbee/DEBIAN/ 69 cp debian/config debian/bitlbee/DEBIAN/ 65 dh_installchangelogs doc/CHANGES 66 dh_installexamples 67 dh_installdocs #--link-doc=bitlbee-common 68 # TODO: Restore --link-doc up here and remove the hack below once 69 # Hardy and Lenny are deprecated. 70 for p in bitlbee bitlbee-libpurple bitlbee-dev; do rm -rf debian/$$p/usr/share/doc/$$p; ln -s bitlbee-common debian/$$p/usr/share/doc/$$p; done 71 dh_installdebconf 72 dh_installinit 73 ifeq ($(DH_OPTIONS),-a) 74 cp -a debian/bitlbee/etc debian/bitlbee-libpurple 75 endif 76 dh_installman 77 dh_strip 78 dh_link 79 dh_compress 80 dh_fixperms 81 dh_installdeb 82 ifeq ($(DH_OPTIONS),-a) 83 cp -a debian/bitlbee/DEBIAN/post* debian/bitlbee/DEBIAN/pre* debian/bitlbee-libpurple/DEBIAN 84 endif 85 dh_shlibdeps 86 ifdef BITLBEE_VERSION 87 dh_gencontrol -- -v1:$(BITLBEE_VERSION)-0 -Vbee:Version=1:$(BITLBEE_VERSION)-0 88 else 89 dh_gencontrol -- -Vbee:Version=$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}' | sed -e 's/+[^+]*$$//') 90 endif 91 dh_md5sums 92 dh_builddeb 70 93 71 po2debconf debian/templates > debian/bitlbee/DEBIAN/templates 72 cp debian/conffiles debian/bitlbee/DEBIAN/ 73 74 if [ "$(DEBUG)" = "0" ]; then strip -R .comment -R .note debian/bitlbee/usr/sbin/bitlbee; fi 94 binary-indep: build install 95 $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common 75 96 76 cd debian/bitlbee; \ 77 find usr -type f -exec md5sum {} \; > DEBIAN/md5sums 78 dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee 79 ifdef BITLBEE_FORCE_VERSION 80 dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v1:$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' 81 else 82 dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' 83 endif 97 binary-arch: build install 98 $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common 84 99 85 dpkg --build debian/bitlbee .. 100 binary-%: build install 101 make -f debian/rules binary-common DH_OPTIONS=-p$* 86 102 87 binary-indep: install-indep 88 [ "`whoami`" = "root" -a -d debian ] 89 90 chown -R root.root debian/bitlbee-dev/ 91 find debian/bitlbee-dev/usr/share/ -type d -exec chmod 755 {} \; 92 find debian/bitlbee-dev/usr/share/ -type f -exec chmod 644 {} \; 93 94 cp debian/changelog debian/bitlbee-dev/usr/share/doc/bitlbee-dev/changelog.Debian 95 gzip -9 debian/bitlbee-dev/usr/share/doc/bitlbee-dev/changelog.Debian 96 cp debian/copyright debian/bitlbee-dev/usr/share/doc/bitlbee-dev/copyright 97 98 cd debian/bitlbee-dev; \ 99 find usr -type f -exec md5sum {} \; > DEBIAN/md5sums 100 101 ifdef BITLBEE_FORCE_VERSION 102 dpkg-gencontrol -ldebian/changelog -isp -pbitlbee-dev -Pdebian/bitlbee-dev -v1:$(BITLBEE_VERSION)-0 103 else 104 dpkg-gencontrol -ldebian/changelog -isp -pbitlbee-dev -Pdebian/bitlbee-dev 105 endif 106 107 dpkg --build debian/bitlbee-dev .. 108 109 binary: binary-arch binary-indep 110 build: build-arch 111 install: install-arch install-indep 112 113 .PHONY: build-arch build clean binary-arch binary install-arch install binary-indep install-indep 103 binary: binary-indep binary-arch 104 .PHONY: build clean binary-indep binary-arch binary-common binary install -
doc/Makefile
r051372c r41d415b 1 1 -include ../Makefile.settings 2 ifdef SRCDIR 3 SRCDIR := $(SRCDIR)doc/ 4 endif 2 5 3 6 all: … … 7 10 install: 8 11 mkdir -p $(DESTDIR)$(MANDIR)/man8/ $(DESTDIR)$(MANDIR)/man5/ 9 install -m 0644 bitlbee.8 $(DESTDIR)$(MANDIR)/man8/10 install -m 0644 bitlbee.conf.5 $(DESTDIR)$(MANDIR)/man5/12 install -m 0644 $(SRCDIR)bitlbee.8 $(DESTDIR)$(MANDIR)/man8/ 13 install -m 0644 $(SRCDIR)bitlbee.conf.5 $(DESTDIR)$(MANDIR)/man5/ 11 14 $(MAKE) -C user-guide $@ 12 15 -
doc/user-guide/Makefile
r051372c r41d415b 1 1 -include ../../Makefile.settings 2 ifdef SRCDIR 3 SRCDIR := $(SRCDIR)doc/user-guide/ 4 endif 5 2 6 EXTRAPARANEWLINE = 1 3 7 # EXTRAPARANEWLINE = 0 … … 38 42 chmod 0755 $(DESTDIR)$(DATADIR) 39 43 rm -f $(DESTDIR)$(DATADIR)/help.txt # Prevent help function from breaking in running sessions 40 install -m 0644 help.txt $(DESTDIR)$(DATADIR)/help.txt44 install -m 0644 $(SRCDIR)help.txt $(DESTDIR)$(DATADIR)/help.txt 41 45 42 46 uninstall: -
doc/user-guide/commands.xml
r051372c r41d415b 484 484 </bitlbee-setting> 485 485 486 <bitlbee-setting name="buddy_sendbuffer" type="boolean" scope="global"> 487 <default>false</default> 488 489 <description> 490 <para> 491 By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data. 492 </para> 493 494 <para> 495 Using the <emphasis>buddy_sendbuffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent. 496 </para> 497 498 <para> 499 Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases. 500 </para> 501 </description> 502 </bitlbee-setting> 503 504 <bitlbee-setting name="buddy_sendbuffer_delay" type="integer" scope="global"> 505 <default>200</default> 506 507 <description> 508 509 <para> 510 Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds. 511 </para> 512 513 <para> 514 See also the <emphasis>buddy_sendbuffer</emphasis> setting. 486 <bitlbee-setting name="away_reply_timeout" type="integer" scope="global"> 487 <default>3600</default> 488 489 <description> 490 <para> 491 Most IRC servers send a user's away message every time s/he gets a private message, to inform the sender that they may not get a response immediately. With this setting set to 0, BitlBee will also behave like this. 492 </para> 493 494 <para> 495 Since not all IRC clients do an excellent job at suppressing these messages, this setting lets BitlBee do it instead. BitlBee will wait this many seconds (or until the away state/message changes) before re-informing you that the person's away. 515 496 </para> 516 497 </description> … … 593 574 594 575 <bitlbee-setting name="handle_unknown" type="string" scope="global"> 595 <default> root</default>576 <default>add_channel</default> 596 577 <possible-values>root, add, add_private, add_channel, ignore</possible-values> 597 578 … … 771 752 </description> 772 753 </bitlbee-setting> 754 755 <bitlbee-setting name="paste_buffer" type="boolean" scope="global"> 756 <default>false</default> 757 758 <description> 759 <para> 760 By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data. 761 </para> 762 763 <para> 764 Using the <emphasis>paste_buffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent. 765 </para> 766 767 <para> 768 Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases. 769 </para> 770 </description> 771 </bitlbee-setting> 772 773 <bitlbee-setting name="paste_buffer_delay" type="integer" scope="global"> 774 <default>200</default> 775 776 <description> 777 778 <para> 779 Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds. 780 </para> 781 782 <para> 783 See also the <emphasis>paste_buffer</emphasis> setting. 784 </para> 785 </description> 786 </bitlbee-setting> 773 787 774 788 <bitlbee-setting name="port" type="integer" scope="account"> … … 1128 1142 1129 1143 <bitlbee-command name="identify"> 1130 <syntax>identify <password></syntax>1144 <syntax>identify [-noload|-force] <password></syntax> 1131 1145 <short-description>Identify yourself with your password</short-description> 1132 1146 … … 1138 1152 <para> 1139 1153 Once you're registered, you can change your password using <emphasis>set password <password></emphasis>. 1154 </para> 1155 1156 <para> 1157 The <emphasis>-noload</emphasis> and <emphasis>-force</emphasis> flags can be used to identify when you're logged into some IM accounts already. <emphasis>-force</emphasis> will let you identify yourself and load all saved accounts (and keep the accounts you're logged into already). 1158 </para> 1159 1160 <para> 1161 <emphasis>-noload</emphasis> will log you in but not load any accounts and settings saved under your current nickname. These will be overwritten once you save your settings (i.e. when you disconnect). 1140 1162 </para> 1141 1163 </description> … … 1182 1204 1183 1205 </bitlbee-command> 1206 1207 <bitlbee-command name="transfers"> 1208 <short-description>Monitor, cancel, or reject file transfers</short-description> 1209 <syntax>transfers [<cancel> id | <reject>]</syntax> 1210 1211 <description> 1212 <para> 1213 Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers <action></emphasis> for more information. 1214 </para> 1215 1216 <ircexample> 1217 <ircline nick="ulim">transfers</ircline> 1218 </ircexample> 1219 </description> 1220 1221 <bitlbee-command name="cancel"> 1222 <short-description>Cancels the file transfer with the given id</short-description> 1223 <syntax>transfers <cancel> id</syntax> 1224 1225 <description> 1226 <para>Cancels the file transfer with the given id</para> 1227 </description> 1228 1229 <ircexample> 1230 <ircline nick="ulim">transfers cancel 1</ircline> 1231 <ircline nick="root">Canceling file transfer for test</ircline> 1232 </ircexample> 1233 </bitlbee-command> 1234 1235 <bitlbee-command name="reject"> 1236 <short-description>Rejects all incoming transfers</short-description> 1237 <syntax>transfers <reject></syntax> 1238 1239 <description> 1240 <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para> 1241 </description> 1242 1243 <ircexample> 1244 <ircline nick="ulim">transfers reject</ircline> 1245 </ircexample> 1246 </bitlbee-command> 1247 </bitlbee-command> 1248 1184 1249 </chapter> -
doc/user-guide/help.xml
r051372c r41d415b 14 14 <varlistentry><term>quickstart</term><listitem><para>A short introduction into BitlBee</para></listitem></varlistentry> 15 15 <varlistentry><term>commands</term><listitem><para>All available commands and settings</para></listitem></varlistentry> 16 <varlistentry><term>channels</term><listitem><para>About creating and customizing channels</para></listitem></varlistentry> 16 17 <varlistentry><term>away</term><listitem><para>About setting away states</para></listitem></varlistentry> 17 18 <varlistentry><term>smileys</term><listitem><para>A summary of some non-standard smileys you might find and fail to understand</para></listitem></varlistentry> -
doc/user-guide/misc.xml
r051372c r41d415b 117 117 </sect1> 118 118 119 <sect1 id="nick_changes"> 120 <title>Changing your nickname</title> 121 122 <para> 123 BitlBee now allows you to change your nickname. So far this was not possible because it made managing saved accounts more complicated. 124 </para> 125 126 <para> 127 The restriction no longer exists now though. When you change your nick (just using the <emphasis>/nick</emphasis> command), your logged-in status will be reset, which means any changes made to your settings/accounts will not be saved. 128 </para> 129 130 <para> 131 To restore your logged-in status, you need to either use the <emphasis>register</emphasis> command to create an account under the new nickname, or use <emphasis>identify -noload</emphasis> to re-identify yourself under the new nickname. The <emphasis>-noload</emphasis> flag tells the command to verify your password and log you in, but not load any new settings. See <emphasis>help identify</emphasis> for more information. 132 </para> 133 134 </sect1> 135 136 <sect1 id="channels"> 137 <title>Dealing with channels</title> 138 139 <para> 140 You can have as many channels in BitlBee as you want. You maintain your channel list using the <emphasis>channel</emphasis> command. You can create new channels by just joining them, like on regular IRC networks. 141 </para> 142 143 <para> 144 You can create two kinds of channels. Control channels, and groupchat channels. By default, BitlBee will set up new channels as control channels if their name starts with an &, and as chat channels if it starts with a #. 145 </para> 146 147 <para> 148 Control channels are where you see your contacts. By default, you will have one control channel called &bitlbee, containing all your contacts. But you can create more, if you want, and divide your contact list accross several channels. 149 </para> 150 151 <para> 152 For example, you can have one channel with all contacts from your MSN Messenger account in it. Or all contacts from the group called "Work". 153 </para> 154 155 <para> 156 Type <emphasis>help channels2</emphasis> to read more. 157 </para> 158 159 </sect1> 160 161 <sect1 id="channels2"> 162 <title>Creating a channel</title> 163 164 <para> 165 When you create a new channel, BitlBee will try to guess from its name which contacts to fill it with. For example, if the channel name (excluding the &) matches the name of a group in which you have one or more contacts, the channel will contain all those contacts. 166 </para> 167 168 <para> 169 Any valid account ID (so a number, protocol name or part of screenname, as long as it's unique) can also be used as a channel name. So if you just join &msn, it will contain all your MSN contacts (as long as you have only one MSN account set up). And if you have a Facebook account set up, you can see its contacts by just joining &facebook. 170 </para> 171 172 <para> 173 To start a simple group chat, you simply join a channel which a name starting with #, and invite people into it. All people you invite have to be on the same IM network and contact list. 174 </para> 175 176 <para> 177 If you want to configure your own channels, you can use the <emphasis>channel set</emphasis>. 178 </para> 179 180 </sect1> 181 119 182 </chapter> -
help.c
r051372c r41d415b 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-200 5Wilmer van der Gaast and others *4 * Copyright 2002-2009 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 169 169 return NULL; 170 170 } 171 172 int help_add_mem( help_t **help, const char *title, const char *content ) 173 { 174 help_t *h, *l = NULL; 175 176 for( h = *help; h; h = h->next ) 177 { 178 if( g_strcasecmp( h->title, title ) == 0 ) 179 return 0; 180 181 l = h; 182 } 183 184 if( l ) 185 h = l->next = g_new0( struct help, 1 ); 186 else 187 *help = h = g_new0( struct help, 1 ); 188 h->fd = -1; 189 h->title = g_strdup( title ); 190 h->length = strlen( content ); 191 h->offset.mem_offset = g_strdup( content ); 192 193 return 1; 194 } -
help.h
r051372c r41d415b 46 46 void help_free( help_t **help ); 47 47 char *help_get( help_t **help, char *title ); 48 int help_add_mem( help_t **help, const char *title, const char *content_ ); 48 49 49 50 #endif -
ipc.c
r051372c r41d415b 138 138 139 139 if( strchr( irc->umode, 'w' ) ) 140 irc_write( irc, ":%s WALLOPS :%s", irc-> myhost, cmd[1] );140 irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] ); 141 141 } 142 142 … … 147 147 148 148 if( strchr( irc->umode, 's' ) ) 149 irc_write( irc, ":%s NOTICE %s :%s", irc-> myhost, irc->nick, cmd[1] );149 irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] ); 150 150 } 151 151 … … 156 156 157 157 if( strchr( irc->umode, 'o' ) ) 158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc-> myhost, irc->nick, cmd[1] );158 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] ); 159 159 } 160 160 … … 176 176 return; 177 177 178 if( nick_cmp( cmd[1], irc-> nick ) != 0 )178 if( nick_cmp( cmd[1], irc->user->nick ) != 0 ) 179 179 return; /* It's not for us. */ 180 180 181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc-> mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );181 irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] ); 182 182 irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); 183 183 } … … 188 188 ipc_to_master_str( "HELLO\r\n" ); 189 189 else 190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc-> host, irc->nick, irc->realname );190 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 191 191 } 192 192 … … 514 514 } 515 515 516 child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );516 child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); 517 517 518 518 child_list = g_slist_append( child_list, child ); … … 552 552 } 553 553 554 b_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL );554 b_input_add( serversock, B_EV_IO_READ, new_ipc_client, NULL ); 555 555 556 556 return 1; … … 597 597 return 0; 598 598 } 599 child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );599 child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); 600 600 601 601 child_list = g_slist_append( child_list, child ); -
irc.c
r051372c r41d415b 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 24 24 */ 25 25 26 #define BITLBEE_CORE27 26 #include "bitlbee.h" 28 #include "sock.h"29 #include "crypting.h"30 27 #include "ipc.h" 31 32 static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); 33 34 GSList *irc_connection_list = NULL; 35 36 static char *set_eval_password( set_t *set, char *value ) 37 { 38 irc_t *irc = set->data; 39 40 if( irc->status & USTATUS_IDENTIFIED && value ) 41 { 42 irc_setpass( irc, value ); 43 return NULL; 44 } 45 else 46 { 47 return SET_INVALID; 48 } 49 } 50 51 static char *set_eval_charset( set_t *set, char *value ) 52 { 53 irc_t *irc = set->data; 54 char *test; 55 gsize test_bytes = 0; 56 GIConv ic, oc; 57 58 if( g_strcasecmp( value, "none" ) == 0 ) 59 value = g_strdup( "utf-8" ); 60 61 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 62 { 63 return NULL; 64 } 65 66 /* Do a test iconv to see if the user picked an IRC-compatible 67 charset (for example utf-16 goes *horribly* wrong). */ 68 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 69 test_bytes > 1 ) 70 { 71 g_free( test ); 72 g_iconv_close( oc ); 73 irc_usermsg( irc, "Unsupported character set: The IRC protocol " 74 "only supports 8-bit character sets." ); 75 return NULL; 76 } 77 g_free( test ); 78 79 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 80 { 81 g_iconv_close( oc ); 82 return NULL; 83 } 84 85 if( irc->iconv != (GIConv) -1 ) 86 g_iconv_close( irc->iconv ); 87 if( irc->oconv != (GIConv) -1 ) 88 g_iconv_close( irc->oconv ); 89 90 irc->iconv = ic; 91 irc->oconv = oc; 92 93 return value; 94 } 95 96 static char *set_eval_away_status( set_t *set, char *value ) 97 { 98 irc_t *irc = set->data; 99 account_t *a; 100 101 g_free( set->value ); 102 set->value = g_strdup( value ); 103 104 for( a = irc->accounts; a; a = a->next ) 105 { 106 struct im_connection *ic = a->ic; 107 108 if( ic && ic->flags & OPT_LOGGED_IN ) 109 imc_away_send_update( ic ); 110 } 111 112 return value; 113 } 28 #include "dcc.h" 29 30 GSList *irc_connection_list; 31 32 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ); 33 static char *set_eval_charset( set_t *set, char *value ); 34 static char *set_eval_password( set_t *set, char *value ); 114 35 115 36 irc_t *irc_new( int fd ) … … 118 39 struct sockaddr_storage sock; 119 40 socklen_t socklen = sizeof( sock ); 41 char *host = NULL, *myhost = NULL; 42 irc_user_t *iu; 120 43 set_t *s; 44 bee_t *b; 121 45 122 46 irc = g_new0( irc_t, 1 ); … … 125 49 sock_make_nonblocking( irc->fd ); 126 50 127 irc->r_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc );51 irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc ); 128 52 129 53 irc->status = USTATUS_OFFLINE; 130 54 irc->last_pong = gettime(); 131 55 132 irc-> userhash = g_hash_table_new( g_str_hash, g_str_equal );56 irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal ); 133 57 irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); 134 135 strcpy( irc->umode, UMODE );136 irc->mynick = g_strdup( ROOT_NICK );137 irc->channel = g_strdup( ROOT_CHAN );138 58 139 59 irc->iconv = (GIConv) -1; … … 142 62 if( global.conf->hostname ) 143 63 { 144 irc->myhost = g_strdup( global.conf->hostname );64 myhost = g_strdup( global.conf->hostname ); 145 65 } 146 66 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) … … 151 71 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 152 72 { 153 irc->myhost = g_strdup( ipv6_unwrap( buf ) );73 myhost = g_strdup( ipv6_unwrap( buf ) ); 154 74 } 155 75 } … … 162 82 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 163 83 { 164 irc->host = g_strdup( ipv6_unwrap( buf ) );165 } 166 } 167 168 if( irc->host == NULL )169 irc->host = g_strdup( "localhost.localdomain" );170 if( irc->myhost == NULL )171 irc->myhost = g_strdup( "localhost.localdomain" );84 host = g_strdup( ipv6_unwrap( buf ) ); 85 } 86 } 87 88 if( host == NULL ) 89 host = g_strdup( "localhost.localdomain" ); 90 if( myhost == NULL ) 91 myhost = g_strdup( "localhost.localdomain" ); 172 92 173 93 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 174 94 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); 175 176 irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );177 95 178 96 irc_connection_list = g_slist_append( irc_connection_list, irc ); 179 97 180 s = set_add( &irc->set, "away", NULL, set_eval_away_status, irc ); 98 b = irc->b = bee_new(); 99 b->ui_data = irc; 100 b->ui = &irc_ui_funcs; 101 102 s = set_add( &b->set, "away_devoice", "true", set_eval_away_devoice, irc ); 103 s = set_add( &b->set, "away_reply_timeout", "3600", set_eval_int, irc ); 104 s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc ); 105 s = set_add( &b->set, "default_target", "root", NULL, irc ); 106 s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc ); 107 s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc ); 108 s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc ); 109 s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc ); 110 s = set_add( &b->set, "ops", "both", set_eval_irc_channel_ops, irc ); 111 s = set_add( &b->set, "paste_buffer", "false", set_eval_bool, irc ); 112 s->old_key = g_strdup( "buddy_sendbuffer" ); 113 s = set_add( &b->set, "paste_buffer_delay", "200", set_eval_int, irc ); 114 s->old_key = g_strdup( "buddy_sendbuffer_delay" ); 115 s = set_add( &b->set, "password", NULL, set_eval_password, irc ); 181 116 s->flags |= SET_NULL_OK; 182 s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); 183 s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); 184 s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc ); 185 s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc ); 186 s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); 187 s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); 188 s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); 189 s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc ); 190 s = set_add( &irc->set, "debug", "false", set_eval_bool, irc ); 191 s = set_add( &irc->set, "default_target", "root", NULL, irc ); 192 s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); 193 s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc ); 194 s = set_add( &irc->set, "handle_unknown", "root", NULL, irc ); 195 s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); 196 s = set_add( &irc->set, "ops", "both", set_eval_ops, irc ); 197 s = set_add( &irc->set, "password", NULL, set_eval_password, irc ); 198 s->flags |= SET_NULL_OK; 199 s = set_add( &irc->set, "private", "true", set_eval_bool, irc ); 200 s = set_add( &irc->set, "query_order", "lifo", NULL, irc ); 201 s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); 202 s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); 203 s = set_add( &irc->set, "show_offline", "false", set_eval_bool, irc ); 204 s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); 205 s = set_add( &irc->set, "status", NULL, set_eval_away_status, irc ); 206 s->flags |= SET_NULL_OK; 207 s = set_add( &irc->set, "strip_html", "true", NULL, irc ); 208 s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc ); 209 s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); 210 s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); 117 s = set_add( &b->set, "private", "true", set_eval_bool, irc ); 118 s = set_add( &b->set, "query_order", "lifo", NULL, irc ); 119 s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc ); 120 s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc ); 121 s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc ); 122 s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc ); 123 s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc ); 124 125 irc->root = iu = irc_user_new( irc, ROOT_NICK ); 126 iu->host = g_strdup( myhost ); 127 iu->fullname = g_strdup( ROOT_FN ); 128 iu->f = &irc_user_root_funcs; 129 130 iu = irc_user_new( irc, NS_NICK ); 131 iu->host = g_strdup( myhost ); 132 iu->fullname = g_strdup( ROOT_FN ); 133 iu->f = &irc_user_root_funcs; 134 135 irc->user = g_new0( irc_user_t, 1 ); 136 irc->user->host = g_strdup( host ); 211 137 212 138 conf_loaddefaults( irc ); 213 139 214 140 /* Evaluator sets the iconv/oconv structures. */ 215 set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); 216 217 return( irc ); 141 set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) ); 142 143 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" ); 144 145 g_free( myhost ); 146 g_free( host ); 147 148 nogaim_init(); 149 150 return irc; 218 151 } 219 152 … … 236 169 237 170 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 238 irc-> nick ? irc->nick : "(NONE)", irc->host, reason );171 irc->user->nick ? irc->user->nick : "(NONE)", irc->user->host, reason ); 239 172 240 173 g_free( reason ); … … 246 179 247 180 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 248 irc-> nick ? irc->nick : "(NONE)", irc->host, "No reason given" );181 irc->user->nick ? irc->user->nick : "(NONE)", irc->user->host, "No reason given" ); 249 182 } 250 183 … … 267 200 } 268 201 269 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 270 { 271 g_free( key ); 272 273 return( TRUE ); 274 } 275 276 /* Because we have no garbage collection, this is quite annoying */ 202 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 203 277 204 void irc_free( irc_t * irc ) 278 205 { 279 user_t *user, *usertmp;280 281 206 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 282 207 283 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc-> set, "save_on_quit" ) )208 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) 284 209 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 285 irc_usermsg( irc, "Error while saving settings!");210 log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick ); 286 211 287 212 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 288 289 while( irc->accounts )290 {291 if( irc->accounts->ic )292 imc_logout( irc->accounts->ic, FALSE );293 else if( irc->accounts->reconnect )294 cancel_auto_reconnect( irc->accounts );295 296 if( irc->accounts->ic == NULL )297 account_del( irc, irc->accounts );298 else299 /* Nasty hack, but account_del() doesn't work in this300 case and we don't want infinite loops, do we? ;-) */301 irc->accounts = irc->accounts->next;302 }303 213 304 214 while( irc->queries != NULL ) 305 215 query_del( irc, irc->queries ); 306 216 307 while( irc->set ) 308 set_del( &irc->set, irc->set->key ); 309 310 if (irc->users != NULL) 311 { 312 user = irc->users; 313 while( user != NULL ) 314 { 315 g_free( user->nick ); 316 g_free( user->away ); 317 g_free( user->handle ); 318 if( user->user != user->nick ) g_free( user->user ); 319 if( user->host != user->nick ) g_free( user->host ); 320 if( user->realname != user->nick ) g_free( user->realname ); 321 b_event_remove( user->sendbuf_timer ); 322 323 usertmp = user; 324 user = user->next; 325 g_free( usertmp ); 326 } 327 } 217 /* This is a little bit messy: bee_free() frees all b->users which 218 calls us back to free the corresponding irc->users. So do this 219 before we clear the remaining ones ourselves. */ 220 bee_free( irc->b ); 221 222 while( irc->users ) 223 irc_user_free( irc, (irc_user_t *) irc->users->data ); 224 225 while( irc->channels ) 226 irc_channel_free( irc->channels->data ); 328 227 329 228 if( irc->ping_source_id > 0 ) … … 337 236 irc->fd = -1; 338 237 339 g_hash_table_foreach_remove( irc-> userhash, irc_free_hashkey, NULL );340 g_hash_table_destroy( irc-> userhash );238 g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL ); 239 g_hash_table_destroy( irc->nick_user_hash ); 341 240 342 241 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); … … 350 249 g_free( irc->sendbuffer ); 351 250 g_free( irc->readbuffer ); 352 353 g_free( irc->nick );354 g_free( irc->user );355 g_free( irc->host );356 g_free( irc->realname );357 251 g_free( irc->password ); 358 359 g_free( irc->myhost ); 360 g_free( irc->mynick ); 361 362 g_free( irc->channel ); 363 364 g_free( irc->last_target ); 252 g_free( irc->last_root_cmd ); 365 253 366 254 g_free( irc ); … … 374 262 } 375 263 264 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 265 { 266 g_free( key ); 267 268 return( TRUE ); 269 } 270 376 271 /* USE WITH CAUTION! 377 272 Sets pass without checking */ 378 void irc_setpass (irc_t *irc, const char *pass) 273 void irc_setpass (irc_t *irc, const char *pass) 379 274 { 380 275 g_free (irc->password); … … 387 282 } 388 283 284 static char *set_eval_password( set_t *set, char *value ) 285 { 286 irc_t *irc = set->data; 287 288 if( irc->status & USTATUS_IDENTIFIED && value ) 289 { 290 irc_setpass( irc, value ); 291 return NULL; 292 } 293 else 294 { 295 return SET_INVALID; 296 } 297 } 298 299 static char **irc_splitlines( char *buffer ); 300 389 301 void irc_process( irc_t *irc ) 390 302 { … … 394 306 if( irc->readbuffer != NULL ) 395 307 { 396 lines = irc_ tokenize( irc->readbuffer );308 lines = irc_splitlines( irc->readbuffer ); 397 309 398 310 for( i = 0; *lines[i] != '\0'; i ++ ) … … 431 343 "`help set charset' for more information. Your " 432 344 "message was ignored.", 433 set_getstr( &irc-> set, "charset" ) );345 set_getstr( &irc->b->set, "charset" ) ); 434 346 435 347 g_free( conv ); … … 438 350 else 439 351 { 440 irc_write( irc, ":%s NOTICE AUTH :%s", irc-> myhost,352 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, 441 353 "Warning: invalid characters received at login time." ); 442 354 … … 476 388 } 477 389 478 /* Splits a long string into separate lines. The array is NULL-terminated and, unless the string 479 contains an incomplete line at the end, ends with an empty string. */ 480 char **irc_tokenize( char *buffer ) 390 /* Splits a long string into separate lines. The array is NULL-terminated 391 and, unless the string contains an incomplete line at the end, ends with 392 an empty string. Could use g_strsplit() but this one does it in-place. 393 (So yes, it's destructive.) */ 394 static char **irc_splitlines( char *buffer ) 481 395 { 482 396 int i, j, n = 3; … … 609 523 } 610 524 611 void irc_reply( irc_t *irc, int code, char *format, ... )612 {613 char text[IRC_MAX_LINE];614 va_list params;615 616 va_start( params, format );617 g_vsnprintf( text, IRC_MAX_LINE, format, params );618 va_end( params );619 irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );620 621 return;622 }623 624 int irc_usermsg( irc_t *irc, char *format, ... )625 {626 char text[1024];627 va_list params;628 char is_private = 0;629 user_t *u;630 631 u = user_find( irc, irc->mynick );632 is_private = u->is_private;633 634 va_start( params, format );635 g_vsnprintf( text, sizeof( text ), format, params );636 va_end( params );637 638 return( irc_msgfrom( irc, u->nick, text ) );639 }640 641 525 void irc_write( irc_t *irc, char *format, ... ) 642 526 { … … 649 533 return; 650 534 } 535 536 void irc_write_all( int now, char *format, ... ) 537 { 538 va_list params; 539 GSList *temp; 540 541 va_start( params, format ); 542 543 temp = irc_connection_list; 544 while( temp != NULL ) 545 { 546 irc_t *irc = temp->data; 547 548 if( now ) 549 { 550 g_free( irc->sendbuffer ); 551 irc->sendbuffer = g_strdup( "\r\n" ); 552 } 553 irc_vawrite( temp->data, format, params ); 554 if( now ) 555 { 556 bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ); 557 } 558 temp = temp->next; 559 } 560 561 va_end( params ); 562 return; 563 } 651 564 652 565 void irc_vawrite( irc_t *irc, char *format, va_list params ) … … 696 609 in the event queue. */ 697 610 /* Really can't be done as long as the code doesn't do error checking very well: 698 if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) */611 if( bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ) ) */ 699 612 700 613 /* So just always do it via the event handler. */ 701 irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc );614 irc->w_watch_source_id = b_input_add( irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc ); 702 615 } 703 616 … … 705 618 } 706 619 707 void irc_write_all( int now, char *format, ... ) 708 { 709 va_list params; 710 GSList *temp; 711 712 va_start( params, format ); 713 714 temp = irc_connection_list; 715 while( temp != NULL ) 716 { 717 irc_t *irc = temp->data; 718 719 if( now ) 720 { 721 g_free( irc->sendbuffer ); 722 irc->sendbuffer = g_strdup( "\r\n" ); 723 } 724 irc_vawrite( temp->data, format, params ); 725 if( now ) 726 { 727 bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ); 728 } 729 temp = temp->next; 730 } 731 732 va_end( params ); 733 return; 734 } 735 736 void irc_names( irc_t *irc, char *channel ) 737 { 738 user_t *u; 739 char namelist[385] = ""; 740 struct groupchat *c = NULL; 741 char *ops = set_getstr( &irc->set, "ops" ); 742 743 /* RFCs say there is no error reply allowed on NAMES, so when the 744 channel is invalid, just give an empty reply. */ 745 746 if( g_strcasecmp( channel, irc->channel ) == 0 ) 747 { 748 for( u = irc->users; u; u = u->next ) if( u->online ) 749 { 750 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) 620 int irc_check_login( irc_t *irc ) 621 { 622 if( irc->user->user && irc->user->nick ) 623 { 624 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 625 { 626 irc_send_num( irc, 464, ":This server is password-protected." ); 627 return 0; 628 } 629 else 630 { 631 irc_channel_t *ic; 632 irc_user_t *iu = irc->user; 633 634 irc->user = irc_user_new( irc, iu->nick ); 635 irc->user->user = iu->user; 636 irc->user->host = iu->host; 637 irc->user->fullname = iu->fullname; 638 irc->user->f = &irc_user_self_funcs; 639 g_free( iu->nick ); 640 g_free( iu ); 641 642 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 643 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 644 645 irc->status |= USTATUS_LOGGED_IN; 646 647 irc_send_login( irc ); 648 649 irc->umode[0] = '\0'; 650 irc_umode_set( irc, "+" UMODE, TRUE ); 651 652 ic = irc->default_channel = irc_channel_new( irc, ROOT_CHAN ); 653 irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root ); 654 irc_channel_add_user( ic, irc->user ); 655 656 irc->last_root_cmd = g_strdup( ROOT_CHAN ); 657 658 irc_send_msg( irc->root, "PRIVMSG", ROOT_CHAN, 659 "Welcome to the BitlBee gateway!\n\n" 660 "If you've never used BitlBee before, please do read the help " 661 "information using the \x02help\x02 command. Lots of FAQs are " 662 "answered there.\n" 663 "If you already have an account on this server, just use the " 664 "\x02identify\x02 command to identify yourself.", NULL ); 665 666 /* This is for bug #209 (use PASS to identify to NickServ). */ 667 if( irc->password != NULL ) 751 668 { 752 irc_reply( irc, 353, "= %s :%s", channel, namelist ); 753 *namelist = 0; 669 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 670 671 irc_setpass( irc, NULL ); 672 root_command( irc, send_cmd ); 673 g_free( send_cmd[1] ); 754 674 } 755 675 756 if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )757 strcat( namelist, "+" );758 else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||759 ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )760 strcat( namelist, "@" );761 762 strcat( namelist, u->nick );763 strcat( namelist, " " );764 }765 }766 else if( ( c = irc_chat_by_channel( irc, channel ) ) )767 {768 GList *l;769 770 /* root and the user aren't in the channel userlist but should771 show up in /NAMES, so list them first: */772 sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,773 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );774 775 for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )776 {777 if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )778 {779 irc_reply( irc, 353, "= %s :%s", channel, namelist );780 *namelist = 0;781 }782 783 strcat( namelist, u->nick );784 strcat( namelist, " " );785 }786 }787 788 if( *namelist )789 irc_reply( irc, 353, "= %s :%s", channel, namelist );790 791 irc_reply( irc, 366, "%s :End of /NAMES list", channel );792 }793 794 int irc_check_login( irc_t *irc )795 {796 if( irc->user && irc->nick )797 {798 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )799 {800 irc_reply( irc, 464, ":This server is password-protected." );801 return 0;802 }803 else804 {805 irc_login( irc );806 676 return 1; 807 677 } … … 814 684 } 815 685 816 void irc_login( irc_t *irc ) 817 { 818 user_t *u; 819 820 irc_reply( irc, 1, ":Welcome to the BitlBee gateway, %s", irc->nick ); 821 irc_reply( irc, 2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost ); 822 irc_reply( irc, 3, ":%s", IRCD_INFO ); 823 irc_reply( irc, 4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); 824 irc_reply( irc, 5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee " 825 "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", 826 CTYPES, CMODES, MAX_NICK_LENGTH - 1 ); 827 irc_motd( irc ); 828 irc->umode[0] = '\0'; 829 irc_umode_set( irc, "+" UMODE, 1 ); 830 831 u = user_add( irc, irc->mynick ); 832 u->host = g_strdup( irc->myhost ); 833 u->realname = g_strdup( ROOT_FN ); 834 u->online = 1; 835 u->send_handler = root_command_string; 836 u->is_private = 0; /* [SH] The channel is root's personal playground. */ 837 irc_spawn( irc, u ); 838 839 u = user_add( irc, NS_NICK ); 840 u->host = g_strdup( irc->myhost ); 841 u->realname = g_strdup( ROOT_FN ); 842 u->online = 0; 843 u->send_handler = root_command_string; 844 u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */ 845 846 u = user_add( irc, irc->nick ); 847 u->user = g_strdup( irc->user ); 848 u->host = g_strdup( irc->host ); 849 u->realname = g_strdup( irc->realname ); 850 u->online = 1; 851 irc_spawn( irc, u ); 852 853 irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n" 854 "If you've never used BitlBee before, please do read the help " 855 "information using the \x02help\x02 command. Lots of FAQs are " 856 "answered there.\n" 857 "If you already have an account on this server, just use the " 858 "\x02identify\x02 command to identify yourself." ); 859 860 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 861 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); 862 863 irc->status |= USTATUS_LOGGED_IN; 864 865 /* This is for bug #209 (use PASS to identify to NickServ). */ 866 if( irc->password != NULL ) 867 { 868 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 869 870 irc_setpass( irc, NULL ); 871 root_command( irc, send_cmd ); 872 g_free( send_cmd[1] ); 873 } 874 } 875 876 void irc_motd( irc_t *irc ) 877 { 878 int fd; 879 880 fd = open( global.conf->motdfile, O_RDONLY ); 881 if( fd == -1 ) 882 { 883 irc_reply( irc, 422, ":We don't need MOTDs." ); 884 } 885 else 886 { 887 char linebuf[80]; /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */ 888 char *add, max; 889 int len; 890 891 linebuf[79] = len = 0; 892 max = sizeof( linebuf ) - 1; 893 894 irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost ); 895 while( read( fd, linebuf + len, 1 ) == 1 ) 896 { 897 if( linebuf[len] == '\n' || len == max ) 898 { 899 linebuf[len] = 0; 900 irc_reply( irc, 372, ":- %s", linebuf ); 901 len = 0; 902 } 903 else if( linebuf[len] == '%' ) 904 { 905 read( fd, linebuf + len, 1 ); 906 if( linebuf[len] == 'h' ) 907 add = irc->myhost; 908 else if( linebuf[len] == 'v' ) 909 add = BITLBEE_VERSION; 910 else if( linebuf[len] == 'n' ) 911 add = irc->nick; 912 else 913 add = "%"; 914 915 strncpy( linebuf + len, add, max - len ); 916 while( linebuf[++len] ); 917 } 918 else if( len < max ) 919 { 920 len ++; 921 } 922 } 923 irc_reply( irc, 376, ":End of MOTD" ); 924 close( fd ); 925 } 926 } 927 928 void irc_topic( irc_t *irc, char *channel ) 929 { 930 struct groupchat *c = irc_chat_by_channel( irc, channel ); 931 932 if( c && c->topic ) 933 irc_reply( irc, 332, "%s :%s", channel, c->topic ); 934 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 935 irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC ); 936 else 937 irc_reply( irc, 331, "%s :No topic for this channel", channel ); 938 } 939 940 void irc_umode_set( irc_t *irc, char *s, int allow_priv ) 686 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) 941 687 { 942 688 /* allow_priv: Set to 0 if s contains user input, 1 if you want 943 689 to set a "privileged" mode (+o, +R, etc). */ 944 char m[256], st = 1, *t; 690 char m[128], st = 1; 691 const char *t; 945 692 int i; 946 693 char changes[512], *p, st2 = 2; … … 950 697 951 698 for( t = irc->umode; *t; t ++ ) 952 m[(int)*t] = 1; 953 699 if( *t < sizeof( m ) ) 700 m[(int)*t] = 1; 701 954 702 p = changes; 955 703 for( t = s; *t; t ++ ) … … 957 705 if( *t == '+' || *t == '-' ) 958 706 st = *t == '+'; 959 else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) 707 else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || 708 ( st == 1 && strchr( UMODES, *t ) ) || 709 ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) 960 710 { 961 711 if( m[(int)*t] != st) … … 974 724 memset( irc->umode, 0, sizeof( irc->umode ) ); 975 725 976 for( i = 0; i < 256&& strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )726 for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) 977 727 if( m[i] ) 978 728 irc->umode[strlen(irc->umode)] = i; 979 729 980 730 if( badflag ) 981 irc_reply( irc, 501, ":Unknown MODE flag" ); 982 /* Deliberately no !user@host on the prefix here */ 731 irc_send_num( irc, 501, ":Unknown MODE flag" ); 983 732 if( *changes ) 984 irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes ); 985 } 986 987 void irc_spawn( irc_t *irc, user_t *u ) 988 { 989 irc_join( irc, u, irc->channel ); 990 } 991 992 void irc_join( irc_t *irc, user_t *u, char *channel ) 993 { 994 char *nick; 995 996 if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) ) 997 irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel ); 998 999 if( nick_cmp( u->nick, irc->nick ) == 0 ) 1000 { 1001 irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE ); 1002 irc_names( irc, channel ); 1003 irc_topic( irc, channel ); 1004 } 1005 1006 nick = g_strdup( u->nick ); 1007 nick_lc( nick ); 1008 if( g_hash_table_lookup( irc->watches, nick ) ) 1009 { 1010 irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" ); 1011 } 1012 g_free( nick ); 1013 } 1014 1015 void irc_part( irc_t *irc, user_t *u, char *channel ) 1016 { 1017 irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" ); 1018 } 1019 1020 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ) 1021 { 1022 irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" ); 1023 } 1024 1025 void irc_kill( irc_t *irc, user_t *u ) 1026 { 1027 char *nick, *s; 1028 char reason[128]; 1029 1030 if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) ) 1031 { 1032 if( u->ic->acc->server ) 1033 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1034 u->ic->acc->server ); 1035 else if( ( s = strchr( u->ic->acc->user, '@' ) ) ) 1036 g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, 1037 s + 1 ); 1038 else 1039 g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, 1040 u->ic->acc->prpl->name, irc->myhost ); 1041 1042 /* proto_opt might contain garbage after the : */ 1043 if( ( s = strchr( reason, ':' ) ) ) 1044 *s = 0; 1045 } 1046 else 1047 { 1048 strcpy( reason, "Leaving..." ); 1049 } 1050 1051 irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason ); 1052 1053 nick = g_strdup( u->nick ); 1054 nick_lc( nick ); 1055 if( g_hash_table_lookup( irc->watches, nick ) ) 1056 { 1057 irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" ); 1058 } 1059 g_free( nick ); 1060 } 1061 1062 int irc_send( irc_t *irc, char *nick, char *s, int flags ) 1063 { 1064 struct groupchat *c = NULL; 1065 user_t *u = NULL; 1066 1067 if( strchr( CTYPES, *nick ) ) 1068 { 1069 if( !( c = irc_chat_by_channel( irc, nick ) ) ) 1070 { 1071 irc_reply( irc, 403, "%s :Channel does not exist", nick ); 1072 return( 0 ); 1073 } 1074 } 1075 else 1076 { 1077 u = user_find( irc, nick ); 1078 1079 if( !u ) 1080 { 1081 if( irc->is_private ) 1082 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 1083 else 1084 irc_usermsg( irc, "Nick `%s' does not exist!", nick ); 1085 return( 0 ); 1086 } 1087 } 1088 1089 if( *s == 1 && s[strlen(s)-1] == 1 ) 1090 { 1091 if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 ) 1092 { 1093 if( s[7] == ' ' ) s ++; 1094 s += 3; 1095 *(s++) = '/'; 1096 *(s++) = 'm'; 1097 *(s++) = 'e'; 1098 *(s++) = ' '; 1099 s -= 4; 1100 s[strlen(s)-1] = 0; 1101 } 1102 else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 ) 1103 { 1104 u = user_find( irc, irc->mynick ); 1105 irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" ); 1106 return( 1 ); 1107 } 1108 else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 ) 1109 { 1110 u = user_find( irc, irc->mynick ); 1111 irc_privmsg( irc, u, "NOTICE", irc->nick, "", s ); 1112 return( 1 ); 1113 } 1114 else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 ) 1115 { 1116 if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 ) 1117 { 1118 time_t current_typing_notice = time( NULL ); 1119 1120 if( current_typing_notice - u->last_typing_notice >= 5 ) 1121 { 1122 u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 ); 1123 u->last_typing_notice = current_typing_notice; 1124 } 1125 } 1126 return( 1 ); 1127 } 1128 else 1129 { 1130 irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" ); 1131 return( 0 ); 1132 } 1133 } 1134 1135 if( u ) 1136 { 1137 /* For the next message, we probably do have to send new notices... */ 1138 u->last_typing_notice = 0; 1139 u->is_private = irc->is_private; 1140 1141 if( u->is_private ) 1142 { 1143 if( !u->online ) 1144 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 1145 else if( u->away ) 1146 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 1147 } 1148 1149 if( u->send_handler ) 1150 { 1151 u->send_handler( irc, u, s, flags ); 1152 return 1; 1153 } 1154 } 1155 else if( c && c->ic && c->ic->acc && c->ic->acc->prpl ) 1156 { 1157 return( imc_chat_msg( c, s, 0 ) ); 1158 } 1159 1160 return( 0 ); 1161 } 1162 1163 static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond ) 1164 { 1165 user_t *u = data; 1166 1167 /* Shouldn't happen, but just to be sure. */ 1168 if( u->sendbuf_len < 2 ) 1169 return FALSE; 1170 1171 u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */ 1172 imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); 1173 1174 g_free( u->sendbuf ); 1175 u->sendbuf = NULL; 1176 u->sendbuf_len = 0; 1177 u->sendbuf_timer = 0; 1178 u->sendbuf_flags = 0; 1179 1180 return FALSE; 1181 } 1182 1183 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) 1184 { 1185 if( !u || !u->ic ) return; 1186 1187 if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) 1188 { 1189 int delay; 1190 1191 if( u->sendbuf_len > 0 && u->sendbuf_flags != flags) 1192 { 1193 /* Flush the buffer */ 1194 b_event_remove( u->sendbuf_timer ); 1195 buddy_send_handler_delayed( u, -1, 0 ); 1196 } 1197 1198 if( u->sendbuf_len == 0 ) 1199 { 1200 u->sendbuf_len = strlen( msg ) + 2; 1201 u->sendbuf = g_new( char, u->sendbuf_len ); 1202 u->sendbuf[0] = 0; 1203 u->sendbuf_flags = flags; 1204 } 1205 else 1206 { 1207 u->sendbuf_len += strlen( msg ) + 1; 1208 u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len ); 1209 } 1210 1211 strcat( u->sendbuf, msg ); 1212 strcat( u->sendbuf, "\n" ); 1213 1214 delay = set_getint( &irc->set, "buddy_sendbuffer_delay" ); 1215 if( delay <= 5 ) 1216 delay *= 1000; 1217 1218 if( u->sendbuf_timer > 0 ) 1219 b_event_remove( u->sendbuf_timer ); 1220 u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u ); 1221 } 1222 else 1223 { 1224 imc_buddy_msg( u->ic, u->handle, msg, flags ); 1225 } 1226 } 1227 1228 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ) 1229 { 1230 char last = 0; 1231 char *s = msg, *line = msg; 1232 1233 /* The almighty linesplitter .. woohoo!! */ 1234 while( !last ) 1235 { 1236 if( *s == '\r' && *(s+1) == '\n' ) 1237 *(s++) = 0; 1238 if( *s == '\n' ) 1239 { 1240 last = s[1] == 0; 1241 *s = 0; 1242 } 1243 else 1244 { 1245 last = s[0] == 0; 1246 } 1247 if( *s == 0 ) 1248 { 1249 if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 ) 1250 { 1251 irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host, 1252 type, to, line + 4 ); 1253 } 1254 else 1255 { 1256 irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host, 1257 type, to, prefix ? prefix : "", line ); 1258 } 1259 line = s + 1; 1260 } 1261 s ++; 1262 } 1263 1264 return( 1 ); 1265 } 1266 1267 int irc_msgfrom( irc_t *irc, char *nick, char *msg ) 1268 { 1269 user_t *u = user_find( irc, nick ); 1270 static char *prefix = NULL; 1271 1272 if( !u ) return( 0 ); 1273 if( prefix && *prefix ) g_free( prefix ); 1274 1275 if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 ) 1276 { 1277 int len = strlen( irc->nick) + 3; 1278 prefix = g_new (char, len ); 1279 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) ); 1280 prefix[len-1] = 0; 1281 } 1282 else 1283 { 1284 prefix = ""; 1285 } 1286 1287 return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) ); 1288 } 1289 1290 int irc_noticefrom( irc_t *irc, char *nick, char *msg ) 1291 { 1292 user_t *u = user_find( irc, nick ); 1293 1294 if( u ) 1295 return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) ); 1296 else 1297 return( 0 ); 733 irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, 734 irc->user->user, irc->user->host, irc->user->nick, 735 changes ); 1298 736 } 1299 737 … … 1334 772 } 1335 773 1336 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ) 1337 { 1338 struct groupchat *c; 1339 account_t *a; 1340 1341 /* This finds the connection which has a conversation which belongs to this channel */ 1342 for( a = irc->accounts; a; a = a->next ) 1343 { 1344 if( a->ic == NULL ) 1345 continue; 1346 1347 c = a->ic->groupchats; 1348 while( c ) 1349 { 1350 if( c->channel && g_strcasecmp( c->channel, channel ) == 0 ) 1351 return c; 1352 1353 c = c->next; 1354 } 1355 } 1356 1357 return NULL; 1358 } 774 static char *set_eval_charset( set_t *set, char *value ) 775 { 776 irc_t *irc = (irc_t*) set->data; 777 char *test; 778 gsize test_bytes = 0; 779 GIConv ic, oc; 780 781 if( g_strcasecmp( value, "none" ) == 0 ) 782 value = g_strdup( "utf-8" ); 783 784 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 785 { 786 return NULL; 787 } 788 789 /* Do a test iconv to see if the user picked an IRC-compatible 790 charset (for example utf-16 goes *horribly* wrong). */ 791 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 792 test_bytes > 1 ) 793 { 794 g_free( test ); 795 g_iconv_close( oc ); 796 irc_usermsg( irc, "Unsupported character set: The IRC protocol " 797 "only supports 8-bit character sets." ); 798 return NULL; 799 } 800 g_free( test ); 801 802 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 803 { 804 g_iconv_close( oc ); 805 return NULL; 806 } 807 808 if( irc->iconv != (GIConv) -1 ) 809 g_iconv_close( irc->iconv ); 810 if( irc->oconv != (GIConv) -1 ) 811 g_iconv_close( irc->oconv ); 812 813 irc->iconv = ic; 814 irc->oconv = oc; 815 816 return value; 817 } 818 819 char *set_eval_away_devoice( set_t *set, char *value ) 820 { 821 irc_t *irc = set->data; 822 823 if( !is_bool( value ) ) 824 return SET_INVALID; 825 826 /* The usual problem: The setting isn't actually changed at this 827 point and we need it to be, so do it by hand. */ 828 g_free( set->value ); 829 set->value = g_strdup( value ); 830 831 bee_irc_channel_update( irc, NULL, NULL ); 832 833 return value; 834 } -
irc.h
r051372c r41d415b 5 5 \********************************************************************/ 6 6 7 /* The big hairy IRCd part of the project*/7 /* The IRC-based UI (for now the only one) */ 8 8 9 9 /* … … 33 33 #define IRC_PING_STRING "PinglBee" 34 34 35 #define UMODES "abisw" 36 #define UMODES_PRIV "Ro" 37 #define CMODES "nt" 38 #define CMODE "t" 39 #define UMODE "s" 40 #define CTYPES "&#" 35 #define UMODES "abisw" /* Allowed umodes (although they mostly do nothing) */ 36 #define UMODES_PRIV "Ro" /* Allowed, but not by user directly */ 37 #define UMODES_KEEP "R" /* Don't allow unsetting using /MODE */ 38 #define CMODES "nt" /* Allowed modes */ 39 #define CMODE "t" /* Default mode */ 40 #define UMODE "s" /* Default mode */ 41 42 #define CTYPES "&#" /* Valid channel name prefixes */ 41 43 42 44 typedef enum … … 48 50 USTATUS_SHUTDOWN = 8 49 51 } irc_status_t; 52 53 struct irc_user; 50 54 51 55 typedef struct irc … … 59 63 GIConv iconv, oconv; 60 64 61 int sentbytes; 62 time_t oldtime; 63 65 struct irc_user *root; 66 struct irc_user *user; 67 68 char *last_root_cmd; 69 70 char *password; /* HACK: Used to save the user's password, but before 71 logging in, this may contain a password we should 72 send to identify after USER/NICK are received. */ 73 74 char umode[8]; 75 76 struct query *queries; 77 GSList *file_transfers; 78 79 GSList *users, *channels; 80 struct irc_channel *default_channel; 81 GHashTable *nick_user_hash; 82 GHashTable *watches; 83 84 gint r_watch_source_id; 85 gint w_watch_source_id; 86 gint ping_source_id; 87 88 struct bee *b; 89 } irc_t; 90 91 typedef enum 92 { 93 IRC_USER_PRIVATE = 1, 94 IRC_USER_AWAY = 2, 95 } irc_user_flags_t; 96 97 typedef struct irc_user 98 { 99 irc_t *irc; 100 64 101 char *nick; 65 102 char *user; 66 103 char *host; 67 char *realname; 68 char *password; /* HACK: Used to save the user's password, but before 69 logging in, this may contain a password we should 70 send to identify after USER/NICK are received. */ 71 72 char umode[8]; 73 74 char *myhost; 75 char *mynick; 76 77 char *channel; 78 int c_id; 79 80 char is_private; /* Not too nice... */ 81 char *last_target; 82 83 struct query *queries; 84 struct account *accounts; 85 struct chat *chatrooms; 86 87 struct __USER *users; 88 GHashTable *userhash; 89 GHashTable *watches; 90 struct __NICK *nicks; 104 char *fullname; 105 106 /* Nickname in lowercase for case sensitive searches */ 107 char *key; 108 109 irc_user_flags_t flags; 110 111 GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */ 112 guint pastebuf_timer; 113 time_t away_reply_timeout; /* Only send a 301 if this time passed. */ 114 115 struct bee_user *bu; 116 117 const struct irc_user_funcs *f; 118 } irc_user_t; 119 120 struct irc_user_funcs 121 { 122 gboolean (*privmsg)( irc_user_t *iu, const char *msg ); 123 gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp ); 124 }; 125 126 extern const struct irc_user_funcs irc_user_root_funcs; 127 extern const struct irc_user_funcs irc_user_self_funcs; 128 129 typedef enum 130 { 131 IRC_CHANNEL_JOINED = 1, 132 133 /* Hack: Set this flag right before jumping into IM when we expect 134 a call to imcb_chat_new(). */ 135 IRC_CHANNEL_CHAT_PICKME = 0x10000, 136 } irc_channel_flags_t; 137 138 typedef struct irc_channel 139 { 140 irc_t *irc; 141 char *name; 142 char mode[8]; 143 int flags; 144 145 char *topic; 146 char *topic_who; 147 time_t topic_time; 148 149 GSList *users; /* struct irc_channel_user */ 91 150 struct set *set; 92 93 gint r_watch_source_id; 94 gint w_watch_source_id; 95 gint ping_source_id; 96 } irc_t; 97 98 #include "user.h" 99 151 152 GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */ 153 guint pastebuf_timer; 154 155 const struct irc_channel_funcs *f; 156 void *data; 157 } irc_channel_t; 158 159 struct irc_channel_funcs 160 { 161 gboolean (*privmsg)( irc_channel_t *ic, const char *msg ); 162 gboolean (*join)( irc_channel_t *ic ); 163 gboolean (*part)( irc_channel_t *ic, const char *msg ); 164 gboolean (*topic)( irc_channel_t *ic, const char *new ); 165 gboolean (*invite)( irc_channel_t *ic, irc_user_t *iu ); 166 167 gboolean (*_init)( irc_channel_t *ic ); 168 gboolean (*_free)( irc_channel_t *ic ); 169 }; 170 171 typedef enum 172 { 173 IRC_CHANNEL_USER_OP = 1, 174 IRC_CHANNEL_USER_HALFOP = 2, 175 IRC_CHANNEL_USER_VOICE = 4, 176 } irc_channel_user_flags_t; 177 178 typedef struct irc_channel_user 179 { 180 irc_user_t *iu; 181 int flags; 182 } irc_channel_user_t; 183 184 typedef enum 185 { 186 IRC_CC_TYPE_DEFAULT, 187 IRC_CC_TYPE_REST, 188 IRC_CC_TYPE_GROUP, 189 IRC_CC_TYPE_ACCOUNT, 190 } irc_control_channel_type_t; 191 192 struct irc_control_channel 193 { 194 irc_control_channel_type_t type; 195 struct bee_group *group; 196 struct account *account; 197 }; 198 199 extern const struct bee_ui_funcs irc_ui_funcs; 200 201 /* irc.c */ 100 202 extern GSList *irc_connection_list; 101 203 … … 103 205 void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 104 206 void irc_free( irc_t *irc ); 105 106 void irc_exec( irc_t *irc, char **cmd ); 207 void irc_setpass (irc_t *irc, const char *pass); 208 107 209 void irc_process( irc_t *irc ); 108 210 char **irc_parse_line( char *line ); 109 211 char *irc_build_line( char **cmd ); 110 212 111 void irc_vawrite( irc_t *irc, char *format, va_list params );112 213 void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 113 214 void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 114 void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 115 G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); 116 char **irc_tokenize( char *buffer ); 117 118 void irc_login( irc_t *irc ); 215 void irc_vawrite( irc_t *irc, char *format, va_list params ); 216 119 217 int irc_check_login( irc_t *irc ); 120 void irc_motd( irc_t *irc ); 121 void irc_names( irc_t *irc, char *channel ); 122 void irc_topic( irc_t *irc, char *channel ); 123 void irc_umode_set( irc_t *irc, char *s, int allow_priv ); 124 void irc_who( irc_t *irc, char *channel ); 125 void irc_spawn( irc_t *irc, user_t *u ); 126 void irc_join( irc_t *irc, user_t *u, char *channel ); 127 void irc_part( irc_t *irc, user_t *u, char *channel ); 128 void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ); 129 void irc_kill( irc_t *irc, user_t *u ); 130 void irc_invite( irc_t *irc, char *nick, char *channel ); 131 void irc_whois( irc_t *irc, char *nick ); 132 void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */ 133 134 int irc_send( irc_t *irc, char *nick, char *s, int flags ); 135 int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg ); 136 int irc_msgfrom( irc_t *irc, char *nick, char *msg ); 137 int irc_noticefrom( irc_t *irc, char *nick, char *msg ); 138 139 void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); 140 struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ); 218 219 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); 220 221 /* irc_channel.c */ 222 irc_channel_t *irc_channel_new( irc_t *irc, const char *name ); 223 irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ); 224 irc_channel_t *irc_channel_get( irc_t *irc, char *id ); 225 int irc_channel_free( irc_channel_t *ic ); 226 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu ); 227 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu, gboolean silent, const char *msg ); 228 irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu ); 229 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who ); 230 void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags ); 231 void irc_channel_printf( irc_channel_t *ic, char *format, ... ); 232 gboolean irc_channel_name_ok( const char *name ); 233 int irc_channel_name_cmp( const char *a_, const char *b_ ); 234 void irc_channel_update_ops( irc_channel_t *ic, char *value ); 235 char *set_eval_irc_channel_ops( struct set *set, char *value ); 236 237 /* irc_commands.c */ 238 void irc_exec( irc_t *irc, char **cmd ); 239 240 /* irc_send.c */ 241 void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); 242 void irc_send_login( irc_t *irc ); 243 void irc_send_motd( irc_t *irc ); 244 void irc_usermsg( irc_t *irc, char *format, ... ); 245 void irc_send_join( irc_channel_t *ic, irc_user_t *iu ); 246 void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason ); 247 void irc_send_quit( irc_user_t *iu, const char *reason ); 248 void irc_send_names( irc_channel_t *ic ); 249 void irc_send_topic( irc_channel_t *ic, gboolean topic_change ); 250 void irc_send_whois( irc_user_t *iu ); 251 void irc_send_who( irc_t *irc, GSList *l, const char *channel ); 252 void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix ); 253 void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg ); 254 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 ); 255 void irc_send_nick( irc_user_t *iu, const char *new ); 256 void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu, 257 irc_channel_user_flags_t old, irc_channel_user_flags_t new ); 258 259 /* irc_user.c */ 260 irc_user_t *irc_user_new( irc_t *irc, const char *nick ); 261 int irc_user_free( irc_t *irc, irc_user_t *iu ); 262 irc_user_t *irc_user_by_name( irc_t *irc, const char *nick ); 263 int irc_user_set_nick( irc_user_t *iu, const char *new ); 264 gint irc_user_cmp( gconstpointer a_, gconstpointer b_ ); 265 const char *irc_user_get_away( irc_user_t *iu ); 266 267 /* irc_util.c */ 268 char *set_eval_timezone( struct set *set, char *value ); 269 char *irc_format_timestamp( irc_t *irc, time_t msg_ts ); 270 271 /* irc_im.c */ 272 void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu ); 141 273 142 274 #endif -
irc_commands.c
r051372c r41d415b 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 06Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 53 53 else if( global.conf->auth_pass ) 54 54 { 55 irc_ reply( irc, 464, ":Incorrect password" );55 irc_send_num( irc, 464, ":Incorrect password" ); 56 56 } 57 57 else … … 65 65 static void irc_cmd_user( irc_t *irc, char **cmd ) 66 66 { 67 irc->user = g_strdup( cmd[1] );68 irc-> realname = g_strdup( cmd[4] );67 irc->user->user = g_strdup( cmd[1] ); 68 irc->user->fullname = g_strdup( cmd[4] ); 69 69 70 70 irc_check_login( irc ); … … 73 73 static void irc_cmd_nick( irc_t *irc, char **cmd ) 74 74 { 75 if( irc->status & USTATUS_IDENTIFIED && irc->nick ) 76 { 77 irc_reply( irc, 438, "%s %s :You can only change your nick if you're not " 78 "logged in (i.e. pre-identify)", irc->nick, cmd[1] ); 79 } 80 /* This is not clean, but for now it'll have to be like this... */ 81 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) || ( user_find( irc, cmd[1] ) != NULL ) ) 82 { 83 irc_reply( irc, 433, "%s :This nick is already in use", cmd[1] ); 75 if( irc_user_by_name( irc, cmd[1] ) ) 76 { 77 irc_send_num( irc, 433, ":This nick is already in use" ); 84 78 } 85 79 else if( !nick_ok( cmd[1] ) ) 86 80 { 87 81 /* [SH] Invalid characters. */ 88 irc_reply( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); 89 } 90 else if(irc->nick) 91 { 92 if( user_find( irc, irc->nick ) ) 93 user_rename(irc, irc->nick, cmd[1]); 94 95 irc_write( irc, ":%s!%s@%s NICK %s", irc->nick, irc->user, irc->host, cmd[1] ); 96 g_free(irc->nick); 97 irc->nick = g_strdup( cmd[1] ); 98 } 99 else 100 { 101 irc->nick = g_strdup( cmd[1] ); 82 irc_send_num( irc, 432, ":This nick contains invalid characters" ); 83 } 84 else if( irc->user->nick ) 85 { 86 if( irc->status & USTATUS_IDENTIFIED ) 87 { 88 irc_setpass( irc, NULL ); 89 irc->status &= ~USTATUS_IDENTIFIED; 90 irc_umode_set( irc, "-R", 1 ); 91 irc_usermsg( irc, "Changing nicks resets your identify status. " 92 "Re-identify or register a new account if you want " 93 "your configuration to be saved. See \x02help " 94 "nick_changes\x02." ); 95 } 96 97 irc_user_set_nick( irc->user, cmd[1] ); 98 } 99 else 100 { 101 irc->user->nick = g_strdup( cmd[1] ); 102 102 103 103 irc_check_login( irc ); … … 115 115 static void irc_cmd_ping( irc_t *irc, char **cmd ) 116 116 { 117 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost ); 118 } 117 irc_write( irc, ":%s PONG %s :%s", irc->root->host, 118 irc->root->host, cmd[1]?cmd[1]:irc->root->host ); 119 } 120 121 static void irc_cmd_pong( irc_t *irc, char **cmd ) 122 { 123 /* We could check the value we get back from the user, but in 124 fact we don't care, we're just happy s/he's still alive. */ 125 irc->last_pong = gettime(); 126 irc->pinging = 0; 127 } 128 129 static void irc_cmd_join( irc_t *irc, char **cmd ) 130 { 131 irc_channel_t *ic; 132 133 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 134 ic = irc_channel_new( irc, cmd[1] ); 135 136 if( ic == NULL ) 137 { 138 irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] ); 139 return; 140 } 141 142 if( ic->flags & IRC_CHANNEL_JOINED ) 143 return; /* Dude, you're already there... 144 RFC doesn't have any reply for that though? */ 145 146 if( ic->f->join && !ic->f->join( ic ) ) 147 /* The story is: FALSE either means the handler showed an error 148 message, or is doing some work before the join should be 149 confirmed. (In the latter case, the caller should take care 150 of that confirmation.) 151 TRUE means all's good, let the user join the channel right away. */ 152 return; 153 154 irc_channel_add_user( ic, irc->user ); 155 } 156 157 static void irc_cmd_names( irc_t *irc, char **cmd ) 158 { 159 irc_channel_t *ic; 160 161 if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 162 irc_send_names( ic ); 163 /* With no args, we should show /names of all chans. Make the code 164 below work well if necessary. 165 else 166 { 167 GSList *l; 168 169 for( l = irc->channels; l; l = l->next ) 170 irc_send_names( l->data ); 171 } 172 */ 173 } 174 175 static void irc_cmd_part( irc_t *irc, char **cmd ) 176 { 177 irc_channel_t *ic; 178 179 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 180 { 181 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 182 } 183 else if( irc_channel_del_user( ic, irc->user, FALSE, cmd[2] ) ) 184 { 185 if( ic->f->part ) 186 ic->f->part( ic, NULL ); 187 } 188 else 189 { 190 irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] ); 191 } 192 } 193 194 static void irc_cmd_whois( irc_t *irc, char **cmd ) 195 { 196 char *nick = cmd[1]; 197 irc_user_t *iu = irc_user_by_name( irc, nick ); 198 199 if( iu ) 200 irc_send_whois( iu ); 201 else 202 irc_send_num( irc, 401, "%s :Nick does not exist", nick ); 203 } 204 205 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 206 { 207 /* For some reason irssi tries a whowas when whois fails. We can 208 ignore this, but then the user never gets a "user not found" 209 message from irssi which is a bit annoying. So just respond 210 with not-found and irssi users will get better error messages */ 211 212 irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] ); 213 irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] ); 214 } 215 216 static void irc_cmd_motd( irc_t *irc, char **cmd ) 217 { 218 irc_send_motd( irc ); 219 } 220 221 static void irc_cmd_mode( irc_t *irc, char **cmd ) 222 { 223 if( irc_channel_name_ok( cmd[1] ) ) 224 { 225 irc_channel_t *ic; 226 227 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 228 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 229 else if( cmd[2] ) 230 { 231 if( *cmd[2] == '+' || *cmd[2] == '-' ) 232 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); 233 else if( *cmd[2] == 'b' ) 234 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] ); 235 } 236 else 237 irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode ); 238 } 239 else 240 { 241 if( nick_cmp( cmd[1], irc->user->nick ) == 0 ) 242 { 243 if( cmd[2] ) 244 irc_umode_set( irc, cmd[2], 0 ); 245 else 246 irc_send_num( irc, 221, "+%s", irc->umode ); 247 } 248 else 249 irc_send_num( irc, 502, ":Don't touch their modes" ); 250 } 251 } 252 253 static void irc_cmd_who( irc_t *irc, char **cmd ) 254 { 255 char *channel = cmd[1]; 256 irc_channel_t *ic; 257 258 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 259 irc_send_who( irc, irc->users, "**" ); 260 else if( ( ic = irc_channel_by_name( irc, channel ) ) ) 261 irc_send_who( irc, ic->users, channel ); 262 else 263 irc_send_num( irc, 403, "%s :No such channel", channel ); 264 } 265 266 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 267 { 268 irc_channel_t *ic; 269 irc_user_t *iu; 270 271 if( !cmd[2] ) 272 { 273 irc_send_num( irc, 412, ":No text to send" ); 274 return; 275 } 276 277 /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ 278 if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) 279 { 280 cmd[2] += 4; 281 strcpy( cmd[2], "/me" ); 282 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 283 cmd[2][strlen(cmd[2])-1] = '\0'; 284 } 285 286 if( irc_channel_name_ok( cmd[1] ) && 287 ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 288 { 289 if( ic->f->privmsg ) 290 ic->f->privmsg( ic, cmd[2] ); 291 } 292 else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) 293 { 294 if( cmd[2][0] == '\001' ) 295 { 296 char **ctcp; 297 298 if( iu->f->ctcp == NULL ) 299 return; 300 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 301 cmd[2][strlen(cmd[2])-1] = '\0'; 302 303 ctcp = split_command_parts( cmd[2] + 1 ); 304 iu->f->ctcp( iu, ctcp ); 305 } 306 else if( iu->f->privmsg ) 307 { 308 iu->flags |= IRC_USER_PRIVATE; 309 iu->f->privmsg( iu, cmd[2] ); 310 } 311 } 312 else 313 { 314 irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); 315 } 316 } 317 318 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 319 { 320 /* [SH] This aliases the NickServ command to PRIVMSG root */ 321 /* [TV] This aliases the NS command to PRIVMSG root as well */ 322 root_command( irc, cmd + 1 ); 323 } 324 325 119 326 120 327 static void irc_cmd_oper( irc_t *irc, char **cmd ) … … 126 333 { 127 334 irc_umode_set( irc, "+o", 1 ); 128 irc_reply( irc, 381, ":Password accepted" ); 129 } 130 else 131 { 132 irc_reply( irc, 432, ":Incorrect password" ); 133 } 134 } 135 136 static void irc_cmd_mode( irc_t *irc, char **cmd ) 137 { 138 if( strchr( CTYPES, *cmd[1] ) ) 139 { 140 if( cmd[2] ) 141 { 142 if( *cmd[2] == '+' || *cmd[2] == '-' ) 143 irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] ); 144 else if( *cmd[2] == 'b' ) 145 irc_reply( irc, 368, "%s :No bans possible", cmd[1] ); 146 } 147 else 148 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE ); 149 } 150 else 151 { 152 if( nick_cmp( cmd[1], irc->nick ) == 0 ) 153 { 154 if( cmd[2] ) 155 irc_umode_set( irc, cmd[2], 0 ); 156 else 157 irc_reply( irc, 221, "+%s", irc->umode ); 158 } 159 else 160 irc_reply( irc, 502, ":Don't touch their modes" ); 161 } 162 } 163 164 static void irc_cmd_names( irc_t *irc, char **cmd ) 165 { 166 irc_names( irc, cmd[1]?cmd[1]:irc->channel ); 167 } 168 169 static void irc_cmd_part( irc_t *irc, char **cmd ) 170 { 171 struct groupchat *c; 172 173 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 174 { 175 user_t *u = user_find( irc, irc->nick ); 176 177 /* Not allowed to leave control channel */ 178 irc_part( irc, u, irc->channel ); 179 irc_join( irc, u, irc->channel ); 180 } 181 else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) ) 182 { 183 user_t *u = user_find( irc, irc->nick ); 184 185 irc_part( irc, u, c->channel ); 186 187 if( c->ic ) 188 { 189 c->joined = 0; 190 c->ic->acc->prpl->chat_leave( c ); 191 } 192 } 193 else 194 { 195 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 196 } 197 } 198 199 static void irc_cmd_join( irc_t *irc, char **cmd ) 200 { 201 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 202 ; /* Dude, you're already there... 203 RFC doesn't have any reply for that though? */ 204 else if( cmd[1] ) 205 { 206 struct chat *c; 207 208 if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 ) 209 irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] ); 210 else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic ) 211 chat_join( irc, c, cmd[2] ); 212 else 213 irc_reply( irc, 403, "%s :No such channel", cmd[1] ); 335 irc_send_num( irc, 381, ":Password accepted" ); 336 } 337 else 338 { 339 irc_send_num( irc, 432, ":Incorrect password" ); 214 340 } 215 341 } … … 217 343 static void irc_cmd_invite( irc_t *irc, char **cmd ) 218 344 { 219 char *nick = cmd[1], *channel = cmd[2]; 220 struct groupchat *c = irc_chat_by_channel( irc, channel ); 221 user_t *u = user_find( irc, nick ); 222 223 if( u && c && ( u->ic == c->ic ) ) 224 if( c->ic && c->ic->acc->prpl->chat_invite ) 225 { 226 c->ic->acc->prpl->chat_invite( c, u->handle, NULL ); 227 irc_reply( irc, 341, "%s %s", nick, channel ); 228 return; 229 } 230 231 irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel ); 232 } 233 234 static void irc_cmd_privmsg( irc_t *irc, char **cmd ) 235 { 236 if ( !cmd[2] ) 237 { 238 irc_reply( irc, 412, ":No text to send" ); 239 } 240 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 241 { 242 irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] ); 243 } 244 else 245 { 246 if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) 247 { 248 unsigned int i; 249 char *t = set_getstr( &irc->set, "default_target" ); 250 251 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target ) 252 cmd[1] = irc->last_target; 253 else if( g_strcasecmp( t, "root" ) == 0 ) 254 cmd[1] = irc->mynick; 255 256 for( i = 0; i < strlen( cmd[2] ); i ++ ) 257 { 258 if( cmd[2][i] == ' ' ) break; 259 if( cmd[2][i] == ':' || cmd[2][i] == ',' ) 260 { 261 cmd[1] = cmd[2]; 262 cmd[2] += i; 263 *cmd[2] = 0; 264 while( *(++cmd[2]) == ' ' ); 265 break; 266 } 267 } 268 269 irc->is_private = 0; 270 271 if( cmd[1] != irc->last_target ) 272 { 273 g_free( irc->last_target ); 274 irc->last_target = g_strdup( cmd[1] ); 275 } 276 } 277 else 278 { 279 irc->is_private = 1; 280 } 281 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); 282 } 283 } 284 285 static void irc_cmd_who( irc_t *irc, char **cmd ) 286 { 287 char *channel = cmd[1]; 288 user_t *u = irc->users; 289 struct groupchat *c; 290 GList *l; 291 292 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 293 while( u ) 294 { 295 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname ); 296 u = u->next; 297 } 298 else if( g_strcasecmp( channel, irc->channel ) == 0 ) 299 while( u ) 300 { 301 if( u->online ) 302 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); 303 u = u->next; 304 } 305 else if( ( c = irc_chat_by_channel( irc, channel ) ) ) 306 for( l = c->in_room; l; l = l->next ) 307 { 308 if( ( u = user_findhandle( c->ic, l->data ) ) ) 309 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); 310 } 311 else if( ( u = user_find( irc, channel ) ) ) 312 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname ); 313 314 irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" ); 345 irc_channel_t *ic; 346 irc_user_t *iu; 347 348 if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL ) 349 { 350 irc_send_num( irc, 401, "%s :No such nick", cmd[1] ); 351 return; 352 } 353 else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL ) 354 { 355 irc_send_num( irc, 403, "%s :No such channel", cmd[2] ); 356 return; 357 } 358 359 if( !ic->f->invite ) 360 irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] ); 361 else if( ic->f->invite( ic, iu ) ) 362 irc_send_num( irc, 341, "%s %s", iu->nick, ic->name ); 315 363 } 316 364 317 365 static void irc_cmd_userhost( irc_t *irc, char **cmd ) 318 366 { 319 user_t *u;320 367 int i; 321 368 … … 327 374 328 375 for( i = 1; cmd[i]; i ++ ) 329 if( ( u = user_find( irc, cmd[i] ) ) ) 330 { 331 if( u->online && u->away ) 332 irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host ); 333 else 334 irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); 335 } 376 { 377 irc_user_t *iu = irc_user_by_name( irc, cmd[i] ); 378 379 if( iu ) 380 irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick, 381 irc_user_get_away( iu ) ? '-' : '+', 382 iu->user, iu->host ); 383 } 336 384 } 337 385 338 386 static void irc_cmd_ison( irc_t *irc, char **cmd ) 339 387 { 340 user_t *u;341 388 char buff[IRC_MAX_LINE]; 342 389 int lenleft, i; … … 354 401 while( *this ) 355 402 { 403 irc_user_t *iu; 404 356 405 if( ( next = strchr( this, ' ' ) ) ) 357 406 *next = 0; 358 407 359 if( ( u = user_find( irc, this ) ) && u->online ) 360 { 361 lenleft -= strlen( u->nick ) + 1; 408 if( ( iu = irc_user_by_name( irc, this ) ) && 409 iu->bu && iu->bu->flags & BEE_USER_ONLINE ) 410 { 411 lenleft -= strlen( iu->nick ) + 1; 362 412 363 413 if( lenleft < 0 ) 364 414 break; 365 415 366 strcat( buff, u->nick );416 strcat( buff, iu->nick ); 367 417 strcat( buff, " " ); 368 418 } … … 387 437 buff[strlen(buff)-1] = '\0'; 388 438 389 irc_ reply( irc, 303, ":%s", buff );439 irc_send_num( irc, 303, ":%s", buff ); 390 440 } 391 441 … … 400 450 { 401 451 char *nick; 402 user_t *u;452 irc_user_t *iu; 403 453 404 454 if( !cmd[i][0] || !cmd[i][1] ) … … 408 458 nick_lc( nick ); 409 459 410 u = user_find( irc, nick );460 iu = irc_user_by_name( irc, nick ); 411 461 412 462 if( cmd[i][0] == '+' ) … … 415 465 g_hash_table_insert( irc->watches, nick, nick ); 416 466 417 if( u && u->online ) 418 irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" ); 467 if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) 468 irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, 469 iu->host, (int) time( NULL ), "is online" ); 419 470 else 420 irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); 471 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", 472 (int) time( NULL ), "is offline" ); 421 473 } 422 474 else if( cmd[i][0] == '-' ) … … 429 481 g_free( okey ); 430 482 431 irc_ reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );483 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 432 484 } 433 485 } … … 437 489 static void irc_cmd_topic( irc_t *irc, char **cmd ) 438 490 { 439 char *channel = cmd[1]; 440 char *topic = cmd[2]; 441 442 if( topic ) 443 { 444 /* Send the topic */ 445 struct groupchat *c = irc_chat_by_channel( irc, channel ); 446 if( c && c->ic && c->ic->acc->prpl->chat_topic ) 447 c->ic->acc->prpl->chat_topic( c, topic ); 448 } 449 else 450 { 451 /* Get the topic */ 452 irc_topic( irc, channel ); 491 irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] ); 492 const char *new = cmd[2]; 493 494 if( ic == NULL ) 495 { 496 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 497 } 498 else if( new ) 499 { 500 if( ic->f->topic == NULL ) 501 irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name ); 502 else if( ic->f->topic( ic, new ) ) 503 irc_send_topic( ic, TRUE ); 504 } 505 else 506 { 507 irc_send_topic( ic, FALSE ); 453 508 } 454 509 } … … 456 511 static void irc_cmd_away( irc_t *irc, char **cmd ) 457 512 { 458 user_t *u = user_find( irc, irc->nick ); 459 char *away = cmd[1]; 460 461 if( !u ) return; 462 463 if( away && *away ) 464 { 513 if( cmd[1] && *cmd[1] ) 514 { 515 char away[strlen(cmd[1])+1]; 465 516 int i, j; 466 517 467 518 /* Copy away string, but skip control chars. Mainly because 468 519 Jabber really doesn't like them. */ 469 u->away = g_malloc( strlen( away ) + 1 ); 470 for( i = j = 0; away[i]; i ++ ) 471 if( ( u->away[j] = away[i] ) >= ' ' ) 520 for( i = j = 0; cmd[1][i]; i ++ ) 521 if( ( away[j] = cmd[1][i] ) >= ' ' ) 472 522 j ++; 473 u->away[j] = 0; 474 475 irc_reply( irc, 306, ":You're now away: %s", u->away ); 476 /* irc_umode_set( irc, irc->myhost, "+a" ); */ 477 } 478 else 479 { 480 if( u->away ) g_free( u->away ); 481 u->away = NULL; 482 /* irc_umode_set( irc, irc->myhost, "-a" ); */ 483 irc_reply( irc, 305, ":Welcome back" ); 484 } 485 486 set_setstr( &irc->set, "away", u->away ); 487 } 488 489 static void irc_cmd_whois( irc_t *irc, char **cmd ) 490 { 491 char *nick = cmd[1]; 492 user_t *u = user_find( irc, nick ); 493 494 if( u ) 495 { 496 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname ); 497 498 if( u->ic ) 499 irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user, 500 u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "", 501 u->ic->acc->prpl->name ); 502 else 503 irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); 504 505 if( !u->online ) 506 irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" ); 507 else if( u->away ) 508 irc_reply( irc, 301, "%s :%s", u->nick, u->away ); 509 if( u->status_msg ) 510 irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg ); 511 512 irc_reply( irc, 318, "%s :End of /WHOIS list", nick ); 513 } 514 else 515 { 516 irc_reply( irc, 401, "%s :Nick does not exist", nick ); 517 } 518 } 519 520 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 521 { 522 /* For some reason irssi tries a whowas when whois fails. We can 523 ignore this, but then the user never gets a "user not found" 524 message from irssi which is a bit annoying. So just respond 525 with not-found and irssi users will get better error messages */ 526 527 irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] ); 528 irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] ); 529 } 530 531 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 532 { 533 /* [SH] This aliases the NickServ command to PRIVMSG root */ 534 /* [TV] This aliases the NS command to PRIVMSG root as well */ 535 root_command( irc, cmd + 1 ); 536 } 537 538 static void irc_cmd_motd( irc_t *irc, char **cmd ) 539 { 540 irc_motd( irc ); 541 } 542 543 static void irc_cmd_pong( irc_t *irc, char **cmd ) 544 { 545 /* We could check the value we get back from the user, but in 546 fact we don't care, we're just happy he's still alive. */ 547 irc->last_pong = gettime(); 548 irc->pinging = 0; 523 away[j] = '\0'; 524 525 irc_send_num( irc, 306, ":You're now away: %s", away ); 526 set_setstr( &irc->b->set, "away", away ); 527 } 528 else 529 { 530 irc_send_num( irc, 305, ":Welcome back" ); 531 set_setstr( &irc->b->set, "away", NULL ); 532 } 549 533 } 550 534 551 535 static void irc_cmd_version( irc_t *irc, char **cmd ) 552 536 { 553 irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU ); 537 irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ", 538 BITLBEE_VERSION, irc->root->host, ARCH, CPU ); 554 539 } 555 540 556 541 static void irc_cmd_completions( irc_t *irc, char **cmd ) 557 542 { 558 user_t *u = user_find( irc, irc->mynick );559 543 help_t *h; 560 544 set_t *s; 561 545 int i; 562 546 563 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );547 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" ); 564 548 565 549 for( i = 0; commands[i].command; i ++ ) 566 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS", commands[i].command );550 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command ); 567 551 568 552 for( h = global.help; h; h = h->next ) 569 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help", h->title );570 571 for( s = irc-> set; s; s = s->next )572 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set", s->key );573 574 irc_ privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );553 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title ); 554 555 for( s = irc->b->set; s; s = s->next ) 556 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key ); 557 558 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" ); 575 559 } 576 560 … … 582 566 ipc_to_master( cmd ); 583 567 584 irc_ reply( irc, 382, "%s :Rehashing", global.conf_file );568 irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); 585 569 } 586 570 … … 591 575 { "quit", 0, irc_cmd_quit, 0 }, 592 576 { "ping", 0, irc_cmd_ping, 0 }, 593 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 577 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 578 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN }, 579 { "names", 1, irc_cmd_names, IRC_CMD_LOGGED_IN }, 580 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN }, 581 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN }, 582 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN }, 583 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN }, 594 584 { "mode", 1, irc_cmd_mode, IRC_CMD_LOGGED_IN }, 595 { "names", 0, irc_cmd_names, IRC_CMD_LOGGED_IN }, 596 { "part", 1, irc_cmd_part, IRC_CMD_LOGGED_IN }, 597 { "join", 1, irc_cmd_join, IRC_CMD_LOGGED_IN }, 598 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 585 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 599 586 { "privmsg", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 600 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 601 { "who", 0, irc_cmd_who, IRC_CMD_LOGGED_IN }, 587 { "nickserv", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 588 { "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 589 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN }, 590 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 591 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, 602 592 { "userhost", 1, irc_cmd_userhost, IRC_CMD_LOGGED_IN }, 603 593 { "ison", 1, irc_cmd_ison, IRC_CMD_LOGGED_IN }, 604 594 { "watch", 1, irc_cmd_watch, IRC_CMD_LOGGED_IN }, 595 { "invite", 2, irc_cmd_invite, IRC_CMD_LOGGED_IN }, 596 #if 0 597 { "notice", 1, irc_cmd_privmsg, IRC_CMD_LOGGED_IN }, 598 #endif 605 599 { "topic", 1, irc_cmd_topic, IRC_CMD_LOGGED_IN }, 606 { "away", 0, irc_cmd_away, IRC_CMD_LOGGED_IN }, 607 { "whois", 1, irc_cmd_whois, IRC_CMD_LOGGED_IN }, 608 { "whowas", 1, irc_cmd_whowas, IRC_CMD_LOGGED_IN }, 609 { "nickserv", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 610 { "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN }, 611 { "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN }, 612 { "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN }, 613 { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN }, 614 { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, 600 { "oper", 2, irc_cmd_oper, IRC_CMD_LOGGED_IN }, 615 601 { "die", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 616 602 { "deaf", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, … … 638 624 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 639 625 { 640 irc_ reply( irc, 462, ":Only allowed before logging in" );626 irc_send_num( irc, 462, ":Only allowed before logging in" ); 641 627 } 642 628 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 643 629 { 644 irc_ reply( irc, 451, ":Register first" );630 irc_send_num( irc, 451, ":Register first" ); 645 631 } 646 632 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 647 633 { 648 irc_ reply( irc, 481, ":Permission denied - You're not an IRC operator" );634 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" ); 649 635 } 650 636 else if( n_arg < irc_commands[i].required_parameters ) 651 637 { 652 irc_ reply( irc, 461, "%s :Need more parameters", cmd[0] );638 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] ); 653 639 } 654 640 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) … … 667 653 668 654 if( irc->status >= USTATUS_LOGGED_IN ) 669 irc_ reply( irc, 421, "%s :Unknown command", cmd[0] );670 } 655 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] ); 656 } -
lib/Makefile
r051372c r41d415b 8 8 9 9 -include ../Makefile.settings 10 ifdef SRCDIR 11 SRCDIR := $(SRCDIR)lib/ 12 endif 10 13 11 14 # [SH] Program variables 12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o15 objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o 13 16 14 17 CFLAGS += -Wall … … 37 40 $(objects): ../Makefile.settings Makefile 38 41 39 $(objects): %.o: %.c42 $(objects): %.o: $(SRCDIR)%.c 40 43 @echo '*' Compiling $< 41 44 @$(CC) -c $(CFLAGS) $< -o $@ -
lib/events.h
r051372c r41d415b 48 48 the given callback function. */ 49 49 typedef enum { 50 GAIM_INPUT_READ = 1 << 1, 51 GAIM_INPUT_WRITE = 1 << 2 50 B_EV_IO_READ = 1 << 0, 51 B_EV_IO_WRITE = 1 << 1, 52 B_EV_FLAG_FORCE_ONCE = 1 << 16, 53 B_EV_FLAG_FORCE_REPEAT = 1 << 17, 52 54 } b_input_condition; 53 55 typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); -
lib/events_glib.c
r051372c r41d415b 49 49 b_event_handler function; 50 50 gpointer data; 51 guint flags; 51 52 } GaimIOClosure; 52 53 … … 76 77 77 78 if (condition & GAIM_READ_COND) 78 gaim_cond |= GAIM_INPUT_READ;79 gaim_cond |= B_EV_IO_READ; 79 80 if (condition & GAIM_WRITE_COND) 80 gaim_cond |= GAIM_INPUT_WRITE;81 gaim_cond |= B_EV_IO_WRITE; 81 82 82 83 event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data ); … … 87 88 event_debug( "Returned FALSE, cancelling.\n" ); 88 89 89 return st; 90 if (closure->flags & B_EV_FLAG_FORCE_ONCE) 91 return FALSE; 92 else if (closure->flags & B_EV_FLAG_FORCE_REPEAT) 93 return TRUE; 94 else 95 return st; 90 96 } 91 97 … … 105 111 closure->function = function; 106 112 closure->data = data; 113 closure->flags = condition; 107 114 108 if (condition & GAIM_INPUT_READ)115 if (condition & B_EV_IO_READ) 109 116 cond |= GAIM_READ_COND; 110 if (condition & GAIM_INPUT_WRITE)117 if (condition & B_EV_IO_WRITE) 111 118 cond |= GAIM_WRITE_COND; 112 119 -
lib/events_libevent.c
r051372c r41d415b 60 60 b_event_handler function; 61 61 void *data; 62 guint flags; 62 63 }; 63 64 … … 126 127 { 127 128 if( event & EV_READ ) 128 cond |= GAIM_INPUT_READ;129 cond |= B_EV_IO_READ; 129 130 if( event & EV_WRITE ) 130 cond |= GAIM_INPUT_WRITE;131 cond |= B_EV_IO_WRITE; 131 132 } 132 133 … … 150 151 return; 151 152 } 152 else if( !st )153 else if( !st && !( b_ev->flags & B_EV_FLAG_FORCE_REPEAT ) ) 153 154 { 154 155 event_debug( "Handler returned FALSE: " ); … … 174 175 event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); 175 176 176 if( ( condition & GAIM_INPUT_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) ||177 ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )177 if( ( condition & B_EV_IO_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || 178 ( condition & B_EV_IO_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) 178 179 { 179 180 /* We'll stick with this libevent entry, but give it a new BitlBee id. */ … … 198 199 199 200 out_cond = EV_PERSIST; 200 if( condition & GAIM_INPUT_READ )201 if( condition & B_EV_IO_READ ) 201 202 out_cond |= EV_READ; 202 if( condition & GAIM_INPUT_WRITE )203 if( condition & B_EV_IO_WRITE ) 203 204 out_cond |= EV_WRITE; 204 205 … … 212 213 } 213 214 215 b_ev->flags = condition; 214 216 g_hash_table_insert( id_hash, &b_ev->id, b_ev ); 215 217 return b_ev->id; -
lib/http_client.c
r051372c r41d415b 149 149 if( req->bytes_written < req->request_length ) 150 150 req->inpa = b_input_add( source, 151 req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,151 req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE, 152 152 http_connected, req ); 153 153 else 154 req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );154 req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req ); 155 155 156 156 return FALSE; … … 234 234 /* There will be more! */ 235 235 req->inpa = b_input_add( req->fd, 236 req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,236 req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ, 237 237 http_incoming_data, req ); 238 238 -
lib/misc.c
r051372c r41d415b 647 647 return ret; 648 648 } 649 650 char **split_command_parts( char *command ) 651 { 652 static char *cmd[IRC_MAX_ARGS+1]; 653 char *s, q = 0; 654 int k; 655 656 memset( cmd, 0, sizeof( cmd ) ); 657 cmd[0] = command; 658 k = 1; 659 for( s = command; *s && k < IRC_MAX_ARGS; s ++ ) 660 if( *s == ' ' && !q ) 661 { 662 *s = 0; 663 while( *++s == ' ' ); 664 if( *s == '"' || *s == '\'' ) 665 { 666 q = *s; 667 s ++; 668 } 669 if( *s ) 670 { 671 cmd[k++] = s; 672 s --; 673 } 674 else 675 { 676 break; 677 } 678 } 679 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) 680 { 681 char *cpy; 682 683 for( cpy = s; *cpy; cpy ++ ) 684 cpy[0] = cpy[1]; 685 } 686 else if( *s == q ) 687 { 688 q = *s = 0; 689 } 690 691 /* Full zero-padding for easier argc checking. */ 692 while( k <= IRC_MAX_ARGS ) 693 cmd[k++] = NULL; 694 695 return cmd; 696 } -
lib/misc.h
r051372c r41d415b 69 69 G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); 70 70 71 G_MODULE_EXPORT char **split_command_parts( char *command ); 72 71 73 #endif -
lib/proxy.c
r051372c r41d415b 91 91 b_event_remove(phb->inpa); 92 92 if( phb->proxy_func ) 93 phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ);93 phb->proxy_func(phb->proxy_data, -1, B_EV_IO_READ); 94 94 else { 95 phb->func(phb->data, -1, GAIM_INPUT_READ);95 phb->func(phb->data, -1, B_EV_IO_READ); 96 96 g_free(phb); 97 97 } … … 102 102 b_event_remove(phb->inpa); 103 103 if( phb->proxy_func ) 104 phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ);104 phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ); 105 105 else { 106 phb->func(phb->data, source, GAIM_INPUT_READ);106 phb->func(phb->data, source, B_EV_IO_READ); 107 107 g_free(phb); 108 108 } … … 147 147 return -1; 148 148 } else { 149 phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);149 phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb); 150 150 phb->fd = fd; 151 151 … … 179 179 if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) || 180 180 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { 181 phb->func(phb->data, source, GAIM_INPUT_READ);181 phb->func(phb->data, source, B_EV_IO_READ); 182 182 g_free(phb->host); 183 183 g_free(phb); … … 186 186 187 187 close(source); 188 phb->func(phb->data, -1, GAIM_INPUT_READ);188 phb->func(phb->data, -1, B_EV_IO_READ); 189 189 g_free(phb->host); 190 190 g_free(phb); … … 204 204 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 205 205 close(source); 206 phb->func(phb->data, -1, GAIM_INPUT_READ);206 phb->func(phb->data, -1, B_EV_IO_READ); 207 207 g_free(phb->host); 208 208 g_free(phb); … … 215 215 if (send(source, cmd, strlen(cmd), 0) < 0) { 216 216 close(source); 217 phb->func(phb->data, -1, GAIM_INPUT_READ);217 phb->func(phb->data, -1, B_EV_IO_READ); 218 218 g_free(phb->host); 219 219 g_free(phb); … … 230 230 if (send(source, cmd, strlen(cmd), 0) < 0) { 231 231 close(source); 232 phb->func(phb->data, -1, GAIM_INPUT_READ);232 phb->func(phb->data, -1, B_EV_IO_READ); 233 233 g_free(phb->host); 234 234 g_free(phb); … … 240 240 if (send(source, cmd, strlen(cmd), 0) < 0) { 241 241 close(source); 242 phb->func(phb->data, -1, GAIM_INPUT_READ);243 g_free(phb->host); 244 g_free(phb); 245 return FALSE; 246 } 247 248 phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);242 phb->func(phb->data, -1, B_EV_IO_READ); 243 g_free(phb->host); 244 g_free(phb); 245 return FALSE; 246 } 247 248 phb->inpa = b_input_add(source, B_EV_IO_READ, http_canread, phb); 249 249 250 250 return FALSE; … … 273 273 memset(packet, 0, sizeof(packet)); 274 274 if (read(source, packet, 9) >= 4 && packet[1] == 90) { 275 phb->func(phb->data, source, GAIM_INPUT_READ);275 phb->func(phb->data, source, B_EV_IO_READ); 276 276 g_free(phb->host); 277 277 g_free(phb); … … 280 280 281 281 close(source); 282 phb->func(phb->data, -1, GAIM_INPUT_READ);282 phb->func(phb->data, -1, B_EV_IO_READ); 283 283 g_free(phb->host); 284 284 g_free(phb); … … 299 299 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 300 300 close(source); 301 phb->func(phb->data, -1, GAIM_INPUT_READ);301 phb->func(phb->data, -1, B_EV_IO_READ); 302 302 g_free(phb->host); 303 303 g_free(phb); … … 309 309 if (!(hp = gethostbyname(phb->host))) { 310 310 close(source); 311 phb->func(phb->data, -1, GAIM_INPUT_READ);311 phb->func(phb->data, -1, B_EV_IO_READ); 312 312 g_free(phb->host); 313 313 g_free(phb); … … 326 326 if (write(source, packet, 9) != 9) { 327 327 close(source); 328 phb->func(phb->data, -1, GAIM_INPUT_READ);329 g_free(phb->host); 330 g_free(phb); 331 return FALSE; 332 } 333 334 phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);328 phb->func(phb->data, -1, B_EV_IO_READ); 329 g_free(phb->host); 330 g_free(phb); 331 return FALSE; 332 } 333 334 phb->inpa = b_input_add(source, B_EV_IO_READ, s4_canread, phb); 335 335 336 336 return FALSE; … … 359 359 if (read(source, buf, 10) < 10) { 360 360 close(source); 361 phb->func(phb->data, -1, GAIM_INPUT_READ);361 phb->func(phb->data, -1, B_EV_IO_READ); 362 362 g_free(phb->host); 363 363 g_free(phb); … … 366 366 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { 367 367 close(source); 368 phb->func(phb->data, -1, GAIM_INPUT_READ);369 g_free(phb->host); 370 g_free(phb); 371 return FALSE; 372 } 373 374 phb->func(phb->data, source, GAIM_INPUT_READ);368 phb->func(phb->data, -1, B_EV_IO_READ); 369 g_free(phb->host); 370 g_free(phb); 371 return FALSE; 372 } 373 374 phb->func(phb->data, source, B_EV_IO_READ); 375 375 g_free(phb->host); 376 376 g_free(phb); … … 396 396 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { 397 397 close(source); 398 phb->func(phb->data, -1, GAIM_INPUT_READ);398 phb->func(phb->data, -1, B_EV_IO_READ); 399 399 g_free(phb->host); 400 400 g_free(phb); … … 402 402 } 403 403 404 phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);404 phb->inpa = b_input_add(source, B_EV_IO_READ, s5_canread_again, phb); 405 405 } 406 406 … … 414 414 if (read(source, buf, 2) < 2) { 415 415 close(source); 416 phb->func(phb->data, -1, GAIM_INPUT_READ);416 phb->func(phb->data, -1, B_EV_IO_READ); 417 417 g_free(phb->host); 418 418 g_free(phb); … … 422 422 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { 423 423 close(source); 424 phb->func(phb->data, -1, GAIM_INPUT_READ);424 phb->func(phb->data, -1, B_EV_IO_READ); 425 425 g_free(phb->host); 426 426 g_free(phb); … … 442 442 if (read(source, buf, 2) < 2) { 443 443 close(source); 444 phb->func(phb->data, -1, GAIM_INPUT_READ);444 phb->func(phb->data, -1, B_EV_IO_READ); 445 445 g_free(phb->host); 446 446 g_free(phb); … … 450 450 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { 451 451 close(source); 452 phb->func(phb->data, -1, GAIM_INPUT_READ);452 phb->func(phb->data, -1, B_EV_IO_READ); 453 453 g_free(phb->host); 454 454 g_free(phb); … … 465 465 if (write(source, buf, 3 + i + j) < 3 + i + j) { 466 466 close(source); 467 phb->func(phb->data, -1, GAIM_INPUT_READ);467 phb->func(phb->data, -1, B_EV_IO_READ); 468 468 g_free(phb->host); 469 469 g_free(phb); … … 471 471 } 472 472 473 phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);473 phb->inpa = b_input_add(source, B_EV_IO_READ, s5_readauth, phb); 474 474 } else { 475 475 s5_sendconnect(phb, source); … … 491 491 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 492 492 close(source); 493 phb->func(phb->data, -1, GAIM_INPUT_READ);493 phb->func(phb->data, -1, B_EV_IO_READ); 494 494 g_free(phb->host); 495 495 g_free(phb); … … 513 513 if (write(source, buf, i) < i) { 514 514 close(source); 515 phb->func(phb->data, -1, GAIM_INPUT_READ);516 g_free(phb->host); 517 g_free(phb); 518 return FALSE; 519 } 520 521 phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);515 phb->func(phb->data, -1, B_EV_IO_READ); 516 g_free(phb->host); 517 g_free(phb); 518 return FALSE; 519 } 520 521 phb->inpa = b_input_add(source, B_EV_IO_READ, s5_canread, phb); 522 522 523 523 return FALSE; -
lib/ssl_bogus.c
r051372c r41d415b 59 59 b_input_condition ssl_getdirection( void *conn ) 60 60 { 61 return GAIM_INPUT_READ;61 return B_EV_IO_READ; 62 62 } 63 63 -
lib/ssl_client.h
r051372c r41d415b 71 71 G_MODULE_EXPORT int ssl_getfd( void *conn ); 72 72 73 /* This function returns GAIM_INPUT_READ/WRITE. With SSL connections it's73 /* This function returns B_EV_IO_READ/WRITE. With SSL connections it's 74 74 possible that something has to be read while actually were trying to 75 75 write something (think about key exchange/refresh/etc). So when an -
lib/ssl_gnutls.c
r051372c r41d415b 106 106 struct scd *conn = data; 107 107 108 return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE );108 return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); 109 109 } 110 110 … … 244 244 { 245 245 return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? 246 GAIM_INPUT_WRITE : GAIM_INPUT_READ );247 } 246 B_EV_IO_WRITE : B_EV_IO_READ ); 247 } -
lib/ssl_nss.c
r051372c r41d415b 193 193 { 194 194 /* Just in case someone calls us, let's return the most likely case: */ 195 return GAIM_INPUT_READ;195 return B_EV_IO_READ; 196 196 } -
lib/ssl_openssl.c
r051372c r41d415b 102 102 struct scd *conn = data; 103 103 104 return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE );104 return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); 105 105 } 106 106 … … 270 270 b_input_condition ssl_getdirection( void *conn ) 271 271 { 272 return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );273 } 272 return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ ); 273 } -
lib/ssl_sspi.c
r051372c r41d415b 275 275 GaimInputCondition ssl_getdirection( void *conn ) 276 276 { 277 return GAIM_INPUT_WRITE; /* FIXME: or GAIM_INPUT_READ */278 } 277 return B_EV_IO_WRITE; /* FIXME: or B_EV_IO_READ */ 278 } -
nick.c
r051372c r41d415b 78 78 79 79 nick_strip( nick ); 80 if( set_getbool( &acc-> irc->set, "lcnicks" ) )80 if( set_getbool( &acc->bee->set, "lcnicks" ) ) 81 81 nick_lc( nick ); 82 82 } … … 92 92 void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) 93 93 { 94 irc_t *irc = (irc_t*) acc->bee->ui_data; 94 95 int inf_protection = 256; 95 96 96 97 /* Now, find out if the nick is already in use at the moment, and make 97 98 subtle changes to make it unique. */ 98 while( !nick_ok( nick ) || user_find( acc->irc, nick ) )99 while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) ) 99 100 { 100 101 if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) … … 112 113 int i; 113 114 114 irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! "115 116 117 118 119 120 irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );115 irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! " 116 "This used to be a fatal BitlBee bug, but we tried to fix it. " 117 "This message should *never* appear anymore. " 118 "If it does, please *do* send us a bug report! " 119 "Please send all the following lines in your report:" ); 120 121 irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); 121 122 for( i = 0; i < MAX_NICK_LENGTH; i ++ ) 122 irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );123 124 irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "125 126 123 irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); 124 125 irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " 126 "Good luck, and please don't forget to paste the lines up here " 127 "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); 127 128 128 129 g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); -
protocols/Makefile
r051372c r41d415b 8 8 9 9 -include ../Makefile.settings 10 ifdef SRCDIR 11 SRCDIR := $(SRCDIR)protocols/ 12 endif 10 13 11 14 # [SH] Program variables 12 objects = nogaim.o 15 objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o 16 13 17 14 18 # [SH] The next two lines should contain the directory name (in $(subdirs)) … … 49 53 $(objects): ../Makefile.settings Makefile 50 54 51 $(objects): %.o: %.c55 $(objects): %.o: $(SRCDIR)%.c 52 56 @echo '*' Compiling $< 53 57 @$(CC) -c $(CFLAGS) $< -o $@ -
protocols/jabber/Makefile
r051372c r41d415b 8 8 9 9 -include ../../Makefile.settings 10 ifdef SRCDIR 11 SRCDIR := $(SRCDIR)protocols/jabber/ 12 endif 10 13 11 14 # [SH] Program variables 12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s asl.o15 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o 13 16 14 17 CFLAGS += -Wall … … 33 36 $(objects): ../../Makefile.settings Makefile 34 37 35 $(objects): %.o: %.c38 $(objects): %.o: $(SRCDIR)%.c 36 39 @echo '*' Compiling $< 37 40 @$(CC) -c $(CFLAGS) $< -o $@ -
protocols/jabber/conference.c
r051372c r41d415b 92 92 { 93 93 char *normalized = jabber_normalize( name ); 94 GSList *l; 94 95 struct groupchat *ret; 95 96 struct jabber_chat *jc; 96 97 97 for( ret = ic->groupchats; ret; ret = ret->next ) 98 { 98 for( l = ic->groupchats; l; l = l->next ) 99 { 100 ret = l->data; 99 101 jc = ret->data; 100 102 if( strcmp( normalized, jc->name ) == 0 ) … … 103 105 g_free( normalized ); 104 106 105 return ret;107 return l ? ret : NULL; 106 108 } 107 109 -
protocols/jabber/io.c
r051372c r41d415b 64 64 most cases it probably won't be necessary.) */ 65 65 if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 ) 66 jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, ic );66 jd->w_inpa = b_input_add( jd->fd, B_EV_IO_WRITE, jabber_write_callback, ic ); 67 67 } 68 68 else … … 504 504 505 505 if( jd->r_inpa <= 0 ) 506 jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );506 jd->r_inpa = b_input_add( jd->fd, B_EV_IO_READ, jabber_read_callback, ic ); 507 507 508 508 greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " -
protocols/jabber/iq.c
r051372c r41d415b 91 91 pack = 0; 92 92 } 93 else if( strcmp( s, XMLNS_DISCO VER) == 0 )94 { 95 const char *features[] = { XMLNS_DISCO VER,93 else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 ) 94 { 95 const char *features[] = { XMLNS_DISCO_INFO, 96 96 XMLNS_VERSION, 97 97 XMLNS_TIME, … … 99 99 XMLNS_MUC, 100 100 XMLNS_PING, 101 XMLNS_SI, 102 XMLNS_BYTESTREAMS, 103 XMLNS_FILETRANSFER, 101 104 NULL }; 102 105 const char **f; … … 118 121 { 119 122 xt_free_node( reply ); 120 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );123 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); 121 124 pack = 0; 122 125 } … … 124 127 else if( strcmp( type, "set" ) == 0 ) 125 128 { 126 if( !( c = xt_find_node( node->children, "query" ) ) || 127 !( s = xt_find_attr( c, "xmlns" ) ) ) 129 if( ( c = xt_find_node( node->children, "si" ) ) && 130 ( s = xt_find_attr( c, "xmlns" ) ) && 131 ( strcmp( s, XMLNS_SI ) == 0 ) ) 132 { 133 return jabber_si_handle_request( ic, node, c ); 134 } 135 else if( !( c = xt_find_node( node->children, "query" ) ) || 136 !( s = xt_find_attr( c, "xmlns" ) ) ) 128 137 { 129 138 return XT_HANDLED; 130 139 } 131 140 else if( strcmp( s, XMLNS_ROSTER ) == 0 ) 141 { 132 142 /* This is a roster push. XMPP servers send this when someone 133 143 was added to (or removed from) the buddy list. AFAIK they're 134 144 sent even if we added this buddy in our own session. */ 135 if( strcmp( s, XMLNS_ROSTER ) == 0 )136 {137 145 int bare_len = strlen( ic->acc->user ); 138 146 … … 151 159 152 160 xt_free_node( reply ); 153 reply = jabber_make_error_packet( node, "not-allowed", "cancel" );161 reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL ); 154 162 pack = 0; 155 163 } 156 164 } 165 else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 ) 166 { 167 /* Bytestream Request (stage 2 of file transfer) */ 168 return jabber_bs_recv_request( ic, node, c ); 169 } 157 170 else 158 171 { 159 172 xt_free_node( reply ); 160 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );173 reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); 161 174 pack = 0; 162 175 } … … 369 382 while( ( c = xt_find_node( c, "item" ) ) ) 370 383 { 371 struct xt_node *group = xt_find_node( node->children, "group" );384 struct xt_node *group = xt_find_node( c->children, "group" ); 372 385 char *jid = xt_find_attr( c, "jid" ); 373 386 char *name = xt_find_attr( c, "name" ); … … 378 391 if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 379 392 { 380 if( initial || imcb_find_buddy( ic, jid ) == NULL ) 381 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 382 group->text : NULL ); 393 imcb_add_buddy( ic, jid, ( group && group->text_len ) ? 394 group->text : NULL ); 383 395 384 396 if( name ) … … 543 555 static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); 544 556 545 int jabber_add_to_roster( struct im_connection *ic, c har *handle, char *name)557 int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group ) 546 558 { 547 559 struct xt_node *node; … … 553 565 if( name ) 554 566 xt_add_attr( node, "name", name ); 567 if( group ) 568 xt_add_child( node, xt_new_node( "group", group, NULL ) ); 555 569 556 570 /* And pack it into a roster-add packet */ … … 576 590 strcmp( s, "result" ) == 0 ) 577 591 { 578 if( imcb_find_buddy(ic, jid ) == NULL )592 if( bee_user_by_handle( ic->bee, ic, jid ) == NULL ) 579 593 imcb_add_buddy( ic, jid, NULL ); 580 594 } … … 608 622 return st; 609 623 } 624 625 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); 626 627 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ) 628 { 629 struct xt_node *node, *query; 630 struct jabber_buddy *bud; 631 632 if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL ) 633 { 634 /* Who cares about the unknown... */ 635 imcb_log( ic, "Couldn't find buddy: %s", bare_jid); 636 return XT_HANDLED; 637 } 638 639 if( bud->features ) /* been here already */ 640 return XT_HANDLED; 641 642 node = xt_new_node( "query", NULL, NULL ); 643 xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO ); 644 645 if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) ) 646 { 647 imcb_log( ic, "WARNING: Couldn't generate feature query" ); 648 xt_free_node( node ); 649 return XT_HANDLED; 650 } 651 652 jabber_cache_add( ic, query, jabber_iq_parse_features ); 653 654 return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; 655 } 656 657 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) 658 { 659 struct xt_node *c; 660 struct jabber_buddy *bud; 661 char *feature, *xmlns, *from; 662 663 if( !( from = xt_find_attr( node, "from" ) ) || 664 !( c = xt_find_node( node->children, "query" ) ) || 665 !( xmlns = xt_find_attr( c, "xmlns" ) ) || 666 !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) ) 667 { 668 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); 669 return XT_HANDLED; 670 } 671 if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) 672 { 673 /* Who cares about the unknown... */ 674 imcb_log( ic, "Couldn't find buddy: %s", from ); 675 return XT_HANDLED; 676 } 677 678 c = c->children; 679 while( ( c = xt_find_node( c, "feature" ) ) ) 680 { 681 feature = xt_find_attr( c, "var" ); 682 if( feature ) 683 bud->features = g_slist_append( bud->features, g_strdup( feature ) ); 684 c = c->next; 685 } 686 687 return XT_HANDLED; 688 } 689 690 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); 691 692 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ) 693 { 694 struct xt_node *node, *query; 695 struct jabber_data *jd = ic->proto_data; 696 697 node = xt_new_node( "query", NULL, NULL ); 698 xt_add_attr( node, "xmlns", xmlns ); 699 700 if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) ) 701 { 702 imcb_log( ic, "WARNING: Couldn't generate server query" ); 703 xt_free_node( node ); 704 } 705 706 jd->have_streamhosts--; 707 jabber_cache_add( ic, query, jabber_iq_parse_server_features ); 708 709 return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; 710 } 711 712 /* 713 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info 714 */ 715 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) 716 { 717 struct xt_node *c; 718 struct jabber_data *jd = ic->proto_data; 719 char *xmlns, *from; 720 721 if( !( c = xt_find_node( node->children, "query" ) ) || 722 !( from = xt_find_attr( node, "from" ) ) || 723 !( xmlns = xt_find_attr( c, "xmlns" ) ) ) 724 { 725 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); 726 return XT_HANDLED; 727 } 728 729 jd->have_streamhosts++; 730 731 if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 ) 732 { 733 char *itemjid; 734 735 /* answer from server */ 736 737 c = c->children; 738 while( ( c = xt_find_node( c, "item" ) ) ) 739 { 740 itemjid = xt_find_attr( c, "jid" ); 741 742 if( itemjid ) 743 jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO ); 744 745 c = c->next; 746 } 747 } 748 else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) 749 { 750 char *category, *type; 751 752 /* answer from potential proxy */ 753 754 c = c->children; 755 while( ( c = xt_find_node( c, "identity" ) ) ) 756 { 757 category = xt_find_attr( c, "category" ); 758 type = xt_find_attr( c, "type" ); 759 760 if( type && ( strcmp( type, "bytestreams" ) == 0 ) && 761 category && ( strcmp( category, "proxy" ) == 0 ) ) 762 jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS ); 763 764 c = c->next; 765 } 766 } 767 else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 ) 768 { 769 char *host, *jid, *port_s; 770 int port; 771 772 /* answer from proxy */ 773 774 if( ( c = xt_find_node( c->children, "streamhost" ) ) && 775 ( host = xt_find_attr( c, "host" ) ) && 776 ( port_s = xt_find_attr( c, "port" ) ) && 777 ( sscanf( port_s, "%d", &port ) == 1 ) && 778 ( jid = xt_find_attr( c, "jid" ) ) ) 779 { 780 jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 ); 781 782 sh->jid = g_strdup( jid ); 783 sh->host = g_strdup( host ); 784 g_snprintf( sh->port, sizeof( sh->port ), "%u", port ); 785 786 imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port ); 787 jd->streamhosts = g_slist_append( jd->streamhosts, sh ); 788 } 789 } 790 791 if( jd->have_streamhosts == 0 ) 792 jd->have_streamhosts++; 793 794 return XT_HANDLED; 795 } -
protocols/jabber/jabber.c
r051372c r41d415b 65 65 66 66 s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); 67 68 s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc ); 67 69 68 70 s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); … … 266 268 struct jabber_data *jd = ic->proto_data; 267 269 270 while( jd->filetransfers ) 271 imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" ); 272 273 while( jd->streamhosts ) 274 { 275 jabber_streamhost_t *sh = jd->streamhosts->data; 276 jd->streamhosts = g_slist_remove( jd->streamhosts, sh ); 277 g_free( sh->jid ); 278 g_free( sh->host ); 279 g_free( sh ); 280 } 281 268 282 if( jd->fd >= 0 ) 269 283 jabber_end_stream( ic ); 270 284 271 285 while( ic->groupchats ) 272 jabber_chat_free( ic->groupchats );286 jabber_chat_free( ic->groupchats->data ); 273 287 274 288 if( jd->r_inpa >= 0 ) … … 401 415 } 402 416 403 if( jabber_add_to_roster( ic, who, NULL ) )417 if( jabber_add_to_roster( ic, who, NULL, group ) ) 404 418 presence_send_request( ic, who, "subscribe" ); 405 419 } … … 549 563 ret->send_typing = jabber_send_typing; 550 564 ret->handle_cmp = g_strcasecmp; 565 ret->transfer_request = jabber_si_transfer_request; 551 566 552 567 register_protocol( ret ); -
protocols/jabber/jabber.h
r051372c r41d415b 61 61 } jabber_buddy_flags_t; 62 62 63 /* Stores a streamhost's (a.k.a. proxy) data */ 64 typedef struct 65 { 66 char *jid; 67 char *host; 68 char port[6]; 69 } jabber_streamhost_t; 70 63 71 typedef enum 64 72 { … … 91 99 GHashTable *node_cache; 92 100 GHashTable *buddies; 101 102 GSList *filetransfers; 103 GSList *streamhosts; 104 int have_streamhosts; 93 105 }; 94 106 … … 127 139 struct jabber_away_state *away_state; 128 140 char *away_message; 141 GSList *features; 129 142 130 143 time_t last_msg; … … 140 153 char *my_full_jid; /* Separate copy because of case sensitivity. */ 141 154 struct jabber_buddy *me; 155 }; 156 157 struct jabber_transfer 158 { 159 /* bitlbee's handle for this transfer */ 160 file_transfer_t *ft; 161 162 /* the stream's private handle */ 163 gpointer streamhandle; 164 165 /* timeout for discover queries */ 166 gint disco_timeout; 167 gint disco_timeout_fired; 168 169 struct im_connection *ic; 170 171 struct jabber_buddy *bud; 172 173 int watch_in; 174 int watch_out; 175 176 char *ini_jid; 177 char *tgt_jid; 178 char *iq_id; 179 char *sid; 180 int accepted; 181 182 size_t bytesread, byteswritten; 183 int fd; 184 struct sockaddr_storage saddr; 142 185 }; 143 186 … … 167 210 168 211 /* Some supported extensions/legacy stuff */ 169 #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ 170 #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ 171 #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ 172 #define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ 173 #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ 174 #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ 175 #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ 176 #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ 177 #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ 178 #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */ 179 #define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ 212 #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ 213 #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ 214 #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ 215 #define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ 216 #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ 217 #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ 218 #define XMLNS_XDATA "jabber:x:data" /* XEP-0004 */ 219 #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* XEP-0085 */ 220 #define XMLNS_DISCO_INFO "http://jabber.org/protocol/disco#info" /* XEP-0030 */ 221 #define XMLNS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" /* XEP-0030 */ 222 #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ 223 #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user" /* XEP-0045 */ 224 #define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ 225 #define XMLNS_FEATURE "http://jabber.org/protocol/feature-neg" /* XEP-0020 */ 226 #define XMLNS_SI "http://jabber.org/protocol/si" /* XEP-0095 */ 227 #define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */ 228 #define XMLNS_BYTESTREAMS "http://jabber.org/protocol/bytestreams" /* XEP-0065 */ 229 #define XMLNS_IBB "http://jabber.org/protocol/ibb" /* XEP-0047 */ 180 230 181 231 /* iq.c */ … … 185 235 int jabber_get_roster( struct im_connection *ic ); 186 236 int jabber_get_vcard( struct im_connection *ic, char *bare_jid ); 187 int jabber_add_to_roster( struct im_connection *ic, c har *handle, char *name);237 int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group ); 188 238 int jabber_remove_from_roster( struct im_connection *ic, char *handle ); 239 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ); 240 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ); 241 242 /* si.c */ 243 int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode ); 244 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); 245 void jabber_si_free_transfer( file_transfer_t *ft); 246 247 /* s5bytestream.c */ 248 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode); 249 gboolean jabber_bs_send_start( struct jabber_transfer *tf ); 250 gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len ); 189 251 190 252 /* message.c */ … … 200 262 char *set_eval_tls( set_t *set, char *value ); 201 263 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); 202 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );264 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ); 203 265 void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ); 204 266 struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); -
protocols/jabber/jabber_util.c
r051372c r41d415b 99 99 } 100 100 101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ) 102 102 { 103 103 struct xt_node *node, *c; … … 111 111 c = xt_new_node( "error", NULL, c ); 112 112 xt_add_attr( c, "type", err_type ); 113 114 /* Add the error code, if present */ 115 if (err_code) 116 xt_add_attr( c, "code", err_code ); 113 117 114 118 /* To make the actual error packet, we copy the original packet and … … 275 279 presence_send_request( bla->ic, bla->handle, "subscribed" ); 276 280 277 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 278 imcb_ask_add( bla->ic, bla->handle, NULL ); 281 imcb_ask_add( bla->ic, bla->handle, NULL ); 279 282 280 283 g_free( bla->handle ); … … 458 461 459 462 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && 460 ( bare_exists || imcb_find_buddy(ic, jid ) ) )463 ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) ) 461 464 { 462 465 *s = '/'; … … 479 482 if( bud == NULL ) 480 483 /* No match. Create it now? */ 481 return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? 484 return ( ( flags & GET_BUDDY_CREAT ) && 485 bee_user_by_handle( ic->bee, ic, jid_ ) ) ? 482 486 jabber_buddy_add( ic, jid_ ) : NULL; 483 487 else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) -
protocols/jabber/presence.c
r051372c r41d415b 205 205 struct jabber_data *jd = ic->proto_data; 206 206 struct xt_node *node, *cap; 207 struct groupchat *c;207 GSList *l; 208 208 int st; 209 209 … … 229 229 /* Have to send this update to all groupchats too, the server won't 230 230 do this automatically. */ 231 for( c = ic->groupchats; c && st; c = c->next ) 232 { 231 for( l = ic->groupchats; l && st; l = l->next ) 232 { 233 struct groupchat *c = l->data; 233 234 struct jabber_chat *jc = c->data; 234 235 -
protocols/msn/Makefile
r051372c r41d415b 8 8 9 9 -include ../../Makefile.settings 10 ifdef SRCDIR 11 SRCDIR := $(SRCDIR)protocols/msn/ 12 endif 10 13 11 14 # [SH] Program variables … … 33 36 $(objects): ../../Makefile.settings Makefile 34 37 35 $(objects): %.o: %.c38 $(objects): %.o: $(SRCDIR)%.c 36 39 @echo '*' Compiling $< 37 40 @$(CC) -c $(CFLAGS) $< -o $@ -
protocols/msn/msn.c
r051372c r41d415b 79 79 if( md ) 80 80 { 81 /** Disabling MSN ft support for now. 82 while( md->filetransfers ) { 83 imcb_file_canceled( md->filetransfers->data, "Closing connection" ); 84 } 85 */ 86 81 87 if( md->fd >= 0 ) 82 88 closesocket( md->fd ); … … 98 104 g_free( md->grouplist ); 99 105 106 while( md->grpq ) 107 { 108 struct msn_groupadd *ga = md->grpq->data; 109 g_free( ga->group ); 110 g_free( ga->who ); 111 g_free( ga ); 112 md->grpq = g_slist_remove( md->grpq, ga ); 113 } 114 100 115 g_free( md ); 101 116 } … … 116 131 struct msn_switchboard *sb; 117 132 133 #ifdef DEBUG 134 if( strcmp( who, "raw" ) == 0 ) 135 { 136 msn_write( ic, message, strlen( message ) ); 137 msn_write( ic, "\r\n", 2 ); 138 } 139 else 140 #endif 118 141 if( ( sb = msn_sb_by_handle( ic, who ) ) ) 119 142 { … … 176 199 static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) 177 200 { 178 msn_buddy_list_add( ic, "FL", who, who );201 msn_buddy_list_add( ic, "FL", who, who, group ); 179 202 } 180 203 … … 217 240 { 218 241 struct msn_switchboard *sb; 242 struct groupchat *c = imcb_chat_new( ic, who ); 219 243 220 244 if( ( sb = msn_sb_by_handle( ic, who ) ) ) … … 234 258 msn_sb_write_msg( ic, m ); 235 259 236 return NULL; 237 } 238 239 return NULL; 260 return c; 261 } 240 262 } 241 263 … … 247 269 static void msn_add_permit( struct im_connection *ic, char *who ) 248 270 { 249 msn_buddy_list_add( ic, "AL", who, who );271 msn_buddy_list_add( ic, "AL", who, who, NULL ); 250 272 } 251 273 … … 259 281 struct msn_switchboard *sb; 260 282 261 msn_buddy_list_add( ic, "BL", who, who );283 msn_buddy_list_add( ic, "BL", who, who, NULL ); 262 284 263 285 /* If there's still a conversation with this person, close it. */ … … 328 350 ret->send_typing = msn_send_typing; 329 351 ret->handle_cmp = g_strcasecmp; 352 //ret->transfer_request = msn_ftp_transfer_request; 330 353 331 354 register_protocol(ret); -
protocols/msn/msn.h
r051372c r41d415b 70 70 int trId; 71 71 72 GSList *msgq ;72 GSList *msgq, *grpq; 73 73 GSList *switchboards; 74 74 int sb_failures; 75 75 time_t first_sb_failure; 76 GSList *filetransfers; 76 77 77 78 const struct msn_away_state *away_state; … … 118 119 char *who; 119 120 char *text; 121 }; 122 123 struct msn_groupadd 124 { 125 char *who; 126 char *group; 120 127 }; 121 128 … … 159 166 int msn_write( struct im_connection *ic, char *s, int len ); 160 167 int msn_logged_in( struct im_connection *ic ); 161 int msn_buddy_list_add( struct im_connection *ic, c har *list, char *who, char *realname);168 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ); 162 169 int msn_buddy_list_remove( struct im_connection *ic, char *list, char *who ); 163 170 void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); … … 189 196 void msn_sb_stop_keepalives( struct msn_switchboard *sb ); 190 197 198 /* invitation.c */ 199 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); 200 191 201 #endif //_MSN_H -
protocols/msn/msn_util.c
r051372c r41d415b 51 51 } 52 52 53 int msn_buddy_list_add( struct im_connection *ic, c har *list, char *who, char *realname_)53 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) 54 54 { 55 55 struct msn_data *md = ic->proto_data; 56 char buf[1024], *realname; 56 char buf[1024], *realname, groupid[8]; 57 58 *groupid = '\0'; 59 if( group ) 60 { 61 int i; 62 for( i = 0; i < md->groupcount; i ++ ) 63 if( g_strcasecmp( md->grouplist[i], group ) == 0 ) 64 { 65 g_snprintf( groupid, sizeof( groupid ), " %d", i ); 66 break; 67 } 68 69 if( *groupid == '\0' ) 70 { 71 /* Have to create this group, it doesn't exist yet. */ 72 struct msn_groupadd *ga; 73 GSList *l; 74 75 for( l = md->grpq; l; l = l->next ) 76 { 77 ga = l->data; 78 if( g_strcasecmp( ga->group, group ) == 0 ) 79 break; 80 } 81 82 ga = g_new0( struct msn_groupadd, 1 ); 83 ga->who = g_strdup( who ); 84 ga->group = g_strdup( group ); 85 md->grpq = g_slist_prepend( md->grpq, ga ); 86 87 if( l == NULL ) 88 { 89 char *groupname = msn_http_encode( group ); 90 g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); 91 g_free( groupname ); 92 return msn_write( ic, buf, strlen( buf ) ); 93 } 94 else 95 { 96 /* This can happen if the user's doing lots of adds to a 97 new group at once; we're still waiting for the server 98 to confirm group creation. */ 99 return 1; 100 } 101 } 102 } 57 103 58 104 realname = msn_http_encode( realname_ ); 59 60 g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s\r\n", ++md->trId, list, who, realname ); 61 if( msn_write( ic, buf, strlen( buf ) ) ) 62 { 63 g_free( realname ); 64 65 return( 1 ); 66 } 67 105 g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); 68 106 g_free( realname ); 69 107 70 return ( 0);108 return msn_write( ic, buf, strlen( buf ) ); 71 109 } 72 110 … … 94 132 struct msn_buddy_ask_data *bla = data; 95 133 96 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); 97 98 if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) 99 imcb_ask_add( bla->ic, bla->handle, NULL ); 134 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL ); 135 136 imcb_ask_add( bla->ic, bla->handle, NULL ); 100 137 101 138 g_free( bla->handle ); … … 108 145 struct msn_buddy_ask_data *bla = data; 109 146 110 msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname );147 msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL ); 111 148 112 149 g_free( bla->handle ); -
protocols/msn/ns.c
r051372c r41d415b 76 76 if( msn_write( ic, s, strlen( s ) ) ) 77 77 { 78 ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic );78 ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic ); 79 79 imcb_log( ic, "Connected to server, waiting for reply" ); 80 80 } … … 533 533 else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 ) 534 534 { 535 const char *group = NULL; 536 int num; 537 538 if( cmd[6] != NULL && sscanf( cmd[6], "%d", &num ) == 1 && num < md->groupcount ) 539 group = md->grouplist[num]; 540 535 541 http_decode( cmd[5] ); 536 imcb_add_buddy( ic, cmd[4], NULL);542 imcb_add_buddy( ic, cmd[4], group ); 537 543 imcb_rename_buddy( ic, cmd[4], cmd[5] ); 538 544 } … … 604 610 imc_logout( ic, TRUE ); 605 611 return( 0 ); 612 } 613 } 614 else if( strcmp( cmd[0], "ADG" ) == 0 ) 615 { 616 char *group = g_strdup( cmd[3] ); 617 int groupnum, i; 618 GSList *l, *next; 619 620 http_decode( group ); 621 if( sscanf( cmd[4], "%d", &groupnum ) == 1 ) 622 { 623 if( groupnum >= md->groupcount ) 624 { 625 md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 ); 626 for( i = md->groupcount; i <= groupnum; i ++ ) 627 md->grouplist[i] = NULL; 628 md->groupcount = groupnum + 1; 629 } 630 g_free( md->grouplist[groupnum] ); 631 md->grouplist[groupnum] = group; 632 } 633 else 634 { 635 /* Shouldn't happen, but if it does, give up on the group. */ 636 g_free( group ); 637 imcb_error( ic, "Syntax error" ); 638 imc_logout( ic, TRUE ); 639 return 0; 640 } 641 642 for( l = md->grpq; l; l = next ) 643 { 644 struct msn_groupadd *ga = l->data; 645 next = l->next; 646 if( g_strcasecmp( ga->group, group ) == 0 ) 647 { 648 if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) ) 649 return 0; 650 651 g_free( ga->group ); 652 g_free( ga->who ); 653 g_free( ga ); 654 md->grpq = g