4
\$\begingroup\$

I made a website last night that allows people to sync HTML5 <video>s (playing/pausing). The way it does this is by using Ajax to run a MySQL query every 2 seconds to check if anyone has paused the video. Depending on the response, it plays/pauses it. If someone plays/pauses the video, it calls a page through Ajax to update the database.

This is the page that plays the video and manages the syncing:

<!DOCTYPE HTML>
<html>
    <head>
        <meta name="viewport" content="width=device-width">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    </head>
    <body>
    <?php
        require('/connect/streaming.php'); //On this page: $con = mysqli_connect(host, user, pass, database)
        $query = "SELECT link FROM vids WHERE vidKey = ?";
        $stmt = mysqli_stmt_init($con);
        $stmt->prepare($query);
        $stmt->bind_param('s', $_GET['id']);
        $stmt->execute();
        $resultFirst = $stmt->get_result();
        $result = mysqli_fetch_assoc($resultFirst);
    ?>
        <video controls autoplay name="media" id="vid">
            <source src="<?php echo $result['link']; ?>" type="video/<?php echo $_GET['type']; ?>">
        </video><br>
        <a onclick="flipCheck()" id="checkA">Click here to disable checks</a>
        <script>
            var checking = true;
            function flipCheck() {
                if (checking) {
                    checking = false;
                    $("#checkA").html("Click here to enable checks");
                }
                else {
                    checking = true;
                    $("#checkA").html("Click here to disable checks");
                }
            }
            //Pause video on load
            $(document).ready(function() {
              var vid = document.getElementById("vid"); 
              vid.pause();
            });

            //Every second, check what others are doing
            window.setInterval(function(){
              request({'type': 'get', 'vidId': <?php echo $_GET['id']; ?> });
            }, 2000);

            //On play, tell the server
            vid.onplaying = function() {
                request({'type': 'update', 'vidId': <?php echo $_GET['id']; ?>, 'timestamp': vid.currentTime, 'status': 'playing' });
            };

            //On pause, tell the server
            vid.onpause = function() {
                request({'type': 'update', 'vidId': <?php echo $_GET['id']; ?>, 'timestamp': vid.currentTime, 'status': 'paused' });
            };

            //Function to request data
            function request(funcData) {
                if (checking) {
                    $.ajax(
                    {
                        url: "https://chipperyman.com/streaming/process.php", 
                        type: "GET",
                        dataType: 'json',
                        data: funcData,
                        success: function(result){
                            console.log(result);
                            if (result['msg'] == 'paused') {
                                vid.pause();
                                vid.currentTime = result['timestamp'];
                            }
                            else if (result['msg'] == 'playing') {
                                if (vid.paused) {
                                    vid.currentTime = result['timestamp'];
                                    vid.play();
                                }
                            }
                    }}); 
                }
            }
        </script> 
    </body>
</html>

This is the page that manages the Ajax calls:

<?php
//MySQL
require('/connect/streaming.php'); //On this page: $con = mysqli_connect(host, user, pass, database)
//Setup checkArgs
function checkArgs(){
    $args = func_get_args();
    foreach ($args as $arg){
        if (!isset($_GET[$arg])) {
            die(json_encode(array('response' => 'error', "msg" => "Missing args")));
        }
    }
}

//Check for type and vidId
checkArgs('type', 'vidId');
//If we're updating 
if ($_GET['type'] == 'update') {
    checkArgs('timestamp', 'status');
    $query = "UPDATE vids SET timestamp = ?, status = ? WHERE vidKey = ?";
    $stmt = mysqli_stmt_init($con);
    $stmt->prepare($query);
    $stmt->bind_param('dsi', $_GET['timestamp'], $_GET['status'], $_GET['vidId']);
    $stmt->execute();
    $response = array("response" => "success", "msg" => "Preformed action.");
}
else if ($_GET['type'] == 'get') {
    $query = "SELECT * FROM vids WHERE vidKey = ?";
    $stmt = mysqli_stmt_init($con);
    $stmt->prepare($query);
    $stmt->bind_param('i', $_GET['vidId']);
    $stmt->execute();
    $resultFirst = $stmt->get_result();
    $result = mysqli_fetch_assoc($resultFirst);
    $response = array("response" => "success", "msg" => $result['status'], "timestamp" => $result['timestamp']);
}
else {
    $response = array("response" => "error", "msg" => "Invalid type argument");
}
echo json_encode($response);

This is the database layout:

MySQL Database Layout

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I'm not that familiar with the HTML5 video tag, so I will not say anything about that.

Your code is open to reflected XSS here: <?php echo $_GET['id']; ?> (inside script tags).

You might also think about extracting some code blocks to functions to increase readability and reduce duplication. For example you have SELECT * FROM vids WHERE vidKey = ? twice, which amounts to quite a lot of duplication (oddly, you one use s and once i). A function like getVideoByKey might be helpful here.

\$\endgroup\$
2
  • \$\begingroup\$ In .htaccess there's a script that strips tags from all GET and POST tags. I will work on the second part, thank you. \$\endgroup\$ Commented Oct 29, 2015 at 22:11
  • \$\begingroup\$ @Chipperyman filtering tags is not enough against XSS, as the user input is echoed inside script tags. \$\endgroup\$ Commented Oct 30, 2015 at 11:45

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.