summaryrefslogtreecommitdiff
path: root/ychat-0.2
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2013-04-06 13:14:41 +0200
committerPaul Buetow <paul@buetow.org>2013-04-06 13:14:41 +0200
commit9cd3ccffd5372dfde3af478e3f832f18db4be3f1 (patch)
tree631c295a4a4a16b57502b847626763a279bf6df7 /ychat-0.2
parent13aaf70af703748fe096e0664c305cd202637ad2 (diff)
tagging tags
Diffstat (limited to 'ychat-0.2')
-rwxr-xr-xychat-0.2/CHAT.cpp10
-rwxr-xr-xychat-0.2/CHAT.h26
-rwxr-xr-xychat-0.2/CONF.cpp10
-rwxr-xr-xychat-0.2/CONF.h26
-rwxr-xr-xychat-0.2/HTML.cpp10
-rwxr-xr-xychat-0.2/HTML.h26
-rwxr-xr-xychat-0.2/MUTX.cpp10
-rwxr-xr-xychat-0.2/MUTX.h26
-rwxr-xr-xychat-0.2/Makefile12
-rwxr-xr-xychat-0.2/README.txt177
-rwxr-xr-xychat-0.2/SOCK.cpp10
-rwxr-xr-xychat-0.2/SOCK.h26
-rwxr-xr-xychat-0.2/TOOL.cpp33
-rwxr-xr-xychat-0.2/TOOL.h15
-rwxr-xr-xychat-0.2/base.cpp88
-rwxr-xr-xychat-0.2/base.h28
-rwxr-xr-xychat-0.2/chat.cpp121
-rwxr-xr-xychat-0.2/chat.h40
-rwxr-xr-xychat-0.2/cmnd.cpp19
-rwxr-xr-xychat-0.2/cmnd.h18
-rwxr-xr-xychat-0.2/conf.cpp75
-rwxr-xr-xychat-0.2/conf.h24
-rwxr-xr-xychat-0.2/conf.txt47
-rwxr-xr-xychat-0.2/cont.cpp24
-rwxr-xr-xychat-0.2/cont.h25
-rwxr-xr-xychat-0.2/data.h62
-rw-r--r--ychat-0.2/gfx/CVS/Entries3
-rw-r--r--ychat-0.2/gfx/CVS/Repository1
-rw-r--r--ychat-0.2/gfx/CVS/Root1
-rwxr-xr-xychat-0.2/gfx/y_ani_black.gifbin0 -> 61100 bytes
-rwxr-xr-xychat-0.2/gfx/y_ani_white.gifbin0 -> 53536 bytes
-rwxr-xr-xychat-0.2/glob.h56
-rwxr-xr-xychat-0.2/html.cpp132
-rwxr-xr-xychat-0.2/html.h42
-rw-r--r--ychat-0.2/html/CVS/Entries9
-rw-r--r--ychat-0.2/html/CVS/Repository1
-rw-r--r--ychat-0.2/html/CVS/Root1
-rwxr-xr-xychat-0.2/html/blank.html4
-rwxr-xr-xychat-0.2/html/frameset.html20
-rwxr-xr-xychat-0.2/html/index.html31
-rwxr-xr-xychat-0.2/html/input.html32
-rwxr-xr-xychat-0.2/html/notfound.html10
-rwxr-xr-xychat-0.2/html/online.html6
-rwxr-xr-xychat-0.2/html/stream.html29
-rwxr-xr-xychat-0.2/html/y_ani.gifbin0 -> 35107 bytes
-rwxr-xr-xychat-0.2/incl.h16
-rwxr-xr-xychat-0.2/main.cpp86
-rwxr-xr-xychat-0.2/msgs.h38
-rwxr-xr-xychat-0.2/mutx.cpp20
-rwxr-xr-xychat-0.2/mutx.h21
-rwxr-xr-xychat-0.2/name.cpp30
-rwxr-xr-xychat-0.2/name.h28
-rwxr-xr-xychat-0.2/pool.cpp214
-rwxr-xr-xychat-0.2/pool.h77
-rwxr-xr-xychat-0.2/reqp.cpp224
-rwxr-xr-xychat-0.2/reqp.h45
-rwxr-xr-xychat-0.2/room.cpp18
-rwxr-xr-xychat-0.2/room.h34
-rwxr-xr-xychat-0.2/sock.cpp218
-rwxr-xr-xychat-0.2/sock.h51
-rwxr-xr-xychat-0.2/thrd.cpp27
-rwxr-xr-xychat-0.2/thrd.h26
-rwxr-xr-xychat-0.2/todo.txt7
-rwxr-xr-xychat-0.2/user.cpp143
-rwxr-xr-xychat-0.2/user.h79
65 files changed, 2768 insertions, 0 deletions
diff --git a/ychat-0.2/CHAT.cpp b/ychat-0.2/CHAT.cpp
new file mode 100755
index 0000000..1358a06
--- /dev/null
+++ b/ychat-0.2/CHAT.cpp
@@ -0,0 +1,10 @@
+#ifndef GCHT_CXX
+#define GCHT_CXX
+
+#include "CHAT.h"
+
+using namespace std;
+
+chat* CHAT::obj;
+
+#endif
diff --git a/ychat-0.2/CHAT.h b/ychat-0.2/CHAT.h
new file mode 100755
index 0000000..6c015f4
--- /dev/null
+++ b/ychat-0.2/CHAT.h
@@ -0,0 +1,26 @@
+#ifndef GCHT_H
+#define GCHT_H
+
+#include "chat.h"
+
+using namespace std;
+
+class CHAT
+{
+private:
+ static chat* obj;
+
+public:
+ static void init()
+ {
+ obj = new chat();
+ }
+
+ static chat& get()
+ {
+ return *obj;
+ }
+};
+
+
+#endif
diff --git a/ychat-0.2/CONF.cpp b/ychat-0.2/CONF.cpp
new file mode 100755
index 0000000..8b5441c
--- /dev/null
+++ b/ychat-0.2/CONF.cpp
@@ -0,0 +1,10 @@
+#ifndef GCON_CXX
+#define GCON_CXX
+
+#include "CONF.h"
+
+using namespace std;
+
+conf* CONF::obj;
+
+#endif
diff --git a/ychat-0.2/CONF.h b/ychat-0.2/CONF.h
new file mode 100755
index 0000000..f3dc5c9
--- /dev/null
+++ b/ychat-0.2/CONF.h
@@ -0,0 +1,26 @@
+#ifndef GCON_H
+#define GCON_H
+
+#include "conf.h"
+
+using namespace std;
+
+class CONF
+{
+private:
+ static conf* obj;
+
+public:
+ static void init()
+ {
+ obj = new conf( CONFILE );
+ }
+
+ static conf& get()
+ {
+ return *obj;
+ }
+};
+
+
+#endif
diff --git a/ychat-0.2/HTML.cpp b/ychat-0.2/HTML.cpp
new file mode 100755
index 0000000..a93bc0a
--- /dev/null
+++ b/ychat-0.2/HTML.cpp
@@ -0,0 +1,10 @@
+#ifndef GHTM_CXX
+#define GHTM_CXX
+
+#include "HTML.h"
+
+using namespace std;
+
+html* HTML::obj;
+
+#endif
diff --git a/ychat-0.2/HTML.h b/ychat-0.2/HTML.h
new file mode 100755
index 0000000..16bf13d
--- /dev/null
+++ b/ychat-0.2/HTML.h
@@ -0,0 +1,26 @@
+#ifndef GHTM_H
+#define GHTM_H
+
+#include "html.h"
+
+using namespace std;
+
+class HTML
+{
+private:
+ static html* obj;
+
+public:
+ static void init()
+ {
+ obj = new html();
+ }
+
+ static html& get()
+ {
+ return *obj;
+ }
+};
+
+
+#endif
diff --git a/ychat-0.2/MUTX.cpp b/ychat-0.2/MUTX.cpp
new file mode 100755
index 0000000..41382f3
--- /dev/null
+++ b/ychat-0.2/MUTX.cpp
@@ -0,0 +1,10 @@
+#ifndef GMUT_CXX
+#define GMUT_CXX
+
+#include "MUTX.h"
+
+using namespace std;
+
+mutx* MUTX::obj;
+
+#endif
diff --git a/ychat-0.2/MUTX.h b/ychat-0.2/MUTX.h
new file mode 100755
index 0000000..f2e9980
--- /dev/null
+++ b/ychat-0.2/MUTX.h
@@ -0,0 +1,26 @@
+#ifndef GMUT_H
+#define GMUT_H
+
+#include "mutx.h"
+
+using namespace std;
+
+class MUTX
+{
+private:
+ static mutx* obj;
+
+public:
+ static void init()
+ {
+ obj = new mutx();
+ }
+
+ static mutx& get()
+ {
+ return *obj;
+ }
+};
+
+
+#endif
diff --git a/ychat-0.2/Makefile b/ychat-0.2/Makefile
new file mode 100755
index 0000000..7506171
--- /dev/null
+++ b/ychat-0.2/Makefile
@@ -0,0 +1,12 @@
+SRCS=base.cpp chat.cpp CHAT.cpp cmnd.cpp conf.cpp CONF.cpp cont.cpp html.cpp HTML.cpp main.cpp mutx.cpp MUTX.cpp name.cpp pool.cpp reqp.cpp room.cpp sock.cpp SOCK.cpp thrd.cpp TOOL.cpp user.cpp
+OBJS=$(SRCS:.cpp=.o)
+CC=c++
+LDFLAGS=-lstdc++ -g
+LDADD=-pthread -D_THREAD_SAFE
+all: ychat
+$(SRCS):
+ $(CC) $(CFLAGS) -c $*.cpp
+ychat: $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDADD)
+clean:
+ rm *.o
diff --git a/ychat-0.2/README.txt b/ychat-0.2/README.txt
new file mode 100755
index 0000000..af513e8
--- /dev/null
+++ b/ychat-0.2/README.txt
@@ -0,0 +1,177 @@
+yChat++; Homepage: www.yChat.org; Version 0.2
+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.
+
+-----------------------------------------------------------------
+
+Notes: I programmed this on FreeBSD but should also compile without
+big problems on Linux or other UNIX-like systems.
+If you have tested one of those then pleace write me the name of the OS,
+kernel version, make version and compiler & version. I will list it
+right here:
+
+The following platforms have been tested with success:
+
+- FreeBSD 5.0-RELEASE, GCC 3.2.1, FreeBSD 5.0 make and GNU make 3.80
+
+- Linux Kernel 2.4.19, GCC 3.2.0, GNU make 3.79.1
+
+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 me an email and tell me
+what you can/like/would help ;-]. Please also take a look at the
+yChat++ homepage ( www.yChat.org ).
+
+Installation: Just invoke "make", edit the conf.txt and run the
+server with ./ychat, point your webbrowser to http://yourip:port/index.html
+( ignoring the index.html on the end of the url will not work! ).
+... have fun :-).
+
+If you like customizing 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.
+
+Files:
+
+conf.txt - The yChat configuration file. ( read by conf.cpp ).
+
+base.cpp - Encapsulates vector fields of room's or user ( may be later
+ hash_maps ) and provides methods for manipulating base data
+ objects.
+
+main.cpp - This includes the required manager headers for starting
+ the server and finally regulates the correct starting.
+
+pool.cpp - The implementation of the thread pool. all threads are stored
+ in a queue. Each thread will be reused if the assigned job is
+ finished.
+
+reqp.cpp - This class implements the http request parser. If a client
+ starts a request to the server the reqp class will be
+ invoked.
+
+room.cpp - Specifies a chat room. For each chat room an instance of
+ this class exists.
+
+thrd.cpp - This class is needed by sock.cpp while creating a POSIX thread.
+ All data which a thread needs to do its tasks are stored in a
+ thrd object and then a pointer to it will be passed to the
+ POSIX thread function.
+
+user.cpp - Specifies a chat user. For each chat user an instance of
+ this class exists.
+
+Abstract classes:
+
+cont.cpp - All classes which need to store "key - value" data sets
+ inherit from this class. ( cont for content ).
+
+name.cpp - All classes which own a private member string name inherit
+ from this class. It also provides public get_name and
+ set_name methods.
+
+As described ( main.cpp ), there are so called managers. Managers are
+accessible through their assigned wrapper classes and may be
+instanciated only once.
+
+chat.cpp - The chat manager. Is responsible for managing the internal
+ data structure of the system and also covers a lot of
+ important methods of the system.
+
+conf.cpp - The config manager. Parses the config file specified in
+ glob.h and stores all the values of it in a map.
+
+html.cpp - The html-template manager. Reads the requested html-template
+ files, stores them in an internal cache ( averts reading
+ template-files from hd twice or more ) and parses the
+ partivular template in order to substituate dynamic values
+ of it.
+
+mutx.cpp - The mutex manager. Contains all global mutex handlers for
+ synchronizing POSIX thread shared data. until now only the
+ stdout is synchronized by mutx.cpp because most of objects
+ use their own mutex'.
+
+sock.cpp - The socket manager. Manages the socket connections. There
+ are multiplexed sockets. For each requests a new POSIX thread
+ will be created.
+
+Files written in capital letters contain static C++ classes
+
+CHAT.cpp - Static wrapper for the dynamic chat class. holds one global
+ reachable instance of chat until the program shuts down.
+
+CONF.cpp - Static wrapper for the dynamic conf class. holds one global
+ reachable instance of conf until the program shuts down.
+
+HTML.cpp - Static wrapper for the dynamic html class. holds one global
+ reachable instance of conf until the program shuts down.
+
+MUTX.cpp - Static wrapper for the dynamic mutx class. holds one global
+ reachable instance of conf until the program shuts down.
+
+SOCK.cpp - Static wrapper for the dynamic sock class. holds one global
+ reachable instance of conf until the program shuts down.
+
+TOOL.cpp - Static class which includes some usefull global reachable
+ methods which are not integraded in independent classes.
+
+Special header files ( all other header files which are not listed here
+belong to their respective .cpp files ):
+
+data.h - Implements a generic class ( template class ) for accessing
+ data from a base ( see base.cpp ) object. this methods are
+ all inline and use rekursive algorithm and function pointers.
+
+glob.h - Defines global variables which are known by compilation
+ time.
+
+incl.h - This file is included from every other header file and
+ includes a set of headers which every class should be able
+ to use.
+
+msgs.h - Defines console output messages for verbosity level 0 ( see
+ glob.h for setting up verbosity levels ). and also defines
+ all the system messages. you may edit this file for translating
+ the system user language.
+
+
+The basic class structure:
+
+ base
+ |
+ |
+ data<type> name
+ / \ / \
+ / \ / \
+chat room user
+
+ cont
+ / \
+ / \
+conf html
+
+Version Lines of code
+ 0.1 2402
+ 0.2 2377
+
+New in 0.2:
+ - POST request now work.
+ - Thread pool ( pool.cpp ).
+ - Bugfixes
diff --git a/ychat-0.2/SOCK.cpp b/ychat-0.2/SOCK.cpp
new file mode 100755
index 0000000..c5b451e
--- /dev/null
+++ b/ychat-0.2/SOCK.cpp
@@ -0,0 +1,10 @@
+#ifndef GSOC_CXX
+#define GSOC_CXX
+
+#include "SOCK.h"
+
+using namespace std;
+
+sock* SOCK::obj;
+
+#endif
diff --git a/ychat-0.2/SOCK.h b/ychat-0.2/SOCK.h
new file mode 100755
index 0000000..dacc05f
--- /dev/null
+++ b/ychat-0.2/SOCK.h
@@ -0,0 +1,26 @@
+#ifndef GSOC_H
+#define GSOC_H
+
+#include "sock.h"
+
+using namespace std;
+
+class SOCK
+{
+private:
+ static sock* obj;
+
+public:
+ static void init()
+ {
+ obj = new sock();
+ }
+
+ static sock& get()
+ {
+ return *obj;
+ }
+};
+
+
+#endif
diff --git a/ychat-0.2/TOOL.cpp b/ychat-0.2/TOOL.cpp
new file mode 100755
index 0000000..7709695
--- /dev/null
+++ b/ychat-0.2/TOOL.cpp
@@ -0,0 +1,33 @@
+#ifndef TOOL_CXX
+#define TOOL_CXX
+
+#include <time.h>
+#include "TOOL.h"
+
+int
+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;
+}
+
+long
+TOOL::unixtime()
+{
+ return (long) time( NULL );
+}
+
+#endif
diff --git a/ychat-0.2/TOOL.h b/ychat-0.2/TOOL.h
new file mode 100755
index 0000000..de2c4a2
--- /dev/null
+++ b/ychat-0.2/TOOL.h
@@ -0,0 +1,15 @@
+#ifndef TOOL_H
+#define TOOL_H
+
+#include "incl.h"
+
+using namespace std;
+
+class TOOL
+{
+public:
+ static int string2int( string s_digit );
+ static long unixtime();
+};
+
+#endif
diff --git a/ychat-0.2/base.cpp b/ychat-0.2/base.cpp
new file mode 100755
index 0000000..9a67340
--- /dev/null
+++ b/ychat-0.2/base.cpp
@@ -0,0 +1,88 @@
+// template class data implementation;
+
+#ifndef BASE_CPP
+#define BASE_CPP
+
+#include "base.h"
+
+base::base()
+{
+ pthread_mutex_init (&mut_vec_elem, NULL );
+}
+
+base::~base( )
+{
+ pthread_mutex_destroy( &mut_vec_elem );
+}
+
+void
+base::add_elem( name* p_name )
+{
+ pthread_mutex_lock ( &mut_vec_elem );
+ vec_elem.push_back ( p_name );
+ pthread_mutex_unlock( &mut_vec_elem );
+}
+
+bool
+base::del_elem( string &s_name )
+{
+ vector<name*>::iterator iter;
+ pthread_mutex_lock ( &mut_vec_elem );
+
+ iter = vec_elem.begin();
+ while( iter != vec_elem.end() )
+ {
+ if ( (*iter)->get_name() == s_name )
+ {
+ vec_elem.erase( iter );
+ pthread_mutex_unlock( &mut_vec_elem );
+ return true;
+ }
+ iter++;
+ }
+
+ pthread_mutex_unlock( &mut_vec_elem );
+ return false;
+}
+
+name*
+base::get_elem( string &s_name, bool &b_found )
+{
+ vector<name*>::iterator iter;
+ pthread_mutex_lock ( &mut_vec_elem );
+
+ iter = vec_elem.begin();
+ while( iter != vec_elem.end() )
+ {
+ if ( (*iter)->get_name() == s_name )
+ {
+ b_found = true;
+ pthread_mutex_unlock( &mut_vec_elem );
+ return (*iter);
+ }
+ iter++;
+ }
+
+ pthread_mutex_unlock( &mut_vec_elem );
+
+ b_found = false;
+
+ return new name();
+}
+
+void
+base::run_func( void (*func)(name*, void*), void* v_arg )
+{
+ vector<name*>::iterator iter;
+ pthread_mutex_lock ( &mut_vec_elem );
+
+ // execute func foreach element of vec_elem with
+ // 1st argument: a pointer of a element of vec_elem.
+ // 2nd argument: a void pointer of a object.
+ for( iter = vec_elem.begin(); iter != vec_elem.end(); iter++ )
+ ( *func ) ( (*iter), v_arg );
+
+ pthread_mutex_unlock( &mut_vec_elem );
+}
+
+#endif
diff --git a/ychat-0.2/base.h b/ychat-0.2/base.h
new file mode 100755
index 0000000..d1c37ba
--- /dev/null
+++ b/ychat-0.2/base.h
@@ -0,0 +1,28 @@
+// template class data declaration;
+
+#ifndef BASE_H
+#define BASE_H
+
+#include <vector>
+#include "incl.h"
+#include "name.h"
+
+class base
+{
+private:
+ vector<name*> vec_elem ;
+ pthread_mutex_t mut_vec_elem;
+
+public:
+ base();
+ ~base();
+
+ virtual void add_elem( name* p_name ); // add a element.
+ virtual bool del_elem( string &s_name ); // delete a alement.
+ virtual name* get_elem( string &s_name, bool &b_found ); // get a element.
+
+ // execute func on all elements of vec_elem. v_pointer is the argument.
+ virtual void run_func( void (*func)(name*, void*), void* v_arg );
+};
+
+#endif
diff --git a/ychat-0.2/chat.cpp b/ychat-0.2/chat.cpp
new file mode 100755
index 0000000..7b0ccd2
--- /dev/null
+++ b/ychat-0.2/chat.cpp
@@ -0,0 +1,121 @@
+// class chat implementation.
+
+#ifndef CHAT_CXX
+#define CHAT_CXX
+
+#include "chat.h"
+#include "CONF.h"
+#include "MUTX.h"
+
+using namespace std;
+
+chat::chat( )
+{
+}
+
+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*)&param );
+
+ if ( *( (bool*)param.elem[1] ) )
+ return (user*)param.elem[2];
+}
+
+void
+chat::get_user_( name *name_obj, void *v_arg )
+{
+ container* param = (container*) v_arg;
+ room *room_obj = static_cast<room*>(name_obj);
+ 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"] = 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"] = 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 _VERBOSE
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cout << NEWROOM << s_room << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#endif
+
+ add_elem( p_room );
+ }
+
+ user *p_user = new user( s_user );
+
+ // add user to the room.
+ p_room->add_user( p_user );
+
+ // post "username enters the chat" into the room.
+ p_room->msg_post( new string( s_user.append( USERENTR ) ) );
+
+#ifdef _VERBOSE
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cout << LOGINPR << s_user << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#endif
+}
+
+void
+chat::post( user* u_user, map_string &map_params )
+{
+ string s_msg( "<font color=\"" );
+ s_msg.append( u_user->get_col1() )
+ .append( "\">" )
+ .append( u_user->get_name() )
+ .append( ": " )
+ .append( map_params["message"] )
+ .append( "</font><br>\n" );
+
+ u_user->get_p_room()->msg_post( &s_msg );
+}
+
+#endif
diff --git a/ychat-0.2/chat.h b/ychat-0.2/chat.h
new file mode 100755
index 0000000..164c0c4
--- /dev/null
+++ b/ychat-0.2/chat.h
@@ -0,0 +1,40 @@
+// class chat declaration.
+
+#ifndef CHAT_H
+#define CHAT_H
+
+#include <vector>
+#include "incl.h"
+#include "data.h"
+#include "room.h"
+#include "user.h"
+
+using namespace std;
+
+class chat : public data<room>
+{
+private:
+
+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_( name* name_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/ychat-0.2/cmnd.cpp b/ychat-0.2/cmnd.cpp
new file mode 100755
index 0000000..9ab008a
--- /dev/null
+++ b/ychat-0.2/cmnd.cpp
@@ -0,0 +1,19 @@
+// class cmnd implementation.
+
+#ifndef CMND_CXX
+#define CMND_CXX
+
+#include "cmnd.h"
+#include "MUTX.h"
+
+using namespace std;
+
+cmnd::cmnd( )
+{
+}
+
+cmnd::~cmnd()
+{
+}
+
+#endif
diff --git a/ychat-0.2/cmnd.h b/ychat-0.2/cmnd.h
new file mode 100755
index 0000000..2eb1db2
--- /dev/null
+++ b/ychat-0.2/cmnd.h
@@ -0,0 +1,18 @@
+// class cmnd declaration.
+
+#ifndef CMND_H
+#define CMND_H
+
+#include "incl.h"
+
+using namespace std;
+
+class cmnd
+{
+public:
+ // public methods:
+ explicit cmnd( ); // a standard constructor.
+ ~cmnd( );
+};
+
+#endif
diff --git a/ychat-0.2/conf.cpp b/ychat-0.2/conf.cpp
new file mode 100755
index 0000000..5214edb
--- /dev/null
+++ b/ychat-0.2/conf.cpp
@@ -0,0 +1,75 @@
+// class conf implementation.
+
+#ifndef CONF_CXX
+#define CONF_CXX
+
+#include <fstream>
+#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
+
+ ifstream fs_conf( get_name().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 VERBOSE
+ cout << s_key << "=" << s_val << endl;
+#endif
+
+ // fill the map.
+ map_vals[s_key] = s_val;
+ }
+
+ fs_conf.close();
+ fs_conf.~ifstream();
+}
+
+#endif
diff --git a/ychat-0.2/conf.h b/ychat-0.2/conf.h
new file mode 100755
index 0000000..a3b5022
--- /dev/null
+++ b/ychat-0.2/conf.h
@@ -0,0 +1,24 @@
+// class conf declaration. this class parses the server config file.
+
+#ifndef CONF_H
+#define 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
diff --git a/ychat-0.2/conf.txt b/ychat-0.2/conf.txt
new file mode 100755
index 0000000..c31c554
--- /dev/null
+++ b/ychat-0.2/conf.txt
@@ -0,0 +1,47 @@
+#
+# please notice this:
+# the server parses this configuration file while starting or by an
+# administrator's request.
+#
+# not allowed are semicolons ';' inside or before the quotes " ",
+# otherwise this might result in errors.
+#
+# the syntax is easy: KEYNAME="value";
+#
+# 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@ychat.org );
+#
+
+# server specific configurations ( not allowed to be removed ):
+
+HTMLTEMP="html/"; # directory of the html-template files.
+THRDPOOL="10"; # thread pool size. every time all threads are used so many new
+ # threads will be added to the pool.
+THRDQUEU="100"; # length of the thread pool queue.
+SRVRPORT="2000"; # local port on which the server listens.
+STRDROOM="Lounge"; # the name of the standard room.
+
+# 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="#000000";
+
+# 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.
+
+# 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++ Basic - Fast Simple Extensible";
+
+# end.
diff --git a/ychat-0.2/cont.cpp b/ychat-0.2/cont.cpp
new file mode 100755
index 0000000..91cbbca
--- /dev/null
+++ b/ychat-0.2/cont.cpp
@@ -0,0 +1,24 @@
+// class cont implementation.
+
+#ifndef CONT_CXX
+#define CONT_CXX
+
+#include "cont.h"
+#include "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
diff --git a/ychat-0.2/cont.h b/ychat-0.2/cont.h
new file mode 100755
index 0000000..06a09e2
--- /dev/null
+++ b/ychat-0.2/cont.h
@@ -0,0 +1,25 @@
+// class cont declaration. defines a simple data container class.
+
+#ifndef CONT_H
+#define CONT_H
+
+#include "incl.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
diff --git a/ychat-0.2/data.h b/ychat-0.2/data.h
new file mode 100755
index 0000000..55dbc69
--- /dev/null
+++ b/ychat-0.2/data.h
@@ -0,0 +1,62 @@
+#ifndef DATA_H
+#define DATA_H
+
+#include "base.h"
+#include "MUTX.h"
+
+using namespace std;
+
+template<class type>
+class data : public base
+{
+public:
+
+ // 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( &data<type>::msg_post_ , (void*)s_msg );
+ }
+ static void msg_post_( name* name_obj, void* v_arg )
+ {
+ string *p_msg = (string*) v_arg;
+ type *type_obj = static_cast<type*>(name_obj);
+
+ type_obj -> msg_post( p_msg );
+ }
+
+ void get_data( map_string *p_map_string )
+ {
+ run_func( &data<type>::get_data_ , (void*)p_map_string );
+ }
+ static void get_data_( name* name_obj, void* v_arg )
+ {
+ map_string *map_params = (map_string*) v_arg;
+ type *type_obj = static_cast<type*>(name_obj);
+
+ 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( &data<type>::get_user_list_, (void*)&c );
+ }
+ static void get_user_list_( name* name_obj, void* v_arg )
+ {
+ container *c = (container*) v_arg;
+ type *type_obj = static_cast<type*>(name_obj);
+
+ type_obj -> get_user_list( *((string*)c->elem[0]), *((string*)c->elem[1]) );
+ }
+};
+
+#endif
diff --git a/ychat-0.2/gfx/CVS/Entries b/ychat-0.2/gfx/CVS/Entries
new file mode 100644
index 0000000..5178e8f
--- /dev/null
+++ b/ychat-0.2/gfx/CVS/Entries
@@ -0,0 +1,3 @@
+/y_ani_black.gif/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/y_ani_white.gif/1.1.1.1/Fri Mar 21 15:54:56 2003//
+D
diff --git a/ychat-0.2/gfx/CVS/Repository b/ychat-0.2/gfx/CVS/Repository
new file mode 100644
index 0000000..6d97963
--- /dev/null
+++ b/ychat-0.2/gfx/CVS/Repository
@@ -0,0 +1 @@
+ychat/gfx
diff --git a/ychat-0.2/gfx/CVS/Root b/ychat-0.2/gfx/CVS/Root
new file mode 100644
index 0000000..6de547b
--- /dev/null
+++ b/ychat-0.2/gfx/CVS/Root
@@ -0,0 +1 @@
+:pserver:paul@internal.ath.cx:/home/cvsroot
diff --git a/ychat-0.2/gfx/y_ani_black.gif b/ychat-0.2/gfx/y_ani_black.gif
new file mode 100755
index 0000000..06274c2
--- /dev/null
+++ b/ychat-0.2/gfx/y_ani_black.gif
Binary files differ
diff --git a/ychat-0.2/gfx/y_ani_white.gif b/ychat-0.2/gfx/y_ani_white.gif
new file mode 100755
index 0000000..168c937
--- /dev/null
+++ b/ychat-0.2/gfx/y_ani_white.gif
Binary files differ
diff --git a/ychat-0.2/glob.h b/ychat-0.2/glob.h
new file mode 100755
index 0000000..37741f8
--- /dev/null
+++ b/ychat-0.2/glob.h
@@ -0,0 +1,56 @@
+// 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.
+#define CONFILE "conf.txt"
+
+// 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
+
+// definition for verbosity level 0 ( normal outputs ). see vmsg.h for custumizing all
+// the messages. this messages will only printed out by the master thread.
+#define _VERBOSE
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// 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;
+
+struct container
+{
+ void* elem[3];
+};
+
+#endif
diff --git a/ychat-0.2/html.cpp b/ychat-0.2/html.cpp
new file mode 100755
index 0000000..ad0de08
--- /dev/null
+++ b/ychat-0.2/html.cpp
@@ -0,0 +1,132 @@
+// class html implementation.
+
+#ifndef HTML_CXX
+#define HTML_CXX
+
+#include <fstream>
+#include "html.h"
+#include "CHAT.h"
+#include "MUTX.h"
+
+using namespace std;
+
+html::html( )
+{
+ set_name( 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() );
+
+ if ( ! fs_templ )
+ {
+ map_params["request"] = CONF::get().get_val( "NOTFOUND" );
+ return parse( map_params );
+ }
+
+ auto char c_buf[READBUF];
+
+ while( fs_templ.getline( c_buf, READBUF ) )
+ s_templ.append( string( c_buf ).append( "\n" ) );
+
+ fs_templ.close();
+
+#ifdef _VERBOSE
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cout << TECACHE << s_path << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#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 = 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_p_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
+
diff --git a/ychat-0.2/html.h b/ychat-0.2/html.h
new file mode 100755
index 0000000..9acf5a9
--- /dev/null
+++ b/ychat-0.2/html.h
@@ -0,0 +1,42 @@
+// class html declaration. this class manages the html-template files.
+
+#ifndef HTML_H
+#define HTML_H
+
+#include "incl.h"
+#include "cont.h"
+#include "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.
+ virtual string parse( map_string &map_params );
+
+ virtual void online_list( user *p_user, map_string &map_params );
+};
+
+#endif
diff --git a/ychat-0.2/html/CVS/Entries b/ychat-0.2/html/CVS/Entries
new file mode 100644
index 0000000..6738646
--- /dev/null
+++ b/ychat-0.2/html/CVS/Entries
@@ -0,0 +1,9 @@
+/blank.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/frameset.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/index.html/1.2/Sun Mar 23 19:03:13 2003//
+/input.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/notfound.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/online.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/stream.html/1.1.1.1/Fri Mar 21 15:54:56 2003//
+/y_ani.gif/1.1.1.1/Fri Mar 21 15:54:56 2003//
+D
diff --git a/ychat-0.2/html/CVS/Repository b/ychat-0.2/html/CVS/Repository
new file mode 100644
index 0000000..3648237
--- /dev/null
+++ b/ychat-0.2/html/CVS/Repository
@@ -0,0 +1 @@
+ychat/html
diff --git a/ychat-0.2/html/CVS/Root b/ychat-0.2/html/CVS/Root
new file mode 100644
index 0000000..6de547b
--- /dev/null
+++ b/ychat-0.2/html/CVS/Root
@@ -0,0 +1 @@
+:pserver:paul@internal.ath.cx:/home/cvsroot
diff --git a/ychat-0.2/html/blank.html b/ychat-0.2/html/blank.html
new file mode 100755
index 0000000..4ddd1a7
--- /dev/null
+++ b/ychat-0.2/html/blank.html
@@ -0,0 +1,4 @@
+<html>
+ <body>
+ </body>
+</html>
diff --git a/ychat-0.2/html/frameset.html b/ychat-0.2/html/frameset.html
new file mode 100755
index 0000000..fe6b973
--- /dev/null
+++ b/ychat-0.2/html/frameset.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<title>
+ %%PGETITLE%%
+</title>
+</head>
+ <frameset rows="*,60">
+ <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">
+ </frameset>
+ <frameset rows="*,0">
+ <frame src="input.html?event=input&nick=%%nick%%&tmpid=%%tmpid%%" name="input">
+ <frame src="blank.html" name="blank">
+ </frameset>
+ </frameset>
+</html>
diff --git a/ychat-0.2/html/index.html b/ychat-0.2/html/index.html
new file mode 100755
index 0000000..172c851
--- /dev/null
+++ b/ychat-0.2/html/index.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+<title>
+ %%PGETITLE%%
+</title>
+</head>
+<body>
+Welcome to
+<pre>
+ ___ _ _
+ _ _ / __\ |__ __ _| |_
+| | | |/ / | '_ \ / _` | __|
+| |_| / /___| | | | (_| | |_
+ \__, \____/|_| |_|\__,_|\__|
+ |___/
+</pre>
+
+<br>
+%%PGETITLE%%
+<br>
+<br>
+%%INFO%%
+Enter your nick:
+<form action="frameset.html" method="POST">
+ <input type="hidden" name="event" value="login">
+ <input type="hidden" name="room" value="%%STRDROOM%%">
+ <input type="text" name="nick">
+ <input type="submit" value="login">
+</form>
+</body>
+</html>
diff --git a/ychat-0.2/html/input.html b/ychat-0.2/html/input.html
new file mode 100755
index 0000000..e6fb016
--- /dev/null
+++ b/ychat-0.2/html/input.html
@@ -0,0 +1,32 @@
+<html>
+ <head>
+ <title>
+ %%PGETITLE%%
+ </title>
+ <script language="JavaScript">
+ <!--
+ function delout()
+ {
+ document.input.message.focus();
+ document.input.message.select();
+ document.input.submit();
+ return false;
+ }
+ function selectinput()
+ {
+ document.input.message.select();
+ }
+ //-->
+ </script>
+ </head>
+ <body>
+ <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();">
+ </form>
+ </body>
+</html>
diff --git a/ychat-0.2/html/notfound.html b/ychat-0.2/html/notfound.html
new file mode 100755
index 0000000..574e341
--- /dev/null
+++ b/ychat-0.2/html/notfound.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>
+ %%PGETITLE%%
+</title>
+</head>
+<body>
+ Page not found.
+</body>
+</html>
diff --git a/ychat-0.2/html/online.html b/ychat-0.2/html/online.html
new file mode 100755
index 0000000..7f29b0e
--- /dev/null
+++ b/ychat-0.2/html/online.html
@@ -0,0 +1,6 @@
+<html>
+ <meta http-equiv="refresh" content="20">
+ <body>
+ %%MESSAGE%%
+ </body>
+</html>
diff --git a/ychat-0.2/html/stream.html b/ychat-0.2/html/stream.html
new file mode 100755
index 0000000..66f8bbd
--- /dev/null
+++ b/ychat-0.2/html/stream.html
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <title>
+ %%PGETITLE%%
+ </title>
+ <script language="JavaScript">
+ function autoScroll()
+ {
+ window.scroll(1, 50000 );
+ timer = setTimeout('autoScroll()',200);
+ }
+
+ autoScroll();
+
+ function stopScroll()
+ {
+ clearTimeout(timer);
+ }
+
+ function startScroll()
+ {
+ timer = setTimeout('autoScroll()', 200);
+ }
+ </script>
+</head>
+<body>
+ Welcome to yChat %%nick%%!
+ <br>
+ <br>
diff --git a/ychat-0.2/html/y_ani.gif b/ychat-0.2/html/y_ani.gif
new file mode 100755
index 0000000..e730988
--- /dev/null
+++ b/ychat-0.2/html/y_ani.gif
Binary files differ
diff --git a/ychat-0.2/incl.h b/ychat-0.2/incl.h
new file mode 100755
index 0000000..f8e483f
--- /dev/null
+++ b/ychat-0.2/incl.h
@@ -0,0 +1,16 @@
+// 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>
+
+// std::string.
+#include <string>
+
+// include all the custom global variables.
+#include "glob.h"
+// include all the custom messages.
+#include "msgs.h"
diff --git a/ychat-0.2/main.cpp b/ychat-0.2/main.cpp
new file mode 100755
index 0000000..2cbc713
--- /dev/null
+++ b/ychat-0.2/main.cpp
@@ -0,0 +1,86 @@
+/*
+ * yChat++; Homepage: www.yChat.org
+ * Copyright (C) 2003 Paul C. Buetow ( Snooper@yChat.org, ICQ: 11655527 )
+ * -----------------------------------------------------------------
+ *
+ * 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.
+ *
+ */
+
+// 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 "CHAT.h"
+
+// include the config manager.
+#include "CONF.h"
+
+// include the html-template manager.
+#include "HTML.h"
+
+// include the mutex manager for global synchronization.
+#include "MUTX.h"
+
+// include the socket manager.
+#include "SOCK.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 HTML::init()
+ // invokations assumes an initialized CONF class.
+ MUTX::init(); // init the mutex manager.
+ CONF::init(); // init the config manager.
+ HTML::init(); // init the html-template manager.
+ SOCK::init(); // init the socket manager.
+ CHAT::init(); // init the chat 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.
+ SOCK::get().start();
+
+#ifdef _VERBOSE
+ cout << DOWNMSG << endl;
+#endif
+
+ return 0;
+}
diff --git a/ychat-0.2/msgs.h b/ychat-0.2/msgs.h
new file mode 100755
index 0000000..f57301c
--- /dev/null
+++ b/ychat-0.2/msgs.h
@@ -0,0 +1,38 @@
+#ifndef MSGS_H
+#define MSGS_H
+
+// message templates.
+// will post "nickname enters the chat" into the room.
+#define USERENTR " enters the chat<br>\n"
+#define USERLEAV " leaves the chat<br>\n"
+
+// several error messages which will apear by the clients.
+#define E_NONICK "You need to specify a nick name<br><br>"
+#define E_NOTONL "An error occured. Your nick is not online<br><br>"
+#define E_ONLINE "The nick you have specified is already online. Try another nick.<br><br>"
+
+// all the custom messages for verbosity outputs. this messages may not
+// be used for html-template value substituation except the CONTACT and
+// DESCRIP variables. the verbosity output will appear in the standard
+// output of the server.
+// alphabetical ordered.
+#define CFILEOK "Parsing config file "
+#define CFILENO "Failed opening config file "
+#define CONNECT "Receiving connection "
+#define CONTACT "Contact: www.yChat.org, Mail@yChat.org "
+#define DESCRIP "yChat++ Copyright (C) 2003 Paul C. Buetow, Volker Richer "
+#define DOWNMSG "Shutting down "
+#define LOGINPR "Login procedure succeeded for nick "
+#define NEWROOM "Adding room "
+#define REQUEST "Request string "
+#define SEPERAT "----------------------------------------- "
+#define SOCKCRT "Creating server socket "
+#define SOCKERR "Could not create socket. Trying next port "
+#define SOCKRDY "Server socket is ready. See port above "
+#define STARTMS "Starting up "
+#define TECACHE "Caching template "
+#define THREADS "Starting thread job "
+#define THREADE "Exiting thread job "
+#define VERSION "Version: 0.2"
+
+#endif
diff --git a/ychat-0.2/mutx.cpp b/ychat-0.2/mutx.cpp
new file mode 100755
index 0000000..bbd5ced
--- /dev/null
+++ b/ychat-0.2/mutx.cpp
@@ -0,0 +1,20 @@
+// class mutx implementation.
+
+#ifndef MUTX_CXX
+#define MUTX_CXX
+
+#include "mutx.h"
+
+using namespace std;
+
+mutx::mutx()
+{
+ pthread_mutex_init( &mut_stdout, NULL );
+}
+
+mutx::~mutx()
+{
+ pthread_mutex_destroy( &mut_stdout );
+}
+
+#endif
diff --git a/ychat-0.2/mutx.h b/ychat-0.2/mutx.h
new file mode 100755
index 0000000..4f6c950
--- /dev/null
+++ b/ychat-0.2/mutx.h
@@ -0,0 +1,21 @@
+// class mutx declaration.
+
+#ifndef MUTX_H
+#define 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/ychat-0.2/name.cpp b/ychat-0.2/name.cpp
new file mode 100755
index 0000000..3ef1280
--- /dev/null
+++ b/ychat-0.2/name.cpp
@@ -0,0 +1,30 @@
+// 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
diff --git a/ychat-0.2/name.h b/ychat-0.2/name.h
new file mode 100755
index 0000000..28a2f91
--- /dev/null
+++ b/ychat-0.2/name.h
@@ -0,0 +1,28 @@
+// 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:
+ // small inline methods:
+ 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/ychat-0.2/pool.cpp b/ychat-0.2/pool.cpp
new file mode 100755
index 0000000..503d0f7
--- /dev/null
+++ b/ychat-0.2/pool.cpp
@@ -0,0 +1,214 @@
+// class pool implementation.
+
+#ifndef POOL_CXX
+#define POOL_CXX
+
+#include "pool.h"
+
+#include "CONF.h"
+#include "MUTX.h"
+#include "TOOL.h"
+#include "thrd.h"
+
+using namespace std;
+
+pool::pool()
+{
+ i_thrd_pool_size = TOOL::string2int( CONF::get().get_val( "THRDPOOL" ) );
+ i_thrd_pool_queue = TOOL::string2int( 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 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "malloc" << endl;
+ pthread_mutex_unlock( &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 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "malloc" << endl;
+ pthread_mutex_unlock( &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 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "pthread_mutex_init " << strerror( rtn ) << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+ exit(-1);
+ }
+
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_empty), NULL ) ) != 0 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "pthread_cond_init " << strerror( rtn ) << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+ exit(-1);
+ }
+
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_full), NULL ) ) != 0 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "pthread_cond_init " << strerror( rtn ) << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+ exit(-1);
+ }
+
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_empty), NULL ) ) != 0 )
+ {
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cerr << "pthread_cond_init " << strerror( rtn ) << endl;
+ pthread_mutex_unlock( &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 )
+{
+#ifdef _VERBOSE
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cout << THREADS << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#endif
+
+ // 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();
+
+ free(v_pointer);
+
+#ifdef _VERBOSE
+ pthread_mutex_lock ( &MUTX::get().mut_stdout );
+ cout << THREADE << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#endif
+}
+
+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;
+ pthread_cond_signal( &(tpool->queue_not_empty) );
+ }
+
+ else
+ {
+ tpool->queue_tail->next = workp;
+ tpool->queue_tail = workp;
+ }
+
+ tpool->cur_queue_size++;
+ pthread_mutex_unlock( &(tpool->queue_lock) );
+ return 1;
+}
+
+#endif
diff --git a/ychat-0.2/pool.h b/ychat-0.2/pool.h
new file mode 100755
index 0000000..358b79f
--- /dev/null
+++ b/ychat-0.2/pool.h
@@ -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/ychat-0.2/reqp.cpp b/ychat-0.2/reqp.cpp
new file mode 100755
index 0000000..6cea6a9
--- /dev/null
+++ b/ychat-0.2/reqp.cpp
@@ -0,0 +1,224 @@
+// class reqp implementation.
+
+#ifndef REQP_CXX
+#define REQP_CXX
+
+#include "reqp.h"
+#include "CHAT.h"
+#include "HTML.h"
+#include "MUTX.h"
+#include "sock.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_CACHEC = "Cash-control: no-cache\n";
+string reqp::HTTP_CONNEC = "Connection: keep-alive\n";
+string reqp::HTTP_COTYPE = "Content-Type: text/html\n\n";
+
+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];
+ read ( p_thrd->get_sock() , c_req, READBUF );
+ 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 ( &MUTX::get().mut_stdout );
+ cout << REQUEST << s_ret << endl;
+ pthread_mutex_unlock( &MUTX::get().mut_stdout );
+#endif
+
+ map_params["request"] = s_ret;
+
+ return s_ret;
+}
+
+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 )
+{
+ // create the http header.
+ string s_rep( HTTP_CODEOK ); s_rep.append( HTTP_SERVER );
+ s_rep.append( HTTP_CONTAC ); s_rep.append( HTTP_CACHEC );
+ s_rep.append( HTTP_CONNEC ); s_rep.append( HTTP_COTYPE );
+
+ // store all request informations in map_params. store the url in
+ // map_params["request"].
+ get_url( p_thrd, s_req, map_params );
+
+ // check the event variable.
+ string s_event( map_params["event"] );
+ if ( ! s_event.empty() )
+ {
+ // login procedure.
+ if ( s_event == "login" )
+ {
+ CHAT::get().login( map_params );
+ }
+
+ else
+ {
+ bool b_found;
+ user* u_user = CHAT::get().get_user( map_params["nick"], b_found );
+
+ if ( ! b_found )
+ {
+ map_params["INFO"] = E_NOTONL;
+ map_params["request"] = CONF::get().get_val( "STARTMPL" ); // redirect to the startpage.
+ }
+
+ // if a message post.
+ else if ( s_event == "post" )
+ CHAT::get().post( u_user, map_params );
+
+ // if a request for the online list of the active room.
+ else if ( s_event == "online" )
+ HTML::get().online_list( u_user, map_params );
+ }
+ }
+
+ // parse and get the requested html-template and also use
+ // the values stored in map_params for %%KEY%% substituations.
+ s_rep.append( HTML::get().parse( map_params ) );
+
+ // return the parsed html-template.
+ return s_rep;
+}
+
+#endif
diff --git a/ychat-0.2/reqp.h b/ychat-0.2/reqp.h
new file mode 100755
index 0000000..4e68a25
--- /dev/null
+++ b/ychat-0.2/reqp.h
@@ -0,0 +1,45 @@
+// 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_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 );
+};
+
+#endif
diff --git a/ychat-0.2/room.cpp b/ychat-0.2/room.cpp
new file mode 100755
index 0000000..0e905e6
--- /dev/null
+++ b/ychat-0.2/room.cpp
@@ -0,0 +1,18 @@
+// 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
diff --git a/ychat-0.2/room.h b/ychat-0.2/room.h
new file mode 100755
index 0000000..077fd28
--- /dev/null
+++ b/ychat-0.2/room.h
@@ -0,0 +1,34 @@
+// class room declaration.
+
+#ifndef ROOM_H
+#define ROOM_H
+
+#include "incl.h"
+#include "data.h"
+#include "name.h"
+#include "user.h"
+
+using namespace std;
+
+class room : public data<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/ychat-0.2/sock.cpp b/ychat-0.2/sock.cpp
new file mode 100755
index 0000000..c996ff5
--- /dev/null
+++ b/ychat-0.2/sock.cpp
@@ -0,0 +1,218 @@
+// 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 SOCK_CXX
+#define SOCK_CXX
+
+#include <unistd.h>
+
+#include "sock.h"
+#include "CHAT.h"
+#include "CONF.h"
+#include "MUTX.h"
+#include "TOOL.h"
+
+#include "chat.h"
+#include "user.h"
+
+using namespace std;
+
+sock::sock()
+{
+ this->b_run = true;
+ this->i_req = 0;
+ this->req_parser = new reqp();
+ this->thrd_pool = new pool();
+}
+
+void
+sock::chat_stream( int i_sock, map_string &map_params )
+{
+ user* p_user = CHAT::get().get_user( map_params["nick"] );
+ p_user->set_sock( i_sock );
+
+ string s_msg( "" );
+
+ pthread_mutex_lock ( &(p_user->mut_message) );
+
+ while( p_user->get_online() )
+ {
+ pthread_cond_wait( &(p_user->cond_message), &(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_mutex_unlock( &(p_user->mut_message) );
+
+ // remove the user from its room.
+ string s_user( p_user->get_name() );
+ p_user->get_p_room()->del_elem( s_user );
+
+ // post the room that the user has left the chat.
+ p_user->get_p_room()->msg_post( new string( p_user->get_name().append( USERLEAV ) ) );
+
+ 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)
+ {
+ cerr << "Sock: socket error" << endl;
+
+ if ( ++i_port > MAXPORT )
+ exit(-1);
+
+ cerr << SOCKERR << i_port << endl;
+ 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)
+ {
+ cerr << "Sock: bind error" << endl;
+
+ if ( ++i_port > MAXPORT )
+ exit(-1);
+
+ cout << SOCKERR << i_port << endl;
+ return make_socket( i_port );
+ }
+
+ 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)
+ {
+ cerr << "Sock: read error " << endl;
+ }
+
+ else
+ {
+ // stores the request params.
+ map_string map_params;
+
+ // get the s_rep ( HTML response which will be send imediatly to the client
+ // and fill map_params with request values.
+ auto string s_temp=(string)c_req;
+
+ string s_rep = req_parser->parse( p_thrd, string( c_req ), map_params );
+
+ // send s_rep to the client.
+ send( i_sock, s_rep.c_str(), s_rep.size(), 0 );
+
+ // prove if this is a request for a chat stream!
+ if ( map_params["event"] == "stream" )
+ chat_stream( i_sock, map_params );
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+sock::start()
+{
+ auto int i_port = TOOL::string2int( CONF::get().get_val( "SRVRPORT" ) );
+
+ int sock;
+ fd_set active_fd_set, read_fd_set;
+ int i;
+ struct sockaddr_in clientname;
+ size_t size;
+
+#ifdef _VERBOSE
+ cout << SOCKCRT << "localhost:" << i_port << endl;
+#endif
+
+ // create the server socket and set it up to accept connections.
+ sock = make_socket ( i_port );
+
+ if (listen (sock, 1) < 0)
+ {
+ cerr << "Sock: listen error" << endl;
+ exit( EXIT_FAILURE );
+ }
+
+#ifdef _VERBOSE
+ cout << SOCKRDY << endl;
+#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)
+ {
+ cerr << "Sock: select error" << endl;
+ 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++;
+ int new_sock;
+ size = sizeof (clientname);
+ new_sock = accept (sock,
+ (struct sockaddr *) &clientname,
+ &size);
+
+ if (new_sock < 0)
+ {
+ cerr << "Sock: accept error" << endl;
+ close ( new_sock );
+ }
+
+#ifdef _VERBOSE
+ cout << CONNECT << i_req << " "
+ << inet_ntoa( clientname.sin_addr )
+ << ":"
+ << ntohs ( clientname.sin_port )
+ << endl;
+#endif
+
+ FD_SET (new_sock, &active_fd_set);
+ }
+
+ else
+ {
+ thrd_pool->run( (void*) new thrd( i ) );
+ FD_CLR( i, &active_fd_set );
+ }
+ }
+ }
+}
+
+#endif
diff --git a/ychat-0.2/sock.h b/ychat-0.2/sock.h
new file mode 100755
index 0000000..abb5878
--- /dev/null
+++ b/ychat-0.2/sock.h
@@ -0,0 +1,51 @@
+// class sock declaration.
+
+#ifndef SOCK_H
+#define 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"
+
+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.
+
+ // the chat stream there all the chat messages will sent through.
+ static void chat_stream( int i_sock, map_string &map_params );
+
+ // 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.
+ virtual int read_write( thrd* p_thrd, int filedes );
+ virtual int start();
+};
+
+#endif
diff --git a/ychat-0.2/thrd.cpp b/ychat-0.2/thrd.cpp
new file mode 100755
index 0000000..7c9be50
--- /dev/null
+++ b/ychat-0.2/thrd.cpp
@@ -0,0 +1,27 @@
+// class thrd implementation.
+
+#ifndef THRD_CXX
+#define THRD_CXX
+
+#include "thrd.h"
+#include "SOCK.h"
+
+using namespace std;
+
+thrd::thrd( int i_sock )
+{
+ this->i_sock = i_sock;
+}
+
+thrd::~thrd()
+{
+ shutdown ( get_sock() , 2 );
+}
+
+void
+thrd::run()
+{
+ SOCK::get().read_write( this, i_sock );
+}
+
+#endif
diff --git a/ychat-0.2/thrd.h b/ychat-0.2/thrd.h
new file mode 100755
index 0000000..fecdb49
--- /dev/null
+++ b/ychat-0.2/thrd.h
@@ -0,0 +1,26 @@
+// 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/ychat-0.2/todo.txt b/ychat-0.2/todo.txt
new file mode 100755
index 0000000..47869ce
--- /dev/null
+++ b/ychat-0.2/todo.txt
@@ -0,0 +1,7 @@
+mysql
+tempid
+commands
+hash_maps
+free pthread memory ( reusable thread pool ? )
+pthread mode 2
+semaphore sync ( ?? )
diff --git a/ychat-0.2/user.cpp b/ychat-0.2/user.cpp
new file mode 100755
index 0000000..5a4068b
--- /dev/null
+++ b/ychat-0.2/user.cpp
@@ -0,0 +1,143 @@
+// class user implementation.
+
+#ifndef USER_CXX
+#define USER_CXX
+
+#include "user.h"
+#include "CONF.h"
+#include "TOOL.h"
+
+using namespace std;
+
+user::user( string s_name ) : name( s_name )
+{
+ this -> b_online = true;
+ this -> l_time = TOOL::unixtime();
+ this -> s_col1 = CONF::get().get_val( "USERCOL1" );
+
+ 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);
+}
+
+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 );
+}
+
+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( )
+{
+ string s_ret( "" );
+ pthread_mutex_lock ( &mut_s_mess );
+ s_ret.append( s_mess );
+ s_mess = *new string("");
+ 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_p_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 );
+}
+
+void
+user::renew_stamp( )
+{
+ pthread_mutex_lock ( &mut_l_time );
+ l_time = 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
diff --git a/ychat-0.2/user.h b/ychat-0.2/user.h
new file mode 100755
index 0000000..1bdd79e
--- /dev/null
+++ b/ychat-0.2/user.h
@@ -0,0 +1,79 @@
+// class user declaration.
+#ifndef USER_H
+#define USER_H
+
+#include "incl.h"
+#include "name.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_agnt; // user's http user agent.
+ string s_away; // user's last away message.
+ string s_col1; // user's nick color.
+ string s_mess; // message string which has to be sent to the user.
+ room* p_room; // pointer to the user's room.
+
+ 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;
+
+public:
+ pthread_cond_t cond_message;
+ pthread_mutex_t mut_message;
+
+ // small inline methods:
+ string get_col1() const { return s_col1; }
+ void set_col1 ( string s_col1 ) { this -> s_col1 = s_col1; }
+
+ rang get_rang ( ) const { return r_rang; }
+ void set_rang ( rang r_rang ) { r_oldr = this -> r_rang;
+ this -> r_rang = r_rang; }
+
+ bool new_msgs ( ) { return s_mess.empty(); }
+ // 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 bool get_online();
+ virtual void set_online( bool b_online );
+ virtual room* get_p_room();
+ virtual void set_p_room( room* p_room );
+ virtual int get_sock ( );
+ virtual void set_sock ( int i_sock );
+
+
+ virtual void renew_stamp();
+
+ // gets the message and clears s_mess;
+ virtual string get_mess();
+
+ // 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