diff options
| author | Paul Buetow <paul@buetow.org> | 2013-04-06 13:14:42 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2013-04-06 13:14:42 +0200 |
| commit | 98eac951f8087b213f5850bd126dcb279db360a8 (patch) | |
| tree | c121f5c4df1aab847defa539990c1315bd5ba4a8 | |
| parent | 0537da9d1e0f593130fc3967befb71e673b016bc (diff) | |
tagging ychat-0.6ychat-0.6
| -rwxr-xr-x[-rw-r--r--] | Makefile.in | 123 | ||||
| -rwxr-xr-x | README | 126 | ||||
| -rw-r--r-- | aclocal.m4 | 20 | ||||
| -rwxr-xr-x | base.cpp | 59 | ||||
| -rwxr-xr-x | base.h | 71 | ||||
| -rwxr-xr-x | chat.cpp | 162 | ||||
| -rwxr-xr-x | chat.h | 46 | ||||
| -rwxr-xr-x | conf.cpp | 87 | ||||
| -rwxr-xr-x | conf.h | 24 | ||||
| -rwxr-xr-x | conf.txt | 45 | ||||
| -rwxr-xr-x | configure | 1695 | ||||
| -rw-r--r-- | configure.in | 25 | ||||
| -rwxr-xr-x | cont.cpp | 24 | ||||
| -rwxr-xr-x | cont.h | 29 | ||||
| -rwxr-xr-x | dir.cpp | 58 | ||||
| -rwxr-xr-x | dir.h | 32 | ||||
| -rwxr-xr-x | glob.h | 103 | ||||
| -rw-r--r-- | hmap.cpp | 195 | ||||
| -rw-r--r-- | hmap.h | 125 | ||||
| -rwxr-xr-x | html.cpp | 170 | ||||
| -rwxr-xr-x | html.h | 42 | ||||
| -rwxr-xr-x | html/frameset.html | 8 | ||||
| -rwxr-xr-x | html/help.html | 17 | ||||
| -rwxr-xr-x | html/index.html | 6 | ||||
| -rwxr-xr-x | html/input.html | 19 | ||||
| -rwxr-xr-x | incl.h | 18 | ||||
| -rwxr-xr-x | lang.cpp | 79 | ||||
| -rwxr-xr-x | lang.h | 24 | ||||
| -rw-r--r-- | lang/de | 10 | ||||
| -rw-r--r-- | lang/en | 7 | ||||
| -rw-r--r-- | logd.cpp | 82 | ||||
| -rw-r--r-- | logd.h | 25 | ||||
| -rwxr-xr-x | main.cpp | 124 | ||||
| -rw-r--r-- | mcon.cpp | 40 | ||||
| -rw-r--r-- | mcon.h | 24 | ||||
| -rwxr-xr-x | menu.cpp | 115 | ||||
| -rwxr-xr-x | menu.h | 30 | ||||
| -rw-r--r-- | mman.cpp | 190 | ||||
| -rw-r--r-- | mman.h | 38 | ||||
| -rwxr-xr-x | modl.cpp | 178 | ||||
| -rwxr-xr-x | modl.h | 32 | ||||
| -rw-r--r-- | mods/commands/yc_col.cpp | 84 | ||||
| -rw-r--r-- | mods/commands/yc_m.cpp | 38 | ||||
| -rw-r--r-- | mods/commands/yc_me.cpp | 38 | ||||
| -rw-r--r-- | mods/commands/yc_q.cpp | 25 | ||||
| -rw-r--r-- | mods/commands/yc_template.cpp | 29 | ||||
| -rw-r--r-- | mods/commands/yc_test.cpp | 12 | ||||
| -rw-r--r-- | mods/commands/yc_version.cpp | 22 | ||||
| -rwxr-xr-x | mods/compile.sh | 9 | ||||
| -rw-r--r-- | mods/html/yc_help.cpp | 45 | ||||
| -rwxr-xr-x | msgs.h | 49 | ||||
| -rwxr-xr-x | mutx.cpp | 20 | ||||
| -rwxr-xr-x | mutx.h | 21 | ||||
| -rwxr-xr-x | name.cpp | 31 | ||||
| -rwxr-xr-x | name.h | 30 | ||||
| -rwxr-xr-x | ncur.cpp | 159 | ||||
| -rwxr-xr-x | ncur.h | 43 | ||||
| -rwxr-xr-x | pool.cpp | 261 | ||||
| -rwxr-xr-x | pool.h | 77 | ||||
| -rwxr-xr-x | quickstart.sh | 34 | ||||
| -rwxr-xr-x | reqp.cpp | 326 | ||||
| -rwxr-xr-x | reqp.h | 48 | ||||
| -rwxr-xr-x | room.cpp | 16 | ||||
| -rwxr-xr-x | room.h | 34 | ||||
| -rw-r--r-- | s_chat.cpp | 10 | ||||
| -rw-r--r-- | s_chat.h | 27 | ||||
| -rw-r--r-- | s_conf.cpp | 10 | ||||
| -rw-r--r-- | s_conf.h | 27 | ||||
| -rw-r--r-- | s_html.cpp | 10 | ||||
| -rw-r--r-- | s_html.h | 27 | ||||
| -rw-r--r-- | s_lang.cpp | 10 | ||||
| -rw-r--r-- | s_lang.h | 28 | ||||
| -rw-r--r-- | s_mman.cpp | 10 | ||||
| -rw-r--r-- | s_mman.h | 38 | ||||
| -rw-r--r-- | s_modl.cpp | 10 | ||||
| -rw-r--r-- | s_modl.h | 27 | ||||
| -rw-r--r-- | s_mutx.cpp | 10 | ||||
| -rw-r--r-- | s_mutx.h | 27 | ||||
| -rw-r--r-- | s_ncur.cpp | 10 | ||||
| -rw-r--r-- | s_ncur.h | 26 | ||||
| -rw-r--r-- | s_sman.cpp | 10 | ||||
| -rw-r--r-- | s_sman.h | 27 | ||||
| -rw-r--r-- | s_sock.cpp | 10 | ||||
| -rw-r--r-- | s_sock.h | 27 | ||||
| -rw-r--r-- | s_tool.cpp | 131 | ||||
| -rw-r--r-- | s_tool.h | 21 | ||||
| -rw-r--r-- | sess.cpp | 39 | ||||
| -rw-r--r-- | sess.h | 28 | ||||
| -rw-r--r-- | sman.cpp | 93 | ||||
| -rw-r--r-- | sman.h | 45 | ||||
| -rwxr-xr-x | sock.cpp | 394 | ||||
| -rwxr-xr-x | sock.h | 74 | ||||
| -rwxr-xr-x | thrd.cpp | 29 | ||||
| -rwxr-xr-x | thrd.h | 29 | ||||
| -rwxr-xr-x | todo.txt | 39 | ||||
| -rwxr-xr-x | user.cpp | 312 | ||||
| -rwxr-xr-x | user.h | 92 |
97 files changed, 7281 insertions, 204 deletions
diff --git a/Makefile.in b/Makefile.in index 0f62701..2a9ca34 100644..100755 --- a/Makefile.in +++ b/Makefile.in @@ -1,111 +1,12 @@ -MAKE=gmake -HEADER?=docs/header.txt -PREFIX=@prefix@ -EFIND=@efind@ -BIN=./bin/ychat -all: build modules base - @echo "Now edit the ychat.conf and run ychat!" - @echo "The config file is searched in the following order:" - @echo " ./ychat.conf " - @echo " ~/.ychat/ychat.conf " - @echo " ./etc/ychat.conf " - @echo " /etc/ychat.conf " - @echo " $(PREFIX)/etc/ychat.conf " - @echo WARNING! This software is EXPERIMENTAL! -install: all - @echo "===> Installing to ${PREFIX}" - @for i in bin share/ychat lib/ychat; do \ - if ! [ -d ${PREFIX}/$$i ]; then \ - mkdir -p ${PREFIX}/$$i; \ - fi; \ - done; - @cp -fR ./mods ${PREFIX}/share/ychat/mods; - @cp -fR ./etc ${PREFIX}/share/ychat/etc; - @cp -fR ./html ${PREFIX}/share/ychat/html; - @cp -f ./README ./COPYING ${PREFIX}/share/ychat; - @cp -f ./bin/ychat ${PREFIX}/bin; -deinstall: uninstall -uninstall: - @echo "===> Uninstalling from ${PREFIX}" - @for i in ${PREFIX}/bin/ychat ${PREFIX}/share/ychat \ - ${PREFIX}/lib/ychat; do \ - rm -Rf $$i; \ - done -strip: all - @strip ${BIN} - @echo "===> Stripped binary size: `du -hs ${BIN} | \ - sed 's/\.\/bin\///'`" -base: - @if test -f bin/ychat; then echo "==> Backing up old binary"; \ - if test -f bin/ychat.old; then \ - rm -f bin/ychat.old; \ - fi; \ - mv bin/ychat bin/ychat.old; \ - fi - @${MAKE} -C ./src -modules: - @if test -d ./src/mods; then \ - ${MAKE} -C ./src/mods; \ - fi -stats: - @perl scripts/stats.pl -run_loop: - @while (true); do ./bin/ychat; done -run: - ./bin/ychat -base_start: base - ./bin/ychat -license: - @more COPYING -#//<<* -yhttpdbase: - @perl scripts/makeyhttpd.pl || echo "You need to have perl to do this!" - @echo yhttpd code base has been generated in ../yhttpd -#//*>> -clean: clean_base clean_modules -clean_base: - @if [ -f ./src/Makefile ]; then ${MAKE} -C ./src clean; fi -clean_modules: - @if [ -d ./src/mods ]; then ${MAKE} -C ./src/mods clean; fi -help: - @echo "You may run ${MAKE} with the following parameters:" - @grep "^ ${MAKE} " README - @echo "For more questions read the README file or contact mail@ychat.org!" -mrproper: clean - @if [ -f ./src/Makefile ]; then ${MAKE} -C ./src mrproper; fi - @if [ -d src/mods ]; then ${MAKE} -C ./src/mods mrproper; fi - @if [ -d ./bin ]; then rm -Rf ./bin; fi - @if [ -d ./obj ]; then rm -Rf ./obj; fi - @find ./ -name "*core*" -exec rm -f {} \; - @find ./log/ -type f | grep -v CVS | xargs rm -f - @rm -f Makefile -version: - @./scripts/version.sh -debug: - @gdb bin/ychat ychat.core -confdebug: - @CXXFLAGS='-g3 -ggdb' ./configure -dist: - @./scripts/makedist.sh -ssltest: - openssl genrsa -des3 -out privkey.pem 2048 - openssl req -new -x509 -key privkey.pem -out cert.pem -days 1095 - @mv -f privkey.pem cert.pem etc -headers: - @${EFIND} ./ -regex '\./src/.*\.(h|(cpp)|(tmpl))' -exec \ - sh -c 'export FILE={}; ${MAKE} header' \; -header: - @echo "===> Processing ${FILE}" - @sed -n '/*:/d; w .tmp' ${FILE} - @header=`sed 's/\(.*\)/ echo " \*: \1"/' ${HEADER}`; \ - echo '/*:*' > ${FILE}; eval "$$header" >> ${FILE}; \ - echo ' *:*/' >> ${FILE}; cat .tmp >> ${FILE}; rm -f .tmp -replace: - @${EFIND} ./ -regex '\./src/.*\.(h|(cpp)|(tmpl))' -exec \ - sh -c 'sed -n "s/$(FROM)/$(INTO)/g; \ - w .tmp" {} && mv -f .tmp {}' \; -build: - @awk '{ if ($$2 == "BUILDNR") print $$1,$$2,$$3+1; else print }' \ - src/build.h >.tmp && mv -f .tmp src/build.h -touch: - find ./ -type f -exec touch {} \; +SRCS=chat.cpp s_chat.cpp conf.cpp s_conf.cpp cont.cpp dir.cpp html.cpp s_html.cpp lang.cpp s_lang.cpp logd.cpp main.cpp modl.cpp s_modl.cpp mutx.cpp s_mutx.cpp name.cpp pool.cpp reqp.cpp room.cpp sock.cpp s_sock.cpp thrd.cpp s_tool.cpp user.cpp sess.cpp sman.cpp s_sman.cpp s_mman.cpp mman.cpp mcon.cpp menu.cpp ncur.cpp s_ncur.cpp +OBJS=$(SRCS:.cpp=.o) +CC=g++ +LDFLAGS=@LDFLAGS@ -lstdc++ -lmysqlclient -lncurses -g +LDADD=-pthread -D_THREAD_SAFE +all: ychat +$(SRCS): + $(CC) $(CFLAGS) -c $*.cpp +ychat: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDADD) +clean: + rm *.o @@ -1,6 +1,5 @@ -yChat; Homepage: www.yChat.org; Version 0.5.4-RELEASE +yChat++; Homepage: www.yChat.org; Version 0.6 Copyright (C) 2003 Paul C. Buetow, Volker Richter -Copyright (C) 2005 Paul C. Buetow ----------------------------------------------------------------- This program is free software; you can redistribute it and/or @@ -19,74 +18,123 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ----------------------------------------------------------------- -0.0.0 LEGACY YCHAT 0.5 TABLE OF CONTENTS +0.0.0 YCHAT++ TABLE OF CONTENTS 1.0.0 REQUIREMENTS 1.1.0 TESTED PLATFORMS 1.2.0 IMPORTANT NOTES -1.3.0 HOW TO OBTAIN YCHAT +1.3.0 HOW TO OBTAIN YCHAT++ 1.3.1 INSTALLATION +1.4.0 HOW TO USE SCREEN WITH YCHAT++ 1.5.0 CUSTOMIZATION 1.6.0 FILES -1.7.0 WRITING BUG REPORTS 1.8.0 CONTACT 1.0.0 REQUIREMENTS: -- gcc 3.x +- gcc 3.2 The GNU C++ compiler. +- mysql-client 4.x ( 3.x may do too ) + Includes libmysqlclient and the mysql.h header files. + +- ncurses 5.x + Includes libncurses and the ncurses.h header files. + +- screen + Only needed if yChat should run in background with + ncurses enabled. + 1.1.0 TESTED PLATFORMS: The following platforms have been tested with success: - Linux with GCC 3.2.0, GNU make 3.79.1 -- FreeBSD 5.1-RELEASE-p2, GCC 3.2.2, GNU make 3.80 -- FreeBSD 5.3-RELEASE, GCC 3.4, GNU make 3.80 +- FreeBSD 5.1-RELEASE-p2, GCC 3.2.2, GNU make 3.80 ( standard make does not seem work on FreeBSD ). 1.2.0 IMPORTANT NOTES: Before you compile the source you have to be sure to use at least GCC version 3.x with pthreads enabled. ( Type gcc -v to check it ). GCC 2.95 did not work while testing on linux and WON'T BE SUPPORTED! -If you like to support yChat please write us an email and tell what -you can/like/would help ;-]. Please also take a look at the yChat +If you like to support yChat++, please write us an email and tell what +you can/like/would help ;-]. Please also take a look at the yChat++ homepage which is located at http://www.yChat.org. -1.3.0 HOW TO OBTAIN YCHAT: +1.3.0 HOW TO OBTAIN YCHAT++: yChat can be downloaded as a source package or through CVS. The packages are located at http://www.yChat.org -> Sourcecode -> Packages or go to http://programming.buetow.org/CPP-yChat . -For CVS download type also look at the homepage please. +For CVS download type: + +cvs -d:pserver:anonymous@cvs.ychat.berlios.de:/cvsroot/ychat login +( You will be asked for a password. Use "just enter" ). + +cvs -z3 -d:pserver:anonymous@cvs.ychat.berlios.de:/cvsroot/ychat co \ + ychat +( The sources will be copied into your local folder. However, if you + want to obtain the yChat++ Basic sources then replace "ychat" + "ychat-basic" ). + +cvs -d:pserver:anonymous@cvs.ychat.berlios.de:/cvsroot/ychat logout +( Logs your CVS session out ). + +Now you may continue with the installation. 1.3.1 INSTALLATION: -Invoke "./configure" and afterwards "make", edit the conf.txt. +If you dont want to use yChat's ncurses based administration interface +you may remove the #define NCURSES line in the glob.h and enable +#define SERVMSG and #define VERBOSE instead. + +Now invoke "./configure" and afterwards "make", edit the conf.txt ( be +sure to enter a valid mysql account ) host. Now we want to compile all the dynamic loadable modules of ychat. -Invoke "cd cmnd && ./compile.sh && cd -". All command modules should get +Invoke "cd mods && ./compile.sh && cd -". All modules should get compiled. Now its time to run the server with ./ychat. -Then point your webbrowser to http://yourip:port ! - +Then point your webbrowser to http://yourip:port/index.html ( ignoring +the index.html on the end of the url will not work! ). ... have fun :-). + +1.4.0 HOW TO USE SCREEN WITH YCHAT++: + +If you are running yChat in ncurses mode you might want to install +the tool which is called "screen". This will enable you putting the +ncurses interface into the background, closing the terminal session +and reusing the interface later through another terminal. + +Just do: + + screen -S ychat ./ychat ( creates a new session and starts ychat in it ) + strg+d+a ( will detach the ychat session ) + ( closing the terminal ) + ( opening a new terminal ) + screen -r ychat ( will return you to the ychat process ) + +Screen will terminate automaticaly if all processes in its sessions are +terminated. + +For a closer look read the screen manual page ( man screen ). + 1.5.0 CUSTOMIZATION: If you like to customize the design/layout/language of yChat, you will have to edit msgs.h and glob.h before you compile the sources. Afterwards you can -change the html-template files which are placed in the html/ subdirectory. -Dynamic loadable modules can be found in the cmnd/ subdirectory. +change the html-template files which are placed in the html/ subdirectory and +the language-template files which are placed in the lang/ subdirectory. +Dynamic loadable modules can be found in the mods/ subdirectory. ( chat +commands are realized through modules too ). 1.6.0 FILES: ( This list is not complete ) conf.txt - The yChat configuration file. ( read by conf.cpp ). -Files in ./src: - base.cpp - Encapsulates vector fields of room's or user ( may be later hash_maps ) and provides methods for manipulating data objects. @@ -203,44 +251,6 @@ The basic class structure: / \ conf html -1.7 WRITING BUG REPORTS - -How to submit a good bug report? - -Send them to Bug@yChat.org. - -First you should give the following information: -- yChat version, if CVS (or devel. tarball) then which day? -- operating system / distribution and it's version -- when did it crash? did you do something? can you reproduce the crash? - -Getting backtrace of the crash also helps a lot, especially if yChat crashes randomly. If after crash you see text: - - "segmentation fault (core dumped)" - -It writes a file named "core" or "ychat.core" depending on your OS to directory where you started yChat. If it doesn't print the "(core dumped)" or you can't find the core file, you'll have to raise the limit for max. core file size before running yChat. To do this, say: - - ulimit -c unlimited - -So, if you have the core file and GNU debugger (gdb), you can get the backtrace with: - - gdb ychat core - bt - -Paste all the lines starting from line having #0 at the beginning. - -Here's an example session: - - in reqp::parse(thrd*, std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >&) () - (gdb) bt - #0 0x0805c287 in reqp::parse(thrd*, std::string, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >&) () - #1 0x0806060f in sock::read_write(thrd*, int) () - #2 0x080612ba in thrd::run() () - #3 0x0805a3b8 in pool::run_func(void*) () - #4 0x0805a375 in pool::tpool_thread(void*) () - #5 0x281d44ae in _thread_start () from /usr/lib/libc_r.so.5 - (gdb) - 1.8 CONTACT: You may contact us through the following addresses: diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..8146300 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,20 @@ +AC_DEFUN(AC_CHECK_EXTRA,[ + AC_ARG_WITH( + extra-libs, + [ --with-extra-libs=DIR comma separated list of additional lib directories ], + [ + EXTRA=`echo $withval | sed -e ':a;s/,/ -L/;t a'` + LDFLAGS="$LDFLAGS -L$EXTRA" + ] + ) + AC_ARG_WITH( + extra-includes, + [ --with-extra-includes=DIR comma separated list of additional include directories ], + [ + EXTRA=`echo $withval | sed -e ':a;s/,/ -I/;t a'` + CPPFLAGS="$CPPFLAGS -I$EXTRA" + ] + ) +]) + + diff --git a/base.cpp b/base.cpp new file mode 100755 index 0000000..82b3030 --- /dev/null +++ b/base.cpp @@ -0,0 +1,59 @@ +#ifndef BASE_CPP +#define BASE_CPP + +#include "base.h" + +template<class type> +base<type>::base() +{ + map_elem = new hmap<type*,string>(80); + pthread_mutex_init (&mut_map_elem, NULL ); +} + +template<class type> +base<type>::~base( ) +{ + pthread_mutex_destroy( &mut_map_elem ); +} + +template<class type> +void +base<type>::add_elem( type* p_type ) +{ + pthread_mutex_lock ( &mut_map_elem ); + map_elem->add_elem ( p_type, p_type->get_name()); + pthread_mutex_unlock( &mut_map_elem ); +} + +template<class type> +void +base<type>::del_elem( string &s_name ) +{ + pthread_mutex_lock ( &mut_map_elem ); + map_elem->del_elem ( s_name ); + pthread_mutex_unlock( &mut_map_elem ); +} + +template<class type> +type* +base<type>::get_elem( string &s_name, bool &b_found ) +{ + pthread_mutex_lock ( &mut_map_elem ); + type* p_type = map_elem->get_elem( s_name ); + pthread_mutex_unlock( &mut_map_elem ); + + b_found = p_type == NULL ? false : true; + + return p_type; +} + +template<class type> +void +base<type>::run_func( void (*func)(type*, void*), void* v_arg ) +{ + pthread_mutex_lock ( &mut_map_elem ); + map_elem->run_func( func, v_arg ); + pthread_mutex_unlock( &mut_map_elem ); +} + +#endif @@ -0,0 +1,71 @@ +// template class data declaration; + +#ifndef BASE_H +#define BASE_H + +#include "incl.h" +#include "hmap.h" + +template<class type> +class base +{ +private: + hmap<type*,string>* map_elem; + pthread_mutex_t mut_map_elem; + +public: + base(); + ~base(); + + virtual void add_elem( type* p_type ); // add a element. + virtual void del_elem( string &s_name ); // delete a alement. + virtual type* get_elem( string &s_name, bool &b_found ); // get a element. + + // execute func on all elements of map_elem. v_pointer is the argument. + virtual void run_func( void (*func)(type*, void*), void* v_arg ); + + // chat::msg_post sends to all users of the system a message. + // room::msg_post sends to all users of the room a message. + // user::msg_post sends to the user a message. + void msg_post( string *s_msg ) + { + run_func( &base<type>::msg_post_ , (void*)s_msg ); + } + static void msg_post_( type* type_obj, void* v_arg ) + { + string *p_msg = (string*) v_arg; + type_obj -> msg_post( p_msg ); + } + + void get_data( map_string *p_map_string ) + { + run_func( &base<type>::get_data_ , (void*)p_map_string ); + } + static void get_data_( type* type_obj, void* v_arg ) + { + map_string *map_params = (map_string*) v_arg; + type_obj -> get_data ( map_params ); + } + + // chat::get_user_list gets a list of all users of the system. + // room::get_user_list gets a list of all users of the room. + // user::get_user_list gets a "list" of a user <font color="usercolor">username</font>seperator + void get_user_list( string &s_list, string &s_seperator ) + { + + container c; + c.elem[0] = (void*) &s_list; + c.elem[1] = (void*) &s_seperator; + + run_func( &base<type>::get_user_list_, (void*)&c ); + } + static void get_user_list_( type* type_obj, void* v_arg ) + { + container *c = (container*) v_arg; + type_obj -> get_user_list( *((string*)c->elem[0]), *((string*)c->elem[1]) ); + } +}; + +#include "base.cpp" + +#endif diff --git a/chat.cpp b/chat.cpp new file mode 100755 index 0000000..fa6200c --- /dev/null +++ b/chat.cpp @@ -0,0 +1,162 @@ +// class chat implementation. + +#ifndef s_chat_CXX +#define s_chat_CXX + +#include "chat.h" +#include "s_conf.h" +#include "s_tool.h" +#include "s_ncur.h" + +using namespace std; + +chat::chat( ) +{ + if ( s_conf::get + ().get_val( "HTML" ) == "OFF" ) + b_strip_html = true; + else + b_strip_html = false; +} + +chat::~chat( ) +{} + +user* +chat::get_user( string &s_user ) +{ + bool b_flag; + return get_user( s_user, b_flag ); +} + +user* +chat::get_user( string &s_user, bool &b_found ) +{ + container param; + + param.elem[0] = (void*) &s_user ; + param.elem[1] = (void*) &b_found; + + b_found = false; + + run_func( get_user_, (void*)¶m ); + + if ( *( (bool*)param.elem[1] ) ) + return (user*)param.elem[2]; +} + +void +chat::get_user_( room *room_obj, void *v_arg ) +{ + container* param = (container*) v_arg; + param->elem[2] = (void*)room_obj->get_elem( *((string*)param->elem[0]), *((bool*)param->elem[1]) ); +} + +void +chat::login( map_string &map_params ) +{ + string s_user = map_params["nick"]; + + // prove if nick is empty: + if ( s_user.empty() ) + { + map_params["INFO"] = E_NONICK; + map_params["request"] = s_conf::get + ().get_val( "STARTMPL" ); // redirect to the startpage. + return; + } + + // prove if the nick ist alphanumeric: + else if ( ! s_tool::is_alpha_numeric( s_user ) ) + { + map_params["INFO"] = E_ALPNUM; + map_params["request"] = s_conf::get + ().get_val( "STARTMPL" ); // redirect to the startpage. + return; + } + + bool b_flag; + + // prove if nick is already online / logged in. + get_user( s_user, b_flag ); + + if ( b_flag ) + { + map_params["INFO"] = E_ONLINE; + map_params["request"] = s_conf::get + ().get_val( "STARTMPL" ); + return; + } + + string s_room = map_params["room"]; + room* p_room = get_room( s_room , b_flag ); + + // if room does not exist add room to list! + if ( ! b_flag ) + { + p_room = new room( s_room ); + +#ifdef NCURSES + + string s_tmp( NEWROOM ); + s_tmp.append( s_room ); + s_ncur::get + ().print( &s_tmp ); +#endif + + add_elem( p_room ); + } + + user *p_user = new user( s_user ); + + // add user to the room. + p_room->add_user( p_user ); + sess *ns =s_sman::get + ().create_session(); + ns->setValue(string("nick"), (void *)new string(s_user) ); + map_params["tmpid"]=ns->get_id(); + +#ifdef NCURSES + + { + string s_tmp( NEWUSER ); + s_tmp.append( s_user ); + s_ncur::get + ().print( s_tmp.c_str() ); + } +#endif + + // post "username enters the chat" into the room. + p_room->msg_post( new string( p_user->get_colored_name().append( s_lang::get + ().get_val( "USERENTR" ) ) ) ); + +} + +void +chat::post( user* p_user, map_string &map_params ) +{ + + string s_msg( map_params["message"] ); + + auto unsigned i_pos = s_msg.find( "/" ); + if ( i_pos == 0 ) + return p_user->command( s_msg ); + + if ( b_strip_html ) + s_tool::strip_html( &s_msg ); + + string s_post( "<font color=\"#" ); + + s_post.append( p_user->get_col1() ) + .append( "\">" ) + .append( p_user->get_name() ) + .append( ":</font> <font color=\"#") + .append( p_user->get_col2() ) + .append( "\">" ) + .append( s_msg ) + .append( "</font><br>\n" ); + + p_user->get_room()->msg_post( &s_post ); +} + +#endif @@ -0,0 +1,46 @@ +// class chat declaration. + +#ifndef s_chat_H +#define s_chat_H + +#include <vector> +#include "incl.h" +#include "base.h" +#include "room.h" +#include "user.h" +#include "sess.h" +#include "s_lang.h" +#include "s_sman.h" + +using namespace std; + +class chat : public base<room> +{ +private: + bool b_strip_html; + +public: + + + room* get_room( string &s_name, bool &b_found ) + { + return static_cast<room*>( get_elem( s_name, b_found ) ); + } + + // public methods: + explicit chat(); // a standard constructor. + ~chat(); // destructor. + + // get the object of a specific user. + virtual user* get_user( string &s_nick ); + virtual user* get_user( string &s_nick, bool &b_found ); + static void get_user_( room* room_obj, void *v_arg ); + + // will be called every time a user tries to login. + virtual void login( map_string &map_params ); + + // will be called if a user posts a message. + virtual void post ( user* u_user, map_string &map_params ); +}; + +#endif diff --git a/conf.cpp b/conf.cpp new file mode 100755 index 0000000..e4fcc0b --- /dev/null +++ b/conf.cpp @@ -0,0 +1,87 @@ +// class conf implementation. + +#ifndef s_conf_CXX +#define s_conf_CXX + +#include <fstream> +#include "s_ncur.h" +#include "conf.h" + +using namespace std; + +conf::conf( string s_conf = CONFILE ) : name( s_conf ) +{ + parse( ); // parse the config file. +} + +conf::~conf() +{} + +void +conf::parse() +{ +#ifdef VERBOSE + cout << CFILEOK << get_name() << endl; +#endif + + string s_configfile=get_name(); + + string homeconfig=string(getenv("HOME"))+string("/.ychat/")+get_name(); + ifstream homecheck( homeconfig.c_str() ); + if( homecheck ) + { + homecheck.close(); + s_configfile=homeconfig; + } + + ifstream fs_conf( s_configfile.c_str() ); + + if ( ! fs_conf ) + { +#ifdef VERBOSE + cout << CFILENO << get_name() << endl; +#endif + + return; + } + + char c_buf[READBUF]; + + while( fs_conf.getline( c_buf, READBUF ) ) + { + string s_token( c_buf ); + unsigned int ui_pos = s_token.find( "#", 0 ); + + // if line is commented out: + if ( ui_pos == 0 ) + continue; + + ui_pos = s_token.find( ";", 0 ); + + // if token has not been found. + if ( ui_pos == string::npos ) + continue; + + s_token = s_token.substr( 0 , --ui_pos ); + ui_pos = s_token.find ( "\"", 0 ); + + if ( ui_pos == string::npos ) + continue; + + string s_val = s_token.substr( ui_pos+1, s_token.length() ); + string s_key = s_token.substr( 0 , --ui_pos ); + +#ifdef VERBOSE2 + + cout << s_key << "=" << s_val << endl; +#endif + + // fill the map. + map_vals[s_key] = s_val; + } + + fs_conf.close(); + fs_conf.~ifstream(); +} + +#endif @@ -0,0 +1,24 @@ +// class conf declaration. this class parses the server config file. + +#ifndef s_conf_H +#define s_conf_H + +#include "incl.h" +#include "cont.h" +#include "name.h" + +using namespace std; + +class conf : public cont, name +{ +private: + +public: + // public methods: + conf ( string s_conf ); // standard constructor. + ~conf(); // standard destructor. + + virtual void parse( ); // parses the config file. +}; + +#endif @@ -11,24 +11,46 @@ # all lines which do not contain a semicolon and at least two quotes # or start with a # will be ignored. # -# greets, paul c. buetow ( snooper at ychat dot org ); +# greets, paul c. buetow ( snooper@ychat.org ); # # server specific configurations ( not allowed to be removed ): HTMLTEMP="html/"; # directory of the html-template files. -THRDPOOL="1"; # Initial pool size. -THRDPMAX="52"; # Max thread pool size +THRDPOOL="50"; # thread pool size. +THRDQUEU="50"; # length of the thread pool queue. SRVRPORT="3000"; # local port on which the server listens. STRDROOM="Lounge"; # the name of the standard room. LANGUAGE="en"; # language of the chat outputs ( CONSOLE OUTPUT IS NOT AFFECTED ) +# MySQL Settings +MYSQL_HOST="www.ychat.org"; +MYSQL_USER="ychat"; +MYSQL_PASS="yctest"; +MYSQL_DB="ychat"; + +#MySQL Connection Manager Settings +MIN_CONNECTIONS="1"; +MAX_CONNECTIONS="5"; + # the html template file which will be send if the requested file does not exists. NOTFOUND="notfound.html"; # specifies the standard start html-template. STARTMPL="index.html"; # user's standard nick color. -USERCOL1="#FFFFFF"; +USERCOL1="AAAAAA"; +# user's standard text color. +USERCOL2="FFFFFF"; + +# superuser level names. level 0 has the most provileges. +SULEVEL0="Coder"; # programmer. +SULEVEL1="Admin"; # administrator. +SULEVEL2="Magic"; # super user with special privileges. +SULEVEL3="Super"; # temporary super user. +SULEVEL4="Basic"; # normal user without special privileges. +SULEVEL5="Guest"; # guest user, has almost no privileges. +SULEVEL6="Restr"; # a very restricted user. +SULEVEL7="Outbn"; # banned out of the system. # length of the generated session id SESSION_LENGTH="32"; @@ -36,19 +58,24 @@ SESSION_LENGTH="32"; # html = "OFF" strips all html tags from incoming messages HTML="OFF"; -# Logging +# LOGGING: # relative or absolute path to logfile ACCESS_LOG="log/access_log"; -# we're using buffered logging for performance +# We're using buffered logging for performance # LOG_LINES specifies after how many lines the log is flushed into a file -# if you don't want buffered logging set LOG_LINES to 1 +# if you don't want buffered logging set LOG_LINES to 1. LOG_LINES="10"; -# values which are used by the html-templates and are not sticked within the yC++ core source! +# values which are used by the html-templates and are not sticked within the yC++ +# core source! GRAPHICS="http://paul.buetow.info/yChat"; # url for graphic files etc. -PGETITLE="yChat 0.5.x - Fast Simple Extensible"; +PGETITLE="yChat - Fast and extensible "; + +# yChat may preload all available modules. +PRE_MODS_COMMANDS="ON"; # yChat will preload mods/commands/*.so on start if set to "ON". +PRE_MODS_HTML="ON"; # yChat will preload mods/html/*.so on start if set to "ON". # do not edit beyond this line @@ -1,5 +1,1694 @@ -#!/bin/sh +#! /bin/sh -cd ./src -./configure +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-extra-libs=DIR comma separated list of additional lib directories " +ac_help="$ac_help + --with-extra-includes=DIR comma separated list of additional include directories " + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:530: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 545 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:551: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 562 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 579 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:614: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:646: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 657 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:688: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:693: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:721: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi + + + + # Check whether --with-extra-libs or --without-extra-libs was given. +if test "${with_extra_libs+set}" = set; then + withval="$with_extra_libs" + + EXTRA=`echo $withval | sed -e ':a;s/,/ -L/;t a'` + LDFLAGS="$LDFLAGS -L$EXTRA" + + +fi + + # Check whether --with-extra-includes or --without-extra-includes was given. +if test "${with_extra_includes+set}" = set; then + withval="$with_extra_includes" + + EXTRA=`echo $withval | sed -e ':a;s/,/ -I/;t a'` + CPPFLAGS="$CPPFLAGS -I$EXTRA" + + +fi + + + +echo $ac_n "checking for library containing dlopen""... $ac_c" 1>&6 +echo "configure:777: checking for library containing dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_search_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_func_search_save_LIBS="$LIBS" +ac_cv_search_dlopen="no" +cat > conftest.$ac_ext <<EOF +#line 784 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { +dlopen() +; return 0; } +EOF +if { (eval echo configure:795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_dlopen="none required" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +test "$ac_cv_search_dlopen" = "no" && for i in dl; do +LIBS="-l$i $ac_func_search_save_LIBS" +cat > conftest.$ac_ext <<EOF +#line 806 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen(); + +int main() { +dlopen() +; return 0; } +EOF +if { (eval echo configure:817: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_dlopen="-l$i" +break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done +LIBS="$ac_func_search_save_LIBS" +fi + +echo "$ac_t""$ac_cv_search_dlopen" 1>&6 +if test "$ac_cv_search_dlopen" != "no"; then + test "$ac_cv_search_dlopen" = "none required" || LIBS="$ac_cv_search_dlopen $LIBS" + +else : + +fi +if test "$ac_cv_search_dlopen" = "-ldl"; then +LDFLAGS="$ac_cv_search_dlopen" +fi + + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:843: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 848 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:856: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 873 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 891 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 912 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:950: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 955 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:960: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in string.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:990: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 995 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1000: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in pthread.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1030: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1035 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1040: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo "-> Error: pthread.h could not be found. Try --with-extra-includes=<dirs>"; exit 1; +fi +done + +for ac_hdr in mysql/mysql.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1071: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1076 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1081: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo "-> Error: mysql.h could not be found. Try --with-extra-includes=<dirs>"; exit 1; +fi +done + +echo $ac_n "checking for mysql_init in -lmysqlclient""... $ac_c" 1>&6 +echo "configure:1109: checking for mysql_init in -lmysqlclient" >&5 +ac_lib_var=`echo mysqlclient'_'mysql_init | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lmysqlclient $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1117 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char mysql_init(); + +int main() { +mysql_init() +; return 0; } +EOF +if { (eval echo configure:1128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo mysqlclient | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lmysqlclient $LIBS" + +else + echo "$ac_t""no" 1>&6 +"-> Error: libmysqlclient could not be found. Try --with-extra-libs=<dirs>"; exit 1; +fi + +for ac_hdr in netinet/in.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1160: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1165 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1170: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo "-> Error: netinet/in.h could not be found. Try --with-extra-includes=<dirs>"; exit 1; +fi +done + +for ac_hdr in sys/time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1201: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1206 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo "-> Error: sys/time.h could not be found. Try --with-extra-includes=<dirs>"; exit 1; +fi +done + +echo $ac_n "checking for newwin in -lncurses""... $ac_c" 1>&6 +echo "configure:1239: checking for newwin in -lncurses" >&5 +ac_lib_var=`echo ncurses'_'newwin | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lncurses $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1247 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char newwin(); + +int main() { +newwin() +; return 0; } +EOF +if { (eval echo configure:1258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo ncurses | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lncurses $LIBS" + +else + echo "$ac_t""no" 1>&6 +"-> Error: libncurses could not be found. Try --with-extra-libs=<dirs>";exit 1; +fi + +for ac_hdr in ncurses.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1290: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1295 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1300: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo "-> Error ncurses.h could not be found. Try --with-extra-includes=<dirs"; exit1; +fi +done + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1328: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1333 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1403: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <<EOF +#line 1410 "configure" +#include "confdefs.h" + +int main() { +} $ac_kw foo() { +; return 0; } +EOF +if { (eval echo configure:1417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <<EOF +#define inline $ac_cv_c_inline +EOF + ;; +esac + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CPP@%$CPP%g +s%@CXX@%$CXX%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <<EOF + +EOF +cat >> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +echo "You are now ready to compile. Type make" diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..da45484 --- /dev/null +++ b/configure.in @@ -0,0 +1,25 @@ +AC_INIT(Makefile.in) +AC_PROG_CPP +AC_PROG_CXX + +AC_CHECK_EXTRA +AC_SEARCH_LIBS(dlopen, dl) +if test "$ac_cv_search_dlopen" = "-ldl"; then +LDFLAGS="$ac_cv_search_dlopen" +fi + + +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) +AC_CHECK_HEADERS(string.h) +AC_CHECK_HEADERS(pthread.h,,echo "-> Error: pthread.h could not be found. Try --with-extra-includes=<dirs>"; exit 1;) +AC_CHECK_HEADERS(mysql/mysql.h,,echo "-> Error: mysql.h could not be found. Try --with-extra-includes=<dirs>"; exit 1;) +AC_CHECK_LIB(mysqlclient,mysql_init,,"-> Error: libmysqlclient could not be found. Try --with-extra-libs=<dirs>"; exit 1;) +AC_CHECK_HEADERS(netinet/in.h,,echo "-> Error: netinet/in.h could not be found. Try --with-extra-includes=<dirs>"; exit 1;) +AC_CHECK_HEADERS(sys/time.h,,echo "-> Error: sys/time.h could not be found. Try --with-extra-includes=<dirs>"; exit 1;) +AC_CHECK_LIB(ncurses,newwin,,"-> Error: libncurses could not be found. Try --with-extra-libs=<dirs>";exit 1;) +AC_CHECK_HEADERS(ncurses.h,,echo "-> Error ncurses.h could not be found. Try --with-extra-includes=<dirs"; exit1;) +AC_C_CONST +AC_C_INLINE +AC_OUTPUT(Makefile) +echo "You are now ready to compile. Type make" diff --git a/cont.cpp b/cont.cpp new file mode 100755 index 0000000..891c2fa --- /dev/null +++ b/cont.cpp @@ -0,0 +1,24 @@ +// class cont implementation. + +#ifndef CONT_CXX +#define CONT_CXX + +#include "cont.h" +#include "s_mutx.h" + +using namespace std; + +string +cont::get_val( string s_key ) +{ + if ( map_vals.find( s_key ) != map_vals.end() ) + return map_vals[ s_key ]; + return string(); +} + +cont::~cont() +{ + map_vals.~map_string(); +} + +#endif @@ -0,0 +1,29 @@ +// class cont declaration. defines a simple data container class. + +#ifndef CONT_H +#define CONT_H + +#include "incl.h" +#include "hmap.h" + +using namespace std; + +class cont +{ +protected: + map_string map_vals; + +public: + cont::~cont(); + + // small inline methods: + void clear_vals() + { + map_vals.clear(); + } // removes all values. + + // public methods: + virtual string get_val( string s_key ); // get a specific map_vals value. +}; + +#endif @@ -0,0 +1,58 @@ +#ifndef DIR_CPP +#define DIR_CPP + +#include "dir.h" + +using namespace std; + +dir::dir() +{ + p_dir_vec = new vector<string>; +} + +dir::~dir() +{ + p_dir_vec->clear(); +} + + + +bool +dir::open_dir( char *c_dir ) +{ + return open_dir( *new string( c_dir ) ); +} + +bool +dir::open_dir( string &s_dir ) +{ + dp = opendir( s_dir.c_str() ); + + if ( dp == NULL ) + return false; // Could not open dir. + + return true; // Could open dir with success. +} + +void +dir::close_dir() +{ + if ( dp != NULL ) + closedir( dp ); +} + +void +dir::read_dir() +{ + if ( dp != NULL ) + while( ep = readdir( dp ) ) + p_dir_vec->push_back( *new string( ep->d_name ) ); +} + +vector<string>* +dir::get_dir_vec() +{ + return p_dir_vec; +} + +#endif @@ -0,0 +1,32 @@ + +#ifndef DIR_H +#define DIR_H + +#include <stddef.h> +#include <stdio.h> +#include <sys/types.h> +#include <dirent.h> +#include <vector> +#include "incl.h" + +using namespace std; + +class dir +{ +private: + DIR *dp; + struct dirent *ep; + vector<string>* p_dir_vec; + +public: + dir(); + ~dir(); + + bool open_dir( char *c_dir ); + bool open_dir( string &s_dir ); + void close_dir(); + void read_dir(); + vector<string>* get_dir_vec(); +}; + +#endif @@ -0,0 +1,103 @@ +// global variables. + +#ifndef GLOB_H +#define GLOB_H + +#include <map> +#include <pthread.h> + +// definition of boolean values. +#define true 1 +#define false 0 + +// config filename. ( will be searched in ~/.ychat/ and if not found in the working +// directory of ychat ). +#define CONFILE "conf.txt" + +// the hard limit of mysql connections at the samte time in the mysql connection +// manager. +#define MAXMSQL 20 + +// defines the standard value of the init method of the mysql connection manager +// for the mysql server port. +#define PRTMSQL 3306 + +// the highest port which is allowed to use. if ychat is unable to create the server +// socket it will increment the port number and tries to create another socket. +// this procedure will go on until MAXPORT is reached. +#define MAXPORT 65535 + +// max length of a line read from a socket or a file ( config-file, html-template ). +#define READBUF 1024 + +// max length of a char buffer +#define CHARBUF 100 + +// definition for verbosity level ( normal outputs ). see vmsg.h for custumizing all +// the messages. this messages will only printed out by the master thread. +// dont use this until NCURSES is defined! all messages will appear in the +// ncurses interface anyways. +//#define VERBOSE + +// displays important server messages such as socket or fatal errors! +// dont use this until NCURSES is defined! all messages will appear in the +// ncurses interface anyways. +//#define SERVMSG + +// is used for interaction with the ncurses admin interface at stdout. +#define NCURSES + +// The following values define the positions of the data stats in the NCURSES interface. +#ifdef NCURSES +#define NCUR_HITS_X 21 +#define NCUR_HITS_Y 35 +#define NCUR_MYSQL_X 22 +#define NCUR_MYSQL_Y 2 +#define NCUR_PORT_X 21 +#define NCUR_PORT_Y 2 +#define NCUR_SESSION_X 22 +#define NCUR_SESSION_Y 18 +#define NCUR_THREADS_X 21 +#define NCUR_THREADS_Y 18 +#endif + +// Defines the amount of newlines which have to send to the client's +// chat stream the first log-in. ( prevents white screen because of buffers +// or proxies ). +#define PUSHSTR 1000 + +////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT CHANGE ANYTHING BEHIND THIS LINE! +////////////////////////////////////////////////////////////////////////////////////////// + +using namespace std; + +// internal rang descriptors ( their external names may be specified different ) +enum rang +{ + CODER , // programmer. + ADMIN , // administrator. + MAGIC , // super user with special privileges. + SUPER , // temporary super user. + BASIC , // normal user without special privileges. + GUEST , // guest user, has almost no privileges. + RESTR , // a very restrivted user. + OUTBN // banned out of the system. +}; + +// some custom typedefs for datatypes which are needed often. +typedef map<string, string> map_string; +typedef int function( void *v_arg ); + +struct container +{ + void* elem[4]; +}; + +struct dynmod +{ + function *the_func ; + void *the_module; +}; + +#endif diff --git a/hmap.cpp b/hmap.cpp new file mode 100644 index 0000000..37c9019 --- /dev/null +++ b/hmap.cpp @@ -0,0 +1,195 @@ +#ifndef hmap_cpp +#define hmap_cpp + + +#include "hmap.h" + +using namespace std; + +bool is_prime( int n ); +int next_prime( int n ); + +// Construct the hash table. +template <class obj_type, class key_type> +hmap<obj_type, key_type>::hmap( double mop ) + : i_max_occupied_percentage(mop), array( next_prime( 101 ) ) +{ + lookups = 0; + make_empty( ); +} + +// Insert item x into the hash table. If the item is +// already present, do nothing +template <class obj_type, class key_type> +void hmap<obj_type, key_type>::add_elem( const obj_type &x, const key_type &k ) +{ + // Insert x as active + int i_current_pos = find_pos( k ); + if( is_active( i_current_pos ) ) + return; + + array[ i_current_pos ] = hash_entry( x, k, ACTIVE ); + if( ++occupied > array.size( ) * i_max_occupied_percentage ) + rehash( ); +} + +// Expand the hash table. +template <class obj_type, class key_type> +void hmap<obj_type, key_type>::rehash( ) +{ + vector<hash_entry> old_array = array; + + // Create new double-sized, empty table + array.resize( next_prime( 2 * old_array.size( ) ) ); + for( int j = 0; j < array.size( ); j++ ) + array[ j ].info = EMPTY; + + // Copy table over + make_empty( ); + for( int i = 0; i < old_array.size( ); i++ ) + if( old_array[ i ].info == ACTIVE ) + add_elem( old_array[ i ].element, old_array[ i ].key ); +} + +// Hash function, can only handle strings. +// If you want to hash other objects you will have to +// create a hash table for them +template <class obj_type, class key_type> +unsigned int hmap<obj_type, key_type>::hash( const string & key ) const +{ + unsigned int hash_value = 0; + // cout << key << "%"; + + for( size_t i = 0; i < key.size(); i++ ) + hash_value = ( hash_value << 5 ) ^ key[ i ] ^ hash_value; + + return hash_value; +} + +// Method that performs quadratic probing resolution. +// Return the position where the search for x terminates. +template <class obj_type, class key_type> +int hmap<obj_type, key_type>::find_pos( const key_type &k ) +{ + int i_collision_num = 0; + int i_current_pos = hash( k ) % array.size( ); + lookups++; + + while( array[ i_current_pos ].info != EMPTY && + array[ i_current_pos ].key != k ) + { + // cout << array[ i_current_pos ].element << "!=" << x << endl; + lookups++; + i_current_pos += 2 * ++i_collision_num - 1; // Compute ith probe + + if( i_current_pos >= array.size( ) ) + i_current_pos -= array.size( ); + } + + // cout << i_current_pos << " "; + return i_current_pos; +} + +// Remove item x from the hash table. +template <class obj_type, class key_type> +void hmap<obj_type, key_type>::del_elem( const key_type & k ) +{ + int i_current_pos = find_pos( k ); + if( is_active( i_current_pos ) ) + array[ i_current_pos ].info = DELETED; +} + +// Find item x in the hash table. +// Return a pointer to the matching item or 0 if not found +template <class obj_type, class key_type> +obj_type hmap<obj_type, key_type>::get_elem( const key_type &k ) +{ + int i_current_pos = find_pos( k ); + if( is_active( i_current_pos ) ) + return array[ i_current_pos ].element; + else + return 0; +} + +// Make the hash table logically empty. +template <class obj_type, class key_type> +void hmap<obj_type, key_type>::make_empty( ) +{ + occupied = 0; + for( int i = 0; i < array.size( ); i++ ) + array[ i ].info = EMPTY; +} + +// Return true if i_current_pos exists and is active. +template <class obj_type, class key_type> +bool hmap<obj_type, key_type>::is_active( int i_current_pos ) const +{ + return array[ i_current_pos ].info == ACTIVE; +} + + +// Internal method to test if a positive number is prime. +// Not an efficient algorithm. +template <class obj_type, class key_type> +bool hmap<obj_type, key_type>::is_prime( int n ) const +{ + if( n == 2 || n == 3 ) + return true; + + else if( n == 1 || n % 2 == 0 ) + return false; + + for( int i = 3; i * i <= n; i += 2 ) + if( n % i == 0 ) + return false; + + return true; +} + +// Internal method to return a prime number at least as large as n. +// Assumes n > 0. +template <class obj_type, class key_type> +int hmap<obj_type, key_type>::next_prime( int n ) const +{ + if( n % 2 == 0 ) + n++; + + for( ; !is_prime( n ); n += 2 ) + ; + + return n; +} +template<class obj_type, class key_type> +void +hmap<obj_type, key_type>::run_func( void (*func)(obj_type) ) +{ + for( int i = 0; i < array.size( ); i++ ) + if ( array[i].info == ACTIVE ) + ( *func ) ( array[i].element ); +} + +template<class obj_type, class key_type> +void +hmap<obj_type, key_type>::run_func( void (*func)(obj_type, void*), void* v_arg ) +{ + for( int i = 0; i < array.size( ); i++ ) + if ( array[i].info == ACTIVE ) + ( *func ) ( array[i].element, v_arg ); +} + +template<class obj_type, class key_type> +vector<key_type>* +hmap<obj_type, key_type>::get_key_vector() +{ + vector<key_type>* p_vec = new vector<key_type>; + for( int i = 0; i < array.size( ); i++ ) + if ( array[i].info == ACTIVE ) + p_vec->push_back( array[i].key ); + + return p_vec; +} + + + +#endif + @@ -0,0 +1,125 @@ +#pragma warning(disable:4786) + +#ifndef hmap_h +#define hmap_h + +#include <vector> +#include "incl.h" + +using namespace std; + +// void add_elem( obj_type x, key_type k ) --> Insert x +// void del_elem( key_type k ) --> Remove x +// obj_type get_elem( key_type k ) --> Return item that matches x +// void make_empty( ) --> Remove all items + +template <class obj_type, class key_type> +class hmap +{ +private: + enum entry_type + { + ACTIVE, EMPTY, DELETED + }; + + struct hash_entry + { + obj_type element; + key_type key; + entry_type info; + + hash_entry( const obj_type &e = obj_type( ), const key_type &k = key_type( ), entry_type i = EMPTY ) : element( e ), key( k ), info( i ) + { } + } + ; + + int occupied; + + virtual bool is_active( int i_current_pos ) const; + virtual void rehash( ); + virtual bool is_prime ( int n ) const; + virtual int next_prime( int n ) const; + double i_max_occupied_percentage; + +protected: + int lookups; + unsigned int hash( const string &key ) const; + vector<hash_entry> array; + +public: + hmap( double moc ); + + virtual int find_pos ( const key_type &k ); + virtual void make_empty( ); + virtual void add_elem ( const obj_type &x, const key_type &k ); + virtual void del_elem ( const key_type &k ); + virtual obj_type get_elem ( const key_type &k ); + + virtual void run_func( void (*func)(obj_type) ); + virtual void run_func( void (*func)(obj_type, void*), void* v_arg ); + + virtual vector<key_type>* get_key_vector( ); + + // inline: + void get_size() + { + int size = 0; + for( int j = 0; j < array.size( ); j++ ) + if (array[ j ].info == ACTIVE) + size++; + return size; + }; + + int get_lookups() + { + return lookups; + }; + + int get_capacity() + { + return array.size(); + }; + + double get_lambda() + { + return static_cast<double>(get_size())/static_cast<double>(get_capacity()); + } + + obj_type& operator[]( key_type &k ) + { + return get_elem( k ); + } + +}; + +template <class obj_type, class key_type> +class linearhmap : public hmap<obj_type, key_type> +{ +public: + linearhmap(double moc) : hmap<obj_type, key_type>(moc) + {} + ; + + virtual int find_pos( const key_type &k ) + { + int i_collision_num = 0; + int i_current_pos = hash( k ) % array.size( ); + lookups++; + + while( array[ i_current_pos ].info != EMPTY && + array[ i_current_pos ].key != k ) + { + lookups ++; + i_current_pos++; + + if( i_current_pos >= array.size( ) ) + i_current_pos -= array.size( ); + } + + return i_current_pos; + } +}; + +#include "hmap.cpp" + +#endif diff --git a/html.cpp b/html.cpp new file mode 100755 index 0000000..3051212 --- /dev/null +++ b/html.cpp @@ -0,0 +1,170 @@ +// class html implementation. + +#ifndef s_html_CXX +#define s_html_CXX + +#include <fstream> +#include "html.h" +#include "s_chat.h" +#include "s_mutx.h" +#include "s_ncur.h" + +using namespace std; + +html::html( ) +{ + set_name( s_conf::get + ().get_val( "HTMLTEMP" ) ); + pthread_mutex_init( &mut_map_vals, NULL ); +} + +html::~html( ) +{ + pthread_mutex_destroy( &mut_map_vals ); +} + +void +html::clear_cache( ) +{ + pthread_mutex_lock ( &mut_map_vals ); + clear_vals(); + pthread_mutex_unlock( &mut_map_vals ); +} + +string +html::parse( map_string &map_params ) +{ + string s_file = map_params["request"]; + + // check if s_file is in the container. + pthread_mutex_lock ( &mut_map_vals ); + string s_templ = get_val( s_file ); + pthread_mutex_unlock( &mut_map_vals ); + + // if not, read file. + if ( s_templ.empty() ) + { + auto string s_path = get_name(); + auto ifstream fs_templ( s_path.append( s_file ).c_str(), ios::binary ); + + if ( ! fs_templ ) + { + +#ifdef VERBOSE + cerr << NOFOUND << s_path << endl; +#endif +#ifdef NCURSES + + { + string s_tmp( NOFOUND ); + s_tmp.append( s_path ); + s_ncur::get + ().print( s_tmp ); + } +#endif + if(map_params["request"]==s_conf::get + ().get_val( "NOTFOUND" )) + return ""; + + map_params["request"] = s_conf::get + ().get_val( "NOTFOUND" ); + return parse( map_params ); + + } + + auto char c_buf; + while( !fs_templ.eof() ) + { + fs_templ.get( c_buf ); + s_templ+=c_buf; + } + + fs_templ.close(); + +#ifdef VERBOSE + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cout << TECACHE << s_path << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); +#endif +#ifdef NCURSES + + { + string s_tmp( TECACHE ); + s_tmp.append( s_path ); + s_ncur::get + ().print( s_tmp.c_str() ); + } +#endif + + + + // cache file. + pthread_mutex_lock ( &mut_map_vals ); + map_vals[ s_file ] = s_templ; + pthread_mutex_unlock( &mut_map_vals ); + } + + // find %%KEY%% token and substituate those. + auto unsigned int pos[2]; + pos[0] = pos[1] = 0; + + do + { + pos[0] = s_templ.find( "%%", pos[1] ); + + if ( pos[0] == string::npos ) + break; + + pos[0] += 2; + pos[1] = s_templ.find( "%%", pos[0] ); + + if ( pos[0] == string::npos ) + break; + + // get key and val. + auto string s_key = s_templ.substr( pos[0], pos[1]-pos[0] ); + auto string s_val = s_conf::get + ().get_val( s_key ); + + // if s_val is empty use map_params. + if ( s_val.empty() ) + s_val = map_params[ s_key ]; + + // substituate key with val. + s_templ.replace( pos[0]-2, pos[1]-pos[0]+4, s_val ); + + // calculate the string displacement. + auto int i_dif = s_val.length() - ( pos[1] - pos[0] + 4); + + pos[1] += 2 + i_dif; + + } + while( true ); + + return s_templ; +} + +void +html::online_list( user *p_user, map_string &map_params ) +{ + // prepare user_list. + string s_list ( "" ); + string s_seperator( "<br>" ); + + p_user->get_room()->get_user_list( s_list, s_seperator ); + + // use the collected data as a message in html-templates. + map_params["MESSAGE"] = s_list; + + // renew the timestamp. + p_user->renew_stamp(); + + // send a ping to the client chat stream. + p_user->msg_post( new string("\n") ); +} + +#endif + @@ -0,0 +1,42 @@ +// class html declaration. this class manages the html-template files. + +#ifndef s_html_H +#define s_html_H + +#include "incl.h" +#include "cont.h" +#include "s_conf.h" +#include "user.h" +#include "name.h" + + +using namespace std; + +class html : public cont, name +{ +private: + // needed for synchronizing the map_vals. + pthread_mutex_t mut_map_vals; + +public: + // public methods. + explicit html( ); // simple constructor. + ~html( ); + + // clears the template cache so that new html templates will be read + // from hard disk. this method is needed after changeing s.t. on + // the html-template files. + void clear_cache( ); + + // returns a parsed html-template. this method will check first if the + // required html-template exists inside the classes template cache. if not + // then the file will be read from file and added to the cache. + // afterwards the html-template will be parsed and returned. + // map_params contains the client request parameters which also will be + // used for string substituation. + string parse( map_string &map_params ); + + void online_list( user *p_user, map_string &map_params ); +}; + +#endif diff --git a/html/frameset.html b/html/frameset.html index fe6b973..84a95ef 100755 --- a/html/frameset.html +++ b/html/frameset.html @@ -4,16 +4,16 @@ %%PGETITLE%% </title> </head> - <frameset rows="*,60"> + <frameset rows="*,70"> <noframes> Your browser does not support frames, </noframes> <frameset cols="*,150"> - <frame src="stream.html?event=stream&nick=%%nick%%&tmpid=%%tmpid%%" name="stream"> - <frame src="online.html?event=online&nick=%%nick%%&tmpid=%%tmpid%%" name="online"> + <frame src="stream.html?event=stream&tmpid=%%tmpid%%" name="stream"> + <frame src="online.html?event=online&tmpid=%%tmpid%%" name="online"> </frameset> <frameset rows="*,0"> - <frame src="input.html?event=input&nick=%%nick%%&tmpid=%%tmpid%%" name="input"> + <frame src="input.html?event=input&tmpid=%%tmpid%%" name="input"> <frame src="blank.html" name="blank"> </frameset> </frameset> diff --git a/html/help.html b/html/help.html index ad9a25f..0a3b418 100755 --- a/html/help.html +++ b/html/help.html @@ -1,28 +1,23 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title> - Chat-help - %%ychat.version%% + Chat-help - %%PGETITLE%% </title> <link rel=stylesheet href="style.css" type=text/css> </head> -<body> +<body bgcolor=#000000 text=#ffff00> <table align=center width=500> <tr><td> - Hello %%nick%%, all chat commands available are summarized below (Please notice that only currently - in memory loaded command modules are listed here which should be the case by yChat default configuration). You can also access help for a specific command with the /help command. Example: /help commandname: + Hello %%nick%%, all chat commands available are summarized below: </td></tr> <tr><td> <br> +<table> %%content%% +</table> </td></tr> </table> <br><br> - <center> - <span class="signature"> - yChat is OpenSource - get it at <a class="fancy" target="_blank" href="http://www.yChat.org">http://www.yChat.org</a> - </span> - </center> +<center><span class="signature">yChat is OpenSource - get it at <a target="_blank" href="http://www.yChat.org">http://www.yChat.org</a></span></center> </body> </html> diff --git a/html/index.html b/html/index.html index 7bc01b0..0549ac5 100755 --- a/html/index.html +++ b/html/index.html @@ -19,9 +19,9 @@ Enter your nick: <form action="frameset.html" method="GET"> <input type="hidden" name="event" value="login"> - <input type="hidden" name="room" value="%%STRDROOM%%"> - <input type="text" name="nick"> - <input type="submit" value="login"> + <input type="hidden" name="room" accesskey="r" value="%%STRDROOM%%"> + <input type="text" name="nick" accesskey="n"> + <input type="submit" value="login" accesskey="s"> </form> </td> </tr> diff --git a/html/input.html b/html/input.html index a403d8e..a49cb13 100755 --- a/html/input.html +++ b/html/input.html @@ -4,7 +4,6 @@ %%PGETITLE%% </title> <link rel=stylesheet href="style.css" type=text/css> - <script language="JavaScript"> <!-- function delout() @@ -18,17 +17,29 @@ { document.input.message.select(); } + function popup(site,width,height) + { + var left = (screen.availWidth-width)/2; + var top = (screen.availHeight-height)/2; + var win = window.open(site,"_blank","width="+width+",height="+height+",left="+left+",top="+top+",scrollbars=yes"); + } //--> </script> </head> <body bgcolor=#000000 text=#ffffff> + <table> + <tr><td> <form name="input" action="input.html" target="blank" onsubmit="return delout();"> <input type="hidden" name="event" value="post"> - <input type="hidden" name="nick" value="%%nick%%"> <input type="hidden" name="tmpid" value="%%tmpid%%"> <input type="text" name="message" size="50"> - <input type="submit" value="send"> - <input type="button" value="select" onclick="javascript:selectinput();"> + <input type="submit" value="send" accesskey='s'> + <input type="button" value="select" accesskey='e' onclick="javascript:selectinput();"> </form> + </td> + <td> + <a href='#' onclick="javascript:popup('help.html?event=help&tmpid=%%tmpid%%', 576, 480)">Help</a> + </td></tr> + </table> </body> </html> @@ -0,0 +1,18 @@ +// contains header files which are included by all classes. + +// include some std headers. +#include <iostream> + +// since thread synchronization is a big issue this header needs +// to be included by every other file too. +#include <pthread.h> + +#include <ncurses.h> + +// std::string. +#include <string> + +// include all the custom global variables. +#include "glob.h" +// include all the custom messages. +#include "msgs.h" diff --git a/lang.cpp b/lang.cpp new file mode 100755 index 0000000..be73354 --- /dev/null +++ b/lang.cpp @@ -0,0 +1,79 @@ +// class conf implementation. + +#ifndef s_lang_CXX +#define s_lang_CXX + +#include <fstream> +#include "lang.h" + +using namespace std; + +lang::lang( string s_lang = "en" ) : name( s_lang ) +{ + parse( ); // parse the config file. +} + +lang::~lang() +{} + +void +lang::parse() +{ +#ifdef VERBOSE + cout << CFILEOK << get_name() << endl; +#endif + + string filename("lang/"); + filename.append(get_name()); + + ifstream fs_conf( filename.c_str() ); + + if ( ! fs_conf ) + { +#ifdef VERBOSE + cout << CFILENO << get_name() << endl; +#endif + + return; + } + + char c_buf[READBUF]; + + while( fs_conf.getline( c_buf, READBUF ) ) + { + string s_token( c_buf ); + unsigned int ui_pos = s_token.find( "#", 0 ); + + // if line is commented out: + if ( ui_pos == 0 ) + continue; + + ui_pos = s_token.find( ";", 0 ); + + // if token has not been found. + if ( ui_pos == string::npos ) + continue; + + s_token = s_token.substr( 0 , --ui_pos ); + ui_pos = s_token.find ( "\"", 0 ); + + if ( ui_pos == string::npos ) + continue; + + string s_val = s_token.substr( ui_pos+1, s_token.length() ); + string s_key = s_token.substr( 0 , --ui_pos ); + +#ifdef VERBOSE2 + + cout << s_key << "=" << s_val << endl; +#endif + + // fill the map. + map_vals[s_key] = s_val; + } + + fs_conf.close(); + fs_conf.~ifstream(); +} + +#endif @@ -0,0 +1,24 @@ +// class conf declaration. this class parses the server config file. + +#ifndef s_lang_H +#define s_lang_H + +#include "incl.h" +#include "cont.h" +#include "name.h" + +using namespace std; + +class lang : public cont, name +{ +private: + +public: + // public methods: + lang ( string s_lang ); // standard constructor. + ~lang(); // standard destructor. + + virtual void parse( ); // parses the config file. +}; + +#endif @@ -1,3 +1,11 @@ ERRORCMD="<font color=#ff0000>Befehl nicht gefunden!</font><br>"; USERENTR=" betritt den Chat.<br>"; -USERLEAV=" verläßt den Chat.<br>" +USERLEAV=" verläßt den Chat.<br>"; + +# Chat-help ( || separiert Befehlssyntax und Befehlsbeschreibung. ) +mods/commands/yc_col.so="/col NICKFARBE TEXTFARBE||Ändern der Farbe"; +mods/commands/yc_me.so="/me AKTIONSTEXT||Schreibt den Text kursiv ( einfarbig )"; +mods/commands/yc_m.so="/m AKTIONSTEXT||Schreibt den Text kursiv ( zweifarbig )"; +mods/commands/yc_version.so="/version||Zeigt die Version des laufenden yChats"; +mods/commands/yc_q.so="/q||Verlassen des Chats"; + @@ -1,3 +1,10 @@ ERRORCMD=" <font color='#FF0000'>No such command!</font><br>"; USERENTR=" enters the chat<br>"; USERLEAV=" leaves the chat<br>"; + +# Chat-Hilfe ( || seperates command syntax and command description. ) +mods/commands/yc_col.so="/col NICKCOLOR TEXTCOLOR||Changing the color"; +mods/commands/yc_me.so="/me ACTIONTEXT||Writes the text italic ( one color )"; +mods/commands/yc_m.so="/m ACTIONTEXT||Writes the text italic ( two colors )"; +mods/commands/yc_version.so="/version||Shows version of the running yChat"; +mods/commands/yc_q.so="/q||Leaving the chat"; diff --git a/logd.cpp b/logd.cpp new file mode 100644 index 0000000..5a7fa82 --- /dev/null +++ b/logd.cpp @@ -0,0 +1,82 @@ +#ifndef LOGD_CXX +#define LOGD_CXX + +#include "s_ncur.h" +#include "glob.h" +#include "logd.h" + +logd::logd( string filename ) +{ + if(filename.empty()) + { +#ifdef NCURSES + s_ncur::get + ().print( LOGERR2 ); +#endif +#ifdef SERVMSG + cerr << LOGERR2 << endl; +#endif + exit(1); + } + + s_logfile=filename; + + i_lines=s_tool::string2int( s_conf::get + ().get_val("LOG_LINES")); + +} +void logd::flush() +{ + s_output.open(s_logfile.c_str(), ios::app); + + if(s_output==NULL) + { +#ifdef NCURSES + string s_tmp( LOGERR1 ); + s_tmp.append( s_logfile ); + s_ncur::get + ().print( s_tmp.c_str() ); +#endif +#ifdef SERVMSG + cerr << LOGERR1 << s_logfile << endl; +#endif + exit(1); + } + + + while(!s_queue.empty()) + { + string s_l=s_queue.front(); + s_queue.pop(); + s_output.write(s_l.c_str(), s_l.size()); + + } + s_output.close(); +} +void logd::log( map_string request ) +{ + struct tm *t_m; + time_t t_cur=time(NULL); + t_m=gmtime(&t_cur); + + char buffer[100]; + strftime(buffer, 100, "[%d/%b/%Y:%H:%M:%S %z]", t_m); + string s_time=buffer; + string s_logstr = request["REMOTE_ADDR"] + " - - "+s_time+" \"" + request["QUERY_STRING"]+"\" 200 0 \""+request["request"]+"\" \""+request["User-Agent"]+"\"\n"; + + s_queue.push(s_logstr); + + if(s_queue.size()>=i_lines) + flush(); +} + +logd::~logd() +{ + flush(); +} + + + + + +#endif @@ -0,0 +1,25 @@ +#ifndef LOGD_H +#define LOGD_H + +#include "incl.h" +#include "s_tool.h" +#include "s_conf.h" +#include <fstream> +#include <queue> +#include <time.h> +class logd +{ + +private: + string s_logfile; + queue<string> s_queue; + ofstream s_output; + int i_lines; +public: + logd( string filename ); + ~logd(); + + void flush(); + void log( map_string request ); +}; +#endif diff --git a/main.cpp b/main.cpp new file mode 100755 index 0000000..b59b628 --- /dev/null +++ b/main.cpp @@ -0,0 +1,124 @@ +/* + * yChat++; Contact: www.yChat.org; Mail@yChat.org + * Copyright (C) 2003 Paul C. Buetow, Volker Richter + * ----------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <unistd.h> + +// needed for ignoring SIGPIPE. +#include <signal.h> + +// include header files which are included from every class too. +#include "incl.h" + +// include the chat manager. +#include "s_chat.h" + +// include the config manager. +#include "s_conf.h" + +// include the html-template manager. +#include "s_html.h" + +// include the mutex manager for global synchronization. +#include "s_mutx.h" + +// include the module loader manager for global synchronization. +#include "s_modl.h" + +// include the socket manager. +#include "s_sock.h" + +// include the language manager. +#include "s_lang.h" + +// include the ncurses admin menu. +#include "s_ncur.h" + +// include the session manager. +#include "s_sman.h" + +// include the MySQL Connection Manager. +#include "s_mman.h" + +using namespace std; + +int main() +{ +#ifdef VERBOSE + cout << " ___ _ _ " << endl + << " _ _ / __\\ |__ __ _| |_ " << endl + << "| | | |/ / | '_ \\ / _` | __|" << endl + << "| |_| / /___| | | | (_| | |_ " << endl + << " \\__, \\____/|_| |_|\\__,_|\\__|" << endl + << " |___/ " << endl << endl + + << DESCRIP << endl + << VERSION << ", " + << CONTACT << endl + << SEPERAT << endl + << STARTMS << endl ; +#endif + + // ignore SIGPIPE. otherwise the server will shut down with "Broken pipe" if + // a client unexpected disconnects himself from a SOCK_STREAM. + signal( SIGPIPE, SIG_IGN ); + + // all the static data classes have to be initialized once. otherwise they will + // contain only empty pointers and the chat server won't work correctly. + // the order of the initializations is very importand. for example the s_html::init() + // invokations assumes an initialized s_conf class. + s_mutx::init(); // init the mutex manager. + s_conf::init(); // init the config manager. + s_html::init(); // init the html-template manager. + s_lang::init(); // init the language manager + s_sman::init(); // init the session manager. + s_mman::init(); // init the mysql connection manager. + s_sock::init(); // init the socket manager. + s_chat::init(); // init the chat manager. + + // begin to draw the ncurses amdin interface in a new pthread. +#ifdef NCURSES + + s_ncur::init(); // init the ncurses admin interface. + pthread_t admin_thread; + pthread_create( &admin_thread, + NULL, + s_ncur::get().start, (void*) &s_ncur::get() ); + + // wait until ncurses interface has been initialized. + while ( ! s_ncur::get().is_ready() ) + usleep(100); +#endif + + + + s_modl::init(); // init the module-loader manager. + + // start the socket manager. this one will listen for incoming http requests and will + // forward them to the specified routines which will generate a http response. + s_sock::get().start(); + + +#ifdef VERBOSE + cout << DOWNMSG << endl; +#endif + + return 0; +} diff --git a/mcon.cpp b/mcon.cpp new file mode 100644 index 0000000..bdea95e --- /dev/null +++ b/mcon.cpp @@ -0,0 +1,40 @@ +#ifndef MCON_CXX +#define MCON_CXX + +#include "mcon.h" + +mcon::mcon( MYSQL *mysql ) +{ + this->query_sent=false; + if(mysql==NULL) + cerr << "Warning: mysql seems 0" << endl; + this->myc=mysql; +} +mcon::~mcon() +{ + if(this->query_sent) + mysql_free_result(this->current_result); +} +int mcon::query( string query ) +{ + mysql_real_query( this->myc, query.c_str(), query.size() ); + + if(mysql_error(this->myc)[0] != '\0') + { + cerr << "MySQL error occured: " << mysql_error(this->myc) << endl; + return -1; + } + this->query_sent=true; + + this->current_result=mysql_store_result( this->myc ); +} +MYSQL_ROW mcon::get_next_row() +{ + if(query_sent) + { + return mysql_fetch_row( this->current_result ); + } + + return NULL; +} +#endif @@ -0,0 +1,24 @@ +#ifndef MCON_H +#define MCON_H + +#include <mysql/mysql.h> +#include <string> +#include <iostream> + +using namespace std; + +class mcon +{ + +private: + bool query_sent; + MYSQL_RES *current_result; +public: + MYSQL *myc; + mcon( MYSQL *mysql ); + ~mcon(); + int query(string query); + MYSQL_ROW get_next_row(); + +}; +#endif diff --git a/menu.cpp b/menu.cpp new file mode 100755 index 0000000..c2b277b --- /dev/null +++ b/menu.cpp @@ -0,0 +1,115 @@ +#ifndef MENU_CXX +#define MENU_CXX + +#include "menu.h" +#include "s_sock.h" + +using namespace std; + +menu::menu( int i_startx, int i_starty, int i_width, int i_height, char *c_header, char **choices, int i_numchoices, const chtype ch ) +{ + this->i_startx = i_startx; + this->i_starty = i_starty; + this->i_height = i_height; + this->i_width = i_width; + this->c_header = c_header; + this->choices = choices; + this->i_numchoices = i_numchoices; + + initialize( ch ); +} + +menu::~menu() +{ + /* + wborder(win, ' ', ' ', ' ',' ',' ',' ',' ',' '); + wrefresh(win); + delwin(win); + */ +} + +void +menu::initialize( const chtype ch ) +{ + this->i_highlight = 1; + this->i_choice = 0; + + win = newwin( i_height, i_width, i_starty, i_startx ); + wbkgd(win, ch); + + keypad(win, TRUE); +} + +void +menu::display() +{ + int x, y, i; + + x = 2; + y = 2; + + box( win, 0, 0 ); + mvwprintw( win, y++, x, "%s", c_header ); + + for( i=0; i<i_numchoices; i++ ) + { + y++; + + if( i_highlight == i + 1 ) /* High light the present choice */ + { + wattron( win, A_REVERSE); + mvwprintw( win, y, x, "%d. %s", i, choices[i]); + wattroff( win, A_REVERSE); + } + else + { + mvwprintw( win, y, x, "%d. %s", i, choices[i]); + } + } + + wrefresh( win ); +} + +void +menu::start( void (*swich_case_menu_action)(int) ) +{ + refresh(); + bool b_flag = 1; + + while( b_flag ) + { + display(); + c = wgetch( win ); + + switch(c) + { + case KEY_UP: + if( i_highlight == 1 ) + i_highlight = i_numchoices; + else + --i_highlight; + break; + + case KEY_DOWN: + if( i_highlight == i_numchoices ) + i_highlight = 1; + else + ++i_highlight; + break; + + case 10: + i_choice = i_highlight; + break; + + default: + mvprintw( 1, 70, "%3d %c", c, c); + refresh(); + break; + } + + // Menu action. + ( *swich_case_menu_action ) ( i_choice ); + + } +} +#endif @@ -0,0 +1,30 @@ +#ifndef MENU_H +#define MENU_H + +#include <ncurses.h> +#include "incl.h" + +using namespace std; + +class menu +{ +private: + char **choices; + char *c_header; + + int i_startx, i_starty, i_width, i_height, i_highlight, i_choice, + i_numchoices, c; + + WINDOW *win; + + void initialize( const chtype ch ); + +public: + explicit menu( int i_startx, int i_starty, int i_width, int i_height, char *c_header, char **choices, int i_numchoices, const chtype ch ); + ~menu( ); + + void display(); + void start( void (*swich_case_menu_action)(int) ); +}; + +#endif diff --git a/mman.cpp b/mman.cpp new file mode 100644 index 0000000..5576723 --- /dev/null +++ b/mman.cpp @@ -0,0 +1,190 @@ +#ifndef MMAN_CXX +#define MMAN_CXX + +#include "mman.h" +#include "mcon.h" +#include "mcon.h" +#include "s_mutx.h" +#include "s_ncur.h" +#include "s_tool.h" + +using namespace std; + +mman::mman(int i_initial, int i_max) +{ + pthread_mutex_init( &mut_i_used_con , NULL); + + this->i_used_connections=0; + + if( i_max > MAXMSQL ) + { +#ifdef VERBOSE + cerr << MYLIMIT << MAXMSQL << endl; +#endif + + i_max = MAXMSQL; + + } + + if( i_initial > i_max ) + i_initial = i_max; + + this->i_initial_connections = i_initial; + this->i_max_connections = i_max; + +#ifdef VERBOSE + cout << MYINITC << i_initial << endl + << MYINITM << i_max << endl; +#endif +} +void mman::init( string host, string user, string passwd, string db, unsigned int port) +{ + this->s_host=host; + this->s_user=user; + this->s_pass=passwd; + this->s_db=db; + this->i_port=port; + + for(int i=0; i<this->i_initial_connections;i++) + this->mysql.push_back(new_connection( )); + +} + +#ifdef NCURSES +void +mman::print_init_ncurses() +{ + string s_tmp( MYINITC ); + s_tmp.append( s_tool::int2string( i_initial_connections ) ); + s_ncur::get + ().print( s_tmp ); + + string s_tmp2( MYINITM ); + s_tmp2.append( s_tool::int2string( i_max_connections ) ); + s_ncur::get + ().print( s_tmp2 ); + print_used_connections(1); +} +void +mman::print_used_connections( bool b_refresh ) +{ + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + mvprintw( NCUR_MYSQL_X,NCUR_MYSQL_Y, "MySQL: %d ", i_used_connections); + if ( b_refresh ) + refresh(); + pthread_mutex_unlock( &s_mutx::get().mut_stdout ); +} +#endif + +mman::~mman() +{ + + for(int i = 0; i < this->mysql.size();i++) + { + if(this->mysql[i] != NULL) + mysql_close(this->mysql[i]); + } + + pthread_mutex_destroy( &mut_i_used_con ); +} +MYSQL *mman::get_connection() +{ + if(!this->mysql.empty()) + { + MYSQL *x=this->mysql[this->mysql.size()-1]; + this->mysql.pop_back(); + if(mysql_ping(x)==0) + { + pthread_mutex_lock ( &mut_i_used_con ); + this->i_used_connections--; +#ifdef NCURSES + print_used_connections(1); +#endif + pthread_mutex_unlock( &mut_i_used_con ); + mysql_close(x); + return new_connection(); + } + return x; + } + +#ifdef NCURSES + { + s_ncur::get + ().print( MYERROR ); + } +#endif +#ifdef SERVMSG + cerr << MYERROR << endl; +#endif + + return NULL; +} +MYSQL *mman::new_connection( ) +{ + + pthread_mutex_lock ( &mut_i_used_con ); + if(this->i_used_connections>this->i_max_connections) + { +#ifdef NCURSES + s_ncur::get().shutdown(); + cerr << MYERRO2 << endl; +#endif +#ifdef SERVMSG + cerr << MYERRO2 << endl; +#endif + return NULL; + } + pthread_mutex_unlock( &mut_i_used_con ); + + MYSQL *ms = mysql_init(NULL); + if(!ms) + { +#ifdef NCURSES + s_ncur::get().shutdown(); + cerr << MYERRO1 << endl; +#endif +#ifdef SERVMSG + cerr << MYERRO1 << endl; +#endif + exit(1); + } + if(mysql_real_connect( ms, this->s_host.c_str(), this->s_user.c_str(), this->s_pass.c_str(), this->s_db.c_str() + , this->i_port, NULL, 0 )==NULL) + { +#ifdef NCURSES + s_ncur::get().shutdown(); + cerr << MYMANAG << mysql_error(ms) << endl; +#endif +#ifdef SERVMSG + cerr << MYMANAG << mysql_error(ms) << endl; +#endif + exit(1); + } + + pthread_mutex_lock ( &mut_i_used_con ); + this->i_used_connections++; +#ifdef NCURSES + print_used_connections(0); +#endif + pthread_mutex_unlock( &mut_i_used_con ); + return ms; +} +void mman::free_connection( MYSQL *msql) +{ + pthread_mutex_lock ( &mut_i_used_con ); + this->i_used_connections--; +#ifdef NCURSES + print_used_connections(1); +#endif + pthread_mutex_unlock( &mut_i_used_con ); + + if(mysql_ping( msql )==0) + { + mysql_close( msql ); + this->mysql.push_back( msql ); + } + else + this->mysql.push_back( new_connection() ); +} + +#endif @@ -0,0 +1,38 @@ +#ifndef MMAN_H +#define MMAN_H + +#include <mysql/mysql.h> +#include <string> +#include <vector> +#include "glob.h" +#include "mcon.h" + +using namespace std; +class mman +{ +private: + vector<MYSQL *> mysql; + string s_host; + string s_user; + string s_pass; + string s_db; + unsigned int i_port; + int i_initial_connections; + int i_max_connections; + int i_used_connections; + + pthread_mutex_t mut_i_used_con; +public: + mman(int initial, int max); + ~mman(); + void init( string host, string user, string passwd, string db, unsigned int port = PRTMSQL ); + MYSQL *get_connection(); + MYSQL *new_connection( ); + void free_connection( MYSQL *msql ); +#ifdef NCURSES + void print_init_ncurses(); + void print_used_connections( bool b_refresh ); +#endif + +}; +#endif diff --git a/modl.cpp b/modl.cpp new file mode 100755 index 0000000..9ca0f86 --- /dev/null +++ b/modl.cpp @@ -0,0 +1,178 @@ +// class modl implementation. + +#ifndef MODL_CPP +#define MODL_CPP + +#include <limits.h> +#include <stdlib.h> +#include <dlfcn.h> +#include <stdio.h> + +#include "s_conf.h" +#include "s_mutx.h" +#include "s_ncur.h" +#include "modl.h" +#include "dir.h" + +using namespace std; + +modl::modl( ) +{ + map_mods = new hmap<dynmod*,string>(80); + pthread_mutex_init( &mut_map_mods, NULL ); + + if ( s_conf::get().get_val( "PRE_MODS_COMMANDS" ).compare( "ON" ) == 0 ) + preload_modules( new string("mods/commands/") ); + + if ( s_conf::get().get_val( "PRE_MODS_HTML" ).compare( "ON" ) == 0 ) + preload_modules( new string("mods/html/") ); +} + +modl::~modl() +{ + pthread_mutex_lock ( &mut_map_mods ); + + // dlclose all the_module's first! + map_mods->run_func ( &modl::dlclose_ ); + + // then clean the hash map. + map_mods->make_empty ( ); + + pthread_mutex_unlock ( &mut_map_mods ); + pthread_mutex_destroy( &mut_map_mods ); +} + +void +modl::preload_modules( string *p_path ) +{ + dir* p_dir = new dir(); + p_dir->open_dir( *p_path ); + p_dir->read_dir(); + + vector<string>* p_dir_vec = p_dir->get_dir_vec(); + + if ( ! p_dir_vec->empty() ) + { + vector<string>::iterator iter = p_dir_vec->begin(); + + do + { + if ( iter->length() >= 3 && iter->compare( iter->length()-3, 3, ".so" ) == 0 ) + cache_module( *p_path + *iter ); + } + while ( ++iter != p_dir_vec->end() ); + } + p_dir->close_dir(); + p_dir->~dir(); +} + +void +modl::dlclose_( dynmod* mod ) +{ + dlclose( mod->the_module ); +} + +dynmod* +modl::cache_module( string s_name ) +{ + void *the_module = NULL; + function *the_func = NULL; + + the_module = dlopen( s_name.c_str(), RTLD_NOW ); + + if ( the_module == NULL ) + { + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); +#ifdef NCURSES + + s_ncur::get + ().print( dlerror() ); +#else + + cerr << "dlerror: " << dlerror() << endl; +#endif + + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + return NULL; + } + + the_func = (function*) dlsym( the_module, "extern_function" ); + + if ( the_func == NULL ) + { + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); +#ifdef NCURSES + + s_ncur::get + ().print( dlerror() ); +#else + + cerr << "dlerror: " << dlerror() << endl; +#endif + + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + return NULL; + } + +#ifdef VERBOSE + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cout << MODULEC << s_name << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); +#endif +#ifdef NCURSES + + { + string s_tmp( MODULEC ); + s_tmp.append( s_name ); + s_ncur::get + ().print( s_tmp.c_str() ); + } +#endif + + dynmod *mod = new dynmod; // encapsulates the function and module handler. + mod->the_func = the_func ; // the function to execute + mod->the_module = the_module; // the module handler to close if function + // is not needed anymore. + pthread_mutex_lock ( &mut_map_mods ); + map_mods->add_elem ( mod, s_name ); + pthread_mutex_unlock( &mut_map_mods ); + + // DO NOT CLOSE AS LONG THERE EXIST A POINTER TO THE FUNCTION + // dlclose( module ); + + return mod; +} + +dynmod* +modl::get_module( string s_name ) +{ +#ifdef VERBOSE + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cout << MODULER << s_name << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); +#endif +#ifdef NCURSES + + { + string s_tmp( MODULER ); + s_tmp.append( s_name ); + s_ncur::get + ().print( s_tmp.c_str() ); + } +#endif + pthread_mutex_lock ( &mut_map_mods ); + dynmod* mod = map_mods->get_elem( s_name ); + pthread_mutex_unlock( &mut_map_mods ); + + return ! mod ? cache_module( s_name ) : mod; +} + +#endif @@ -0,0 +1,32 @@ +// class modl declaration. + +#ifndef MODL_H +#define MODL_H + +#include "incl.h" +#include "hmap.h" + +using namespace std; + + +class modl +{ +private: + hmap<dynmod*,string>* map_mods; + pthread_mutex_t mut_map_mods; + + static void dlclose_( dynmod* mod ); + dynmod* cache_module ( string s_name ); + void preload_modules( string *p_path ); + +public: + modl(); + ~modl(); + + dynmod* get_module ( string s_name ); + + hmap<dynmod*,string>* + get_map_mods() { return map_mods; } +}; + +#endif diff --git a/mods/commands/yc_col.cpp b/mods/commands/yc_col.cpp new file mode 100644 index 0000000..5b07c8b --- /dev/null +++ b/mods/commands/yc_col.cpp @@ -0,0 +1,84 @@ +#include <iostream> +#include "../../conf.h" +#include "../../room.h" +#include "../../user.h" +#include "../../s_tool.cpp" +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +typedef vector<string> str_vector; + +extern "C" { + export int extern_function(void *v_arg); + int valid_color( string ); + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + +// string *s_command_line=(string *)c->elem[0]; // contains the whole line + user *p_user = (user*)c->elem[1]; // the corresponding user + str_vector *params= (str_vector*) c->elem[2]; // param array + + string s_color; + string s_color2; + + conf* p_conf = (conf*) c->elem[3]; + + if ( params->empty() ) + { + s_color = p_conf->get_val( "USERCOL1" ); + s_color2 = p_conf->get_val( "USERCOL2" ); + } + + else + { + s_color = (string) params->front(); + params->erase( params->begin() ); + if ( ! params->empty() ) + s_color2 = (string) params->front(); + else + s_color2 = p_conf->get_val( "USERCOL2" ); + } + + s_color = s_tool::to_lower( s_color ); + s_color2 = s_tool::to_lower( s_color2 ); + + if( valid_color(s_color) != 1 ) + { + string *answerstring=new string(s_color + " is not a valid color.<br>\n"); + p_user->msg_post( answerstring ); + } + else if( valid_color(s_color2) != 1 ) + { + string *answerstring=new string( s_color2 + " is not a valid color.<br>\n"); + p_user->msg_post( answerstring ); + } + else + { + string *answerstring=new string(p_user->get_colored_name()+ " changes color to <font color=\"#" + + s_color + "\">" + s_color + "</font> <font color=\"#" + + s_color2 + "\">" + s_color2 + "</font><br>\n"); + p_user->get_room()->msg_post( answerstring ); + p_user->set_col1(s_color); + p_user->set_col2(s_color2); + } + } + int valid_color( string s_color ){ + + if(s_color.size()!=6) return 0; + string valid="abcdef0123456789"; + for(int i=0;i<s_color.size();i++) + { + string s_char=s_color.substr(i,1); + if(valid.find(s_char)==string::npos) + return 0; + } + return 1; + } + +} + diff --git a/mods/commands/yc_m.cpp b/mods/commands/yc_m.cpp new file mode 100644 index 0000000..46b158f --- /dev/null +++ b/mods/commands/yc_m.cpp @@ -0,0 +1,38 @@ +#include <iostream> +#include "../../user.h" +#include "../../room.h" +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +typedef vector<string> str_vector; + +extern "C" { + export int extern_function(void *v_arg); + int valid_color( string ); + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + + user *p_user = (user*) c->elem[1]; // the corresponding user + str_vector *params= (str_vector*) c->elem[2]; // param array + + string s_msg = "<i>" + p_user->get_colored_name() + + " <font color=\"#" + p_user->get_col2() + + "\">"; + if ( ! params->empty() ) + { + str_vector::iterator iter = params->begin(); + for ( iter = params->begin(); iter != params->end(); iter++ ) + s_msg.append( *iter + " " ); + } + + s_msg.append( "</font></i><br>\n" ); + p_user->get_room()->msg_post( &s_msg ); + + } +} + diff --git a/mods/commands/yc_me.cpp b/mods/commands/yc_me.cpp new file mode 100644 index 0000000..5ba5298 --- /dev/null +++ b/mods/commands/yc_me.cpp @@ -0,0 +1,38 @@ +#include <iostream> +#include "../../user.h" +#include "../../room.h" +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +typedef vector<string> str_vector; + +extern "C" { + export int extern_function(void *v_arg); + int valid_color( string ); + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + + user *p_user = (user*) c->elem[1]; // the corresponding user + str_vector *params= (str_vector*) c->elem[2]; // param array + + string s_msg = "<i><font color=\"#" +p_user->get_col1() + "\">" + + p_user->get_name() + " "; + + if ( ! params->empty() ) + { + str_vector::iterator iter = params->begin(); + for ( iter = params->begin(); iter != params->end(); iter++ ) + s_msg.append( *iter + " " ); + } + + s_msg.append( "</font></i><br>\n" ); + p_user->get_room()->msg_post( &s_msg ); + + } +} + diff --git a/mods/commands/yc_q.cpp b/mods/commands/yc_q.cpp new file mode 100644 index 0000000..5776522 --- /dev/null +++ b/mods/commands/yc_q.cpp @@ -0,0 +1,25 @@ +#include <iostream> +#include "../../user.h" + +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + + +extern "C" { + export int extern_function(void *v_arg); + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + string *sCommandLine=(string *)c->elem[0]; + user *p_user = (user*)c->elem[1]; + + string *quitstring=new string("<script language=JavaScript>top.location.href='/index.html';</script>"); + p_user->msg_post( quitstring ); + p_user->set_online(false); + } +} + diff --git a/mods/commands/yc_template.cpp b/mods/commands/yc_template.cpp new file mode 100644 index 0000000..13be617 --- /dev/null +++ b/mods/commands/yc_template.cpp @@ -0,0 +1,29 @@ +#include <iostream> +#include "../../user.h" + +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +typedef vector<string> str_vector; + +extern "C" { + export int extern_function(void *v_arg); + + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + + string *sCommandLine=(string *)c->elem[0]; // contains the whole line + user *p_user = (user*)c->elem[1]; // the corresponding user + str_vector *params=(str_vector*)c->elem[2]; // param array + + + string *quitstring=new string("Text to send<br>"); + p_user->msg_post( quitstring ); + } +} + diff --git a/mods/commands/yc_test.cpp b/mods/commands/yc_test.cpp new file mode 100644 index 0000000..deb3e54 --- /dev/null +++ b/mods/commands/yc_test.cpp @@ -0,0 +1,12 @@ +#include <iostream> + +using namespace std; + +extern "C" { + export int function(void *v_arg); + + int function(void *v_arg) + { + cout << "Hallo " << (char*)v_arg << endl; + } +} diff --git a/mods/commands/yc_version.cpp b/mods/commands/yc_version.cpp new file mode 100644 index 0000000..4ab7673 --- /dev/null +++ b/mods/commands/yc_version.cpp @@ -0,0 +1,22 @@ +#include <iostream> +#include "../../msgs.h" +#include "../../user.h" +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +extern "C" { + export int extern_function(void *v_arg); + int valid_color( string ); + + int extern_function(void *v_arg) + { + container *c=(container *)v_arg; + + user *p_user = (user*)c->elem[1]; // the corresponding user + p_user->msg_post( new string( *new string(VERSION) + "<br>\n") ); + } +} + diff --git a/mods/compile.sh b/mods/compile.sh new file mode 100755 index 0000000..2d2bd6f --- /dev/null +++ b/mods/compile.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +rm */*.so 2> /dev/null + +for i in */*cpp +do + echo Compiling $i + gcc -shared -o $(echo $i | sed s/cpp$/so/) $i +done diff --git a/mods/html/yc_help.cpp b/mods/html/yc_help.cpp new file mode 100644 index 0000000..a746004 --- /dev/null +++ b/mods/html/yc_help.cpp @@ -0,0 +1,45 @@ +#include <iostream> +#include <string> +#include "../../glob.h" +#include "../../hmap.h" +#include "../../lang.h" + +/* + gcc -shared -o yc_name.so yc_name.cpp +*/ + +using namespace std; + +extern "C" { + export int extern_function(void *v_arg); + + int extern_function(void *v_arg) + { + container* c = (container*) v_arg; + string* s_content = &(*((map_string*) c->elem[2]))["content"]; + lang* p_lang = (lang*) c->elem[0]; + + vector<string>* p_vec_keys = + ((hmap<dynmod*,string>*) c->elem[1])->get_key_vector(); + + sort(p_vec_keys->begin(), p_vec_keys->end()); + vector<string>::iterator p_vec_keys_iter = p_vec_keys->begin(); + + while( p_vec_keys_iter != p_vec_keys->end() ) { + if ( p_vec_keys_iter->find( "mods/commands/", 0 ) != string::npos ) + { + s_content->append( "<tr><td>" ); + string s_helptext = p_lang->get_val( *p_vec_keys_iter ) ; + + unsigned int i_pos = s_helptext.find( "||", 0 ); + if ( i_pos != string::npos ) + s_helptext.replace( i_pos, 2, "</td><td>" ); + + s_content->append( s_helptext ); + s_content->append( "</td></tr>\n" ); + } + p_vec_keys_iter++; + } + } +} + @@ -0,0 +1,49 @@ +#ifndef MSGS_H +#define MSGS_H + + +// several error messages which will apear by the clients. +#define E_ALPNUM "The nick you have specified is not alphanumeric, please change that.<br><br>\0" +#define E_NONICK "You need to specify a nick name.<br><br>\0" +#define E_NOTONL "An error occured. Your nick is not online.<br><br>\0" +#define E_ONLINE "The nick you have specified is already online. Try another nick.<br><br>\0" + +// alphabetical ordered: +#define ACCPERR "Sock accept error \0" +#define BINDERR "Sock bind error \0" +#define CFILEOK "Parsing config file \0" +#define CFILENO "Failed opening config file \0" +#define CONTACT "Contact: http://www.yChat.org, Mail@yChat.org, ICQ: 11655527\0" +#define DESCRIP "yChat++: Copyright (C) 2003 Paul C. Buetow, Volker Richter\0" +#define DOWNMSG "Shutting down \0" +#define LISTERR "Sock listen error \0" +#define LOGERR1 "Logging: Could not open logfile \0" +#define LOGERR2 "Logging: No filename specified \0" +#define MODULEC "Caching \0" +#define MODULER "Requesting \0" +#define MYMANAG "MySQL: \0" +#define MYLIMIT "MySQL reached hardlimit of connections: \0" +#define MYINITC "MySQL initial connections: \0" +#define MYINITM "MySQL max. connections: \0" +#define MYERROR "MySQL error: no suitable connection found \0" +#define MYERRO1 "MySQL error: init failed \0" +#define MYERRO2 "MySQL error: reached connection limit \0" +#define NEWREQU "New request \0" +#define NEWROOM "New room \0" +#define NEWUSER "New user \0" +#define NOFOUND "File not found \0" +#define POOLERR "Thread pool malloc error \0" +#define READERR "Sock read error \0" +#define REMUSER "Removing user \0" +#define REQUEST "Request string \0" +#define SELCERR "Sock select error \0" +#define SEPERAT "-----------------------\0" +#define SESSION "Session count \0" +#define SOCKCRT "Created server socket on \0" +#define SOCKERR "Couldn't create socket, trying next port \0" +#define SOCKRDY "Server socket is ready \0" +#define STARTMS "Starting up \0" +#define TECACHE "Caching template \0" +#define VERSION "yChat 0.6-RELEASE \0" + +#endif diff --git a/mutx.cpp b/mutx.cpp new file mode 100755 index 0000000..a0176f5 --- /dev/null +++ b/mutx.cpp @@ -0,0 +1,20 @@ +// class mutx implementation. + +#ifndef s_mutx_CXX +#define s_mutx_CXX + +#include "mutx.h" + +using namespace std; + +mutx::mutx() +{ + pthread_mutex_init( &mut_stdout, NULL ); +} + +mutx::~mutx() +{ + pthread_mutex_destroy( &mut_stdout ); +} + +#endif @@ -0,0 +1,21 @@ +// class mutx declaration. + +#ifndef s_mutx_H +#define s_mutx_H + +#include "incl.h" + +using namespace std; + +class mutx +{ +public: + // this mutex is needed for sync stdout and sdterr of different threads. + pthread_mutex_t mut_stdout; + + // public methods. + explicit mutx( ); // simple constructor. + ~mutx( ); // simple constructor. +}; + +#endif diff --git a/name.cpp b/name.cpp new file mode 100755 index 0000000..d575c37 --- /dev/null +++ b/name.cpp @@ -0,0 +1,31 @@ +// class name implementation. + +#ifndef NAME_CXX +#define NAME_CXX + +#include "name.h" + +using namespace std; + +name::name( string s_name ) +{ + set_name( s_name ); +} + +name::~name() +{} + +string +name::get_name() const +{ + return s_name; +} + +void +name::set_name( string s_name ) +{ + this->s_name = s_name; +} + + +#endif @@ -0,0 +1,30 @@ +// class name declaration. + +#ifndef NAME_H +#define NAME_H + +#include "incl.h" + +using namespace std; + +class name +{ +protected: + // private members: + string s_name; // object's name. + +public: + virtual string get_name ( ) const; + virtual void set_name ( string s_name ); + + + // public methods: + explicit name( ) + { } + ; // a standard constructor. + explicit name( string s_name ); // a standard constructor. + ~name( ); + +}; + +#endif diff --git a/ncur.cpp b/ncur.cpp new file mode 100755 index 0000000..e89d970 --- /dev/null +++ b/ncur.cpp @@ -0,0 +1,159 @@ +#ifndef NCUR_CXX +#define NCUR_CXX + +#include "ncur.h" +#include "s_mman.h" +#include "s_sman.h" +#include "s_sock.h" + +using namespace std; + +ncur::ncur( ) +{ + p_messagelist = new list<char*>; + pthread_mutex_init( &mut_messages, NULL ); + i_message_length = 41; + b_is_ready = false; +} + +ncur::~ncur() +{ + pthread_mutex_destroy( &mut_messages ); +} + +void* +ncur::start( void *v_pointer ) +{ + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + ncur* admin_interface = static_cast<ncur*>(v_pointer); + + initscr(); + start_color(); + clear(); + noecho(); + cbreak(); // Line buffering disabled. pass on everything + + init_pair(1, COLOR_WHITE, COLOR_BLUE); + + mvprintw(0, 2, DESCRIP ); + mvprintw(1, 2, CONTACT ); + + refresh(); + + char *choices[] = { + "Chat manager NI", + "Config manager NI", + "HTML-template manager NI", + "Language manager NI", + "Module-loader manager NI", + "MySQL connection manag. NI", + "Session manager NI", + "Socket manager NI", + "Shut down server", + }; + + admin_interface->p_serveroutput = newwin( 17, 45, 3, 34 ); + wbkgd(admin_interface->p_serveroutput, COLOR_PAIR(1)); + + box ( admin_interface->p_serveroutput, 0, 0 ); + mvwprintw( admin_interface->p_serveroutput, 2, 2, "SERVER SYSTEM MESSAGES" ); + wrefresh ( admin_interface->p_serveroutput ); + + + admin_interface->print( VERSION ); + pthread_mutex_unlock( &s_mutx::get().mut_stdout ); + +#ifdef NCURSES + s_mman::get().print_init_ncurses(); + s_sman::get().print_init_ncurses(); +#endif + + admin_interface->is_ready( true ); + admin_interface->p_menu = new menu( 1, 3, 32, 17, "ADMINISTRATOR's MAIN MENU", choices, 9, COLOR_PAIR(1)); + admin_interface->p_menu->start( &switch_main_menu_ ); + + admin_interface->shutdown(); +} + +void +ncur::shutdown() +{ + endwin(); +} + + +void +ncur::print( string *p_msg ) +{ + print( (char*)p_msg->c_str() ); +} + +void +ncur::print( string s_msg ) +{ + print( (char*)s_msg.c_str() ); +} + +void +ncur::print( char* c_print ) +{ + if ( strlen( c_print ) > i_message_length ) + { + string s_tmp( c_print ); + print( s_tmp.substr( 0, i_message_length ) ); + print( s_tmp.substr( i_message_length, s_tmp.length() ) ); + + return; + } + + char* c_temp = new char[i_message_length]; + int i; + for ( i = 0; i < i_message_length; i++ ) + c_temp[i] = ' '; + c_temp[i] = '\0'; + + memcpy( c_temp, c_print, strlen(c_print) ); + + pthread_mutex_lock( &mut_messages ); + + if ( p_messagelist->size() > 10 ) + p_messagelist->pop_front(); + + p_messagelist->push_back( c_temp ); + + list<char*>::iterator iter; + iter = p_messagelist->begin(); + + for ( i=4; i<16 && iter != p_messagelist->end(); i++, iter++ ) + mvwprintw( p_serveroutput, i, 2, *iter ); + + wrefresh ( p_serveroutput ); + + pthread_mutex_unlock( &mut_messages ); +} + +void +ncur::switch_main_menu_( int i_choice ) +{ + if( i_choice != 0 ) + switch ( i_choice ) + { + case 9: // Shut down server + s_mman::get().~mman(); + mvprintw( 21,2, "Good bye !"); + refresh(); + clrtoeol(); + refresh(); + endwin(); + exit(0); + break; + + default: + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + mvprintw( 20,2, "Selection # %d not yet implemented!", i_choice-1); + refresh(); + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + break; + } +} +#endif @@ -0,0 +1,43 @@ +#ifndef NCUR_H +#define NCUR_H + +#include <ncurses.h> +#include <list> +#include "s_mutx.h" +#include "incl.h" +#include "menu.h" + +using namespace std; + +class ncur +{ +private: + menu* p_menu; + WINDOW* p_serveroutput; + list<char*>* p_messagelist; // contains the messages for p_serveroutput! + pthread_mutex_t mut_messages; // for syncronization of p_serveroutput! + int i_message_length; // the maximum length of a system message! + bool b_is_ready; // is set to TRUE if the admin interface is initialized. + +public: + explicit ncur( ); // a standard constructor. + ~ncur( ); + + static void* start( void *v_pointer ); + void print( char* c_print ); + void print( string s_msg ); + void print( string* p_msg ); + void is_ready( bool b_is_ready ) + { + this->b_is_ready = b_is_ready; + } + bool is_ready() const + { + return b_is_ready; + } + + static void switch_main_menu_( int i_choice ); + void shutdown(); +}; + +#endif diff --git a/pool.cpp b/pool.cpp new file mode 100755 index 0000000..b6e5dec --- /dev/null +++ b/pool.cpp @@ -0,0 +1,261 @@ +// class pool implementation. + +#ifndef POOL_CXX +#define POOL_CXX + +#include "pool.h" + +#include "s_conf.h" +#include "s_mutx.h" +#include "s_tool.h" +#include "s_ncur.h" +#include "s_sock.h" +#include "thrd.h" + +using namespace std; + +pool::pool() +{ + i_thrd_pool_size = s_tool::string2int( s_conf::get + ().get_val( "THRDPOOL" ) ); + i_thrd_pool_queue = s_tool::string2int( s_conf::get + ().get_val( "THRDQUEU" ) ); + tpool_init( &thread_pool, i_thrd_pool_size, i_thrd_pool_queue, 0 ); +} + +pool::~pool() +{ + // tpool_destroy ... +} + +void +pool::tpool_init( tpool_t *tpoolp, int num_worker_threads, int max_queue_size, int do_not_block_when_full ) +{ + int i, rtn; + tpool_t tpool; + + // allocate a pool data structure + if (( tpool = (tpool_t) malloc( sizeof( struct tpool ) ) ) == NULL ) + { +#ifdef NCURSES + s_ncur::get + ().print( POOLERR ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << POOLERR << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + + // initialize th fields + tpool->num_threads = num_worker_threads; + tpool->max_queue_size = max_queue_size; + tpool->do_not_block_when_full = do_not_block_when_full; + + if ( ( tpool->threads = (pthread_t*) malloc( sizeof( pthread_t ) *num_worker_threads ) ) == NULL ) + { +#ifdef NCURSES + s_ncur::get + ().print( POOLERR ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << POOLERR << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + + tpool->cur_queue_size = 0; + tpool->queue_head = NULL; + tpool->queue_tail = NULL; + tpool->queue_closed = 0; + tpool->shutdown = 0; + + if ( ( rtn = pthread_mutex_init( &(tpool->queue_lock), NULL ) ) != 0 ) + { + string s_err( "pthread_mutex_init " ); + s_err.append( strerror( rtn ) ); +#ifdef NCURSES + + s_ncur::get + ().print( s_err ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << s_err << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_empty), NULL ) ) != 0 ) + { + string s_err( "pthread_mutex_init " ); + s_err.append( strerror( rtn ) ); +#ifdef NCURSES + + s_ncur::get + ().print( s_err ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << s_err << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_full), NULL ) ) != 0 ) + { + string s_err( "pthread_mutex_init " ); + s_err.append( strerror( rtn ) ); +#ifdef NCURSES + + s_ncur::get + ().print( s_err ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << s_err << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + else if ( ( rtn = pthread_cond_init( &(tpool->queue_empty), NULL ) ) != 0 ) + { + string s_err( "pthread_mutex_init " ); + s_err.append( strerror( rtn ) ); +#ifdef NCURSES + + s_ncur::get + ().print( s_err ); +#endif + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cerr << s_err << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); + exit(-1); + } + // create threads + for ( i = 0; i < num_worker_threads; i++ ) + pthread_create( &(tpool->threads[i]) , NULL, tpool_thread, (void*)tpool ); + + *tpoolp = tpool; +} + +void* +pool::tpool_thread( void* arg ) +{ + tpool_t tpool = (tpool_t) arg; + tpool_work_t *my_workp; + + while( true ) + { + pthread_mutex_lock( &(tpool->queue_lock) ); + + while ( (tpool->cur_queue_size == 0) && (!tpool->shutdown) ) + pthread_cond_wait( &(tpool->queue_not_empty), &(tpool->queue_lock) ); + + if (tpool->shutdown) + { + pthread_mutex_unlock( &(tpool->queue_lock) ); + pthread_exit( NULL ); + } + + my_workp = tpool->queue_head; + tpool->cur_queue_size--; + + if ( tpool->cur_queue_size == 0) + tpool->queue_head = tpool->queue_tail = NULL; + + else + tpool->queue_head = my_workp->next; + + if ( ( ! tpool->do_not_block_when_full ) && + ( tpool->cur_queue_size == ( tpool->max_queue_size - 1 ) ) ) + pthread_cond_signal( &(tpool->queue_not_full) ); + + if ( tpool->cur_queue_size == 0 ) + pthread_cond_signal( &(tpool->queue_empty) ); + + pthread_mutex_unlock( &(tpool->queue_lock) ); + (*(my_workp->routine))(my_workp->arg); + free((void*)my_workp); + } +} + +void pool::run_func( void *v_pointer ) +{ + s_sock::get + ().increase_num_threads(); + + // recasting the client thread object. + thrd *t = (thrd*) v_pointer; + + // start parsing the client request and sending response's back. + t-> run (); + + // close the client socket. + t->~thrd(); + + s_sock::get + ().decrease_num_threads(); + + free(v_pointer); +} + +int +pool::tpool_add_work( tpool_t tpool, void(*routine)(void*), void* arg ) /// +{ + tpool_work_t *workp; + pthread_mutex_lock( &(tpool->queue_lock) ); + + if( ( tpool->cur_queue_size == tpool->max_queue_size ) && + tpool->do_not_block_when_full ) + { + pthread_mutex_unlock( &(tpool->queue_lock) ); + return -1; + } + + while( ( tpool->cur_queue_size == tpool->max_queue_size ) && + ( ! ( tpool->shutdown || tpool->queue_closed ) ) ) + pthread_cond_wait( &(tpool->queue_not_full), &(tpool->queue_lock) ); + + if( tpool->shutdown || tpool->queue_closed ) + { + pthread_mutex_unlock( &tpool->queue_lock ); + return -1; + } + + // allocate work structure: + workp = (tpool_work_t*) malloc( sizeof( tpool_work_t ) ); + + workp->routine = routine; + workp->arg = arg; + workp->next = NULL; + + if( tpool->cur_queue_size == 0 ) + { + tpool->queue_tail = tpool->queue_head = workp; + } + else + { + (tpool->queue_tail)->next = workp; + tpool->queue_tail = workp; + } + + pthread_cond_signal( &tpool->queue_not_empty ); + tpool->cur_queue_size++; + pthread_mutex_unlock( &(tpool->queue_lock) ); + return 1; +} + +#endif @@ -0,0 +1,77 @@ +// class pool declaration. + +#ifndef POOL_H +#define POOL_H + +#include "incl.h" + +using namespace std; + +class pool +{ +private: + typedef struct tpool_work + { + void (*routine)(void*); /// + void *arg; + struct tpool_work *next; + } + tpool_work_t; + + typedef struct tpool + { + // pool characteristics: + int num_threads; + int max_queue_size; + int do_not_block_when_full; + + // pool state + pthread_t *threads; + int cur_queue_size; + + tpool_work_t *queue_head; + tpool_work_t *queue_tail; + + pthread_mutex_t queue_lock; + pthread_cond_t queue_not_empty; + pthread_cond_t queue_not_full; + pthread_cond_t queue_empty; + + int queue_closed; + int shutdown; + } + *tpool_t; + + int i_thrd_pool_size; + int i_thrd_pool_queue; + + tpool_t thread_pool; + + virtual void + tpool_init( tpool_t *tpoolp, int num_worker_threads, int max_queue_size, int do_not_block_when_full ); + + virtual int + tpool_add_work( tpool_t tpool, void(*routine)(void*), void* arg ); + + // virtual void + // tpool_destroy( tpool_t tpoolp, int finish ); + + static void* + tpool_thread( void* arg); + + static void + run_func( void *v_pointer ); + + // public methods: +public: + explicit pool( ); + ~pool(); + + // inline (speed)! + void run( void *arg ) + { + tpool_add_work( thread_pool, run_func, arg ); + } +}; + +#endif diff --git a/quickstart.sh b/quickstart.sh new file mode 100755 index 0000000..46e1840 --- /dev/null +++ b/quickstart.sh @@ -0,0 +1,34 @@ +#!/bin/sh +STARS="----------------------------------------\n" +echo "Welcome to yChat 0.5 Quickstart" +echo -e $STARS +echo "Copyright 2003, Paul C. Buetow - Volker Richter" +echo "yChat++ is developed under GNU Public License" +echo "http://www.ychat.org" +echo -e "\n" +echo -e "Press enter to begin quickstart" +read +echo "STEP I" +echo -e "$STARS PREPARING SOURCES\n\n\n" +./configure +if [ ! -e ./Makefile ]; then + echo "STEP I UNSUCCESSFUL" + exit 1; +else + echo "STEP II COMPILING SOURCES" +fi +make && +cd mods && +./compile.sh && +cd - +if [ ! -x ./ychat ]; then + echo "STEP II UNSUCCESSFUL" + exit 1 +fi +echo -e "\n\nSTEP II SUCCESSFUL\n\n" +echo -e "yChat is now ready to go. You can start yChat by running ./ychat from your console.\n\n" +echo -e "Should i start the yChat now? [N/y]: " +read startchat +if [ $startchat == "y" ]; then + ./ychat +fi diff --git a/reqp.cpp b/reqp.cpp new file mode 100755 index 0000000..f2062d8 --- /dev/null +++ b/reqp.cpp @@ -0,0 +1,326 @@ +// class reqp implementation. + +#ifndef REQP_CXX +#define REQP_CXX + +#include "reqp.h" +#include "s_chat.h" +#include "s_html.h" +#include "s_modl.h" +#include "s_mutx.h" +#include "s_ncur.h" +#include "s_sock.h" +#include "s_tool.h" +using namespace std; + +// inititialization of static members. +string reqp::HTTP_CODEOK = "HTTP/1.1 200 OK\n"; +string reqp::HTTP_SERVER = "Server: yChat (Unix)\n"; +string reqp::HTTP_CONTAC = "Contact: www.yChat.org\n"; +string reqp::HTTP_EXPIRE = "Expires: 0\n"; +string reqp::HTTP_CACHEC = "Cache-control: no-cache\nPragma: no-cache\n"; +string reqp::HTTP_CONNEC = "Connection: keep-alive\n"; +string reqp::HTTP_COTYPE = "Content-Type: "; + +reqp::reqp( ) +{} + +string +reqp::get_url( thrd* p_thrd, string s_req, map_string &map_params ) +{ + auto unsigned int pos; + string s_ret ( "" ); + string s_vars( "" ); + auto int i_request; + + i_request= ( s_req.find("GET",0) != string::npos ) ? RQ_GET : RQ_POST; + + pos = s_req.find( "HTTP", 0 ); + + if( i_request == RQ_GET ) + s_ret.append( s_req.substr( 5, pos-6 ) ); + else + s_ret.append( s_req.substr( 6, pos-7 ) ); + + // remove ".." from the request. + do + { + pos = s_ret.find( "../", 0 ); + + if ( pos == string::npos ) + break; + + s_ret.replace( pos, pos+2, "" ); + } + while( true ); + + // do not add the string behind "?" tp s_ret and add all params behind "?" to map_params. + if( i_request == RQ_GET ) + pos = s_ret.find( "?", 0 ); + else + pos = s_req.find("\r\n\r\n", 0); + + auto string s_params( "" ); + if ( pos != string::npos ) + { + if( i_request == RQ_GET ) + s_params.append( s_ret.substr( pos+1, s_ret.length() -pos-1 ) ); + + else + s_params = s_req.substr( pos+4, s_req.length() -pos-1 ); + + s_ret = s_ret.substr( 0, pos ); + } + + if ( i_request == RQ_POST && s_params.empty() ) + { + char c_req[READBUF]; + + if ( read ( p_thrd->get_sock() , c_req, READBUF ) <= 0 ) + return "NOBYTE"; + + s_params = string( strstr( c_req, "event" ) ); + + } + + auto unsigned int pos2; + do + { + pos = s_params.find( "=", 0 ); + if ( pos == string::npos ) + break; + + pos2 = s_params.find( "&", 0 ); + if ( pos2 == string::npos ) + { + auto string sValue( s_params.substr(pos+1, s_params.length()-pos-1) ); + auto string tmpstr( url_decode(sValue) ); + map_params[ s_params.substr( 0, pos ) ] = tmpstr; + break; + } + + auto string s_temp= s_params.substr( pos+1, pos2-pos-1 ); + map_params[ s_params.substr( 0, pos ) ] = url_decode(s_temp); + + s_params = s_params.substr( pos2+1, s_params.length()-pos2-1 ); + } + while( true ); + +#ifdef VERBOSE + + pthread_mutex_lock ( &s_mutx::get + ().mut_stdout ); + cout << REQUEST << s_ret << endl; + pthread_mutex_unlock( &s_mutx::get + ().mut_stdout ); +#endif + + map_params["request"] = s_ret; + + return s_ret; +} + +string +reqp::get_content_type( string s_file ) +{ + string s_ext=s_tool::getExtension( s_file ); + + if(s_ext=="") + s_ext="DEFAULT"; + + return s_conf::get + ().get_val( "CT_"+s_ext ); +} +void +reqp::parse_headers( string s_req, map_string &map_params ) +{ + + int pos = s_req.find("\n"); + + map_params["QUERY_STRING"] = s_tool::trim(s_req.substr(0,pos-1)); + + while( pos != string::npos) + { + auto string s_line=s_req.substr(0,pos); + auto int pos2=s_line.find(":"); + + if(pos2!=string::npos) + { + auto string key=s_tool::trim(s_line.substr(0, pos2)); + auto string value=s_tool::trim(s_line.substr(pos2+1)); + + map_params[key]=value; + + } + s_req=s_req.substr(s_line.size()+1); + pos=s_req.find("\n"); + } + +} + + +int +reqp::htoi(string *s) +{ + int value; + int c; + + c=s->c_str()[0]; + if(isupper(c)) + c=tolower(c); + + value=(c>='0' && c<='9'?c-'0':c-'a'+10)*16; + + c=s->c_str()[1]; + if(isupper(c)) + c=tolower(c); + + value+=c>='0' && c<='9'?c-'0':c-'a'+10; + return value; +} + +string +reqp::url_decode( string s_str ) +{ + auto string sDest=""; + int len = s_str.size(); + + for(int i=0;i<len;i++) + { + char ch = s_str.at(i); + if(ch=='+') + { + sDest+=" "; + } + else if(ch=='%') + { + auto string sTmp=s_str.substr(i+1,2); + ch=(char)htoi(&sTmp); + sDest+=ch; + i+=2; + + } + else + + sDest+=ch; + } + return sDest; +} + +string +reqp::get_from_header( string s_req, string s_hdr ) +{ + auto unsigned int pos[2]; + pos[0] = s_req.find( s_hdr, 0 ); + pos[1] = s_req.find( "\n", pos[0] ); + + auto int i_length = s_hdr.length(); + return s_req.substr( pos[0]+i_length, pos[1]-pos[0]-i_length-1 ); +} + +string +reqp::parse( thrd* p_thrd, string s_req, map_string &map_params ) +{ + // store all request informations in map_params. store the url in + // map_params["request"]. + if ( get_url( p_thrd, s_req, map_params ).compare("NOBYTE") == 0 ) + map_params["request"] = s_conf::get().get_val("NOTFOUND"); + + parse_headers( s_req, map_params ); + + // create the http header. + string s_rep( HTTP_CODEOK ); + s_rep.append( HTTP_SERVER ); + s_rep.append( HTTP_CONTAC ); + s_rep.append( HTTP_EXPIRE ); + s_rep.append( HTTP_CACHEC ); + s_rep.append( HTTP_CONNEC ); + s_rep.append( HTTP_COTYPE ); + s_rep.append( get_content_type( map_params["request"] ) ); + s_rep.append("\r\n\r\n"); + + // check the event variable. + + string s_event( map_params["event"] ); + + if ( ! s_event.empty() ) + { + // login procedure. + if ( s_event == "login" ) + { + s_chat::get + ().login( map_params ); + } + else + { + bool b_found; + + // user* p_user = s_chat::get().get_user( map_params["nick"], b_found ); + sess *sess_temp=s_sman::get + ().get_session( map_params["tmpid"] ); + + user *p_user; + if( sess_temp != NULL ) + { + string *s_nick = static_cast<string*>(sess_temp->get_elem(string("nick"))); + p_user = s_chat::get + ().get_user( *s_nick, b_found); + + map_params["nick"] = p_user->get_name().c_str(); + + } + else + return s_rep; + + if ( ! b_found ) + { + map_params["INFO"] = E_NOTONL; + map_params["request"] = s_conf::get + ().get_val( "STARTMPL" ); // redirect to the startpage. + } + // if a message post. + else if ( s_event == "post" ) + s_chat::get + ().post( p_user, map_params ); + + + // if a chat stream + else if ( s_event == "stream" ) + { + string s_msg(s_html::get + ().parse( map_params ) ); + p_user->msg_post( &s_msg); + s_sock::get + ().chat_stream( p_thrd->get_sock(), p_user, map_params ); + } + + // if a request for the online list of the active room. + else if ( s_event == "online" ) + s_html::get + ().online_list( p_user, map_params ); + + else if ( s_event != "input" ) + { + container *c = new container; + c->elem[0] = (void*) &s_lang::get(); + c->elem[1] = (void*) s_modl::get().get_map_mods(); + c->elem[2] = (void*) &map_params; + + string s_mod = "mods/html/yc_" + s_event + ".so"; + ( *(s_modl::get(). + get_module( s_mod )->the_func + ) + ) ( (void*) c ); + } + } + } + // parse and get the requested html-template and also use + // the values stored in map_params for %%KEY%% substituations. + s_rep.append( s_html::get + ().parse( map_params ) ); + + // return the parsed html-template. + return s_rep; +} + +#endif @@ -0,0 +1,48 @@ +// class reqp declaration. this class parses the client requests. + +#ifndef REQP_H +#define REQP_H + +#define RQ_GET 1 +#define RQ_POST 2 + +#include <map> +#include "incl.h" +#include "thrd.h" + +using namespace std; + +typedef map<string, string, less<string> > map_string; + +class reqp +{ +private: + static string HTTP_CODEOK, + HTTP_CODENF, + HTTP_EXPIRE, + HTTP_SERVER, + HTTP_CONTAC, + HTTP_CACHEC, + HTTP_CONNEC, + HTTP_COTYPE; + + // returns the request url from thr client's http request header + // until the first "?" and stores all request parameter values + // ( behind "?" ) into map_params. + virtual string get_url( thrd* p_thrd, string s_req, map_string &map_params ); + // returns a specific value of the client's http request header. + // ( s.t. like the User-Agent, Referer etc... ). + virtual string get_from_header( string s_req, string s_hdr ); + + virtual int htoi( string *s ); + +public: + // public methods. + explicit reqp( ); // simple constructor. + virtual string parse( thrd* p_thrd, string s_req, map_string &map_params ); + virtual string url_decode ( string ); + virtual string get_content_type( string ); + virtual void parse_headers( string s_req, map_string &map_params ); +}; + +#endif diff --git a/room.cpp b/room.cpp new file mode 100755 index 0000000..9ded3ac --- /dev/null +++ b/room.cpp @@ -0,0 +1,16 @@ +// class room implementation. + +#ifndef ROOM_CXX +#define ROOM_CXX + +#include "room.h" + +using namespace std; + +room::room( string s_name ) : name( s_name ) +{} + +room::~room() +{} + +#endif @@ -0,0 +1,34 @@ +// class room declaration. + +#ifndef ROOM_H +#define ROOM_H + +#include "incl.h" +#include "base.h" +#include "name.h" +#include "user.h" + +using namespace std; + +class room : public base<user>, public name +{ +private: + +public: + void add_user( user* p_user ) + { + p_user->set_p_room( this ); + add_elem( p_user ); + } + + user* get_user( string &s_name, bool &b_found ) + { + return static_cast<user*>( get_elem( s_name, b_found ) ); + } + + // public methods: + explicit room( string s_name ); // a constructor. + ~room(); // room destructor. +}; + +#endif diff --git a/s_chat.cpp b/s_chat.cpp new file mode 100644 index 0000000..9e0d01b --- /dev/null +++ b/s_chat.cpp @@ -0,0 +1,10 @@ +#ifndef GCHT_CXX +#define GCHT_CXX + +#include "s_chat.h" + +using namespace std; + +chat* s_chat::obj; + +#endif diff --git a/s_chat.h b/s_chat.h new file mode 100644 index 0000000..fb88a94 --- /dev/null +++ b/s_chat.h @@ -0,0 +1,27 @@ +#ifndef GCHT_H +#define GCHT_H + +#include "chat.h" + +using namespace std; + +class s_chat +{ +private: + static chat* obj; + +public: + static void init() + { + obj = new chat(); + } + + static chat& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_conf.cpp b/s_conf.cpp new file mode 100644 index 0000000..ea1c05a --- /dev/null +++ b/s_conf.cpp @@ -0,0 +1,10 @@ +#ifndef GCON_CXX +#define GCON_CXX + +#include "s_conf.h" + +using namespace std; + +conf* s_conf::obj; + +#endif diff --git a/s_conf.h b/s_conf.h new file mode 100644 index 0000000..fa252dd --- /dev/null +++ b/s_conf.h @@ -0,0 +1,27 @@ +#ifndef GCON_H +#define GCON_H + +#include "conf.h" + +using namespace std; + +class s_conf +{ +private: + static conf* obj; + +public: + static void init() + { + obj = new conf( CONFILE ); + } + + static conf& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_html.cpp b/s_html.cpp new file mode 100644 index 0000000..0899abe --- /dev/null +++ b/s_html.cpp @@ -0,0 +1,10 @@ +#ifndef GHTM_CXX +#define GHTM_CXX + +#include "s_html.h" + +using namespace std; + +html* s_html::obj; + +#endif diff --git a/s_html.h b/s_html.h new file mode 100644 index 0000000..1386f3b --- /dev/null +++ b/s_html.h @@ -0,0 +1,27 @@ +#ifndef GHTM_H +#define GHTM_H + +#include "html.h" + +using namespace std; + +class s_html +{ +private: + static html* obj; + +public: + static void init() + { + obj = new html(); + } + + static html& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_lang.cpp b/s_lang.cpp new file mode 100644 index 0000000..41c2089 --- /dev/null +++ b/s_lang.cpp @@ -0,0 +1,10 @@ +#ifndef GCON_CXX +#define GCON_CXX + +#include "s_lang.h" + +using namespace std; + +lang* s_lang::obj; + +#endif diff --git a/s_lang.h b/s_lang.h new file mode 100644 index 0000000..3247662 --- /dev/null +++ b/s_lang.h @@ -0,0 +1,28 @@ +#ifndef GLANG_H +#define GLANG_H + +#include "lang.h" +#include "s_conf.h" +using namespace std; + +class s_lang +{ +private: + static lang* obj; + +public: + static void init() + { + obj = new lang( s_conf::get + ().get_val( "LANGUAGE" ) ); + } + + static lang& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_mman.cpp b/s_mman.cpp new file mode 100644 index 0000000..b8079e6 --- /dev/null +++ b/s_mman.cpp @@ -0,0 +1,10 @@ +#ifndef GMMAN_CXX +#define GMMAN_CXX + +#include "s_mman.h" + +using namespace std; + +mman* s_mman::obj; + +#endif diff --git a/s_mman.h b/s_mman.h new file mode 100644 index 0000000..e6e3ff4 --- /dev/null +++ b/s_mman.h @@ -0,0 +1,38 @@ +#ifndef GMMAN_H +#define GMMAN_H + +#include "mman.h" +#include "s_conf.h" +#include "s_tool.h" + +using namespace std; + +class s_mman +{ +private: + static mman* obj; + +public: + static void init() + { + obj = new mman( s_tool::string2int(s_conf::get + ().get_val( "MIN_CONNECTIONS" )), s_tool::string2int(s_conf::get + ().get_val( "MAX_CONNECTIONS" ))); + obj->init( s_conf::get + ().get_val( "MYSQL_HOST" ), s_conf::get + ().get_val( "MYSQL_USER" ), s_conf::get + ().get_val( "MYSQL_PASS" ), + s_conf::get + ().get_val( "MYSQL_DB" ), s_tool::string2int(s_conf::get + ().get_val( "MYSQL_PORT" )) ); + } + + static mman& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_modl.cpp b/s_modl.cpp new file mode 100644 index 0000000..f6a5913 --- /dev/null +++ b/s_modl.cpp @@ -0,0 +1,10 @@ +#ifndef GMOD_CXX +#define GMOD_CXX + +#include "s_modl.h" + +using namespace std; + +modl* s_modl::obj; + +#endif diff --git a/s_modl.h b/s_modl.h new file mode 100644 index 0000000..e08181c --- /dev/null +++ b/s_modl.h @@ -0,0 +1,27 @@ +#ifndef GMOD_H +#define GMOD_H + +#include "modl.h" + +using namespace std; + +class s_modl +{ +private: + static modl* obj; + +public: + static void init() + { + obj = new modl(); + } + + static modl& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_mutx.cpp b/s_mutx.cpp new file mode 100644 index 0000000..33c8385 --- /dev/null +++ b/s_mutx.cpp @@ -0,0 +1,10 @@ +#ifndef GMUT_CXX +#define GMUT_CXX + +#include "s_mutx.h" + +using namespace std; + +mutx* s_mutx::obj; + +#endif diff --git a/s_mutx.h b/s_mutx.h new file mode 100644 index 0000000..c379bcb --- /dev/null +++ b/s_mutx.h @@ -0,0 +1,27 @@ +#ifndef GMUT_H +#define GMUT_H + +#include "mutx.h" + +using namespace std; + +class s_mutx +{ +private: + static mutx* obj; + +public: + static void init() + { + obj = new mutx(); + } + + static mutx& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_ncur.cpp b/s_ncur.cpp new file mode 100644 index 0000000..8bb9f20 --- /dev/null +++ b/s_ncur.cpp @@ -0,0 +1,10 @@ +#ifndef S_NCUR_CXX +#define S_NCUR_CXX + +#include "s_ncur.h" + +using namespace std; + +ncur* s_ncur::obj; + +#endif diff --git a/s_ncur.h b/s_ncur.h new file mode 100644 index 0000000..8ced4a6 --- /dev/null +++ b/s_ncur.h @@ -0,0 +1,26 @@ +#ifndef S_NCUR_H +#define S_NCUR_H + +#include "ncur.h" + +using namespace std; + +class s_ncur +{ +private: + static ncur* obj; + +public: + static void init() + { + obj = new ncur(); + } + + static ncur& get + () + { + return *obj; + } +}; + +#endif diff --git a/s_sman.cpp b/s_sman.cpp new file mode 100644 index 0000000..bfb1efd --- /dev/null +++ b/s_sman.cpp @@ -0,0 +1,10 @@ +#ifndef GSMAN_CXX +#define GSMAN_CXX + +#include "s_sman.h" + +using namespace std; + +sman* s_sman::obj; + +#endif diff --git a/s_sman.h b/s_sman.h new file mode 100644 index 0000000..9ef5dcc --- /dev/null +++ b/s_sman.h @@ -0,0 +1,27 @@ +#ifndef GSMAN_H +#define GSMAN_H + +#include "sman.h" + +using namespace std; + +class s_sman +{ +private: + static sman* obj; + +public: + static void init() + { + obj = new sman(); + } + + static sman& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_sock.cpp b/s_sock.cpp new file mode 100644 index 0000000..dd80e71 --- /dev/null +++ b/s_sock.cpp @@ -0,0 +1,10 @@ +#ifndef GSOC_CXX +#define GSOC_CXX + +#include "s_sock.h" + +using namespace std; + +sock* s_sock::obj; + +#endif diff --git a/s_sock.h b/s_sock.h new file mode 100644 index 0000000..ec32ec3 --- /dev/null +++ b/s_sock.h @@ -0,0 +1,27 @@ +#ifndef GSOC_H +#define GSOC_H + +#include "sock.h" + +using namespace std; + +class s_sock +{ +private: + static sock* obj; + +public: + static void init() + { + obj = new sock(); + } + + static sock& get + () + { + return *obj; + } +}; + + +#endif diff --git a/s_tool.cpp b/s_tool.cpp new file mode 100644 index 0000000..4400d16 --- /dev/null +++ b/s_tool.cpp @@ -0,0 +1,131 @@ +#ifndef s_tool_CXX +#define s_tool_CXX + +#include <ctype.h> +#include <time.h> +#include "s_tool.h" + +bool +s_tool::is_alpha_numeric( string &s_digit ) +{ + auto const char *digit = s_digit.c_str(); + auto int i_len = strlen( digit ); + + for( int i=0; i<i_len; i++ ) + { + if ( ! isalnum( *digit ) ) + return false; + digit++; + } + + return true; +} +string +s_tool::trim( string s_str ) +{ + if(s_str.empty()) + return ""; + char c_cur=s_str[0]; + auto int pos=0; + // left trim + while(c_cur==' ' || c_cur == '\n' || c_cur == '\r') + { + s_str.erase(pos,1); + + c_cur=s_str[++pos]; + + } + // right trim + + pos=s_str.size(); + c_cur=s_str[s_str.size()]; + + while(c_cur==' ' || c_cur == '\n' || c_cur == '\0' || c_cur == '\r') + { + s_str.erase(pos,1); + c_cur=s_str[--pos]; + + } + return s_str; +} + +string +s_tool::getExtension( string s_file ) +{ + int pos = s_file.find_last_of("."); + if(pos != string::npos) + { + string s_ext=s_file.substr(pos+1, s_file.size()-(pos+1)); + for(int i = 0;i<s_ext.size();i++) + s_ext[i]=toupper(s_ext[i]); + return s_ext; + } + return ""; +} + +int +s_tool::string2int( string s_digit ) +{ + auto const char *digit = s_digit.c_str(); + int result = 0; + + // Convert each digit char and add into result. + while (*digit >= '0' && *digit <='9') + { + result = (result * 10) + (*digit - '0'); + digit++; + } + + // Check that there were no non-digits at end. + if (*digit != 0) + { + return -1; + } + + return result; +} + +char* +s_tool::int2string( int i_int ) +{ + char *buffer = new char[64]; + sprintf(buffer, "%d", i_int); + return buffer; +} + +long +s_tool::unixtime() +{ + return (long) time( NULL ); +} + + +void +s_tool::strip_html( string *s_str ) +{ + auto int i_pos; + + if((i_pos=s_str->find("<",0))==string::npos) + return; + while(true) + { + + s_str->replace(i_pos,1,"<"); + + if((i_pos=s_str->find("<",0))==string::npos) + return; + + } + + +} +string +s_tool::to_lower( string s ) +{ + string s_tmp(""); + for(int i=0;i < s.size() ;i++) + s_tmp=s_tmp+(char)tolower(s.at(i)); + + return s_tmp; +} +#endif diff --git a/s_tool.h b/s_tool.h new file mode 100644 index 0000000..9e336f6 --- /dev/null +++ b/s_tool.h @@ -0,0 +1,21 @@ +#ifndef s_tool_H +#define s_tool_H + +#include "incl.h" + +using namespace std; + +class s_tool +{ +public: + static bool is_alpha_numeric( string &s_digit ); + static int string2int( string s_digit ); + static char* int2string( int i_int ); + static string trim( string s_str ); + static long unixtime(); + static void strip_html( string *s_str); + static string getExtension( string s_file ); + static string to_lower( string s ); +}; + +#endif diff --git a/sess.cpp b/sess.cpp new file mode 100644 index 0000000..642d2d0 --- /dev/null +++ b/sess.cpp @@ -0,0 +1,39 @@ +#ifndef SESS_CPP +#define SESS_CPP + +#include "sess.h" + +sess::sess( string s_id ) +{ + this->sess_id=s_id; +} + +string sess::get_id() +{ + return this->sess_id; +} + + +void sess::invalidate() +{ + this->sess_id="0"; + this->sess_values.clear(); +} + +void sess::setValue( string s_key, void *lpvalue ) +{ + this->sess_values[s_key]=lpvalue; +} +void *sess::get_elem( string s_key ) +{ + return this->sess_values[s_key]; +} +string sess::dump() +{ + string s_ret=string("Session Dump of Session ") + this->get_id(); + map<string, void*>::const_iterator it; + for(it=this->sess_values.begin();it!=this->sess_values.end();it++) + s_ret=s_ret + "\nkey: " + it->first; + return s_ret; +} +#endif @@ -0,0 +1,28 @@ +#ifndef s_sess_H +#define s_sess_H + +#include "incl.h" +#include "cont.h" +#include "name.h" +#include <map> +#include <string> +#include "hmap.h" +using namespace std; + +typedef map<string, void *> sess_map; + +class sess : public cont, name +{ + +private: + sess_map sess_values; + string sess_id; +public: + sess(string s_id); + string get_id(); + void setValue(string s_key, void *lpvalue); + void *get_elem( string s_key ); + void invalidate(); + string dump(); +}; +#endif diff --git a/sman.cpp b/sman.cpp new file mode 100644 index 0000000..ab3468a --- /dev/null +++ b/sman.cpp @@ -0,0 +1,93 @@ +#ifndef SMAN_CXX +#define SMAN_CXX + +#include "sman.h" + +sman::sman() +{ + this->sessions=new hmap<sess *, string>(80); + this->session_count=0; + pthread_mutex_init( &mut_sessions, NULL ); + pthread_mutex_init( &mut_session_count, NULL ); +} +sman::~sman() +{ + pthread_mutex_lock( &mut_sessions ); + delete this->sessions; + pthread_mutex_unlock( &mut_sessions ); + + pthread_mutex_destroy( &mut_sessions ); + pthread_mutex_destroy( &mut_session_count ); +} +string sman::generate_id( int len ) +{ + string valid_chars=".abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; + string s_ret=""; + srand(time(0)+160682); + for(int i=0;i<len;i++) + { + int i_char=rand() % 64; + s_ret+=valid_chars[i_char]; + } + return s_ret; +} +sess *sman::create_session( ) +{ + string new_id=this->generate_id( s_tool::string2int( s_conf::get + ().get_val( "SESSION_LENGTH" ) ) ); + + sess *new_sess= new sess( new_id ); + + pthread_mutex_lock( &mut_session_count ); + this->session_count++; +#ifdef NCURSES + print_sessions(); +#endif + pthread_mutex_unlock( &mut_session_count ); + + pthread_mutex_lock( &mut_sessions ); + this->sessions->add_elem( new_sess, new_id ); + pthread_mutex_unlock( &mut_sessions ); + + + return new_sess; +} + +sess *sman::get_session( string s_id ) +{ + pthread_mutex_lock( &mut_sessions ); + sess *ret_sess = this->sessions->get_elem( s_id ); + pthread_mutex_unlock( &mut_sessions ); + + return ret_sess; +} +void sman::destroy_session( string s_id ) +{ + pthread_mutex_lock( &mut_session_count ); + this->session_count--; +#ifdef NCURSES + print_sessions(); +#endif + pthread_mutex_unlock( &mut_session_count ); + + this->sessions->del_elem( s_id ); +} + +#ifdef NCURSES +void sman::print_sessions() +{ + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + mvprintw( NCUR_SESSION_X,NCUR_SESSION_Y, "Sessions: %d ", session_count); + refresh(); + pthread_mutex_unlock( &s_mutx::get().mut_stdout ); +} + +void sman::print_init_ncurses() +{ + pthread_mutex_lock( &mut_session_count ); + print_sessions(); + pthread_mutex_unlock( &mut_session_count ); +} + +#endif +#endif @@ -0,0 +1,45 @@ +#ifndef SMAN_H +#define SMAN_H + +#include "incl.h" +#include "hmap.h" +#include "sess.h" +#include "s_mutx.h" +#include "s_ncur.h" +#include "s_tool.h" +#include "s_conf.h" +#include <cstdlib> + +using namespace std; + +class sman +{ +private: + hmap<sess *, string> *sessions; + string generate_id( int len ); + int session_count; + + pthread_mutex_t mut_sessions; + pthread_mutex_t mut_session_count; +#ifdef NCURSES + void print_sessions(); +#endif + +public: + sman(); + ~sman(); + sess *get_session( string s_id ); + int get_session_count( ) + { + return this->session_count; + } + sess *create_session( ); + void destroy_session( string s_id ); +#ifdef NCURSES + void print_init_ncurses(); +#endif +}; + + +#endif + diff --git a/sock.cpp b/sock.cpp new file mode 100755 index 0000000..5d64367 --- /dev/null +++ b/sock.cpp @@ -0,0 +1,394 @@ +// class sock implementation. the multiplex socket implementation has been token from the +// GNU C Library Examples and modified in order to fit in here ( POSIX threads etc. ). + +#ifndef s_sock_CXX +#define s_sock_CXX + +#include <unistd.h> + +#include "sock.h" +#include "s_chat.h" +#include "s_conf.h" +#include "s_tool.h" +#include "s_lang.h" +#include "s_sman.h" +#include "s_mman.h" +#include "s_mutx.h" +#include "s_ncur.h" +#include "chat.h" +#include "user.h" + +using namespace std; + +sock::sock() +{ + this->b_run = true; + this->i_req = 0; + this->i_threads = 2; // currently there are 2 threads running ( admin interface + server listening ); + this->req_parser = new reqp(); + this->thrd_pool = new pool(); + this->log_daemon = new logd(s_conf::get + ().get_val( "ACCESS_LOG" )); + + + pthread_mutex_init( &mut_threads, NULL ); +} + +sock::~sock() +{ + pthread_mutex_destroy( &mut_threads ); +} + +void +sock::chat_stream( int i_sock, user* p_user, map_string &map_params ) +{ + string s_msg( "\n" ); + + + for ( int i = 0; i < PUSHSTR; i++ ) + send( i_sock, s_msg.c_str(), s_msg.size(), 0 ); + + do + { + pthread_mutex_lock ( &(p_user->mut_message) ); + s_msg = p_user->get_mess( ); + if ( 0 > send( i_sock, s_msg.c_str(), s_msg.size(), 0 ) ) + p_user->set_online( false ); + pthread_cond_wait( &(p_user->cond_message), &(p_user->mut_message) ); + } + while( p_user->get_online() ); + + // if there is still a message to send: + s_msg = p_user->get_mess( ); + if ( ! s_msg.empty() ) + send( i_sock, s_msg.c_str(), s_msg.size(), 0 ); + + pthread_mutex_unlock( &(p_user->mut_message) ); + + // remove the user from its room. + string s_user( p_user->get_name() ); + p_user->get_room()->del_elem( s_user ); + +#ifdef NCURSES + + { + string s_tmp( REMUSER ); + s_tmp.append( s_user ); + s_ncur::get + ().print( s_tmp.c_str() ); + } +#endif + // post the room that the user has left the chat. + p_user->get_room()->msg_post( new string( p_user->get_colored_name().append( s_lang::get + ().get_val( "USERLEAV" ) ) ) ); + s_sman::get + ().destroy_session( p_user->get_id() ); + +#ifdef NCURSES + { + string s_tmp( SESSION ); + s_tmp.append( s_tool::int2string( s_sman::get + ().get_session_count() ) ); + s_ncur::get + ().print( s_tmp ); + } +#endif +#ifdef VERBOSE + // cout << REMUSER << s_user << endl + // << SESSION << s_man::get().get_session_count() << endl; + +#endif + + p_user->~user(); +} + +int +sock::make_socket( uint16_t i_port ) +{ + int sock; + struct sockaddr_in name; + + // create the server socket. + sock = socket (PF_INET, SOCK_STREAM, 0); + if (sock < 0) + { + +#ifdef NCURSES + s_ncur::get + ().print( SOCKERR ); +#endif + + if ( ++i_port > MAXPORT ) + exit(-1); + +#ifdef NCURSES + + s_ncur::get + ().print( SOCKERR ); +#endif + + return make_socket( i_port ); + } + + // give the server socket a name. + name.sin_family = AF_INET; + name.sin_port = htons (i_port); + name.sin_addr.s_addr = htonl (INADDR_ANY); + int optval=1; + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int)); + + if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) + { + +#ifdef NCURSES + s_ncur::get + ().print( BINDERR ); +#endif + + if ( ++i_port > MAXPORT ) + exit(-1); + +#ifdef SERVMSG + + cout << SOCKERR << i_port << endl; +#endif +#ifdef NCURSES + + s_ncur::get + ().print( SOCKERR ); +#endif + + return make_socket( i_port ); + } + +#ifdef VERBOSE + cout << SOCKCRT << "localhost:" << i_port << endl; +#endif +#ifdef NCURSES + + string s_tmp( SOCKCRT ); + s_tmp.append( "localhost:" ); + s_tmp.append( s_tool::int2string(i_port) ); + s_ncur::get + ().print( s_tmp ); + mvprintw( NCUR_PORT_X,NCUR_PORT_Y, "Port: %d ", i_port); + refresh(); +#endif + + return sock; +} + +int +sock::read_write( thrd* p_thrd, int i_sock ) +{ + char c_req[2048]; + + int i_bytes; + i_bytes = read (i_sock, c_req, 2048); + + if (i_bytes < 0) + { +#ifdef NCURSES + s_ncur::get + ().print( new string( READERR ) ); +#endif + + } + else + { + // stores the request params. + map_string map_params; + + // get the s_rep ( s_html response which will be send imediatly to the client + // and fill map_params with request values. + auto string s_temp=(string)c_req; + struct sockaddr_in client; + size_t size=sizeof(client); + + getpeername( i_sock, (struct sockaddr *)&client, &size); + + map_params["REMOTE_ADDR"]=inet_ntoa(client.sin_addr); + map_params["REMOTE_PORT"]=ntohs( client.sin_port); + + + string s_rep = req_parser->parse( p_thrd, string( c_req ), map_params ); + // send s_rep to the client. + log_daemon->log(map_params); + + send( i_sock, s_rep.c_str(), s_rep.size(), 0 ); + + // dont need those vals anymore. + map_params.clear(); + + return 0; + } + + return -1; +} + +int +sock::start() +{ +#ifdef NCURSES + s_ncur::get + ().print( STARTMS ); + print_hits(); + print_threads(); +#endif + + auto int i_port = s_tool::string2int( s_conf::get + ().get_val( "SRVRPORT" ) ); + + int sock; + fd_set active_fd_set, read_fd_set; + int i; + struct sockaddr_in clientname; + size_t size; + + + // create the server socket and set it up to accept connections. + sock = make_socket ( i_port ); + + if (listen (sock, 1) < 0) + { +#ifdef NCURSES + s_ncur::get + ().print( LISTERR ); +#endif + + exit( EXIT_FAILURE ); + } + +#ifdef VERBOSE + cout << SOCKRDY << endl; +#endif +#ifdef NCURSES + + s_ncur::get + ().print( SOCKRDY ); +#endif + + // initialize the set of active sockets. + FD_ZERO (&active_fd_set); + FD_SET (sock, &active_fd_set); + + while( b_run ) + { + // block until input arrives on one or more active sockets. + read_fd_set = active_fd_set; + if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) + { + +#ifdef NCURSES + s_ncur::get + ().print( SELCERR ); +#endif + + exit( EXIT_FAILURE ); + } + + // service all the sockets with input pending. + for ( i = 0; i < FD_SETSIZE; i++ ) + if ( FD_ISSET (i, &read_fd_set) ) + { + if ( i == sock ) + { + // connection request on original socket. + i_req++; +#ifdef NCURSES + + print_hits(); +#endif + + int new_sock; + size = sizeof (clientname); + new_sock = accept (sock, + (struct sockaddr *) &clientname, + &size); + + if (new_sock < 0) + { + +#ifdef NCURSES + s_ncur::get + ().print( ACCPERR); +#endif + + close ( new_sock ); + + } + + else + { +#ifdef VERBOSE + cout << NEWREQU << i_req << " " + << inet_ntoa( clientname.sin_addr ) + << ":" + << ntohs ( clientname.sin_port ) + << endl; +#endif + FD_SET (new_sock, &active_fd_set); + } + } + + else + { + +#ifdef NCURSES + /// s_ncur::get().print( NEWREQU ); +#endif + + thrd_pool->run( (void*) new thrd( i ) ); + FD_CLR( i, &active_fd_set ); + } + } + } +} + +void +sock::increase_num_threads() +{ + pthread_mutex_lock( &mut_threads ); + i_threads++; + pthread_mutex_unlock( &mut_threads ); +#ifdef NCURSES + print_threads(); +#endif + +} + +void +sock::decrease_num_threads() +{ + pthread_mutex_lock( &mut_threads ); + i_threads--; + pthread_mutex_unlock( &mut_threads ); + +#ifdef NCURSES + print_threads(); +#endif + +} + +#ifdef NCURSES +void +sock::print_threads() +{ + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + mvprintw( NCUR_THREADS_X,NCUR_THREADS_Y, "Threads: %d ", i_threads); + refresh(); + pthread_mutex_unlock( &s_mutx::get().mut_stdout ); +} + +void +sock::print_hits() +{ + pthread_mutex_lock ( &s_mutx::get().mut_stdout ); + mvprintw( NCUR_HITS_X,NCUR_HITS_Y, "Hits: %d ", i_req); + refresh(); + pthread_mutex_unlock( &s_mutx::get().mut_stdout ); +} +#endif + +#endif @@ -0,0 +1,74 @@ +// class sock declaration. + +#ifndef s_sock_H +#define s_sock_H + +#include <queue> +#include <arpa/inet.h> +#include <errno.h> +#include <netdb.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> + +#include "incl.h" +#include "pool.h" +#include "reqp.h" +#include "thrd.h" +#include "user.h" +#include "logd.h" +using namespace std; + +class sock +{ +private: + // total number of server requests. + unsigned long long int i_req; + + bool b_run; // true while socket manager is running. + reqp* req_parser; // parses the http requests from clients. + pool* thrd_pool; // the thread pool. + logd* log_daemon; // the log daemon + char* c_buffer; // char buffer! + + int i_threads; // total amount of threads inside the thread pool. + pthread_mutex_t mut_threads; + pthread_mutex_t mut_hits; + + // creates a server socket. + virtual int make_socket( uint16_t port ); + +public: + // small inline methods: + bool get_run() const + { + return b_run; + } + bool set_run( bool b_run ) + { + this->b_run = b_run; + } + + // public methods. + explicit sock( ); // simple constructor. + ~sock( ); + virtual int read_write( thrd* p_thrd, int filedes ); + virtual int start(); + + // the chat stream there all the chat messages will sent through. + static void chat_stream( int i_sock, user* p_user, map_string &map_params ); + + void increase_num_threads(); + void decrease_num_threads(); +#ifdef NCURSES + + void print_threads(); + void print_hits(); +#endif + +}; + +#endif diff --git a/thrd.cpp b/thrd.cpp new file mode 100755 index 0000000..b36099c --- /dev/null +++ b/thrd.cpp @@ -0,0 +1,29 @@ +// class thrd implementation. + +#ifndef THRD_CXX +#define THRD_CXX + +#include "thrd.h" +#include "s_sock.h" + +using namespace std; + +thrd::thrd( int i_sock ) +{ + this->i_sock = i_sock; +} + +thrd::~thrd() +{ + shutdown ( get_sock() , 2 ); + close ( get_sock() ); +} + +void +thrd::run() +{ + s_sock::get + ().read_write( this, i_sock ); +} + +#endif @@ -0,0 +1,29 @@ +// class thrd declaration. + +#ifndef THRD_H +#define THRD_H + +#include "incl.h" + +using namespace std; + +class thrd +{ +private: + int i_sock; + +public: + + // small inline methods: + int get_sock() + { + return i_sock; + } + + // public methods: + explicit thrd( int i_sock ); + ~thrd(); // destructor. + virtual void run(); +}; + +#endif diff --git a/todo.txt b/todo.txt new file mode 100755 index 0000000..a91db42 --- /dev/null +++ b/todo.txt @@ -0,0 +1,39 @@ +BRAIN-STORMING: + +bugfixes ( see known bugs ). +rewrite html::online_list as a dynmod mods/html/yc_online_list.so +add password nick protection +add superuser privileges +add libmysqlclient and ncurses test to the configure script +completion of the admin ncurses interface. +user profiles +security: crypto +more modules: commands etc.. +irc support +icq support +hash_map []-operator +hash_map in cont +several different html templates +each user should be able to select his favourite html style +each user should be able to select his favourite system language +makefile as a replacement of mods/compile.sh +kqueue @ freebsd +dynamic thread pool +offline messages ( memos ) +The sanction of HTML tags from the list of the superuser + + + + +10: bugfixes +20: goto 10 + +Linux bugs: +- No bugs which only appear on Linux. + +FreeBSD bugs: +- No bugs which only appear on FreeBSD. + +Bugs wich appear on both, Linux and FreeBSD: +- some user do not log out automaticaly ( we have to implement an activity counter ). +- Segmentation fault if another room is created. multi room usage has not been tested yet but should work without big modifications. diff --git a/user.cpp b/user.cpp new file mode 100755 index 0000000..94d4496 --- /dev/null +++ b/user.cpp @@ -0,0 +1,312 @@ +// class user implementation. + +#ifndef USER_CXX +#define USER_CXX + +#include "user.h" +#include "s_conf.h" +#include "s_modl.h" +#include "s_tool.h" + +using namespace std; + +user::user( string s_name ) : name( s_name ) +{ + this -> b_online = true; + this -> l_time = s_tool::unixtime(); + this -> s_col1 = s_conf::get + ().get_val( "USERCOL1" ); + this -> s_col2 = s_conf::get + ().get_val( "USERCOL2" ); + map_mods = new hmap<dynmod*,string>(80); + + pthread_mutex_init( &mut_b_online, NULL); + pthread_mutex_init( &mut_i_sock , NULL); + pthread_mutex_init( &mut_l_time , NULL); + pthread_mutex_init( &mut_p_room , NULL); + pthread_mutex_init( &mut_s_mess , NULL); + pthread_cond_init ( &cond_message, NULL); + pthread_mutex_init( &mut_message , NULL); + pthread_mutex_init( &mut_map_mods, NULL ); + pthread_mutex_init( &mut_s_col1, NULL ); + pthread_mutex_init( &mut_s_col2, NULL ); + pthread_mutex_init( &mut_s_id, NULL ); + pthread_mutex_init( &mut_r_rang, NULL ); +} + +user::~user() +{ + pthread_mutex_destroy( &mut_b_online ); + pthread_mutex_destroy( &mut_i_sock ); + pthread_mutex_destroy( &mut_l_time ); + pthread_mutex_destroy( &mut_p_room ); + pthread_mutex_destroy( &mut_s_mess ); + pthread_cond_destroy ( &cond_message ); + pthread_mutex_destroy( &mut_message ); + pthread_mutex_destroy( &mut_s_col1 ); + pthread_mutex_destroy( &mut_s_col2 ); + pthread_mutex_destroy( &mut_s_id ); + pthread_mutex_destroy( &mut_r_rang ); +} + +string +user::get_colored_name() +{ + return "<font color=\"#" + get_col1() + "\">" + get_name() + "</font>"; +} + +void +user::get_data( map_string *p_map_data ) +{ + string s_req = (*p_map_data)["!get"]; + + // get the nick and the color of the user. + if ( s_req == "nick" ) + (*p_map_data)[get_name()] = get_col1(); +} + +string +user::get_mess( ) +{ + pthread_mutex_lock ( &mut_s_mess ); + string s_ret = s_mess; + s_mess = ""; + pthread_mutex_unlock( &mut_s_mess ); + return s_ret; +} + +bool +user::get_online( ) +{ + bool b_ret; + pthread_mutex_lock ( &mut_b_online ); + b_ret = b_online; + pthread_mutex_unlock( &mut_b_online ); + return b_ret; +} + +void +user::set_online( bool b_online ) +{ + pthread_mutex_lock ( &mut_b_online ); + this -> b_online = b_online; + pthread_mutex_unlock( &mut_b_online ); +} + +room* +user::get_room( ) +{ + room* p_return; + pthread_mutex_lock ( &mut_p_room ); + p_return = p_room; + pthread_mutex_unlock( &mut_p_room ); + return p_return; +} + +void +user::set_p_room( room* p_room ) +{ + pthread_mutex_lock ( &mut_p_room ); + this -> p_room = p_room; + pthread_mutex_unlock( &mut_p_room ); +} + +int +user::get_sock( ) +{ + int i_ret; + pthread_mutex_lock ( &mut_i_sock ); + i_ret = i_sock; + pthread_mutex_unlock( &mut_i_sock ); + return i_ret; +} + +void +user::set_sock( int i_sock ) +{ + pthread_mutex_lock ( &mut_i_sock ); + this -> i_sock = i_sock; + pthread_mutex_unlock( &mut_i_sock ); +} + +string +user::get_col1() +{ + string s_ret; + pthread_mutex_lock ( &mut_s_col1 ); + s_ret = s_col1; + pthread_mutex_unlock( &mut_s_col1 ); + return s_ret; +} + +string +user::get_col2() +{ + string s_ret; + pthread_mutex_lock ( &mut_s_col2 ); + s_ret = s_col2; + pthread_mutex_unlock( &mut_s_col2 ); + return s_ret; +} + +string +user::get_id() +{ + string s_ret; + pthread_mutex_lock ( &mut_s_id ); + s_ret = s_id; + pthread_mutex_unlock( &mut_s_id ); + return s_ret; +} + +void +user::set_id ( string s_id ) +{ + pthread_mutex_lock ( &mut_s_id ); + this -> s_id = s_id; + pthread_mutex_unlock( &mut_s_id ); +} + +void +user::set_col1 ( string s_col1 ) +{ + pthread_mutex_lock ( &mut_s_col1 ); + this -> s_col1 = s_col1; + pthread_mutex_unlock( &mut_s_col1 ); +} + +void +user::set_col2 ( string s_col2 ) +{ + pthread_mutex_lock ( &mut_s_col2 ); + this -> s_col2 = s_col2; + pthread_mutex_unlock( &mut_s_col2 ); +} + +rang +user::get_rang ( ) +{ + rang r_ret; + pthread_mutex_lock ( &mut_r_rang ); + r_ret = r_rang; + pthread_mutex_unlock(&mut_r_rang ); + return r_ret; +} + +void +user::set_rang ( rang r_rang ) +{ + pthread_mutex_lock ( &mut_r_rang ); + r_oldr = this -> r_rang; + this -> r_rang = r_rang; + pthread_mutex_unlock( &mut_r_rang ); +} + +bool +user::new_msgs ( ) +{ + pthread_mutex_lock ( &mut_s_mess ); + return s_mess.empty(); + pthread_mutex_unlock( &mut_s_mess ); +} + +void +user::command( string &s_command ) +{ + + auto unsigned int pos = s_command.find( "/" ); + auto unsigned int pos2 = s_command.find( " " ); + if( pos != string::npos ) + { + s_command.replace( pos, 1, "" ); + } + else + return; + + + if(pos2==string::npos) + pos2=s_command.size()+1; + + string s_mod( "mods/commands/yc_" ); + string s_command2=s_command.substr(0, pos2-1); + s_mod.append( s_command2 ).append( ".so" ); + + dynmod *mod = s_modl::get + ().get_module( s_mod ); + + if ( mod == NULL ) + { + msg_post( new string( s_lang::get + ().get_val( "ERRORCMD" ) ) ); + return; + } + + vector<string> params; + string *ptr_command; + + // execute the module. + if(s_command.find(" ")!=string::npos) + { + s_command=s_command.substr(s_command2.size()+1); + ptr_command=new string(s_command); + + pos=s_command.find(" "); + pos2=0; + + while(pos != string::npos) + { + string sParam=s_command.substr(pos2,pos - pos2); + params.push_back(sParam); + pos2=pos+1; + pos=s_command.find(" ", pos2); + } + + if(pos2<s_command.size()) + params.push_back(s_command.substr(pos2, s_command.size()-pos2)); + + } + else + { + ptr_command=new string(""); + } + + container *c = new container; + c->elem[0]=(void*) ptr_command; + c->elem[1]=(void*) this; + c->elem[2]=(void*) ¶ms; + c->elem[3]=(void*) &s_conf::get(); + + ( *(mod->the_func) ) ( (void*) c ); + +} + +void +user::renew_stamp( ) +{ + pthread_mutex_lock ( &mut_l_time ); + l_time = s_tool::unixtime(); + pthread_mutex_unlock( &mut_l_time ); +} + +void +user::msg_post( string *p_msg ) +{ + pthread_mutex_lock ( &mut_s_mess ); + s_mess.append( *p_msg ); + pthread_mutex_unlock( &mut_s_mess ); + + pthread_cond_signal( &cond_message ); +} + +void +user::get_user_list( string &s_list, string &s_seperator ) +{ + s_list.append( "<font color=\"" ) + .append( get_col1() ) + .append( "\">" ) + .append( get_name() ) + .append( "</font>\n" ) + .append( s_seperator ); + +} +#endif @@ -0,0 +1,92 @@ +// class user declaration. +#ifndef USER_H +#define USER_H + +#include "incl.h" +#include "hmap.h" +#include "name.h" +#include "s_lang.h" +using namespace std; + +class room; + +class user : public name +{ +private: + // private members: + bool b_away; // true if user is away. + bool b_online; // true if user is online. + int i_sock; // user's stream socket descriptor. + long l_time; // user's last activity time. + rang r_rang; // user's rang ( see enum rang @ globals.h ). + rang r_oldr; // user's previous rang. + string s_id; + string s_agnt; // user's http user agent. + string s_away; // user's last away message. + string s_col1; // user's nick color. + string s_col2; // user's text color. + string s_mess; // message string which has to be sent to the user. + room* p_room; // pointer to the user's room. + + // Modules which are allowed to be executed by the user. + hmap<dynmod*,string>* map_mods; + + pthread_mutex_t mut_map_mods; + pthread_mutex_t mut_b_online; + pthread_mutex_t mut_i_sock; + pthread_mutex_t mut_l_time; + pthread_mutex_t mut_s_mess; + pthread_mutex_t mut_p_room; + pthread_mutex_t mut_s_col1; + pthread_mutex_t mut_s_col2; + pthread_mutex_t mut_s_id; + pthread_mutex_t mut_r_rang; + +public: + pthread_cond_t cond_message; + pthread_mutex_t mut_message; + + // public methods: + explicit user( string s_name ); // a standard constructor. + ~user(); // user destructor. + + // gets specific data of this user und stores it in + // (*p_map_string)["nick"]. this method will be used + // every time data has to be got from every user of a room + // or even of the system. + virtual void get_data( map_string *p_map_data ); + + virtual string get_colored_name(); + virtual bool get_online(); + virtual void set_online( bool b_online ); + virtual room* get_room(); + virtual void set_p_room( room* p_room ); + virtual int get_sock ( ); + virtual void set_sock ( int i_sock ); + virtual string get_col1(); + virtual string get_col2(); + virtual string get_id(); + virtual void set_id( string s_id ); + virtual void set_col1( string s_col1 ); + virtual void set_col2( string s_col2 ); + virtual rang get_rang( ); + virtual void set_rang( rang r_rang ); + virtual bool new_msgs ( ); + + // executes a command. + virtual void command( string &s_command ); + + // gets the message and clears s_mess; + virtual string get_mess(); + + // actualizes the user's timestamp. + virtual void renew_stamp(); + + // Here are starting methods which are mainly needed by the data<type> class. + + // appends a string to s_mess including br. + virtual void msg_post( string *p_msg ); + virtual void get_user_list( string &s_list, string &s_seperator ); +}; + +#endif |
