<?php

/*
 Joao Felipe Santiago S. Orui, jfsso@hotmail.com

 Thanks to
    BROADCAST Chat Server 1.3 (http://www.hartwork.org)
    Writing Socket Servers in PHP (http://www.zend.com/pecl/tutorials/sockets.php)
*/


set_time_limit (0);
ob_end_clean();

defineSERVER_ADDRESS,    "0.0.0.0");
defineSERVER_PORT,    8888);
defineJFCWS_VERSION,    "0.9.0001");
defineCRLF,            "\015\012"    );
defineDEBUG,            0            );

$clients = array();
$active_clients 0;
$timeeee 0;

$sock socket_createAF_INETSOCK_STREAM);
socket_bind$sockSERVER_ADDRESSSERVER_PORT ) or die( "Could not bind " SERVER_ADDRESS ":" SERVER_PORT );
socket_listen$sock );

echo 
"Running\n";

while (
true) {
    if(
DEBUG) echo "big loop\n";
    
$read[0] = $sock;
    
$i 0;
    foreach( 
$clients as $val )
    {
        
$read[ ++$i ] = $val"sock" ];
    }

    
$ready socket_select$read$write$except);

    if (
in_array($sock$read)) {
        
jfcws_init($sock);
    }

    for( 
$i 0$i $active_clients$i++ )
    {
        if(
DEBUG) echo "loop\n";
        if( 
in_array$clients$i ][ 'sock' ], $read ) )
        {
            if(
DEBUG) echo "readloop\n";
            
$temp jfcws_read($i,1024);

            if(!
$temp) {
                if(
DEBUG) echo "continue loop\n";
                continue;
            }

            
$input $clients$i ][ "input" ] . $temp;

            
$input preg_replace"/(^|.)\\x08/"""$input );

            
$clients$i ][ "input" ] = $input;
            if(
DEBUG) echo "start jfcws_eval\n";
            
jfcws_eval$i );
            
#jfcws_close_client( $i );
        
}
        if(
$clients$i ][ "req" ]) {
            
jfcws_read_request$i );
        }

    }
    
sleep(1);
}

socket_close($sock);

function 
jfcws_init($sock) {
    global 
$clients$active_clients;
    if(
DEBUG) echo "welcome\n";
    
$clients$active_clients ] = array();
    
$clients$active_clients ][ 'sock' ] = socket_accept($sock);
    
$active_clients++;
}

function 
jfcws_send_header$index $status 200 $location="") {
    if(
DEBUG) echo "jfcws_send_header: start\n";
    global 
$clients;
    if(!
$clients$index ]['headersent']) {
        if(
DEBUG) echo "jfcws_send_header: sending header\n";
        
$clients$index ]['headersent'] = 1;
        
jfcws_write($indexjfcws_httpstatus($status) . CRLF);
        
jfcws_write($index,"Server: JFCWS/" JFCWS_VERSION CRLF);
        
jfcws_write($index,"Content-Type: text/html" CRLF);
        if(
$clients$index ][ "req" ]["params"][1] == 'mainchat' && eregi("msie",$clients$index ][ "req" ]["user-agent"])) {
            echo 
"ie header\n";
            
jfcws_write($index,"Cache-Control: no-store" CRLF);
            
jfcws_write($index,"Pragma: no-cache" CRLF);
            
jfcws_write($index,"Connection: Keep-Alive" CRLF);
            
jfcws_write($index,"Expires: Thu, 01 Jan 1970 00:00:00 GMT" CRLF);
            
jfcws_write($index,"Transfer-Encoding: chunked" CRLF);
        }
        if(
$clients$index ]['sendcookie']) {
            
jfcws_write($index,$clients$index ]['sendcookie']);
            
$clients$index ]['sendcookie'] = '';
        }
        if(
$location)
            
jfcws_write($index,"Location: {$location}" CRLF);

        
jfcws_write($index,CRLF);

        if(
$location) {
            
jfcws_write($index,"<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">" CRLF);
            
jfcws_write($index,"<TITLE>{$status} Moved</TITLE></HEAD><BODY>" CRLF);
            
jfcws_write($index,"<H1>{$status} Moved</H1>" CRLF);
            
jfcws_write($index,"The document has moved" CRLF);
            
jfcws_write($index,"<A HREF=\"{$location}\">here</A>." CRLF);
            
jfcws_write($index,"</BODY></HTML>    " CRLF);
        }
    }
    if(
DEBUG) echo "jfcws_send_header: end\n";
}

function 
jfcws_write$index$text ) {
    if(
DEBUG) echo "jfcws_write: start\n";
    global 
$clients;
    if(!
$clients$index ]['headersent']) {
        if(
DEBUG) echo "jfcws_write: sending header\n";
        
jfcws_send_header$index );
    }
    @
socket_send$clients$index ][ "sock" ], $textstrlen$text ), );
    if(
DEBUG) echo "jfcws_write: end\n";
}

function 
jfcws_raw_write$sock$text ) {
    @
socket_send$sock$textstrlen$text ), );
}


function 
jfcws_read$index$length 1024) {
    global 
$clients;
    if(
DEBUG) echo "read\n";
    
    
$buf=socket_read($clients$index ][ "sock" ],$length,PHP_BINARY_READ);

    if(
is_bool($buf)) {
        if(
DEBUG) echo "chamar close normal\n";
        
jfcws_close_client($index);
        return 
false;
    } elseif(!
$buf && !eregi("msie",$clients$index ][ "req" ]["user-agent"])) {
        if(
DEBUG) echo "chamar close firefox opera\n";
        
jfcws_close_client($index);
        return 
false;
    } else {
        return 
$buf;
    }
}

function 
jfcws_eval$index ) {
    global 
$clients;
    if(
DEBUG) echo "eval\n";
    list(
$header,$postinput) = preg_split('/\n[\s]*\n/',$clients$index ]['input']);
    
$lines preg_split('/[\n\r]+/',$header);
    
$clients$index ][ "req" ] = array();
    list(
$clients$index ][ "req" ]['method'], $objecttemp$clients$index ][ "req" ]['httpreq']) = split(" "$lines[0], 3);
    list(
$clients$index ][ "req" ]['object'],$query) = explode('?',$objecttemp,2);

    
parse_str($query,$clients$index ][ "get" ]);
    
parse_str($postinput,$clients$index ][ "post" ]);

    
$clients$index ][ "req" ]['params'] = explode("/"$clients$index ][ "req" ]['object']);
    for(
$a=1;$a<count($lines)-1;$a++) {
        list(
$aname,$avalue) = split(": "$lines[$a]);
        
$clients$index ][ "req" ][strtolower($aname)] = $avalue;
    }

    
$cookies_input str_replace("; ","&",$clients$index ][ "req" ][ "cookie" ]);
    
parse_str($cookies_input,$clients$index ][ "cookies" ]);

    
print_r($clients$index ]);
    
$clients$index ][ "input" ] = "";
}

function 
jfcws_read_request$index ) {
    if(
DEBUG) echo "jfcws_read_request: start\n";
    global 
$clients,$active_clients,$sock,$timeeee;
    if ( 
$clients$index ][ "req" ]["method"] == 'GET' ) {
        if(
DEBUG) echo "method get\n";
        if(
$clients$index ][ "req" ]["params"][1] == 'mainchat') {
            if(!
$clients$index ][ "req" ]["firsttime"]) {
                
$sendhead = <<<HEAD
<html>

<head>

<title>Room</title>

<style>
body 
{scrollbar-face-color: #dddddd; scrollbar-highlight-color: #eaeaea; scrollbar-shadow-color: #4a4a4a; scrollbar-3dlight-color: #4a4a4a; scrollbar-arrow-color: #4a4a4a; scrollbar-track-color: #dddddd; scrollbar-darkshadow-color: #dddddd; }
br 
{line-height:5px;}
td 
{font-size : 0.8 em; font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; color : black;}
{text-decoration:none;}
</style>
<script language="JavaScript">
<!--
function scrl(a) 
{ self.scroll(0,4999); t_id = setTimeout("scrl()",1000); }
function stop() 
{ clearTimeout(t_id); }
// -->
</script>
</head>
<body>
HEAD;
                
$clients$index ][ "req" ]["firsttime"] = 1;
                
jfcws_write($index,$sendhead);

                    for( 
$i 0$i $active_clients$i++ ) {
                        if(
$clients$i ][ "req" ]["params"][1] == 'mainchat') {
                            
$date date"Y-d-m H:i:s" );
                            
$greeting = <<<GREETING
<table cellspacing="0" cellpadding="3" border="0" width="100%"><tr><td>


<small>(
{$date})</small>


<b><font color="#000000">
{$clients$index ][ "cookies" ]['jfcws_nickname']}</font></b>

 <i>entra na sala...</i>







</td></tr></table><br>
<script type="text/javascript">scrl();</script>
GREETING;
                        
jfcws_write($i,$greeting CRLF);
                        }
                    }
            }
            if(
$timeeee 2) {
                
jfcws_write($index," ");
                
$timeeee 0;
            }
            
$timeeee++;
        } elseif(
$clients$index ][ "req" ]["params"][1] == 'mainform') {
            if(
DEBUG) echo "show form\n";
            
jfcws_write($index,file_get_contents('jfcwsmainform.html'));
            
jfcws_close_client($index);
        } elseif(
$clients$index ][ "req" ]["params"][1] == 'mainframe') {
            if(
DEBUG) echo "show mainframe\n";
            
jfcws_write($index,file_get_contents('jfcwsmainframe.html'));
            
jfcws_close_client($index);
        } elseif(
$clients$index ][ "req" ]["params"][1] == 'shutdown') {
            if(
DEBUG) echo "shutdown: start\n";
            
jfcws_write($index,"shutdown..." CRLF);
            
socket_close($sock);
            if(
DEBUG) echo "shutdown: complete\n";
            exit;
        } elseif(
$clients$index ][ "req" ]["params"][1] == '' || $clients$index ][ "req" ]["params"][1] == 'index') {
            if(
DEBUG) echo "show index\n";
            
jfcws_write($index,file_get_contents('jfcwsindex.html'));
            
jfcws_close_client($index);
        } else {
            if(
DEBUG) echo "show 404\n";
            
jfcws_send_header($index,404);
            
jfcws_write($index,"NOT FOUND" CRLF);
            
jfcws_close_client($index);
        }
    } elseif ( 
$clients$index ][ "req" ]["method"] == 'POST' ) {
        if(
$clients$index ][ "req" ]["params"][1] == 'login') {
            if(
$clients$index ][ "post" ]['nickname']) {
                
jfcws_setcookie($index,"jfcws_nickname",$clients$index ][ "post" ]['nickname']);
                
jfcws_send_header($index,302,"/mainframe");
                
jfcws_close_client($index);
            } else {
                
jfcws_write($index,"no nickname" CRLF);
                
jfcws_close_client($index);
            }
        } elseif(
$clients$index ][ "req" ]["params"][1] == 'mainform') {
                if(
$clients$index ][ "post" ]['message']) {
                    for( 
$i 0$i $active_clients$i++ ) {
                        if(
$clients$i ][ "req" ]["params"][1] == 'mainchat') {
                            
$date date"Y-d-m H:i:s" );
                            
$message = <<<MESSAGE
<table cellspacing="0" cellpadding="3" border="0" width="100%" style="border: solid 1px #999999"><tr><td bgcolor="#F0F0F0">


<small>(
{$date})</small>


<b><font color="#000000">
{$clients$index ][ "cookies" ]['jfcws_nickname']}</font></b>

 <i>fala para</i>
 <b>Todos:</b>
{$clients$index ][ "post" ]['message']}







</td></tr></table><br>
<script type="text/javascript">scrl();</script>







MESSAGE;

                            
//jfcws_write($i,date( "Y-d-m H:i:s" ) . " [" . $clients[ $index ][ "cookies" ]['jfcws_nickname'] . "]: " . $clients[ $index ][ "post" ]['message'] . "<br>" .  CRLF . "<script type=\"text/javascript\">scrl();</script>" . CRLF);
                            
jfcws_write($i,$message CRLF);
                            if(
DEBUG) echo "sent message\n";
                        }
                    }
                } else {
                    
jfcws_write($i," ");
                }
                
jfcws_write($index,file_get_contents('jfcwsmainform.html'));
                
jfcws_close_client($index);
        } else {
            
jfcws_write($index,"post okay" CRLF);
            
jfcws_close_client($index);
        }
    } else {
        if(
DEBUG) echo "bad request\n";
        
jfcws_send_header($index,400);
        
jfcws_write($index,"BAD REQUEST" CRLF);
        
jfcws_close_client($index);
    }
    if(
DEBUG) echo "jfcws_read_request: end\n";
}

function 
jfcws_close_client$index ) {
    if(
DEBUG) echo "closeeee\n";
    if(
DEBUG) echo "jfcws_close_client: start\n";
    global 
$clients$active_clients;
    if(
DEBUG) echo "close\n";
                    for( 
$i 0$i $active_clients$i++ ) {
                        if(
$clients$i ][ "req" ]["params"][1] == 'mainchat' && $clients$index ][ "req" ]["params"][1] == 'mainchat') {
                            
$date date"Y-d-m H:i:s" );
                            
$greeting = <<<GREETING
<table cellspacing="0" cellpadding="3" border="0" width="100%"><tr><td>


<small>(
{$date})</small>


<b><font color="#000000">
{$clients$index ][ "cookies" ]['jfcws_nickname']}</font></b>

 <i>sai da sala...</i>







</td></tr></table><br>
<script type="text/javascript">scrl();</script>
GREETING;
                            
jfcws_write($i,$greeting CRLF);
                        }
                    }


    @
socket_close$clients$index ][ "sock" ] );
    
$clients$index ] = $clients[ --$active_clients ];
    
array_pop$clients );
    if(
DEBUG) echo "jfcws_close_client: end\n";
}

function 
jfcws_setcookie$index $cookiename$cookievalue $cookieexpire=false $cookiepath="" $cookiedomain="" $cookiesecure=false $cookiehttponly=false ) {
    global 
$clients;
    
$header "Set-Cookie: " urlencode($cookiename) . "=" urlencode($cookievalue);
    if (
$cookiepath)
        
$header .= "; Path={$cookiepath}";
    if (
$cookieexpire != false || $cookieexpire != )
        
$header .= "; Max-Age={$cookieexpire}";
    if (
$cookiepath)
        
$header .= "; Path={$cookiepath}";
    if (
$cookiedomain)
        
$header .= "; Domain={$cookiedomain}";
    if (
$cookiesecure)
        
$header .= "; Secure";
    if (
$cookiehttponly)
        
$header .= "; HttpOnly";
   
$clients$index ]['sendcookie'] .= $header CRLF;
}


function 
jfcws_httpstatus$num ) {
   
$http = array (
       
100 => "HTTP/1.x 100 Continue",
       
101 => "HTTP/1.x 101 Switching Protocols",
       
200 => "HTTP/1.x 200 OK",
       
201 => "HTTP/1.x 201 Created",
       
202 => "HTTP/1.x 202 Accepted",
       
203 => "HTTP/1.x 203 Non-Authoritative Information",
       
204 => "HTTP/1.x 204 No Content",
       
205 => "HTTP/1.x 205 Reset Content",
       
206 => "HTTP/1.x 206 Partial Content",
       
300 => "HTTP/1.x 300 Multiple Choices",
       
301 => "HTTP/1.x 301 Moved Permanently",
       
302 => "HTTP/1.x 302 Found",
       
303 => "HTTP/1.x 303 See Other",
       
304 => "HTTP/1.x 304 Not Modified",
       
305 => "HTTP/1.x 305 Use Proxy",
       
307 => "HTTP/1.x 307 Temporary Redirect",
       
400 => "HTTP/1.x 400 Bad Request",
       
401 => "HTTP/1.x 401 Unauthorized",
       
402 => "HTTP/1.x 402 Payment Required",
       
403 => "HTTP/1.x 403 Forbidden",
       
404 => "HTTP/1.x 404 Not Found",
       
405 => "HTTP/1.x 405 Method Not Allowed",
       
406 => "HTTP/1.x 406 Not Acceptable",
       
407 => "HTTP/1.x 407 Proxy Authentication Required",
       
408 => "HTTP/1.x 408 Request Time-out",
       
409 => "HTTP/1.x 409 Conflict",
       
410 => "HTTP/1.x 410 Gone",
       
411 => "HTTP/1.x 411 Length Required",
       
412 => "HTTP/1.x 412 Precondition Failed",
       
413 => "HTTP/1.x 413 Request Entity Too Large",
       
414 => "HTTP/1.x 414 Request-URI Too Large",
       
415 => "HTTP/1.x 415 Unsupported Media Type",
       
416 => "HTTP/1.x 416 Requested range not satisfiable",
       
417 => "HTTP/1.x 417 Expectation Failed",
       
500 => "HTTP/1.x 500 Internal Server Error",
       
501 => "HTTP/1.x 501 Not Implemented",
       
502 => "HTTP/1.x 502 Bad Gateway",
       
503 => "HTTP/1.x 503 Service Unavailable",
       
504 => "HTTP/1.x 504 Gateway Time-out"       
   
);
  
   return(
$http[$num]);
}


?>