Skip to content
Snippets Groups Projects
Commit 920914fc authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Initial PoC

parents
Branches
No related tags found
No related merge requests found
<?php
//
// Quassel Backlog Search - classes
// developed 2009 by m4yer <m4yer@minad.de> under a Creative Commons Licence by-nc-sa 3.0
//
// password hashing improvements developed 2015 by mamarley
//
function initialAuthenticateUser($plainPassword,$dbHashedPassword,$hashVersion){
switch($hashVersion){
case null:
case 0:
return initialCheckHashedPasswordSha1($plainPassword,$dbHashedPassword);
break;
case 1:
return initialCheckHashedPasswordSha2_512($plainPassword,$dbHashedPassword);
break;
default:
return false;
break;
}
}
function initialCheckHashedPasswordSha1($plainPassword,$dbHashedPassword){
$calculatedPasswordHash=hash("sha1",$plainPassword);
if($calculatedPasswordHash==$dbHashedPassword){
return $calculatedPasswordHash;
}
return false;
}
function initialCheckHashedPasswordSha2_512($plainPassword,$dbHashedPassword){
$dbHashedPasswordArray=explode(":",$dbHashedPassword);
if(count($dbHashedPasswordArray)==2){
$calculatedPasswordHash=hash("sha512",$plainPassword . $dbHashedPasswordArray[1]);
if($calculatedPasswordHash==$dbHashedPasswordArray[0]){
return $dbHashedPasswordArray[0];
}
}
return false;
}
?>
\ No newline at end of file
<?php
require_once('auth_functions.php');
class Backend {
private $dbh;
private $user;
public function connect($configfile) {
$config = parse_ini_file($configfile);
if ($config['local']) {
$this->dbh = new PDO('pgsql:dbname='.$config['dbname'].' user='.$config['user'].' password='.$config['password']);
} else {
$this->dbh = new PDO('pgsql:host='.$config['host'].' port='.$config['port'].' dbname='.$config['dbname'].' user='.$config['user'].' password='.$config['password']);
}
}
public function auth($username, $password) {
if (!isset($username) || !isset($password))
return false;
$stmt = $this->dbh->prepare("SELECT * FROM quasseluser WHERE username = ?");
$stmt->execute(array($_POST['username']));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($rows) !== 1)
return false;
$row = $rows[0];
if (!initialAuthenticateUser($_POST['password'], $row['password'], $row['hashversion']))
return false;
$this->user = array(
'id' => $row['userid'],
'name' => $row['username']
);
return true;
}
public function search($arg_query, $arg_limit, $arg_offset) {
$sql = "SELECT backlog.messageid, buffer.bufferid, buffer.buffername, sender.sender, backlog.\"time\", network.networkname, ts_headline(backlog.message, query) AS message FROM backlog JOIN sender ON backlog.senderid = sender.senderid JOIN buffer ON backlog.bufferid = buffer.bufferid JOIN network ON buffer.networkid = network.networkid, to_tsquery('simple', ?) query WHERE type = 1 AND buffer.userid = ? AND to_tsvector('simple', message) @@ query ORDER BY messageid DESC LIMIT ? OFFSET ?;";
$stmt = $this->dbh->prepare($sql);
$limit = max(min($arg_limit, 50), 10);
$offset = max(0, $arg_offset);
$stmt->execute(array($arg_query, $this->user['id'], $limit, $offset));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function after($arg_id, $arg_buffer, $arg_limit) {
$sql = "SELECT backlog.messageid, buffer.bufferid, buffer.buffername, sender.sender, backlog.\"time\", network.networkname, backlog.message FROM backlog JOIN sender ON backlog.senderid = sender.senderid JOIN buffer ON backlog.bufferid = buffer.bufferid JOIN network ON buffer.networkid = network.networkid WHERE buffer.userid = ? AND buffer.bufferid = ? AND messageid >= ? ORDER BY messageid ASC LIMIT ?;";
$stmt = $this->dbh->prepare($sql);
$limit = max(min($arg_limit+1, 50), 1);
$stmt->execute(array($this->user['id'], $arg_buffer, $arg_id, $limit));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function before($arg_id, $arg_buffer, $arg_limit) {
$sql = "SELECT backlog.messageid, buffer.bufferid, buffer.buffername, sender.sender, backlog.\"time\", network.networkname, backlog.message FROM backlog JOIN sender ON backlog.senderid = sender.senderid JOIN buffer ON backlog.bufferid = buffer.bufferid JOIN network ON buffer.networkid = network.networkid WHERE buffer.userid = ? AND buffer.bufferid = ? AND messageid < ? ORDER BY messageid DESC LIMIT ?;";
$stmt = $this->dbh->prepare($sql);
$limit = max(min($arg_limit, 50), 0);
$stmt->execute(array($this->user['id'], $arg_buffer, $arg_id, $limit));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function context($arg_id, $arg_buffer, $arg_before, $arg_after) {
return array_merge(array_reverse($this->before($arg_id, $arg_buffer, $arg_before)), $this->after($arg_id, $arg_buffer, $arg_after));
}
}
?>
\ No newline at end of file
local=false
dbname=quassel
user=quassel
password=supersecurepassword
host=example.org
port=5436
<?php
require_once('backend.php');
$backend = new Backend();
$backend->connect('/var/www/config.ini');
if (!$backend->auth($_POST['username'], $_POST['password'])) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
header('Status: 403 Forbidden');
exit;
}
header('Content-Type: application/json');
echo json_encode($backend->context(intval($_GET['msg']),intval($_GET['buffer']),intval($_GET['before']),intval($_GET['after'])))."\n";
?>
\ No newline at end of file
<!DOCTYPE html>
<meta charset="utf-8">
<title>Quassel Search</title>
<link rel="stylesheet" href="style.css">
<nav>
<div id="searchbar">
<input type="text" name="q" id="q">
<div id="searchicon"><span>Search</span></div>
</div>
</nav>
<section id="results">
<button id="login">Login</button> <button id="logout">Logout</button>
</section>
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>
var userdata = { "username": localStorage.getItem("username"), "password": localStorage.getItem("password") };
var result = undefined;
var renderBuffer = function (buffer) {
return (
"<buffer>" +
"<h2>" + buffer.network + "" + buffer.name + "</h2>" +
"<article>" +
buffer.messages.map(renderMessage).reduce((x, y) => x + y) +
"</article>" +
"</buffer>"
)
}
var renderMessage = function (message) {
return (
"<message data-id='" + message.messageid + "'>" +
"<time>" + message.time.toLocaleString() + "</time>" +
"<sender>" + message.sender.split("!")[0] + "</sender>" +
"<content>" + message.message + "</content>" +
"</message>"
)
}
var render = function (data) {
return $.map(data, renderBuffer).reduce((x, y) => x + y);
}
var display = function (data) {
$("#results").children().remove();
$("#results").append(data);
}
var sortData = function (data) {
var buffers = {};
data.forEach(message => {
if (!buffers.hasOwnProperty(message.bufferid)) {
buffers[message.bufferid] = {
id: message.bufferid,
name: message.buffername,
network: message.networkname,
messages: []
}
}
message.time = new Date(message.time.replace(" ", "T") + "Z");
buffers[message.bufferid].messages.push(message);
});
return buffers;
}
var show = function (data) {
result = data;
display(render(sortData(data)));
}
var load = function() {
$("#results").children().remove()
$.post("search.php?query="+$("#q").val(), userdata, show, "json");
}
$("#q").keypress(function (e) {
var key = e.which || e.keyCode;
if (key === 13) {
load();
}
})
$("#login").click(function() {
localStorage.setItem("username", prompt("username"));
localStorage.setItem("password", prompt("password"));
})
$("#logout").click(function() {
localStorage.removeItem("username");
localStorage.removeItem("password");
})
</script>
\ No newline at end of file
<?php
require_once('backend.php');
$backend = new Backend();
$backend->connect('/var/www/config.ini');
if (!$backend->auth($_POST['username'], $_POST['password'])) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
header('Status: 403 Forbidden');
exit;
}
header('Content-Type: application/json');
echo json_encode($backend->search($_GET['query'],$_GET['limit'],$_GET['offset']))."\n";
?>
\ No newline at end of file
style.css 0 → 100644
* {
padding: 0;
margin: 0;
box-shadow: border-box;
}
body {
background: #F2F2F2;
font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
font-size: 81.25%;
}
section {
max-width: 1200px;
padding: 56px 4rem 0 4rem;
margin: 0 auto;
}
buffer > article {
background: #fff;
font-size: 13px;
box-shadow: 0 -1px 0 #e5e5e5,0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24)
}
buffer > h2 {
border-bottom: 1px solid transparent;
border-top: 1px solid transparent;
color: #616161;
margin-top: 20px;
padding-bottom: 10px;
padding-left: 22px;
position: relative;
will-change: transform,-webkit-transform;
}
message {
display: flex;
height: 48px;
line-height: 48px;
border-bottom: 1px solid #e5e5e5;
color: #212121;
}
message sender {
width: 148px;
display: inline-block;
font-weight: bold;
flex-shrink: 0;
}
message time {
width: 148px;
display: inline-block;
padding: 0 24px;
text-align: right;
flex-shrink: 0;
}
message content {
padding: 0 24px;
flex-shrink: 1;
overflow: hidden;
}
message:last-child {
border-bottom: none;
}
nav {
position: fixed;
left: 0;
right: 0;
top: 0;
height: 56px;
background: #4285f4;
padding: 0px 4rem;
}
nav input[type=text]::-moz-placeholder {
color: #ffffff;
opacity: 1;
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
}
nav input[type=text]:focus::-moz-placeholder {
color: #757575;
opacity: 1;
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
}
#searchbar {
max-width: 1200px;
margin: 10px auto;
height: 36px;
display: block;
position: relative;
}
nav input[type=text] {
width: 100%;
height: 100%;
display: inline-block;
border: none;
-webkit-transition: background .15s;
transition: background .15s;
background: rgba(255,255,255,.15);
border-radius: 2px;
padding: 0 72px;
color: #ffffff;
box-sizing: border-box;
}
#searchicon {
background-image: url(https://ssl.gstatic.com/bt/C3341AA7A1A076756462EE2E5CD71C11/1x/ic_search_wht_24dp_r1.png);
display: inline-block;
width: 72px;
height: 36px;
position: absolute;
left: 0;
top: 0;
background-repeat: no-repeat;
background-position: center center;
}
#searchicon span {
display: none;
}
nav input[type=text]:hover {
background: rgba(255,255,255,.25);
}
nav input[type=text]:focus {
background: #f6f6f6;
color: #212121;
}
nav input[type=text]:focus+#searchicon {
background-image: url(https://ssl.gstatic.com/bt/C3341AA7A1A076756462EE2E5CD71C11/1x/ic_search_blk_24dp_r1.png);
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment