Kaynağa Gözat

Add Chat Beta and Speedtest framework

Added Chat beta to test
Added framework for speedtest on homepage
causefx 8 yıl önce
ebeveyn
işleme
6b9ea13746

+ 6 - 0
bower_components/speed/empty.php

@@ -0,0 +1,6 @@
+<?php
+header( "HTTP/1.1 200 OK" );
+header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+?>

+ 24 - 0
bower_components/speed/garbage.php

@@ -0,0 +1,24 @@
+<?php
+// Disable Compression
+@ini_set('zlib.output_compression', 'Off');
+@ini_set('output_buffering', 'Off');
+@ini_set('output_handler', '');
+// Headers
+header( "HTTP/1.1 200 OK" );
+// Download follows...
+header('Content-Description: File Transfer');
+header('Content-Type: application/octet-stream');
+header('Content-Disposition: attachment; filename=random.dat'); 
+header('Content-Transfer-Encoding: binary');
+// Never cache me
+header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+// Generate data
+$data=openssl_random_pseudo_bytes(1048576);
+// Deliver chunks of 1048576 bytes
+for($i=0;$i<intval($_GET["ckSize"]);$i++){
+    echo $data;
+    flush();
+}
+?>

+ 3 - 0
bower_components/speed/getIP.php

@@ -0,0 +1,3 @@
+<?php
+echo $_SERVER['REMOTE_ADDR'];
+?>

+ 350 - 0
bower_components/speed/speedtest_worker.js

@@ -0,0 +1,350 @@
+/*
+	HTML5 Speedtest v4.2.1
+	by Federico Dossena
+	https://github.com/adolfintel/speedtest/
+	GNU LGPLv3 License
+*/
+
+// data reported to main thread
+var testStatus = 0 // 0=not started, 1=download test, 2=ping+jitter test, 3=upload test, 4=finished, 5=abort/error
+var dlStatus = '' // download speed in megabit/s with 2 decimal digits
+var ulStatus = '' // upload speed in megabit/s with 2 decimal digits
+var pingStatus = '' // ping in milliseconds with 2 decimal digits
+var jitterStatus = '' // jitter in milliseconds with 2 decimal digits
+var clientIp = '' // client's IP address as reported by getIP.php
+
+// test settings. can be overridden by sending specific values with the start command
+var settings = {
+  time_ul: 15, // duration of upload test in seconds
+  time_dl: 15, // duration of download test in seconds
+  count_ping: 35, // number of pings to perform in ping test
+  url_dl: 'garbage.php', // path to a large file or garbage.php, used for download test. must be relative to this js file
+  url_ul: 'empty.php', // path to an empty file, used for upload test. must be relative to this js file
+  url_ping: 'empty.php', // path to an empty file, used for ping test. must be relative to this js file
+  url_getIp: 'getIP.php', // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
+  xhr_dlMultistream: 10, // number of download streams to use (can be different if enable_quirks is active)
+  xhr_ulMultistream: 3, // number of upload streams to use (can be different if enable_quirks is active)
+  xhr_dlUseBlob: false, // if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize and/or high xhr_dlMultistream)
+  garbagePhp_chunkSize: 20, // size of chunks sent by garbage.php (can be different if enable_quirks is active)
+  enable_quirks: true, // enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers, unless they are already being overridden with the start command
+  allow_fetchAPI: false, // enables Fetch API. currently disabled because it leaks memory like no tomorrow
+  force_fetchAPI: false // when Fetch API is enabled, it will force usage on every browser that supports it
+}
+
+var xhr = null // array of currently active xhr requests
+var interval = null // timer used in tests
+
+/*
+	when set to true (automatically) the download test will use the fetch api instead of xhr.
+	fetch api is used if
+		-allow_fetchAPI is true AND
+		-(we're on chrome that supports fetch api AND enable_quirks is true) OR (we're on any browser that supports fetch api AND force_fetchAPI is true)
+*/
+var useFetchAPI = false
+
+/*
+	listener for commands from main thread to this worker.
+	commands:
+	-status: returns the current status as a string of values spearated by a semicolon (;) in this order: testStatus;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus
+	-abort: aborts the current test
+	-start: starts the test. optionally, settings can be passed as JSON.
+		example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"}
+*/
+this.addEventListener('message', function (e) {
+  var params = e.data.split(' ')
+  if (params[0] === 'status') { // return status
+    postMessage(testStatus + ';' + dlStatus + ';' + ulStatus + ';' + pingStatus + ';' + clientIp + ';' + jitterStatus)
+  }
+  if (params[0] === 'start' && testStatus === 0) { // start new test
+    testStatus = 1
+    try {
+      // parse settings, if present
+      var s = JSON.parse(e.data.substring(5))
+      if (typeof s.url_dl !== 'undefined') settings.url_dl = s.url_dl // download url
+      if (typeof s.url_ul !== 'undefined') settings.url_ul = s.url_ul // upload url
+      if (typeof s.url_ping !== 'undefined') settings.url_ping = s.url_ping // ping url
+      if (typeof s.url_getIp !== 'undefined') settings.url_getIp = s.url_getIp // url to getIP.php
+      if (typeof s.time_dl !== 'undefined') settings.time_dl = s.time_dl // duration of download test
+      if (typeof s.time_ul !== 'undefined') settings.time_ul = s.time_ul // duration of upload test
+      if (typeof s.enable_quirks !== 'undefined') settings.enable_quirks = s.enable_quirks // enable quirks or not
+      if (typeof s.allow_fetchAPI !== 'undefined') settings.allow_fetchAPI = s.allow_fetchAPI // allows fetch api to be used if supported
+      // quirks for specific browsers. more may be added in future releases
+      if (settings.enable_quirks) {
+        var ua = navigator.userAgent
+        if (/Firefox.(\d+\.\d+)/i.test(ua)) {
+          // ff more precise with 1 upload stream
+          settings.xhr_ulMultistream = 1
+        }
+        if (/Edge.(\d+\.\d+)/i.test(ua)) {
+          // edge more precise with 3 download streams
+          settings.xhr_dlMultistream = 3
+        }
+        if ((/Safari.(\d+)/i.test(ua)) && !(/Chrome.(\d+)/i.test(ua))) {
+          // safari more precise with 10 upload streams and 5mb chunks for download test
+          settings.xhr_ulMultistream = 10
+          settings.garbagePhp_chunkSize = 5
+        }
+        if (/Chrome.(\d+)/i.test(ua) && (!!self.fetch)) {
+          // chrome can't handle large xhr very well, use fetch api if available and allowed
+          if (settings.allow_fetchAPI) useFetchAPI = true
+          // chrome more precise with 5 streams
+          settings.xhr_dlMultistream = 5
+        }
+      }
+      if (typeof s.count_ping !== 'undefined') settings.count_ping = s.count_ping // number of pings for ping test
+      if (typeof s.xhr_dlMultistream !== 'undefined') settings.xhr_dlMultistream = s.xhr_dlMultistream // number of download streams
+      if (typeof s.xhr_ulMultistream !== 'undefined') settings.xhr_ulMultistream = s.xhr_ulMultistream // number of upload streams
+      if (typeof s.xhr_dlUseBlob !== 'undefined') settings.xhr_dlUseBlob = s.xhr_dlUseBlob // use blob for download test
+      if (typeof s.garbagePhp_chunkSize !== 'undefined') settings.garbagePhp_chunkSize = s.garbagePhp_chunkSize // size of garbage.php chunks
+      if (typeof s.force_fetchAPI !== 'undefined') settings.force_fetchAPI = s.force_fetchAPI // use fetch api on all browsers that support it if enabled
+      if (settings.allow_fetchAPI && settings.force_fetchAPI && (!!self.fetch)) useFetchAPI = true
+    } catch (e) { }
+    // run the tests
+    console.log(settings)
+    console.log('Fetch API: ' + useFetchAPI)
+    getIp(function () { dlTest(function () { testStatus = 2; pingTest(function () { testStatus = 3; ulTest(function () { testStatus = 4 }) }) }) })
+  }
+  if (params[0] === 'abort') { // abort command
+    clearRequests() // stop all xhr activity
+    if (interval) clearInterval(interval) // clear timer if present
+    testStatus = 5; dlStatus = ''; ulStatus = ''; pingStatus = ''; jitterStatus = '' // set test as aborted
+  }
+})
+// stops all XHR activity, aggressively
+function clearRequests () {
+  if (xhr) {
+    for (var i = 0; i < xhr.length; i++) {
+      if (useFetchAPI) try { xhr[i].cancelRequested = true } catch (e) { }
+      try { xhr[i].onprogress = null; xhr[i].onload = null; xhr[i].onerror = null } catch (e) { }
+      try { xhr[i].upload.onprogress = null; xhr[i].upload.onload = null; xhr[i].upload.onerror = null } catch (e) { }
+      try { xhr[i].abort() } catch (e) { }
+      try { delete (xhr[i]) } catch (e) { }
+    }
+    xhr = null
+  }
+}
+// gets client's IP using url_getIp, then calls the done function
+function getIp (done) {
+  xhr = new XMLHttpRequest()
+  xhr.onload = function () {
+    clientIp = xhr.responseText
+    done()
+  }
+  xhr.onerror = function () {
+    done()
+  }
+  xhr.open('GET', settings.url_getIp + '?r=' + Math.random(), true)
+  xhr.send()
+}
+// download test, calls done function when it's over
+var dlCalled = false // used to prevent multiple accidental calls to dlTest
+function dlTest (done) {
+  if (dlCalled) return; else dlCalled = true // dlTest already called?
+  var totLoaded = 0.0, // total number of loaded bytes
+    startT = new Date().getTime(), // timestamp when test was started
+    failed = false // set to true if a stream fails
+  xhr = []
+  // function to create a download stream. streams are slightly delayed so that they will not end at the same time
+  var testStream = function (i, delay) {
+    setTimeout(function () {
+      if (testStatus !== 1) return // delayed stream ended up starting after the end of the download test
+      if (useFetchAPI) {
+        xhr[i] = fetch(settings.url_dl + '?r=' + Math.random() + '&ckSize=' + settings.garbagePhp_chunkSize).then(function (response) {
+          var reader = response.body.getReader()
+          var consume = function () {
+            return reader.read().then(function (result) {
+              if (result.done) testStream(i); else {
+                totLoaded += result.value.length
+                if (xhr[i].cancelRequested) reader.cancel()
+              }
+              return consume()
+            }.bind(this))
+          }.bind(this)
+          return consume()
+        }.bind(this))
+      } else {
+        var prevLoaded = 0 // number of bytes loaded last time onprogress was called
+        var x = new XMLHttpRequest()
+        xhr[i] = x
+        xhr[i].onprogress = function (event) {
+          if (testStatus !== 1) { try { x.abort() } catch (e) { } } // just in case this XHR is still running after the download test
+          // progress event, add number of new loaded bytes to totLoaded
+          var loadDiff = event.loaded <= 0 ? 0 : (event.loaded - prevLoaded)
+          if (isNaN(loadDiff) || !isFinite(loadDiff) || loadDiff < 0) return // just in case
+          totLoaded += loadDiff
+          prevLoaded = event.loaded
+        }.bind(this)
+        xhr[i].onload = function () {
+          // the large file has been loaded entirely, start again
+          try { xhr[i].abort() } catch (e) { } // reset the stream data to empty ram
+          testStream(i, 0)
+        }.bind(this)
+        xhr[i].onerror = function () {
+          // error, abort
+          failed = true
+          try { xhr[i].abort() } catch (e) { }
+          delete (xhr[i])
+        }.bind(this)
+        // send xhr
+        try { if (settings.xhr_dlUseBlob) xhr[i].responseType = 'blob'; else xhr[i].responseType = 'arraybuffer' } catch (e) { }
+        xhr[i].open('GET', settings.url_dl + '?r=' + Math.random() + '&ckSize=' + settings.garbagePhp_chunkSize, true) // random string to prevent caching
+        xhr[i].send()
+      }
+    }.bind(this), 1 + delay)
+  }.bind(this)
+  // open streams
+  for (var i = 0; i < settings.xhr_dlMultistream; i++) {
+    testStream(i, 100 * i)
+  }
+  // every 200ms, update dlStatus
+  interval = setInterval(function () {
+    var t = new Date().getTime() - startT
+    if (t < 200) return
+    var speed = totLoaded / (t / 1000.0)
+    dlStatus = ((speed * 8) / 925000.0).toFixed(2) // 925000 instead of 1048576 to account for overhead
+    if ((t / 1000.0) > settings.time_dl || failed) { // test is over, stop streams and timer
+      if (failed || isNaN(dlStatus)) dlStatus = 'Fail'
+      clearRequests()
+      clearInterval(interval)
+      done()
+    }
+  }.bind(this), 200)
+}
+// upload test, calls done function whent it's over
+// garbage data for upload test
+var r = new ArrayBuffer(1048576)
+try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
+var req = []
+var reqsmall = []
+for (var i = 0; i < 20; i++) req.push(r)
+req = new Blob(req)
+r = new ArrayBuffer(262144)
+try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
+reqsmall.push(r)
+reqsmall = new Blob(reqsmall)
+var ulCalled = false // used to prevent multiple accidental calls to ulTest
+function ulTest (done) {
+  if (ulCalled) return; else ulCalled = true // ulTest already called?
+  var totLoaded = 0.0 // total number of transmitted bytes
+  var startT = new Date().getTime() // timestamp when test was started
+  var failed = false // set to true if a stream fails
+  xhr = []
+  // function to create an upload stream. streams are slightly delayed so that they will not end at the same time
+  var testStream = function (i, delay) {
+    setTimeout(function () {
+      if (testStatus !== 3) return // delayed stream ended up starting after the end of the upload test
+      var prevLoaded = 0 // number of bytes transmitted last time onprogress was called
+      var x = new XMLHttpRequest()
+      xhr[i] = x
+      var ie11workaround
+      try {
+        xhr[i].upload.onprogress
+        ie11workaround = false
+      } catch (e) {
+        ie11workaround = true
+      }
+      if (ie11workaround) {
+        // IE11 workarond: xhr.upload does not work properly, therefore we send a bunch of small 256k requests and use the onload event as progress. This is not precise, especially on fast connections
+        xhr[i].onload = function () {
+          totLoaded += 262144
+          testStream(i, 0)
+        }
+        xhr[i].onerror = function () {
+          // error, abort
+          failed = true
+          try { xhr[i].abort() } catch (e) { }
+          delete (xhr[i])
+        }
+        xhr[i].open('POST', settings.url_ul + '?r=' + Math.random(), true) // random string to prevent caching
+        xhr[i].setRequestHeader('Content-Encoding', 'identity') // disable compression (some browsers may refuse it, but data is incompressible anyway)
+        xhr[i].send(reqsmall)
+      } else {
+        // REGULAR version, no workaround
+        xhr[i].upload.onprogress = function (event) {
+          if (testStatus !== 3) { try { x.abort() } catch (e) { } } // just in case this XHR is still running after the upload test
+          // progress event, add number of new loaded bytes to totLoaded
+          var loadDiff = event.loaded <= 0 ? 0 : (event.loaded - prevLoaded)
+          if (isNaN(loadDiff) || !isFinite(loadDiff) || loadDiff < 0) return // just in case
+          totLoaded += loadDiff
+          prevLoaded = event.loaded
+        }.bind(this)
+        xhr[i].upload.onload = function () {
+          // this stream sent all the garbage data, start again
+          testStream(i, 0)
+        }.bind(this)
+        xhr[i].upload.onerror = function () {
+          // error, abort
+          failed = true
+          try { xhr[i].abort() } catch (e) { }
+          delete (xhr[i])
+        }.bind(this)
+        // send xhr
+        xhr[i].open('POST', settings.url_ul + '?r=' + Math.random(), true) // random string to prevent caching
+        xhr[i].setRequestHeader('Content-Encoding', 'identity') // disable compression (some browsers may refuse it, but data is incompressible anyway)
+        xhr[i].send(req)
+      }
+    }.bind(this), 1)
+  }.bind(this)
+  // open streams
+  for (var i = 0; i < settings.xhr_ulMultistream; i++) {
+    testStream(i, 100 * i)
+  }
+  // every 200ms, update ulStatus
+  interval = setInterval(function () {
+    var t = new Date().getTime() - startT
+    if (t < 200) return
+    var speed = totLoaded / (t / 1000.0)
+    ulStatus = ((speed * 8) / 925000.0).toFixed(2) // 925000 instead of 1048576 to account for overhead
+    if ((t / 1000.0) > settings.time_ul || failed) { // test is over, stop streams and timer
+      if (failed || isNaN(ulStatus)) ulStatus = 'Fail'
+      clearRequests()
+      clearInterval(interval)
+      done()
+    }
+  }.bind(this), 200)
+}
+// ping+jitter test, function done is called when it's over
+var ptCalled = false // used to prevent multiple accidental calls to pingTest
+function pingTest (done) {
+  if (ptCalled) return; else ptCalled = true // pingTest already called?
+  var prevT = null // last time a pong was received
+  var ping = 0.0 // current ping value
+  var jitter = 0.0 // current jitter value
+  var i = 0 // counter of pongs received
+  var prevInstspd = 0 // last ping time, used for jitter calculation
+  xhr = []
+  // ping function
+  var doPing = function () {
+    prevT = new Date().getTime()
+    xhr[0] = new XMLHttpRequest()
+    xhr[0].onload = function () {
+      // pong
+      if (i === 0) {
+        prevT = new Date().getTime() // first pong
+      } else {
+        var instspd = (new Date().getTime() - prevT) / 2
+        var instjitter = Math.abs(instspd - prevInstspd)
+        if (i === 1) ping = instspd; /* first ping, can't tell jiutter yet*/ else {
+          ping = ping * 0.9 + instspd * 0.1 // ping, weighted average
+          jitter = instjitter > jitter ? (jitter * 0.2 + instjitter * 0.8) : (jitter * 0.9 + instjitter * 0.1) // update jitter, weighted average. spikes in ping values are given more weight.
+        }
+        prevInstspd = instspd
+      }
+      pingStatus = ping.toFixed(2)
+      jitterStatus = jitter.toFixed(2)
+      i++
+      if (i < settings.count_ping) doPing(); else done() // more pings to do?
+    }.bind(this)
+    xhr[0].onerror = function () {
+      // a ping failed, cancel test
+      pingStatus = 'Fail'
+      jitterStatus = 'Fail'
+      clearRequests()
+      done()
+    }.bind(this)
+    // sent xhr
+    xhr[0].open('GET', settings.url_ping + '?r=' + Math.random(), true) // random string to prevent caching
+    xhr[0].send()
+  }.bind(this)
+  doPing() // start first ping
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
bower_components/speed/speedtest_worker.min.js


+ 158 - 0
chat.php

@@ -0,0 +1,158 @@
+<?php
+
+$data = false;
+
+ini_set("display_errors", 1);
+ini_set("error_reporting", E_ALL | E_STRICT);
+
+require_once("user.php");
+require_once("functions.php");
+
+$USER = new User("registration_callback");
+
+$dbfile = DATABASE_LOCATION.'users.db';
+
+$file_db = new PDO("sqlite:" . $dbfile);
+$file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$dbOptions = $file_db->query('SELECT name FROM sqlite_master WHERE type="table" AND name="options"');
+
+$hasOptions = "No";
+
+foreach($dbOptions as $row) :
+
+    if (in_array("options", $row)) :
+        $hasOptions = "Yes";
+    endif;
+
+endforeach;
+
+if($hasOptions == "No") :
+
+    $title = "Organizr";
+    $topbar = "#333333"; 
+    $topbartext = "#66D9EF";
+    $bottombar = "#333333";
+    $sidebar = "#393939";
+    $hoverbg = "#AD80FD";
+    $activetabBG = "#F92671";
+    $activetabicon = "#FFFFFF";
+    $activetabtext = "#FFFFFF";
+    $inactiveicon = "#66D9EF";
+    $inactivetext = "#66D9EF";
+    $loading = "#66D9EF";
+    $hovertext = "#000000";
+
+endif;
+
+if($hasOptions == "Yes") :
+
+    $resulto = $file_db->query('SELECT * FROM options'); 
+    foreach($resulto as $row) : 
+
+        $title = isset($row['title']) ? $row['title'] : "Organizr";
+        $topbartext = isset($row['topbartext']) ? $row['topbartext'] : "#66D9EF";
+        $topbar = isset($row['topbar']) ? $row['topbar'] : "#333333";
+        $bottombar = isset($row['bottombar']) ? $row['bottombar'] : "#333333";
+        $sidebar = isset($row['sidebar']) ? $row['sidebar'] : "#393939";
+        $hoverbg = isset($row['hoverbg']) ? $row['hoverbg'] : "#AD80FD";
+        $activetabBG = isset($row['activetabBG']) ? $row['activetabBG'] : "#F92671";
+        $activetabicon = isset($row['activetabicon']) ? $row['activetabicon'] : "#FFFFFF";
+        $activetabtext = isset($row['activetabtext']) ? $row['activetabtext'] : "#FFFFFF";
+        $inactiveicon = isset($row['inactiveicon']) ? $row['inactiveicon'] : "#66D9EF";
+        $inactivetext = isset($row['inactivetext']) ? $row['inactivetext'] : "#66D9EF";
+        $loading = isset($row['loading']) ? $row['loading'] : "#66D9EF";
+        $hovertext = isset($row['hovertext']) ? $row['hovertext'] : "#000000";
+
+    endforeach;
+
+endif;
+?>
+
+<!DOCTYPE html>
+
+<html lang="en" class="no-js">
+
+    <head>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="msapplication-tap-highlight" content="no" />
+
+        <title><?=$title;?> Chat</title>
+
+        <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
+        <link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css">
+        <link rel="stylesheet" href="bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css"> 
+        <script src="js/menu/modernizr.custom.js"></script>
+
+        <link rel="stylesheet" href="bower_components/animate.css/animate.min.css">
+
+        <link rel="stylesheet" href="css/style.css?v=<?php echo INSTALLEDVERSION; ?>">
+
+        <!--Scripts-->
+        <script src="bower_components/jquery/dist/jquery.min.js"></script>
+        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
+        <script src="bower_components/moment/min/moment.min.js"></script>
+        <script src="bower_components/jquery.nicescroll/jquery.nicescroll.min.js"></script>
+        <script src="bower_components/slimScroll/jquery.slimscroll.min.js"></script>
+        <script src="bower_components/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js"></script>
+        <script src="bower_components/jquery.nicescroll/jquery.nicescroll.min.js"></script>
+        <script src="bower_components/cta/dist/cta.min.js"></script>
+        <script src="bower_components/fullcalendar/dist/fullcalendar.js"></script>
+
+        <script src="js/jqueri_ui_custom/jquery-ui.min.js"></script>
+	    <script src="js/jquery.mousewheel.min.js" type="text/javascript"></script>
+		
+		<!--Other-->
+		<script src="js/ajax.js?v=<?php echo INSTALLEDVERSION; ?>"></script>
+        <script src="chatjs.php" defer="true"></script>
+		
+        <!--[if lt IE 9]>
+        <script src="bower_components/html5shiv/dist/html5shiv.min.js"></script>
+        <script src="bower_components/respondJs/dest/respond.min.js"></script>
+        <![endif]-->
+        <style>
+            <?php if(CUSTOMCSS == "true") : 
+$template_file = "custom.css";
+$file_handle = fopen($template_file, "rb");
+echo fread($file_handle, filesize($template_file));
+fclose($file_handle);
+echo "\n";
+endif; ?>        
+        </style>
+    </head>
+
+    <body class="scroller-body" style="padding: 0px;">
+        <div class="main-wrapper" style="position: initial;">
+            <div id="content" class="container-fluid">
+                <br>
+                <div class="row">
+                    <div class="col-lg-12">
+                        <div class="content-box big-box chat">
+                            <div class="content-title i-block">
+                                <h4 class="zero-m">Welcome To The Chat <?php echo $USER->username;?></h4>
+                            </div>
+                            <div class="box" style="overflow: hidden; width: auto; height: 500px;">
+                                <ul id="messages" class="chat-double chat-container"></ul>
+                            </div>
+                            <form id="message_form">             
+                                <input id="writehere" type="text" class="form-control" placeholder="Enter your text">
+                            </form>
+                        </div>
+                    </div>
+                </div>
+            </div>    
+        </div>
+    </body>
+    
+      <script>
+
+          $(".box").niceScroll({
+                railpadding: {top:0,right:0,left:0,bottom:0},
+                scrollspeed: 30,
+                mousescrollstep: 60
+            });
+  </script>
+
+</html>

+ 96 - 0
chatAJAX.php

@@ -0,0 +1,96 @@
+<?php
+
+define("CHATDB", "chat.db");
+
+if (!file_exists(CHATDB)) {
+    
+    try{
+        $db = new PDO('sqlite:'.CHATDB);
+
+        $sql ="
+          CREATE TABLE IF NOT EXISTS MESSAGES 
+          (ID INTEGER PRIMARY KEY AUTOINCREMENT,
+          USER TEXT NOT NULL,
+          EMAIL TEXT NOT NULL,
+          MESSAGE TEXT NOT NULL,
+          TIME TIMESTAMP NOT NULL DEFAULT((julianday('now') - 2440587.5)*86400.0))";
+
+        $ret = $db->exec($sql);
+        sleep(0.5);
+        $ret = $db->exec('PRAGMA journal_mode = wal;');
+        sleep(0.5);
+        
+
+        header("Refresh:0");
+    }
+    catch(PDOException $e){
+       die('Failed to execute query:'. $e->getMessage());
+    }
+
+   $db=null;
+    
+}elseif(file_exists(CHATDB)) {
+    
+   try{
+        $db = new PDO('sqlite:'.CHATDB);
+    }
+    catch(PDOException $e){
+        die('Failed to connect:'. $e->getMessage());
+    }
+}
+
+//check to see if the ajax call was to update db
+
+if (isset($_POST['text'])){
+
+    $msg=$_POST['text'];
+    $us=$_POST['user'];
+    $email=$_POST['email'];
+
+    $sql ="INSERT INTO MESSAGES (USER,MESSAGE,EMAIL) VALUES(?, ?, ?)";
+
+    try{
+        $ret = $db->prepare($sql);
+        $ret->execute([$us,$msg, $email]);
+    }
+    catch(PDOException $e){
+        console.log('Failed to update db:'. $e->getMessage());
+    }
+}else{
+    //the script will run for 20 seconds after the initial ajax call
+    $time=time()+20;
+
+    while(time()<$time){
+        if ($_POST['time']){
+            $prevtime=$_POST['time'];
+        }
+        else {
+            $prevtime=0;
+        }
+        //query to see if there are new messages
+
+        $sql ="SELECT TIME,USER,MESSAGE,EMAIL FROM MESSAGES WHERE TIME>? ORDER BY TIME ASC";
+
+        try{
+            $ret = $db->prepare($sql);
+            $ret->execute([$prevtime]);
+
+            $resarr = $ret->fetchAll(PDO::FETCH_ASSOC);
+
+            //if there are no new messages in the db, sleep for half a second and then run loop again
+            if (!$resarr)
+                sleep(0.5);
+            else{
+                echo json_encode($resarr);
+                break;
+            }
+        }
+        catch(PDOException $e){
+            console.log('Failed to get messages:'. $e->getMessage());
+        }
+    }
+}
+
+$db=null;
+
+?>

+ 386 - 0
chatjs.php

@@ -0,0 +1,386 @@
+<?php 
+require_once("user.php");
+$USER = new User("registration_callback");
+$userpic = md5( strtolower( trim( $USER->email ) ) );
+header("Content-type: application/javascript");
+?>
+/*
+ * JavaScript MD5
+ * https://github.com/blueimp/JavaScript-MD5
+ *
+ * Copyright 2011, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * https://opensource.org/licenses/MIT
+ *
+ * Based on
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/* global define */
+
+;(function ($) {
+  'use strict'
+
+  /*
+  * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+  * to work around bugs in some JS interpreters.
+  */
+  function safeAdd (x, y) {
+    var lsw = (x & 0xFFFF) + (y & 0xFFFF)
+    var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
+    return (msw << 16) | (lsw & 0xFFFF)
+  }
+
+  /*
+  * Bitwise rotate a 32-bit number to the left.
+  */
+  function bitRotateLeft (num, cnt) {
+    return (num << cnt) | (num >>> (32 - cnt))
+  }
+
+  /*
+  * These functions implement the four basic operations the algorithm uses.
+  */
+  function md5cmn (q, a, b, x, s, t) {
+    return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
+  }
+  function md5ff (a, b, c, d, x, s, t) {
+    return md5cmn((b & c) | ((~b) & d), a, b, x, s, t)
+  }
+  function md5gg (a, b, c, d, x, s, t) {
+    return md5cmn((b & d) | (c & (~d)), a, b, x, s, t)
+  }
+  function md5hh (a, b, c, d, x, s, t) {
+    return md5cmn(b ^ c ^ d, a, b, x, s, t)
+  }
+  function md5ii (a, b, c, d, x, s, t) {
+    return md5cmn(c ^ (b | (~d)), a, b, x, s, t)
+  }
+
+  /*
+  * Calculate the MD5 of an array of little-endian words, and a bit length.
+  */
+  function binlMD5 (x, len) {
+    /* append padding */
+    x[len >> 5] |= 0x80 << (len % 32)
+    x[(((len + 64) >>> 9) << 4) + 14] = len
+
+    var i
+    var olda
+    var oldb
+    var oldc
+    var oldd
+    var a = 1732584193
+    var b = -271733879
+    var c = -1732584194
+    var d = 271733878
+
+    for (i = 0; i < x.length; i += 16) {
+      olda = a
+      oldb = b
+      oldc = c
+      oldd = d
+
+      a = md5ff(a, b, c, d, x[i], 7, -680876936)
+      d = md5ff(d, a, b, c, x[i + 1], 12, -389564586)
+      c = md5ff(c, d, a, b, x[i + 2], 17, 606105819)
+      b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
+      a = md5ff(a, b, c, d, x[i + 4], 7, -176418897)
+      d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
+      c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
+      b = md5ff(b, c, d, a, x[i + 7], 22, -45705983)
+      a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
+      d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
+      c = md5ff(c, d, a, b, x[i + 10], 17, -42063)
+      b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
+      a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
+      d = md5ff(d, a, b, c, x[i + 13], 12, -40341101)
+      c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
+      b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329)
+
+      a = md5gg(a, b, c, d, x[i + 1], 5, -165796510)
+      d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
+      c = md5gg(c, d, a, b, x[i + 11], 14, 643717713)
+      b = md5gg(b, c, d, a, x[i], 20, -373897302)
+      a = md5gg(a, b, c, d, x[i + 5], 5, -701558691)
+      d = md5gg(d, a, b, c, x[i + 10], 9, 38016083)
+      c = md5gg(c, d, a, b, x[i + 15], 14, -660478335)
+      b = md5gg(b, c, d, a, x[i + 4], 20, -405537848)
+      a = md5gg(a, b, c, d, x[i + 9], 5, 568446438)
+      d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
+      c = md5gg(c, d, a, b, x[i + 3], 14, -187363961)
+      b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
+      a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
+      d = md5gg(d, a, b, c, x[i + 2], 9, -51403784)
+      c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
+      b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734)
+
+      a = md5hh(a, b, c, d, x[i + 5], 4, -378558)
+      d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
+      c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
+      b = md5hh(b, c, d, a, x[i + 14], 23, -35309556)
+      a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
+      d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
+      c = md5hh(c, d, a, b, x[i + 7], 16, -155497632)
+      b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
+      a = md5hh(a, b, c, d, x[i + 13], 4, 681279174)
+      d = md5hh(d, a, b, c, x[i], 11, -358537222)
+      c = md5hh(c, d, a, b, x[i + 3], 16, -722521979)
+      b = md5hh(b, c, d, a, x[i + 6], 23, 76029189)
+      a = md5hh(a, b, c, d, x[i + 9], 4, -640364487)
+      d = md5hh(d, a, b, c, x[i + 12], 11, -421815835)
+      c = md5hh(c, d, a, b, x[i + 15], 16, 530742520)
+      b = md5hh(b, c, d, a, x[i + 2], 23, -995338651)
+
+      a = md5ii(a, b, c, d, x[i], 6, -198630844)
+      d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
+      c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
+      b = md5ii(b, c, d, a, x[i + 5], 21, -57434055)
+      a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
+      d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
+      c = md5ii(c, d, a, b, x[i + 10], 15, -1051523)
+      b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
+      a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
+      d = md5ii(d, a, b, c, x[i + 15], 10, -30611744)
+      c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
+      b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
+      a = md5ii(a, b, c, d, x[i + 4], 6, -145523070)
+      d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
+      c = md5ii(c, d, a, b, x[i + 2], 15, 718787259)
+      b = md5ii(b, c, d, a, x[i + 9], 21, -343485551)
+
+      a = safeAdd(a, olda)
+      b = safeAdd(b, oldb)
+      c = safeAdd(c, oldc)
+      d = safeAdd(d, oldd)
+    }
+    return [a, b, c, d]
+  }
+
+  /*
+  * Convert an array of little-endian words to a string
+  */
+  function binl2rstr (input) {
+    var i
+    var output = ''
+    var length32 = input.length * 32
+    for (i = 0; i < length32; i += 8) {
+      output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF)
+    }
+    return output
+  }
+
+  /*
+  * Convert a raw string to an array of little-endian words
+  * Characters >255 have their high-byte silently ignored.
+  */
+  function rstr2binl (input) {
+    var i
+    var output = []
+    output[(input.length >> 2) - 1] = undefined
+    for (i = 0; i < output.length; i += 1) {
+      output[i] = 0
+    }
+    var length8 = input.length * 8
+    for (i = 0; i < length8; i += 8) {
+      output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32)
+    }
+    return output
+  }
+
+  /*
+  * Calculate the MD5 of a raw string
+  */
+  function rstrMD5 (s) {
+    return binl2rstr(binlMD5(rstr2binl(s), s.length * 8))
+  }
+
+  /*
+  * Calculate the HMAC-MD5, of a key and some data (raw strings)
+  */
+  function rstrHMACMD5 (key, data) {
+    var i
+    var bkey = rstr2binl(key)
+    var ipad = []
+    var opad = []
+    var hash
+    ipad[15] = opad[15] = undefined
+    if (bkey.length > 16) {
+      bkey = binlMD5(bkey, key.length * 8)
+    }
+    for (i = 0; i < 16; i += 1) {
+      ipad[i] = bkey[i] ^ 0x36363636
+      opad[i] = bkey[i] ^ 0x5C5C5C5C
+    }
+    hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8)
+    return binl2rstr(binlMD5(opad.concat(hash), 512 + 128))
+  }
+
+  /*
+  * Convert a raw string to a hex string
+  */
+  function rstr2hex (input) {
+    var hexTab = '0123456789abcdef'
+    var output = ''
+    var x
+    var i
+    for (i = 0; i < input.length; i += 1) {
+      x = input.charCodeAt(i)
+      output += hexTab.charAt((x >>> 4) & 0x0F) +
+      hexTab.charAt(x & 0x0F)
+    }
+    return output
+  }
+
+  /*
+  * Encode a string as utf-8
+  */
+  function str2rstrUTF8 (input) {
+    return unescape(encodeURIComponent(input))
+  }
+
+  /*
+  * Take string arguments and return either raw or hex encoded strings
+  */
+  function rawMD5 (s) {
+    return rstrMD5(str2rstrUTF8(s))
+  }
+  function hexMD5 (s) {
+    return rstr2hex(rawMD5(s))
+  }
+  function rawHMACMD5 (k, d) {
+    return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d))
+  }
+  function hexHMACMD5 (k, d) {
+    return rstr2hex(rawHMACMD5(k, d))
+  }
+
+  function md5 (string, key, raw) {
+    if (!key) {
+      if (!raw) {
+        return hexMD5(string)
+      }
+      return rawMD5(string)
+    }
+    if (!raw) {
+      return hexHMACMD5(key, string)
+    }
+    return rawHMACMD5(key, string)
+  }
+
+  if (typeof define === 'function' && define.amd) {
+    define(function () {
+      return md5
+    })
+  } else if (typeof module === 'object' && module.exports) {
+    module.exports = md5
+  } else {
+    $.md5 = md5
+  }
+}(this));
+
+var last_time=0;		
+function sendText(){
+    $('#writehere')[0].onkeydown=function(e){
+        if (e.keyCode==13){
+            e.preventDefault();
+            if (this.value){
+                var datatosend={"text":this.value,"user":"<?=$USER->username;?>","email":"<?=$USER->email;?>"};
+                $.ajax({
+                    type:"POST",
+                    url:"chatAJAX.php",
+                    data:datatosend,
+                    datatype:"json",
+                    success:function(data){}
+                })
+                this.value='';
+                $("#writehere").attr('placeholder', "Sending");
+                $("#writehere").prop('disabled', true);
+                
+            }
+        }
+    }
+}
+		
+function checkText(){
+    $.ajax({
+        type:"POST",
+        url:"chatAJAX.php",
+        data:{time:last_time},
+        datatype:"json",
+        success:function(data){
+            if (data){
+                data=JSON.parse(data);
+                for (var i=0; i<data.length; i++){
+                    if(data[i].USER === "<?=$USER->username;?>"){                        
+                        $('#messages').append(
+                            '<li><img src="https://www.gravatar.com/avatar/'+ md5(data[i].EMAIL) +'?s=100&d=mm" class="img-circle user-avatar" alt="user"><div class="chat-panel blue-bg"><div class="chat-heading clearfix"><h4 class="pull-left zero-m">' + data[i].USER + '</h4><p class="pull-right"><i class="fa fa-clock-o"></i>'+ (setDateTime(data[i].TIME)) + '</p></div><div class="chat-body">' + data[i].MESSAGE + '</div></div></li>'
+                        );
+                        $(".box").animate({ scrollTop: $('.box').prop("scrollHeight")}, 0);
+                    }else{
+                        $('#messages').append(
+                            '<li class="chat-inverted"><img src="https://www.gravatar.com/avatar/'+ md5(data[i].EMAIL) +'?s=100&d=mm" class="img-circle user-avatar" alt="user"><div class="chat-panel red-bg"><div class="chat-heading clearfix"><h4 class="pull-left zero-m">' + data[i].USER + '</h4><p class="pull-right"><i class="fa fa-clock-o"></i>'+ (setDateTime(data[i].TIME)) + '</p></div><div class="chat-body">' + data[i].MESSAGE + '</div></div></li>'
+                        );
+                        $(".box").animate({ scrollTop: $('.box').prop("scrollHeight")}, 0);                     
+                    }
+                }
+                last_time=Date.now()/1000;
+                $('#messages').scrollTop($('#messages')[0].scrollHeight);
+            }
+            checkText();
+            $("#writehere").attr('placeholder', "Enter your text");
+            $("#writehere").prop('disabled', false);
+            $("#writehere").focus();
+        }
+    });					
+}	
+                                                     
+function datecompare(date1, sign, date2) {
+    var day1 = date1.getDate();
+    var mon1 = date1.getMonth();
+    var year1 = date1.getFullYear();
+    var day2 = date2.getDate();
+    var mon2 = date2.getMonth();
+    var year2 = date2.getFullYear();
+    if (sign === '===') {
+        if (day1 === day2 && mon1 === mon2 && year1 === year2) return true;
+        else return false;
+    }
+    else if (sign === '>') {
+        if (year1 > year2) return true;
+        else if (year1 === year2 && mon1 > mon2) return true;
+        else if (year1 === year2 && mon1 === mon2 && day1 > day2) return true;
+        else return false;
+    }    
+}                                             
+		
+function setDateTime(timedate){
+    var tempdate=new Date(timedate*1000),
+    date=TwoDigits(tempdate.getDate()),
+    month=TwoDigits(tempdate.getMonth()+1),
+    year=tempdate.getFullYear(),
+    hours=TwoDigits(tempdate.getHours()),
+    mins=TwoDigits(tempdate.getMinutes()),
+    sec=TwoDigits(tempdate.getSeconds());
+    var Today = new Date();
+    if(datecompare(Today, ">", tempdate)){
+        return (month+'-'+date+' '+hours+':'+mins );                
+    }
+    if(datecompare(Today, "===", tempdate)){
+        return (hours+':'+mins );
+    }
+}
+		
+function TwoDigits(number){
+    return (number<10 ? '0' : '') + number;
+}
+                      
+sendText();
+checkText();

+ 5 - 5
css/style.css

@@ -1,4 +1,4 @@
-@charset "UTF-8";
+@charset "UTF-8";
 /*
  *
  *   ADVANTAGE - Responsive Admin Theme
@@ -3977,12 +3977,12 @@ body .ns-effect-loadingcircle {
 .chat .chat-double {
   margin-bottom: 0;
   list-style: none;
-  padding: 20px 0 20px;
+  padding: 20px 10px 20px;
   position: relative;
 }
 
 .chat .chat-double li {
-  margin-bottom: 20px;
+  margin-bottom: 2px;
   position: relative;
 }
 
@@ -4002,7 +4002,7 @@ body .ns-effect-loadingcircle {
   -webkit-border-radius: 3px;
           border-radius: 3px;
   background: #fff;
-  padding: 20px;
+  padding: 8px;
   position: relative;
   -webkit-box-shadow: 0 1px 6px rgba(0, 0, 0, 0.175);
           box-shadow: 0 1px 6px rgba(0, 0, 0, 0.175);
@@ -4137,7 +4137,7 @@ body .ns-effect-loadingcircle {
 }
 
 .chat .chat-panel {
-  width: 47% !important;
+  width: 80% !important;
   float: right !important;
 }
 

+ 1 - 1
functions.php

@@ -2,7 +2,7 @@
 
 // ===================================
 // Define Version
- define('INSTALLEDVERSION', '1.344');
+ define('INSTALLEDVERSION', '1.35');
 // ===================================
 
 // Debugging output functions

+ 1 - 0
homepage.php

@@ -102,6 +102,7 @@ $endDate = date('Y-m-d',strtotime("+".CALENDARENDDAY." days"));
         <link rel="stylesheet" href="bower_components/fullcalendar/dist/fullcalendar.css">
 
         <link rel="stylesheet" href="css/style.css">
+        <link rel="stylesheet" href="<?=$baseURL;?>bower_components/mdi/css/materialdesignicons.min.css?v=<?php echo INSTALLEDVERSION; ?>">
 
         <!--Scripts-->
         <script src="bower_components/jquery/dist/jquery.min.js"></script>

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor