=config('debug','debuglevel',DEBUG_WARNING)) echo $msg."\n"; } $sock = @socket_create(AF_INET,SOCK_STREAM,SOL_TCP) or die('ERROR: socket_create: '.socket_strerror(socket_last_error())."\n"); @socket_bind($sock,config('listen','device','0.0.0.0'),config('listen','port',80)) or die('ERROR: socket_bind: '.socket_strerror(socket_last_error())."\n"); @socket_listen($sock,config('listen','maxconn',20)) or die('ERROR: socket_listen: '.socket_strerror(socket_last_error())."\n"); @socket_set_nonblock($sock) or die('ERROR: socket_set_nonblock: '.socket_strerror(socket_last_error())."\n"); $conn = array(); $CHATUSER = array(); function chatuser_find($nick) { for ($k=array_keys($GLOBALS['CHATUSER']),$l=sizeof($k),$i=0;$i<$l;$i++) if (!strcasecmp($GLOBALS['CHATUSER'][$k[$i]]['nick'],$nick)) return $k[$i]; return NULL; } function chatuser_prepare($nick) { do { $sid = 's'.strtr(md5($nick.time().mt_rand(100000000,199999999)),'0','g'); } while (isset($GLOBALS['CHATUSER'][$sid])); $GLOBALS['CHATUSER'][$sid] = array( 'nick' => $nick, 'sid' => $sid, 'color' => '000000', 'output' => false ); return $sid; } function chatuser_send($text,$except=NULL) { for ($k=array_keys($GLOBALS['CHATUSER']),$l=sizeof($k),$i=0;$i<$l;$i++) if ($GLOBALS['CHATUSER'][$k[$i]]['output']!==$except) socket_write($GLOBALS['conn'][$GLOBALS['CHATUSER'][$k[$i]]['output']]['sock'],$text."\n"); } function httpd_chat__output($conkey) { parse_str($GLOBALS['conn'][$conkey]['header']['query_string'],$query); if ((!isset($query['sid'])) || (!isset($GLOBALS['CHATUSER'][$query['sid']]))) { socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 307 Temporary Redirect\r\nLocation: /\r\n\r\n"); httpd_core__dropconnection($conkey); return; } if (!empty($GLOBALS['CHATUSER'][$query['sid']]['output'])) { httpd_core__error($conkey, 200); return; } $GLOBALS['CHATUSER'][$query['sid']]['output'] = $conkey; $GLOBALS['CHATUSER'][$query['sid']]['login'] = $GLOBALS['CHATUSER'][$query['sid']]['action'] = time(); $GLOBALS['conn'][$conkey]['tickhandler'] = 'httpd_chat__keepalive'; $GLOBALS['conn'][$conkey]['nexttick'] = time()+15; $GLOBALS['conn'][$conkey]['chatsid'] = $query['sid']; $prebuf = " \n"; socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n". 'Willkommen im Chat. Für '. 'eine Übersicht über die Befehle gib "/help" ein.
Viel Spass!

'. $prebuf.$prebuf.$prebuf.$prebuf.$prebuf); chatuser_send(''.date('H:i ').$GLOBALS['CHATUSER'][$GLOBALS['conn'][$conkey]['chatsid']]['nick'].' hat den Chat betreten.
'); } function httpd_chat__input($conkey) { parse_str($GLOBALS['conn'][$conkey]['header']['query_string'],$query); if ((!isset($query['sid'])) || (!isset($GLOBALS['CHATUSER'][$query['sid']]))) { echo 'No such SID: '.$query['sid'].' - SIDs: '.implode(', ',array_keys($GLOBALS['CHATUSER']))."\n"; socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 307 Temporary Redirect\r\nLocation: /\r\n\r\n"); httpd_core__dropconnection($conkey); return; } $GLOBALS['CHATUSER'][$query['sid']]['action'] = time(); if (isset($query['t'])) { $query['t'] = preg_replace('/[\x00-\x1f]+/','',$query['t']); if (strlen(trim($query['t']))==0) ; else if ($query['t']{0}=='/') {} else { chatuser_send('('. $GLOBALS['CHATUSER'][$query['sid']]['nick'].') '.str_replace('<','<',$query['t']).'
'); } httpd_core__error($conkey,204); } else { socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n". '
'. '
'); httpd_core__dropconnection($conkey); } } function httpd_chat__keepalive($conkey) { if (false===@socket_write($GLOBALS['conn'][$conkey]['sock']," ") && (socket_last_error()==10054 || socket_last_error()==10054)) httpd_chat__quitchat($conkey); else if ($GLOBALS['CHATUSER'][$GLOBALS['conn'][$conkey]['chatsid']]['action']+600'.date('H:i ').$GLOBALS['CHATUSER'][$GLOBALS['conn'][$conkey]['chatsid']]['nick'].' hat den Chat verlassen.
',$conkey); # socket_write($GLOBALS['conn'][$conkey]['sock'],''); httpd_core__dropconnection($conkey); } function httpd_chat__index($conkey) { socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); $loginerror = ''; parse_str($GLOBALS['conn'][$conkey]['header']['query_string'],$query); if (isset($query['nick'])) { if (!preg_match('/^[a-zA-Z0-9]{3,15}$/',$query['nick'])) $loginerror = 'Wrong Nickname.
'; else if (false!=$c=chatuser_find($query['nick'])) $loginerror = 'Nickname in use.
'; else { $sid = chatuser_prepare($query['nick']); socket_write($GLOBALS['conn'][$conkey]['sock'],'DC-HTTPd-Chat: '.$query['nick']. ''. ''); httpd_core__dropconnection($conkey); return; } } socket_write($GLOBALS['conn'][$conkey]['sock'],'DC-HTTPd-Chat'. $loginerror.'
Nickname:
'); httpd_core__dropconnection($conkey); } function httpd_core__error($conkey,$err) { switch ($err) { case 200: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 200 OK\r\n\r\n"); break; case 204: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 204 No Content\r\n\r\n"); break; case 205: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 204 Reset Content\r\n\r\n"); break; case 400: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nError 400: Bad Request."); break; case 403: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nError 403: Forbidden."); break; case 404: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 404 File Not Found\r\nContent-Type: text/plain\r\n\r\nError 404: File Not Found."); break; case 500: default: socket_write($GLOBALS['conn'][$conkey]['sock'],"HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nError 500: Internal Server Error."); break; } httpd_core__dropconnection($conkey); } function testpath($res,$path) { return (substr($res,0,strlen($path))==$path); } function httpd_core__httpreq($conkey) { if (false===strpos($GLOBALS['conn'][$conkey]['httpreq'],"\r\n\r\n")) return; $lines = explode("\r\n",$GLOBALS['conn'][$conkey]['httpreq']); if (!preg_match('/^(GET|POST|HEAD) (\/[^?]*)(\?(.*))? (HTTP\/\d\.\d)$/ism',$lines[0],$a)) httpd_core__error($conkey,400); $GLOBALS['conn'][$conkey]['header'] = array( 'method' => strtoupper($a[1]), 'resource' => $res=rawurldecode($a[2]), 'query_string' => $a[4], 'protocol' => strtoupper($a[5]) ); if (strcasecmp($a[1],'head')) { debug('INFO: '.$GLOBALS['conn'][$conkey]['remote_host'].':'.$GLOBALS['conn'][$conkey]['remote_port'].' requested '.$a[2],DEBUG_INFO); if ($res=='/') httpd_chat__index($conkey); else if (testpath($res, '/input/')) httpd_chat__input($conkey); else if (testpath($res, '/output/')) httpd_chat__output($conkey); else httpd_core__error($conkey,404); } else httpd_core__error($conkey,200); } function httpd_core__watchdog($conkey) { if (false===@socket_write($GLOBALS['conn'][$conkey]['sock'],"\0") && socket_last_error()==10053 || socket_last_error()==10054) httpd_core__dropconnection($conkey); else $GLOBALS['conn'][$conkey]['nexttick']=time()+10; } function httpd_core__dropconnection($conkey) { foreach ($GLOBALS['conn'][$conkey]['closehandler'] as $hnd) if (function_exists($hnd)) $hnd($conkey); @socket_close($GLOBALS['conn'][$conkey]['sock']); debug('NOTICE: Connection closed: '.$GLOBALS['conn'][$conkey]['remote_host'].':'.$GLOBALS['conn'][$conkey]['remote_port'],DEBUG_NOTICE); unset($GLOBALS['conn'][$conkey]); } while (1) { if ($ns = @socket_accept($sock)) { socket_set_nonblock($ns); $peer=''; $port=0; socket_getpeername($ns,$peer,$port); $conn[] = array( 'sock' => $ns, 'closehandler' => array(), 'handler' => 'httpd_core__httpreq', 'nexttick' => time()+10, 'tickhandler' => 'httpd_core__watchdog', 'httpreq' => '', 'remote_host' => $peer, 'remote_port' => $port ); debug('NOTICE: Incoming connection from: '.$peer.':'.$port,DEBUG_NOTICE); $ns = $peer = $port = NULL; } for ($k=array_keys($conn),$i=0,$l=sizeof($k);$i<$l;$i++) { $mycon =& $conn[$k[$i]]; if (false!==($buf=@socket_read($mycon['sock'],1,PHP_BINARY_READ))) { do { $mycon['httpreq'] .= $buf; } while(false!==($buf=@socket_read($mycon['sock'],1,PHP_BINARY_READ))); if (function_exists($mycon['handler'])) { $mycon['handler']($k[$i]); } } else if ($mycon['nexttick'] && $mycon['nexttick']