0

After finally wrapping up some things on my end on different problems, I thought I'd switch my attention to one of my previous projects which I want to work to upgrade.

I have a PHP chatroom, which I am told uses long polling to send and receive messages between users on a website of mine (hosted with WAMP server). The same person who told me it was long polling suggested I use Web Sockets. I've found that PHP Web Sockets are only compatible with HTML5 capable browsers, though another friend pointed out to me recently that those browsers are far and few between.

Anyhow, on that note, I want to build an Android app that would connect to this chatroom. Should I use PHP WebSockets? Or just regular sockets?

And finally, what would it take for me to make this overhaul the current code that I have to turn my chatroom into a more socket-based piece of work?

Here are my files.

post.php:

<?php
session_start();
if(isset($_SESSION['user'])){
    $text = $_POST['text'];
    #chmod("log.html", 0777);
    $fp = fopen("log.html", 'a') or die("Unable to open/write file!");

    fwrite($fp, "<div class='msgln'>(".date("g:i A").") <b>".$_SESSION['user']."</b>: ". formatTextLinksVerbose(stripslashes(htmlspecialchars($text))) ."<br></div>");
    fclose($fp);
    echo "Just wrote the file";
}

function formatTextLinks($text) {
    $words = preg_split("/[\s,\?!]+/", $text);
    $offset = 0;

    foreach($words as $value) {
        preg_match("/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/", $value, $matches);

        $s = $matches[0];
        if(!is_string($s)) continue;
        $pos = strpos($text, $s, $offset);
        if($pos !== false) {
            $helper = "";
            if(strpos($s, "http://") === false || strpos($s, "https://") === false) $helper = "http://";
            if(strpos($s, "http://") !== false) $helper = "";
            if(strpos($s, "https://") !== false) $helper = "";

            $text = substr_replace($text, "<a href='".$helper.rtrim($s, '.')."' target='_blank'>".$s."</a>", $pos, strlen($s));
            $offset = $pos + strlen("<a href='".$helper.rtrim($s, '.')."' target='_blank'>".$s."</a>");
        }
    }

    return $text;
}

function formatTextLinks2($text) {
    $words = preg_split("/[\s,\?!]+/", $text);
    $offset = 0;

    foreach($words as $value) {
        preg_match('/^(http|https|ftp)://([A-Z0-9][A-Z0-9_-]*(?:.[A-Z0-9][A-Z0-9_-]*)+):?(d+)?/?/i', $value, $matches);

        $s = $matches[0];
        if(!is_string($s)) continue;
        $pos = strpos($text, $s, $offset);
        if($pos !== false) {
            $helper = "";
            if(strpos($s, "http://") === false || strpos($s, "https://") === false) $helper = "http://";
            if(strpos($s, "http://") !== false) $helper = "";
            if(strpos($s, "https://") !== false) $helper = "";

            $text = substr_replace($text, "<a href='".$helper.$s."' target='_blank'>".$s."</a>", $pos, strlen($s));
            $offset = $pos + strlen("<a href='".$helper.$s."' target='_blank'>".$s."</a>");
        }
    }

    return $text;
}

function formatTextLinksVerbose($text) {
    $rexProtocol = '(https?://)?';
    $rexDomain   = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
    $rexPort     = '(:[0-9]{1,5})?';
    $rexPath     = '(/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*)?';
    $rexQuery    = '(\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+)?';
    $rexFragment = '(#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+)?';

    $emailPattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD';

    $validTlds = array_fill_keys(explode(" ", ".aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .today .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .yu .za .zm .zw .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--jxalpdlp .xn--kgbechtv .xn--zckzah .arpa"), true);
    $validImgs = array_fill_keys(explode(" ", ".jpg .bmp . png .gif .tiff .jfif .jpeg .tif .ppm .pgm .pbm .pnm .img .svg"), true);

    $position = 0;
    $returnText = "";
    $extraHelper;
    $emailReplacement = "";
    $URLfound = false;
    $emailFound = false;

    while (preg_match("{\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"\'-]?(.|$))}", $text, $match, PREG_OFFSET_CAPTURE, $position))
    {
        //reset our extra helper text variable and emailFound boolean
        $extraHelper = "";
        $emailFound = false;

        list($url, $urlPosition) = $match[0];

        //Debug statement
        //$returnText .= "Well we definitely got a preg_match here. ";

        $wehaveEmail = strpos( "{\s.+@}", substr($text, $position, $urlPosition - $position));
        if($wehaveEmail !== false) {
            echo "We have detected a worthy email! " . substr($text, $wehaveEmail, $urlPosition - $wehaveEmail);
            $falsePositive = strpos( "{\s[\.]+@}", substr($text, $position, $urlPosition - $position));
            if( preg_match( "{\s\.+.*@}", substr($text, $wehaveEmail, $urlPosition - $position), $falseMatches, PREG_OFFSET_CAPTURE)) {
                echo "Uh, never mind. " . $falseMatches[0][0];
            }
        }

        if(preg_match( "/(?<!\S)\w+(?:[.-]\w+)*@/", substr($text, $position, $urlPosition - $position), $eMatches, PREG_OFFSET_CAPTURE))
        {
            //$returnText .= "Whoa, we got an email here!";
            //echo "Our position values are: " . $urlPosition . " " . $position . " and also our first result can be found at: " . strpos(substr($text, $urlPosition - $position, $urlPosition - $position), "{^[\w]@$}");
            echo "Also we have a match at: " . $eMatches[0][0];
            //echo "If we used preg_replace: " . preg_replace("{\b\w*@(?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}\b}", "<a href ='mailto:" . $eMatches[0][0] . $match[2][0] . "'> " . $eMatches[0][0] . $match[2][0] . "</a>", (substr($text, $position, $urlPosition - $position)) . $match[2][0]);
            $emailReplacement = preg_replace("{\s\S+\@(?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}\b}", "<a href='mailto:" . $eMatches[0][0] . $match[2][0] . "'> " . $eMatches[0][0] . $match[2][0] . "</a>", (substr($text, $position, $urlPosition - $position)) . $match[2][0]);
            $emailFound = true;
        }

        else {
        // Append the text leading up to the URL in return value.
        $returnText .= /*"Leading up to URL: " .*/ htmlspecialchars(substr($text, $position, $urlPosition - $position));

        }

        $domain = $match[2][0];
        $port   = $match[3][0];
        $path   = $match[4][0];
        $query  = $match[5][0];
        $fragment = $match[6][0];

        echo "Domain is: " . $domain . " and path is: " . $path . " and query is: " . $query;

        //if the domain variable was captured with extra hyphens
        if(preg_match("{.*-+}", $domain))
        {
            //add to our helper variable
            $extraHelper = $domain;
            $domain = rtrim($domain, "-");
            $extraHelper = substr($extraHelper, strlen($domain));
        }

        //Debug statement
        //$returnText .= "Domain is: " . $domain . " $match[0] is: " . print_r($match[0]);



        // Check if the TLD is valid - or that $domain is an IP address.
        $tld = strtolower(strrchr($domain, '.'));
        if ( preg_match('{\.[0-9]{1,3}}', $tld) || isset($validTlds[$tld]) )
        {
            if($emailFound) {

                //$completeUrl = $emailReplacement;

                echo "Our email replacement string: " . $emailReplacement;

                // Append email hyperlink.
                $returnText .= $emailReplacement . $extraHelper;

            }


            else {
                $img = strtolower(strrchr($path, '.'));
                if(!$emailFound && isset($validImgs[$img]))
                {
                    echo "We found an image!";
                    // Prepend http:// if no protocol specified
                    $completeUrl = $match[1][0] ? $url : "http://$url";

                    // Append the hyperlink.
                    $returnText .= '<a href="' . htmlspecialchars($completeUrl) . '" target="_blank"><img src="' . htmlspecialchars($completeUrl) . '"></a>' . $extraHelper;
                }

                else
                {
                    // Prepend http:// if no protocol specified
                    $completeUrl = $match[1][0] ? $url : "http://$url";

                    // Append the hyperlink.
                    $returnText .= '<a href="' . htmlspecialchars($completeUrl) . '" target="_blank">' . htmlspecialchars("$domain$port$path$query$fragment") . '</a>' . $extraHelper;
                }
            }
        }
        else
        {
            //NOTE: this search function is under construction, it would filter a URL despite trailing alphanumeric characters.
            /*
            //if ANY value from $validTlds[] are INSIDE the $tld string at all
            foreach($validTlds as $needle) {
                $matchTLDindex = strpos($tld, $needle, 0);
                echo "Current needle is " . strval($needle);

                if($matchTLDindex !== false)
                {
                    //make sure the matches are exactly from the beginning of the compared variables
                    if(strcmp($validTlds[$matchTLDindex], substr($tld, strlen($validTlds[$matchTLDindex])) !== false))
                    {
                        $returnText .= "So our valid TLD match is " . strlen($validTlds[$matchTLDindex]) . " and our substring compared was: " . substr($tld, strlen($validTlds[$matchTLDindex])) . " and our index is " . strval($matchTLDindex) . " Just for kicks, one of the first tested TLDs was: " . $validTlds[1];
                        // Append our trailing helper string
                        $extraHelper .= substr($tld, strlen($validTlds[$matchTLDindex]));
                        $tld = $validTlds[$matchTLDindex];
                        //$extraHelper = substr($extraHelper, strlen($tld), strlen($extraHelper));

                        $returnText .= "Currently extraHelper is: " . $extraHelper . " and $tld is " . $tld;
                        // Prepend http:// if no protocol specified
                        $completeUrl = $match[1][0] ? $url : "http://$url";

                        // Append the hyperlink.
                        $returnText .= '<a href="' . htmlspecialchars($completeUrl) . '" target = "_blank">' . htmlspecialchars("$domain$port$path") . '</a>' . $extraHelper;

                        //we found and appended our URL, mark the flag
                        $URLfound = true;

                        //break out of foreach loop, job done
                        break;
                    }
                }
            }
            */
            if($URLfound == false && !$emailFound) {
                // Not a valid URL.
                $returnText .= htmlspecialchars($url);
            }
        }

        // Continue text parsing from after the URL.
        $position = $urlPosition + strlen($url);
    }

    // Append and return the remainder of the text.
    return($returnText . htmlspecialchars_decode((htmlspecialchars(substr($text, $position))), ENT_COMPAT));
}

function formatEmails($text) {
    $words = preg_split("/[\s,\?!]+/", $text);
    $offset = 0;

    foreach($words as $value) {
        preg_match("/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/", $value, $matches);

        $s = $matches[0];
        if(!is_string($s)) continue;
        $pos = strpos($text, $s, $offset);
        if($pos !== false) {
            /*$helper = "";
            if(strpos($s, "http://") === false || strpos($s, "https://") === false) $helper = "http://";
            if(strpos($s, "http://") !== false) $helper = "";
            if(strpos($s, "https://") !== false) $helper = "";*/

            $text = substr_replace($text, "<a href='mailto:".rtrim($s, '.')."' target='_top'>".$s."</a>", $pos, strlen($s));
            $offset = $pos + strlen("<a href='".$helper.$s."' target='_top'>".$s."</a>");
        }
    }

    return $text;
}
?>

chatroom.php:

<?php session_start();
#session_regenerate_id(true);
include ("dbconfig.php");
if(!isset($_SESSION['introd']))
{   
    header("Location: intro.php");
}
if(!isset($_SESSION['user']))
{   
    header("Location: index.php");
}
 ?>
<!DOCTYPE html>
 <html>
<head>
    <title>My Webpage</title>
<!--    <meta name = "viewport" content = "width=device-width, initial-scale=1.0"/>-->
    <link rel = "stylesheet" type = "text/css" href = "site.css" />
    <link rel="shortcut icon" href="/favicon.gif" type="image/gif" />
    <script>




        </script>
</head>

<body>
    <?php include("header.php"); ?>

                <div id="wrapper">
                    <div id="menu">
                        <p class="welcome">Welcome, <b><?php echo $_SESSION['user']; ?></b></p>
                        <div style="clear:both"></div>
                    </div>

                    <div id="chatbox"><?php
                    if(file_exists("log.html") && filesize("log.html") > 0){
                        $handle = fopen("log.html", "r");
                        $contents = fread($handle, filesize("log.html"));
                        fclose($handle);

                        echo $contents;
                    }
                    ?></div>

                    <form name="message" action="">
                        <input name="usermsg" type="text" id="usermsg" size="63" />
                        <input name="submitmsg" type="submit"  id="submitmsg" value="Send" />
                    </form>
                    <div id="sound"></div>
                </div>
                <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
                <script type="text/javascript">
                // jQuery Document
                $(document).ready(function(){

                    var original = document.title;
                    var timeout;

                    window.flashTitle = function (newMsg, howManyTimes) {
                        function step() {
                            document.title = (document.title == original) ? newMsg : original;

                            if (--howManyTimes > 0) {
                                timeout = setTimeout(step, 1000);
                            };
                        };

                        howManyTimes = parseInt(howManyTimes);

                        if (isNaN(howManyTimes)) {
                            howManyTimes = 5;
                        };

                        cancelFlashTitle(timeout);
                        step();
                    };

                    window.cancelFlashTitle = function () {
                        clearTimeout(timeout);
                        document.title = original;
                    };

                    setInterval (loadLog, 2000);    //Reload file every 2500 ms or x ms if you wish to change the second parameter

                    //If user submits the form
                    $("#submitmsg").click(function(event){

                        var clientmsg = $("#usermsg").val();
                        $.post("post.php", {text:clientmsg});
                        //alert("About to post");
                        //event.preventDefault();
                        /*$.ajax({
                            type: "POST",
                            url: "post.php",
                            data: {text:clientmsg},
                            //dataType: text,
                            error: function(){
                                alert("Error receiving text: " + response);
                            },
                            success: function(response){
                                alert("Submission received: " + response);
                            },
                        });*/
                        $("#usermsg").attr("value", "");
                        return false;
                    });

                    function notifyNewMessage(){

                    }



                    //Load the file containing the chat log
                    function loadLog(){     
                        var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height before the request
                        $.ajax({
                            url: "log.html",
                            cache: false,
                            success: function(html){
                                if((html.length - $("#chatbox").html().length) != 0) {
                                    //alert("The new message is: " + html + " /n and chatbox has: " + $("#chatbox").html());
                                    $("#chatbox").html(html); //Insert chat log into the #chatbox div
                                    var soundCheck = <?php echo $_SESSION['sound']; ?>;
                                    //alert(soundCheck);
                                    if(soundCheck == 1){
                                        document.getElementById("sound").innerHTML='<audio autoplay="autoplay"><source src="SCR_WR.mp3" type="audio/mp3" />';
                                    }
                                    flashTitle("New Message!", 6);
                                    //document.title = "My Webpage";
                                }


                                //Auto-scroll           
                                var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height after the request
                                if(newscrollHeight > oldscrollHeight){
                                    $("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div
                                }               
                            },
                        });
                    }
                });
                </script>

                <center><a href='logout.php'>Logout</a></center>    

            <p class = "content"> This is a page that is a scrap work in progress. </p>


            <?php include("footer.php"); ?> 
    </body>
</html>

Any suggestions would be appreciated as to what route to take... I'm alright with getting links to tutorials, just need to get pointed in the right direction. Thanks so much.

Kieran Ojakangas
  • 495
  • 4
  • 18
  • Possible duplicate of [How to implement basic "Long Polling"?](http://stackoverflow.com/questions/333664/how-to-implement-basic-long-polling) – Jeremy Harris Jan 06 '16 at 22:39
  • @JeremyHarris thanks but that's not the case. I AM using long polling. I think I want to change to a more socket-based architecture in my current system. – Kieran Ojakangas Jan 06 '16 at 22:54

0 Answers0