d47081
2 years ago
committed by
GitHub
9 changed files with 565 additions and 44 deletions
@ -0,0 +1,50 @@ |
|||||||
|
<<<<<<< HEAD |
||||||
|
# kvazar-network webapp |
||||||
|
Web-oriented content exploring platform for Kevacoin Blockchain |
||||||
|
|
||||||
|
### requirements |
||||||
|
``` |
||||||
|
php-8^ |
||||||
|
php-curl |
||||||
|
php-mbstring |
||||||
|
php-sqlite3 |
||||||
|
php-pdo |
||||||
|
php-bcmath |
||||||
|
php-gd |
||||||
|
``` |
||||||
|
#### database |
||||||
|
|
||||||
|
https://github.com/kvazar-network/database |
||||||
|
|
||||||
|
##### MySQL |
||||||
|
|
||||||
|
https://github.com/kvazar-network/webapp/tree/master |
||||||
|
|
||||||
|
##### SQLite |
||||||
|
|
||||||
|
https://github.com/kvazar-network/webapp/tree/sqlite |
||||||
|
|
||||||
|
#### crontab |
||||||
|
|
||||||
|
``` |
||||||
|
0 0 * * * /path-to/php /path-to/crontab/sitemap.php > /dev/null 2>&1 |
||||||
|
``` |
||||||
|
|
||||||
|
### nginx sef_mode example |
||||||
|
|
||||||
|
``` |
||||||
|
location / { |
||||||
|
try_files $uri $uri/ =404 @sef; |
||||||
|
} |
||||||
|
|
||||||
|
location @sef { |
||||||
|
rewrite ^(/.*)$ /?$1 last; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### examples |
||||||
|
|
||||||
|
#### yggdrasil |
||||||
|
[http://[203:9fd0:95df:54d7:29db:5ee1:fe2d:95c7]](http://[203:9fd0:95df:54d7:29db:5ee1:fe2d:95c7]) |
||||||
|
======= |
||||||
|
>>>>>>> master |
@ -0,0 +1,268 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
class SQLite { |
||||||
|
|
||||||
|
private PDO $_db; |
||||||
|
|
||||||
|
public function __construct(string $database, string $username, string $password) { |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
$this->_db = new PDO('sqlite:' . $database, $username, $password); |
||||||
|
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
||||||
|
$this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); |
||||||
|
$this->_db->setAttribute(PDO::ATTR_TIMEOUT, 600); |
||||||
|
|
||||||
|
$this->_db->query(' |
||||||
|
CREATE TABLE IF NOT EXISTS "namespace"( |
||||||
|
"nameSpaceId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nameSpaceId">=0), |
||||||
|
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0), |
||||||
|
"hash" CHAR(34) NOT NULL, |
||||||
|
CONSTRAINT "hash_UNIQUE" |
||||||
|
UNIQUE("hash") |
||||||
|
) |
||||||
|
'); |
||||||
|
|
||||||
|
$this->_db->query(' |
||||||
|
CREATE TABLE IF NOT EXISTS "block"( |
||||||
|
"blockId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("blockId">=0), |
||||||
|
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0), |
||||||
|
"lostTransactions" INTEGER NOT NULL CHECK("lostTransactions">=0) |
||||||
|
) |
||||||
|
'); |
||||||
|
|
||||||
|
$this->_db->query(' |
||||||
|
CREATE TABLE IF NOT EXISTS "data"( |
||||||
|
"dataId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("dataId">=0), |
||||||
|
"nameSpaceId" INTEGER NOT NULL CHECK("nameSpaceId">=0), |
||||||
|
"blockId" INTEGER NOT NULL CHECK("blockId">=0), |
||||||
|
"time" INTEGER NOT NULL CHECK("time">=0), |
||||||
|
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0), |
||||||
|
"size" INTEGER NOT NULL, |
||||||
|
"ns" TEXT NOT NULL CHECK("ns" IN(\'0\', \'1\')), |
||||||
|
"deleted" TEXT NOT NULL CHECK("deleted" IN(\'0\', \'1\')), |
||||||
|
"txid" CHAR(64) NOT NULL, |
||||||
|
"key" TEXT NOT NULL, |
||||||
|
"value" TEXT NOT NULL, |
||||||
|
CONSTRAINT "txid_UNIQUE" |
||||||
|
UNIQUE("txid"), |
||||||
|
CONSTRAINT "fk_data_namespace" |
||||||
|
FOREIGN KEY("nameSpaceId") |
||||||
|
REFERENCES "namespace"("nameSpaceId"), |
||||||
|
CONSTRAINT "fk_data_block" |
||||||
|
FOREIGN KEY("blockId") |
||||||
|
REFERENCES "block"("blockId") |
||||||
|
) |
||||||
|
|
||||||
|
'); |
||||||
|
|
||||||
|
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.fk_data_namespase_idx" ON "data" ("nameSpaceId")'); |
||||||
|
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.fk_data_block_idx" ON "data" ("blockId")'); |
||||||
|
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.deleted_INDEX" ON "data" ("deleted")'); |
||||||
|
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.ns_INDEX" ON "data" ("ns")'); |
||||||
|
|
||||||
|
} catch(PDOException $e) { |
||||||
|
trigger_error($e->getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getNamespaceValueByNS(string $ns) { |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `data`.`value` AS `value` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `namespace`.`hash` = ? |
||||||
|
AND `data`.`ns` = "1" |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `data`.`blockId` DESC |
||||||
|
|
||||||
|
LIMIT 1'); |
||||||
|
|
||||||
|
$query->execute([$ns]); |
||||||
|
|
||||||
|
$result = $query->fetch(); |
||||||
|
|
||||||
|
return $result ? $result['value'] : ''; |
||||||
|
|
||||||
|
} catch(PDOException $e) { |
||||||
|
|
||||||
|
trigger_error($e->getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getNamespaceHashByTX(string $txid) { |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `namespace`.`hash` |
||||||
|
|
||||||
|
FROM `namespace` |
||||||
|
JOIN `data` ON (`data`.`nameSpaceId` = `namespace`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `data`.`txid` = ?'); |
||||||
|
|
||||||
|
$query->execute([$txid]); |
||||||
|
|
||||||
|
return $query->rowCount() ? $query->fetch()['hash'] : ''; |
||||||
|
|
||||||
|
} catch(PDOException $e) { |
||||||
|
|
||||||
|
trigger_error($e->getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getData(string $namehash = '', string $txid = '', string $search = '', int $start = 0, int $limit = 10) { |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
if ($txid) { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`, |
||||||
|
`namespace`.`hash` AS `namehash`, |
||||||
|
`data`.`time` AS `time`, |
||||||
|
`data`.`key` AS `key`, |
||||||
|
`data`.`value` AS `value`, |
||||||
|
`data`.`txid` AS `txid` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`) |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `data`.`txid` = ? |
||||||
|
AND `data`.`ns` = "0" |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `block`.`blockId` DESC |
||||||
|
|
||||||
|
LIMIT ' . (int) $start . ',' . (int) $limit); |
||||||
|
|
||||||
|
$query->execute([$txid]); |
||||||
|
|
||||||
|
} else if ($namehash) { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`, |
||||||
|
`namespace`.`hash` AS `namehash`, |
||||||
|
`data`.`time` AS `time`, |
||||||
|
`data`.`key` AS `key`, |
||||||
|
`data`.`value` AS `value`, |
||||||
|
`data`.`txid` AS `txid` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`) |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `namespace`.`hash` = ? |
||||||
|
AND `data`.`ns` = "0" |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `block`.`blockId` DESC |
||||||
|
|
||||||
|
LIMIT ' . (int) $start . ',' . (int) $limit); |
||||||
|
|
||||||
|
$query->execute([$namehash]); |
||||||
|
|
||||||
|
} else if ($search) { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`, |
||||||
|
`namespace`.`hash` AS `namehash`, |
||||||
|
`data`.`time` AS `time`, |
||||||
|
`data`.`key` AS `key`, |
||||||
|
`data`.`value` AS `value`, |
||||||
|
`data`.`txid` AS `txid` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`) |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE (`data`.`key` LIKE :search |
||||||
|
OR `data`.`value` LIKE :search |
||||||
|
OR `block`.`blockId` LIKE :search |
||||||
|
OR `namespace`.`hash` LIKE :search |
||||||
|
OR `data`.`txid` LIKE :search) |
||||||
|
|
||||||
|
AND `data`.`ns` = "0" |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `block`.`blockId` DESC |
||||||
|
|
||||||
|
LIMIT ' . (int) $start . ',' . (int) $limit); |
||||||
|
|
||||||
|
$query->bindValue(':search', '%' . $search . '%', PDO::PARAM_STR); |
||||||
|
|
||||||
|
$query->execute(); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`, |
||||||
|
`namespace`.`hash` AS `namehash`, |
||||||
|
`data`.`time` AS `time`, |
||||||
|
`data`.`key` AS `key`, |
||||||
|
`data`.`value` AS `value`, |
||||||
|
`data`.`txid` AS `txid` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`) |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `data`.`ns` = "0" |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `block`.`blockId` DESC |
||||||
|
|
||||||
|
LIMIT ' . (int) $start . ',' . (int) $limit); |
||||||
|
|
||||||
|
$query->execute(); |
||||||
|
} |
||||||
|
|
||||||
|
$result = $query->fetchAll(); |
||||||
|
|
||||||
|
return $result ? $result : []; |
||||||
|
|
||||||
|
} catch(PDOException $e) { |
||||||
|
|
||||||
|
trigger_error($e->getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getTrends(int $offset = 0) { |
||||||
|
|
||||||
|
try { |
||||||
|
|
||||||
|
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`, |
||||||
|
`namespace`.`hash` AS `namehash`, |
||||||
|
`data`.`time` AS `time`, |
||||||
|
`data`.`key` AS `key`, |
||||||
|
`data`.`value` AS `value`, |
||||||
|
`data`.`txid` AS `txid` |
||||||
|
|
||||||
|
FROM `data` |
||||||
|
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`) |
||||||
|
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`) |
||||||
|
|
||||||
|
WHERE `data`.`ns` = "0" |
||||||
|
AND `data`.`time` >= ' . (int) $offset . ' |
||||||
|
-- AND `data`.`deleted` = "0" -- |
||||||
|
|
||||||
|
ORDER BY `block`.`blockId` DESC'); |
||||||
|
|
||||||
|
$query->execute(); |
||||||
|
|
||||||
|
$result = $query->fetchAll(); |
||||||
|
|
||||||
|
return $result ? $result : []; |
||||||
|
|
||||||
|
} catch(PDOException $e) { |
||||||
|
|
||||||
|
trigger_error($e->getMessage()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,174 @@ |
|||||||
|
<<<<<<< HEAD |
||||||
|
<?php |
||||||
|
|
||||||
|
require_once('../config.php'); |
||||||
|
require_once('../library/icon.php'); |
||||||
|
require_once('../library/sqlite.php'); |
||||||
|
|
||||||
|
$query = isset($_GET['q']) ? preg_replace('/[^\w\s]+/u', '', urldecode($_GET['q'])) : ''; |
||||||
|
$ns = ''; |
||||||
|
$tx = ''; |
||||||
|
$page = 0; |
||||||
|
|
||||||
|
if (isset($_SERVER['REQUEST_URI'])) { |
||||||
|
|
||||||
|
$q = explode('/', $_SERVER['REQUEST_URI']); |
||||||
|
|
||||||
|
if (isset($q[1])) { |
||||||
|
if ($q[1] == 'rss') { |
||||||
|
$rss = true; |
||||||
|
} else if (strlen($q[1]) == 34) { |
||||||
|
$ns = preg_replace('/[^a-zA-Z0-9]+/', '', $q[1]); |
||||||
|
} else if (strlen($q[1]) == 64) { |
||||||
|
$tx = preg_replace('/[^a-zA-Z0-9]+/', '', $q[1]); |
||||||
|
} else if (preg_match('/[0-9]+/', $q[1])) { |
||||||
|
$page = (int) $q[1]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (isset($q[2])) { |
||||||
|
if ($q[2] == 'rss') { |
||||||
|
$rss = true; |
||||||
|
} else if (strlen($q[2]) == 34) { |
||||||
|
$ns = preg_replace('/[^a-zA-Z0-9]+/', '', $q[2]); |
||||||
|
} else if (preg_match('/[0-9]+/', $q[2])) { |
||||||
|
$page = (int) $q[2]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($query) { |
||||||
|
$rss = isset($_GET['rss']) ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
if ($page > 0) { |
||||||
|
$limit = PAGE_LIMIT * $page - PAGE_LIMIT; |
||||||
|
} else { |
||||||
|
$limit = PAGE_LIMIT * $page; |
||||||
|
} |
||||||
|
|
||||||
|
$db = new SQLite(DB_NAME, DB_USERNAME, DB_PASSWORD); |
||||||
|
|
||||||
|
if ($ns) { |
||||||
|
|
||||||
|
$namespaceHash = $ns; |
||||||
|
$namespaceValue = $db->getNamespaceValueByNS($ns); |
||||||
|
|
||||||
|
} else if ($tx) { |
||||||
|
|
||||||
|
$namespaceHash = $db->getNamespaceHashByTX($tx); |
||||||
|
$namespaceValue = $db->getNamespaceValueByNS($namespaceHash); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
$namespaceHash = false; |
||||||
|
$namespaceValue = false; |
||||||
|
} |
||||||
|
|
||||||
|
$trends = []; |
||||||
|
|
||||||
|
if (TRENDS_ENABLED) { |
||||||
|
|
||||||
|
foreach ($db->getTrends(time() - TRENDS_SECONDS_OFFSET) as $value) { |
||||||
|
|
||||||
|
foreach ((array) explode(' ', strip_tags(html_entity_decode(nl2br(trim($value['key']))))) as $trend) { |
||||||
|
|
||||||
|
if (strlen($trend) >= TRENDS_MIN_LENGHT) { |
||||||
|
|
||||||
|
$trend = strtolower($trend); |
||||||
|
|
||||||
|
if (isset($trends[$trend])) { |
||||||
|
$trends[$trend]++; |
||||||
|
} else { |
||||||
|
$trends[$trend] = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
foreach ((array) explode(' ', strip_tags(html_entity_decode(nl2br(trim($value['value']))))) as $trend) { |
||||||
|
|
||||||
|
if (strlen($trend) >= TRENDS_MIN_LENGHT) { |
||||||
|
|
||||||
|
$trend = strtolower($trend); |
||||||
|
|
||||||
|
if (isset($trends[$trend])) { |
||||||
|
$trends[$trend]++; |
||||||
|
} else { |
||||||
|
$trends[$trend] = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
arsort($trends); |
||||||
|
|
||||||
|
$trends = array_slice($trends, 0, TRENDS_LIMIT); |
||||||
|
|
||||||
|
$trends = array_flip($trends); |
||||||
|
} |
||||||
|
|
||||||
|
$data = []; |
||||||
|
foreach ($db->getData($ns, $tx, $query, $limit, PAGE_LIMIT) as $value) { |
||||||
|
$data[] = [ |
||||||
|
'namehash' => $value['namehash'], |
||||||
|
'block' => $value['block'], |
||||||
|
'txid' => $value['txid'], |
||||||
|
'time' => date(($rss ? 'r' : 'd-m-Y H:i'), $value['time']), |
||||||
|
'key' => $rss ? htmlentities(strip_tags(trim($value['key'])), ENT_XML1) : nl2br(trim($value['key'])), |
||||||
|
'value' => $rss ? htmlentities(strip_tags(trim($value['value'])), ENT_XML1): nl2br(trim($value['value'])), |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
$older = false; |
||||||
|
$newer = false; |
||||||
|
|
||||||
|
if (!in_array($page, [0, 1])) { |
||||||
|
if ($page == 2) { |
||||||
|
$newer = ($ns ? $ns : ''); |
||||||
|
} else { |
||||||
|
$newer = ($ns ? $ns . '/' . ($page - 1) : ($page - 1)); |
||||||
|
} |
||||||
|
|
||||||
|
if ($query) { |
||||||
|
$newer = $newer . '?q=' . $query; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($data) { |
||||||
|
if (in_array($page, [0, 1])) { |
||||||
|
$older = ($ns ? $ns . '/2' : '2'); |
||||||
|
} else { |
||||||
|
$older = ($ns ? $ns . '/' . ($page + 1) : ($page + 1)); |
||||||
|
} |
||||||
|
|
||||||
|
if ($query) { |
||||||
|
$older = $older . '?q=' . $query; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($ns) { |
||||||
|
if ($page) { |
||||||
|
$hrefThisPage = $ns . '/' . $page; |
||||||
|
} else { |
||||||
|
$hrefThisPage = $ns; |
||||||
|
} |
||||||
|
} else { |
||||||
|
if ($page) { |
||||||
|
$hrefThisPage = $page; |
||||||
|
} else { |
||||||
|
$hrefThisPage = ''; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($rss) { |
||||||
|
|
||||||
|
header('Content-type: application/xml'); |
||||||
|
require_once('rss.phtml'); |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
require_once('index.phtml'); |
||||||
|
|
||||||
|
} |
||||||
|
======= |
||||||
|
>>>>>>> master |
@ -0,0 +1,21 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> |
||||||
|
<channel> |
||||||
|
<atom:link href="<?php echo BASE_URL; ?><?php echo ($ns ? $ns . '/rss' : |
||||||
|
($query ? '?q=' . $query . '&rss' : 'rss')); ?>" rel="self" type="application/rss+xml"></atom:link> |
||||||
|
<title>KVAZAR - <?php echo ($namespaceValue ? $namespaceValue : |
||||||
|
($namespaceHash ? $namespaceHash : |
||||||
|
($query ? 'SEARCH - ' . $query : 'TODAY'))); ?></title> |
||||||
|
<description>Observe Kevacoin Universe</description> |
||||||
|
<link><?php echo BASE_URL; ?><?php echo ($ns ? $ns : ($query ? '?q=' . $query : false)); ?></link> |
||||||
|
<?php foreach ($data as $item) { ?> |
||||||
|
<item> |
||||||
|
<title><?php echo $item['key']; ?></title> |
||||||
|
<guid><?php echo BASE_URL; ?><?php echo $item['txid']; ?></guid> |
||||||
|
<pubDate><?php echo $item['time']; ?></pubDate> |
||||||
|
<description><?php echo $item['value']; ?></description> |
||||||
|
<link><?php echo BASE_URL; ?><?php echo $item['txid']; ?></link> |
||||||
|
</item> |
||||||
|
<?php } ?> |
||||||
|
</channel> |
||||||
|
</rss> |
Loading…
Reference in new issue