mirror of https://github.com/YGGverse/Yo.git
yggverse
9 months ago
11 changed files with 198 additions and 2416 deletions
@ -1,177 +0,0 @@
@@ -1,177 +0,0 @@
|
||||
<?php |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . '/../../../vendor/autoload.php'; |
||||
|
||||
// Init config |
||||
$config = json_decode( |
||||
file_get_contents( |
||||
__DIR__ . '/../../../config.json' |
||||
) |
||||
); |
||||
|
||||
// Init manticore |
||||
$client = new \Manticoresearch\Client( |
||||
[ |
||||
'host' => $config->manticore->server->host, |
||||
'port' => $config->manticore->server->port, |
||||
] |
||||
); |
||||
|
||||
// Init index |
||||
$index = $client->index( |
||||
$config->manticore->index->document->name |
||||
); |
||||
|
||||
// Connect Yggo DB |
||||
try |
||||
{ |
||||
$yggo = new PDO( |
||||
'mysql:dbname=' . $argv[5] . ';host=' . $argv[1] . ';port=' . $argv[2] . ';charset=utf8', |
||||
$argv[3], |
||||
$argv[4], |
||||
[ |
||||
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' |
||||
] |
||||
); |
||||
|
||||
$yggo->setAttribute( |
||||
PDO::ATTR_ERRMODE, |
||||
PDO::ERRMODE_EXCEPTION |
||||
); |
||||
|
||||
$yggo->setAttribute( |
||||
PDO::ATTR_DEFAULT_FETCH_MODE, |
||||
PDO::FETCH_OBJ |
||||
); |
||||
|
||||
$yggo->setAttribute( |
||||
PDO::ATTR_TIMEOUT, |
||||
600 |
||||
); |
||||
} |
||||
|
||||
catch (Exception $error) |
||||
{ |
||||
var_dump( |
||||
$error |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
$start = isset($argv[7]) ? (int) $argv[7] : 0; |
||||
$limit = isset($argv[8]) ? (int) $argv[8] : 100; |
||||
|
||||
$total = $yggo->query('SELECT COUNT(*) AS `total` FROM `hostPage` |
||||
|
||||
WHERE `hostPage`.`httpCode` = 200 |
||||
AND `hostPage`.`timeUpdated` IS NOT NULL |
||||
AND `hostPage`.`mime` IS NOT NULL |
||||
AND `hostPage`.`size` IS NOT NULL')->fetch()->total; |
||||
|
||||
$processed = $start; |
||||
|
||||
for ($i = 0; $i <= $total; $i++) |
||||
{ |
||||
$query = $yggo->query('SELECT `hostPage`.`hostPageId`, |
||||
`hostPage`.`httpCode`, |
||||
`hostPage`.`mime`, |
||||
`hostPage`.`size`, |
||||
`hostPage`.`timeUpdated`, |
||||
`hostPage`.`uri`, |
||||
|
||||
`host`.`scheme`, |
||||
`host`.`name`, |
||||
`host`.`port`, |
||||
|
||||
( |
||||
SELECT `hostPageDescription`.`title` FROM `hostPageDescription` |
||||
WHERE `hostPageDescription`.`hostPageId` = `hostPage`.`hostPageId` |
||||
ORDER BY `hostPageDescription`.`timeAdded` DESC |
||||
LIMIT 1 |
||||
) AS `title`, |
||||
|
||||
( |
||||
SELECT `hostPageDescription`.`description` FROM `hostPageDescription` |
||||
WHERE `hostPageDescription`.`hostPageId` = `hostPage`.`hostPageId` |
||||
ORDER BY `hostPageDescription`.`timeAdded` DESC |
||||
LIMIT 1 |
||||
) AS `description`, |
||||
|
||||
( |
||||
SELECT `hostPageDescription`.`keywords` FROM `hostPageDescription` |
||||
WHERE `hostPageDescription`.`hostPageId` = `hostPage`.`hostPageId` |
||||
ORDER BY `hostPageDescription`.`timeAdded` DESC |
||||
LIMIT 1 |
||||
) AS `keywords` |
||||
|
||||
FROM `hostPage` |
||||
JOIN `host` ON (`host`.`hostId` = `hostPage`.`hostId`) |
||||
|
||||
WHERE `hostPage`.`httpCode` = 200 |
||||
AND `hostPage`.`timeUpdated` IS NOT NULL |
||||
AND `hostPage`.`mime` IS NOT NULL |
||||
AND `hostPage`.`size` IS NOT NULL |
||||
|
||||
GROUP BY `hostPage`.`hostPageId` |
||||
|
||||
LIMIT ' . $start . ',' . $limit); |
||||
|
||||
|
||||
foreach ($query->fetchAll() as $remote) |
||||
{ |
||||
$url = $remote->scheme . '://' . $remote->name . ($remote->port ? ':' . $remote->port : false) . $remote->uri; |
||||
$crc32url = crc32($url); |
||||
|
||||
// Check for unique URL requested |
||||
if (isset($argv[6])) |
||||
{ |
||||
$local = $index->search('') |
||||
->filter('id', $crc32url) |
||||
->limit(1) |
||||
->get(); |
||||
|
||||
if ($local->getTotal()) |
||||
{ |
||||
// Result |
||||
echo sprintf( |
||||
_('[%s/%s] [skip duplicate] %s') . PHP_EOL, |
||||
$processed++, |
||||
$total, |
||||
$url |
||||
); |
||||
|
||||
continue; |
||||
} |
||||
} |
||||
|
||||
$index->addDocument( |
||||
[ |
||||
'url' => $url, |
||||
'time' => (int) $remote->timeUpdated, |
||||
'code' => (int) $remote->httpCode, |
||||
'size' => (int) $remote->size, |
||||
'mime' => (string) $remote->mime, |
||||
'title' => (string) $remote->title, |
||||
'description' => (string) $remote->description, |
||||
'keywords' => (string) $remote->keywords |
||||
], |
||||
(int) $crc32url |
||||
); |
||||
|
||||
// Result |
||||
echo sprintf( |
||||
_('[%s/%s] [add] %s') . PHP_EOL, |
||||
$processed++, |
||||
$total, |
||||
$url |
||||
); |
||||
} |
||||
|
||||
// Update queue offset |
||||
$start = $start + $limit; |
||||
} |
||||
|
||||
// Done |
||||
echo _('import completed!') . PHP_EOL; |
@ -1,271 +0,0 @@
@@ -1,271 +0,0 @@
|
||||
<?php |
||||
|
||||
// Debug |
||||
ini_set('display_errors', '1'); |
||||
ini_set('display_startup_errors', '1'); |
||||
error_reporting(E_ALL); |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . '/../../vendor/autoload.php'; |
||||
|
||||
// Init config |
||||
$config = json_decode( |
||||
file_get_contents( |
||||
__DIR__ . '/../../config.json' |
||||
) |
||||
); |
||||
|
||||
// Set headers |
||||
header('Content-Type: application/json; charset=utf-8'); |
||||
|
||||
// Action |
||||
switch (!empty($_GET['action']) ? $_GET['action'] : false) { |
||||
|
||||
// Snap methods |
||||
case 'snap': |
||||
|
||||
switch (!empty($_GET['method']) ? $_GET['method'] : false) { |
||||
|
||||
case 'download': |
||||
|
||||
// Validate required attributes |
||||
switch (false) |
||||
{ |
||||
case isset($_GET['source']): |
||||
|
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('valid source required') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
|
||||
case isset($_GET['id']) && preg_match('/^[\d]+$/', $_GET['id']): |
||||
|
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('valid document identifier required') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
|
||||
case isset($_GET['time']) && preg_match('/^[\d]+$/', $_GET['time']): |
||||
|
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('valid time required') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
// Detect remote snap source |
||||
if (preg_match('/^[\d]+$/', $_GET['source'])) |
||||
{ |
||||
if (!isset($config->snap->storage->remote->ftp[$_GET['source']]) || !$config->snap->storage->remote->ftp[$_GET['source']]->enabled) |
||||
{ |
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('requested source not found') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
// Connect remote |
||||
$remote = new \Yggverse\Ftp\Client(); |
||||
|
||||
$connection = $remote->connect( |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->host, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->port, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->username, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->password, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->directory, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->timeout, |
||||
$config->snap->storage->remote->ftp[$_GET['source']]->connection->passive |
||||
); |
||||
|
||||
// Remote host connected |
||||
if ($connection) { |
||||
|
||||
// Prepare snap path |
||||
$filename = sprintf( |
||||
'%s/%s.tar.gz', |
||||
implode( |
||||
'/', |
||||
str_split( |
||||
$_GET['id'] |
||||
) |
||||
), |
||||
$_GET['time'] |
||||
); |
||||
|
||||
// Check snap exist |
||||
if (!$size = $remote->size($filename)) |
||||
{ |
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('requested snap not found') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
// Set headers |
||||
header( |
||||
'Content-Type: application/tar+gzip' |
||||
); |
||||
|
||||
header( |
||||
sprintf( |
||||
'Content-Length: %s', |
||||
$size |
||||
) |
||||
); |
||||
|
||||
header( |
||||
sprintf( |
||||
'Content-Disposition: filename="snap.%s.%s"', |
||||
$_GET['id'], |
||||
basename( |
||||
$filename |
||||
) |
||||
) |
||||
); |
||||
|
||||
// Return file |
||||
$remote->get( |
||||
$filename, |
||||
'php://output' |
||||
); |
||||
|
||||
$remote->close(); |
||||
} |
||||
} |
||||
|
||||
// Local |
||||
else if ($config->snap->storage->local->enabled) |
||||
{ |
||||
// Prefix absolute |
||||
if ('/' === substr($config->snap->storage->local->directory, 0, 1)) |
||||
{ |
||||
$prefix = $config->snap->storage->local->directory; |
||||
} |
||||
|
||||
// Prefix relative |
||||
else |
||||
{ |
||||
$prefix = __DIR__ . '/../../' . $config->snap->storage->local->directory; |
||||
} |
||||
|
||||
// Prepare snap path |
||||
$filename = sprintf( |
||||
'%s/%s/%s.tar.gz', |
||||
$prefix, |
||||
implode( |
||||
'/', |
||||
str_split( |
||||
$_GET['id'] |
||||
) |
||||
), |
||||
$_GET['time'] |
||||
); |
||||
|
||||
// Check snap exist |
||||
if (!file_exists($filename) || !is_readable($filename)) |
||||
{ |
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('requested snap not found') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
// Check snap has valid size |
||||
if (!$size = filesize($filename)) |
||||
{ |
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('requested snap has invalid size') |
||||
] |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
// Set headers |
||||
header( |
||||
'Content-Type: application/tar+gzip' |
||||
); |
||||
|
||||
header( |
||||
sprintf( |
||||
'Content-Length: %s', |
||||
$size |
||||
) |
||||
); |
||||
|
||||
header( |
||||
sprintf( |
||||
'Content-Disposition: filename="snap.%s.%s"', |
||||
$_GET['id'], |
||||
basename( |
||||
$filename |
||||
) |
||||
) |
||||
); |
||||
|
||||
readfile( |
||||
$filename |
||||
); |
||||
|
||||
exit; |
||||
} |
||||
|
||||
else |
||||
{ |
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('requested source not found') |
||||
] |
||||
); |
||||
} |
||||
|
||||
break; |
||||
|
||||
default: |
||||
|
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('Undefined API method') |
||||
] |
||||
); |
||||
} |
||||
|
||||
break; |
||||
|
||||
default: |
||||
|
||||
echo json_encode( |
||||
[ |
||||
'status' => false, |
||||
'message' => _('Undefined API action') |
||||
] |
||||
); |
||||
} |
@ -1,563 +0,0 @@
@@ -1,563 +0,0 @@
|
||||
<?php |
||||
|
||||
// Debug |
||||
# ini_set('display_errors', '1'); |
||||
# ini_set('display_startup_errors', '1'); |
||||
# error_reporting(E_ALL); |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . '/../../vendor/autoload.php'; |
||||
|
||||
// Init config |
||||
$config = json_decode( |
||||
file_get_contents( |
||||
__DIR__ . '/../../config.json' |
||||
) |
||||
); |
||||
|
||||
// Show totals in placeholder |
||||
|
||||
// Init |
||||
$client = new \Manticoresearch\Client( |
||||
[ |
||||
'host' => $config->manticore->server->host, |
||||
'port' => $config->manticore->server->port, |
||||
] |
||||
); |
||||
|
||||
// Init index |
||||
$index = $client->index( |
||||
$config->manticore->index->document->name |
||||
); |
||||
|
||||
// Get totals |
||||
$total = $index->search('') |
||||
->option('cutoff', 0) |
||||
->limit(0) |
||||
->get() |
||||
->getTotal(); |
||||
|
||||
$placeholder = sprintf( |
||||
_('Search in %s documents %s'), |
||||
number_format( |
||||
$total |
||||
), |
||||
$config->webui->search->index->request->url->enabled ? _('or enter new address to crawl...') : false |
||||
); |
||||
|
||||
// Get document data |
||||
$document = $index->getDocumentById( |
||||
isset($_GET['i']) ? $_GET['i'] : 0 |
||||
); |
||||
|
||||
// Get icon |
||||
$hostname = parse_url( |
||||
$document->url, |
||||
PHP_URL_HOST |
||||
); |
||||
|
||||
$identicon = new \Jdenticon\Identicon(); |
||||
|
||||
$identicon->setValue( |
||||
$hostname |
||||
); |
||||
|
||||
$identicon->setSize(36); |
||||
|
||||
$identicon->setStyle( |
||||
[ |
||||
'backgroundColor' => 'rgba(255, 255, 255, 0)', |
||||
'padding' => 0 |
||||
] |
||||
); |
||||
|
||||
$icon = $identicon->getImageDataUri('webp'); |
||||
|
||||
// Get snaps info |
||||
$snaps = []; |
||||
|
||||
/// Prepare location |
||||
$filepath = implode( |
||||
'/', |
||||
str_split( |
||||
$document->getId() |
||||
) |
||||
); |
||||
|
||||
/// Local snaps |
||||
if ($config->snap->storage->local->enabled) |
||||
{ |
||||
/// absolute |
||||
if ('/' === substr($config->snap->storage->local->directory, 0, 1)) |
||||
{ |
||||
$prefix = $config->snap->storage->local->directory; |
||||
} |
||||
|
||||
/// relative |
||||
else |
||||
{ |
||||
$prefix = __DIR__ . '/../../' . $config->snap->storage->local->directory; |
||||
} |
||||
|
||||
$directory = sprintf('%s/%s', $prefix, $filepath); |
||||
|
||||
if (is_dir($directory)) |
||||
{ |
||||
foreach ((array) scandir($directory) as $filename) |
||||
{ |
||||
if (!str_ends_with($filename, '.tar.gz')) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
$basename = basename( |
||||
$filename |
||||
); |
||||
|
||||
$time = preg_replace( |
||||
'/^([\d]+)\.tar\.gz$/', |
||||
'$1', |
||||
$basename |
||||
); |
||||
|
||||
$snaps[_('Local')][] = (object) |
||||
[ |
||||
'source' => 'local', |
||||
'id' => $document->getId(), |
||||
'name' => $basename, |
||||
'time' => $time, |
||||
'size' => filesize( |
||||
sprintf( |
||||
'%s/%s', |
||||
$directory, |
||||
$filename |
||||
) |
||||
), |
||||
]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Remote snaps |
||||
foreach ($config->snap->storage->remote->ftp as $i => $ftp) |
||||
{ |
||||
// Resource enabled |
||||
if (!$ftp->enabled) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
$remote = new \Yggverse\Ftp\Client(); |
||||
|
||||
$connection = $remote->connect( |
||||
$ftp->connection->host, |
||||
$ftp->connection->port, |
||||
$ftp->connection->username, |
||||
$ftp->connection->password, |
||||
$ftp->connection->directory, |
||||
$ftp->connection->timeout, |
||||
$ftp->connection->passive |
||||
); |
||||
|
||||
// Remote host connected |
||||
if ($connection) { |
||||
|
||||
foreach ((array) $remote->nlist($filepath) as $filename) |
||||
{ |
||||
if (!str_ends_with($filename, '.tar.gz')) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
$basename = basename( |
||||
$filename |
||||
); |
||||
|
||||
$time = preg_replace( |
||||
'/^([\d]+)\.tar\.gz$/', |
||||
'$1', |
||||
$basename |
||||
); |
||||
|
||||
$snaps[sprintf(_('Server #%s'), $i + 1)][] = (object) |
||||
[ |
||||
'source' => $i, |
||||
'id' => $document->getId(), |
||||
'name' => $basename, |
||||
'time' => $time, |
||||
'size' => $remote->size($filename), |
||||
]; |
||||
} |
||||
|
||||
$remote->close(); |
||||
} |
||||
} |
||||
|
||||
// Process index request |
||||
if ($config->webui->index->enabled) |
||||
{ |
||||
session_start(); |
||||
|
||||
if (isset($_POST['captcha']) && $_POST['captcha'] == $_SESSION['captcha']) |
||||
{ |
||||
$index->updateDocument( |
||||
[ |
||||
'index' => time() |
||||
], |
||||
$document->getId() |
||||
); |
||||
|
||||
header( |
||||
sprintf( |
||||
'Location: explore.php?i=%d', |
||||
$document->getId() |
||||
) |
||||
); |
||||
} |
||||
|
||||
$captcha = new \Gregwar\Captcha\CaptchaBuilder( |
||||
null, |
||||
new \Gregwar\Captcha\PhraseBuilder( |
||||
$config->webui->captcha->length, |
||||
$config->webui->captcha->phrase |
||||
) |
||||
); |
||||
|
||||
$captcha->setBackgroundColor( |
||||
$config->webui->captcha->background->r, |
||||
$config->webui->captcha->background->g, |
||||
$config->webui->captcha->background->b |
||||
); |
||||
|
||||
$captcha->build(); |
||||
|
||||
$_SESSION['captcha'] = $captcha->getPhrase(); |
||||
} |
||||
|
||||
?> |
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="<?php echo _('en-US'); ?>"> |
||||
<head> |
||||
<title><?php echo _('Yo! explore') ?></title> |
||||
<meta charset="utf-8" /> |
||||
<style> |
||||
|
||||
* { |
||||
border: 0; |
||||
margin: 0; |
||||
padding: 0; |
||||
font-family: Sans-serif; |
||||
color: #ccc; |
||||
} |
||||
|
||||
body { |
||||
background-color: #2e3436; |
||||
word-break: break-word; |
||||
} |
||||
|
||||
header { |
||||
background-color: #34393b; |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
right: 0; |
||||
z-index: 2; |
||||
} |
||||
|
||||
main { |
||||
margin-top: 80px; |
||||
margin-bottom: 76px; |
||||
padding: 0 20px; |
||||
} |
||||
|
||||
main > div { |
||||
max-width: 640px; |
||||
margin: 0 auto; |
||||
padding: 8px 0; |
||||
border-top: 1px #000 dashed; |
||||
font-size: 14px; |
||||
} |
||||
|
||||
main > div > div { |
||||
margin: 8px 0; |
||||
font-size: 13px; |
||||
} |
||||
|
||||
h1 { |
||||
position: fixed; |
||||
top: 2px; |
||||
left: 24px; |
||||
} |
||||
|
||||
h1 > a, |
||||
h1 > a:visited, |
||||
h1 > a:active, |
||||
h1 > a:hover { |
||||
color: #fff; |
||||
font-weight: normal; |
||||
font-size: 22px; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
h2 { |
||||
display: block; |
||||
font-size: 15px; |
||||
font-weight: normal; |
||||
margin: 4px 0; |
||||
color: #fff; |
||||
} |
||||
|
||||
h3 { |
||||
display: block; |
||||
font-size: 13px; |
||||
margin: 4px 0; |
||||
} |
||||
|
||||
pre { |
||||
border-radius: 4px; |
||||
border: 1px #000 dashed; |
||||
font-size: 13px; |
||||
margin: 8px 0; |
||||
max-height: 180px; |
||||
overflow: auto; |
||||
padding: 8px; |
||||
position: relative; |
||||
white-space: pre-wrap; |
||||
} |
||||
|
||||
form { |
||||
display: block; |
||||
max-width: 678px; |
||||
margin: 0 auto; |
||||
text-align: center; |
||||
} |
||||
|
||||
fieldset { |
||||
width: 150px; |
||||
} |
||||
|
||||
input[type="text"], |
||||
input[type="text"]:-webkit-autofill, |
||||
input[type="text"]:-webkit-autofill:focus { |
||||
transition: background-color 0s 600000s, color 0s 600000s; /* chrome */ |
||||
width: 100%; |
||||
margin: 12px 0; |
||||
padding: 6px 0; |
||||
border-radius: 32px; |
||||
background-color: #000; |
||||
color: #fff; |
||||
font-size: 15px; |
||||
text-align: center; |
||||
} |
||||
|
||||
input[type="text"]:hover { |
||||
background-color: #111 |
||||
} |
||||
|
||||
input[type="text"]:focus { |
||||
outline: none; |
||||
background-color: #111 |
||||
} |
||||
|
||||
input[type="text"]:focus::placeholder { |
||||
color: #090808 |
||||
} |
||||
|
||||
label { |
||||
font-size: 14px; |
||||
position: absolute; |
||||
right: 80px; |
||||
top: 18px; |
||||
} |
||||
|
||||
label > input { |
||||
width: auto; |
||||
margin: 0 4px; |
||||
} |
||||
|
||||
button { |
||||
padding: 6px 12px; |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
background-color: #3394fb; |
||||
color: #fff; |
||||
font-size: 14px; |
||||
} |
||||
|
||||
button { |
||||
background-color: #4b9df4; |
||||
height: 32px; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
header button { |
||||
position: fixed; |
||||
top: 12px; |
||||
right: 24px; |
||||
} |
||||
|
||||
a, a:visited, a:active { |
||||
color: #9ba2ac; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
a:hover { |
||||
color: #54a3f7; |
||||
} |
||||
|
||||
ul { |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
ul > li { |
||||
margin-left: 16px; |
||||
font-size: 13px; |
||||
padding: 4px 0; |
||||
} |
||||
|
||||
.text-warning { |
||||
color: #db6161; |
||||
} |
||||
|
||||
</style> |
||||
</head> |
||||
<body> |
||||
<header> |
||||
<form name="search" method="GET" action="search.php"> |
||||
<h1><a href="./"><?php echo _('Yo!') ?></a></h1> |
||||
<input type="text" name="q" placeholder="<?php echo $placeholder ?>" value="" /> |
||||
<?php if ($config->webui->search->extended->enabled) { ?> |
||||
<label for="e"> |
||||
<input type="checkbox" name="e" id="e" value="true" /> |
||||
<?php echo _('Extended') ?> |
||||
</label> |
||||
<?php } ?> |
||||
<button type="submit"> |
||||
<sub> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-search" viewBox="0 0 16 16"> |
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/> |
||||
</svg> |
||||
</sub> |
||||
</button> |
||||
</form> |
||||
</header> |
||||
<main> |
||||
<?php if ($document) { ?> |
||||
<div> |
||||
<?php if (empty($document->time)) { ?> |
||||
<div> |
||||
<?php echo _('Document pending for crawler in queue') ?> |
||||
</div> |
||||
<?php } else { ?> |
||||
<?php if (!empty($document->title)) { ?> |
||||
<h2> |
||||
<?php echo htmlentities($document->title) ?> |
||||
</h2> |
||||
<?php } ?> |
||||
<?php if (!empty($document->description)) { ?> |
||||
<div> |
||||
<?php echo htmlentities($document->description) ?> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if (!empty($document->keywords)) { ?> |
||||
<div> |
||||
<?php echo htmlentities($document->keywords) ?> |
||||
</div> |
||||
<?php } ?> |
||||
<?php } ?> |
||||
<div> |
||||
<a href="<?php echo $document->url ?>"><?php echo htmlentities(urldecode($document->url)) ?></a> |
||||
</div> |
||||
</div> |
||||
<div> |
||||
<div> |
||||
<img src="<?php echo $icon ?>" title="<?php echo $hostname ?>" alt="identicon" /> |
||||
</div> |
||||
<?php if (!empty($document->code)) { ?> |
||||
<h3><?php echo _('HTTP') ?></h3> |
||||
<?php if ($document->code == 200) { ?> |
||||
<div> |
||||
<?php echo $document->code ?> |
||||
</div> |
||||
<?php } else { ?> |
||||
<div class="text-warning"> |
||||
<?php echo $document->code ?> |
||||
</div> |
||||
<?php } ?> |
||||
<?php } ?> |
||||
<?php if (!empty($document->mime)) { ?> |
||||
<h3><?php echo _('MIME') ?></h3> |
||||
<div><?php echo $document->mime ?></div> |
||||
<?php } ?> |
||||
<?php if (!empty($document->size)) { ?> |
||||
<h3><?php echo _('Size') ?></h3> |
||||
<div><?php echo sprintf('%s bytes', number_format($document->size)) ?></div> |
||||
<?php } ?> |
||||
<?php if (!empty($document->time)) { ?> |
||||
<h3><?php echo _('Time') ?></h3> |
||||
<div><?php echo date('c', $document->time) ?></div> |
||||
<?php } ?> |
||||
<?php if ($snaps) { ?> |
||||
<h3><?php echo _('Snaps') ?></h3> |
||||
<ul> |
||||
<?php foreach ($snaps as $source => $snap) { ?> |
||||
<li> |
||||
<?php echo $source ?> |
||||
<ul> |
||||
<?php foreach ($snap as $file) { ?> |
||||
<li> |
||||
<a rel="nofollow" href="api.php?action=snap&method=download&source=<?php echo $file->source ?>&id=<?php echo $file->id ?>&time=<?php echo $file->time ?>"> |
||||
<?php echo sprintf('%s (tar.gz / %s bytes)', date('c', $file->time), number_format($file->size)) ?> |
||||
</a> |
||||
</li> |
||||
<?php } ?> |
||||
</ul> |
||||
</li> |
||||
<?php } ?> |
||||
</ul> |
||||
<?php } ?> |
||||
<?php if (!empty($document->body)) { ?> |
||||
<h3><?php echo _('Cache') ?></h3> |
||||
<pre><?php echo htmlentities($document->body) ?></pre> |
||||
<?php } ?> |
||||
<?php if ($config->webui->index->enabled) { ?> |
||||
<h3><?php echo _('Index') ?></h3> |
||||
<div> |
||||
<?php if ($document->get('index')) { ?> |
||||
<?php echo sprintf(_('Request sent at %s'), date('c', $document->get('index'))) ?> |
||||
<?php } else { ?> |
||||
<img src="<?php echo $captcha->inline(100) ?>" alt="captcha" /> |
||||
<form name="index" method="POST" action="explore.php?i=<?php echo $document->getId() ?>"> |
||||
<fieldset> |
||||
<input type="text" |
||||
name="captcha" |
||||
value="" |
||||
placeholder="<?php echo _('Code on picture'); ?>" |
||||
autocomplete="off" /> |
||||
<button type="submit"> |
||||
<?php echo _('Request') ?> |
||||
</button> |
||||
<button type="submit"> |
||||
<sub> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="white" viewBox="0 0 16 16"> |
||||
<path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41m-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9"/> |
||||
<path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5 5 0 0 0 8 3M3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9z"/> |
||||
</svg> |
||||
</sub> |
||||
</button> |
||||
</fieldset> |
||||
</form> |
||||
<?php } ?> |
||||
</div> |
||||
<?php } ?> |
||||
</div> |
||||
<?php } else { ?> |
||||
<div> |
||||
<?php echo _('Index not found') ?> |
||||
</div> |
||||
<?php } ?> |
||||
</main> |
||||
</body> |
||||
</html> |
@ -1,336 +0,0 @@
@@ -1,336 +0,0 @@
|
||||
<?php |
||||
|
||||
// Debug |
||||
ini_set('display_errors', '1'); |
||||
ini_set('display_startup_errors', '1'); |
||||
error_reporting(E_ALL); |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . '/../../vendor/autoload.php'; |
||||
|
||||
// Init config |
||||
$config = json_decode( |
||||
file_get_contents( |
||||
__DIR__ . '/../../config.json' |
||||
) |
||||
); |
||||
|
||||
// Show totals in placeholder |
||||
|
||||
// Init |
||||
$client = new \Manticoresearch\Client( |
||||
[ |
||||
'host' => $config->manticore->server->host, |
||||
'port' => $config->manticore->server->port, |
||||
] |
||||
); |
||||
|
||||
// Init index |
||||
$index = $client->index( |
||||
$config->manticore->index->document->name |
||||
); |
||||
|
||||
// Get totals |
||||
$total = $index->search('') |
||||
->option('cutoff', 0) |
||||
->limit(0) |
||||
->get() |
||||
->getTotal(); |
||||
|
||||
$placeholder = sprintf( |
||||
_('Search in %s documents %s'), |
||||
number_format( |
||||
$total |
||||
), |
||||
$config->webui->search->index->request->url->enabled ? _('or enter new address to crawl...') : false |
||||
); |
||||
|
||||
?> |
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="<?php echo _('en-US') ?>"> |
||||
<head> |
||||
<title><?php echo _('Yo! Web Search Engine') ?></title> |
||||
<meta charset="utf-8" /> |
||||
<meta name="description" content="<?php echo _('Yo! Micro Web Crawler in PHP & Manticore') ?>" /> |
||||
<meta name="keywords" content="<?php echo _('web, search, engine, crawler, manticore, yggdrasil, js-less, open source') ?>" /> |
||||
<style> |
||||
|
||||
* { |
||||
border: 0; |
||||
margin: 0; |
||||
padding: 0; |
||||
font-family: Sans-serif; |
||||
color: #ccc; |
||||
} |
||||
|
||||
body { |
||||
background-color: #2e3436; |
||||
} |
||||
|
||||
h1 { |
||||
color: #fff; |
||||
font-weight: normal; |
||||
font-size: 36px; |
||||
margin: 16px 0 |
||||
} |
||||
|
||||
form { |
||||
display: block; |
||||
max-width: 640px; |
||||
margin: 16% auto; |
||||
text-align: center; |
||||
} |
||||
|
||||
input, |
||||
input:-webkit-autofill, |
||||
input:-webkit-autofill:focus { |
||||
transition: background-color 0s 600000s, color 0s 600000s; /* chrome */ |
||||
width: 100%; |
||||
margin: 8px 0; |
||||
padding: 12px 0; |
||||
border-radius: 32px; |
||||
background-color: #000; |
||||
color: #fff; |
||||
font-size: 16px; |
||||
text-align: center; |
||||
} |
||||
|
||||
input:hover { |
||||
background-color: #111 |
||||
} |
||||
|
||||
input:focus { |
||||
outline: none; |
||||
background-color: #111 |
||||
} |
||||
|
||||
input:focus::placeholder { |
||||
color: #090808; |
||||
} |
||||
|
||||
button { |
||||
margin: 22px 0; |
||||
padding: 6px 12px; |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
background-color: #3394fb; |
||||
color: #fff; |
||||
font-size: 14px; |
||||
} |
||||
|
||||
button:hover { |
||||
background-color: #4b9df4; |
||||
} |
||||
|
||||
footer { |
||||
position: fixed; |
||||
bottom: 0; |
||||
left:0; |
||||
right: 0; |
||||
text-align: center; |
||||
padding: 24px; |
||||
color: #9ba2ac; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
footer > a, |
||||
footer > a:visited, |
||||
footer > a:active { |
||||
color: #9ba2ac; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
footer > a > svg, |
||||
footer > a:visited > svg, |
||||
footer > a:active > svg { |
||||
fill: #9ba2ac; |
||||
} |
||||
|
||||
footer > a:hover { |
||||
color: #54a3f7; |
||||
} |
||||
|
||||
footer > a:hover svg { |
||||
fill: #54a3f7; |
||||
} |
||||
|
||||
footer > a, |
||||
footer > a:visited, |
||||
footer > a:active { |
||||
text-decoration: none; |
||||
} |
||||
|
||||
/* |
||||
* CSS animation |
||||
* by https://codepen.io/alvarotrigo/pen/GRvYNax |
||||
*/ |
||||
|
||||
main { |
||||
background: #2e3436; |
||||
background: -webkit-linear-gradient(to left, #8f94fb, #4e54c8); |
||||
width: 100%; |
||||
} |
||||
|
||||
ul { |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; |
||||
z-index:-1 |
||||
} |
||||
|
||||
li { |
||||
position: absolute; |
||||
display: block; |
||||
list-style: none; |
||||
width: 20px; |
||||
height: 20px; |
||||
background: rgba(255, 255, 255, 0.2); |
||||
animation: animate 25s linear infinite; |
||||
bottom: -150px; |
||||
} |
||||
|
||||
li:nth-child(1) { |
||||
left: 25%; |
||||
width: 80px; |
||||
height: 80px; |
||||
animation-delay: 0s; |
||||
} |
||||
|
||||
li:nth-child(2) { |
||||
left: 10%; |
||||
width: 20px; |
||||
height: 20px; |
||||
animation-delay: 2s; |
||||
animation-duration: 12s; |
||||
} |
||||
|
||||
li:nth-child(3) { |
||||
left: 70%; |
||||
width: 20px; |
||||
height: 20px; |
||||
animation-delay: 4s; |
||||
} |
||||
|
||||
li:nth-child(4) { |
||||
left: 40%; |
||||
width: 60px; |
||||
height: 60px; |
||||
animation-delay: 0s; |
||||
animation-duration: 18s; |
||||
} |
||||
|
||||
li:nth-child(5) { |
||||
left: 65%; |
||||
width: 20px; |
||||
height: 20px; |
||||
animation-delay: 0s; |
||||
} |
||||
|
||||
li:nth-child(6) { |
||||
left: 75%; |
||||
width: 110px; |
||||
height: 110px; |
||||
animation-delay: 3s; |
||||
} |
||||
|
||||
li:nth-child(7) { |
||||
left: 35%; |
||||
width: 150px; |
||||
height: 150px; |
||||
animation-delay: 7s; |
||||
} |
||||
|
||||
li:nth-child(8) { |
||||
left: 50%; |
||||
width: 25px; |
||||
height: 25px; |
||||
animation-delay: 15s; |
||||
animation-duration: 45s; |
||||
} |
||||
|
||||
li:nth-child(9) { |
||||
left: 20%; |
||||
width: 15px; |
||||
height: 15px; |
||||
animation-delay: 2s; |
||||
animation-duration: 35s; |
||||
} |
||||
|
||||
li:nth-child(10) { |
||||
left: 85%; |
||||
width: 150px; |
||||
height: 150px; |
||||
animation-delay: 0s; |
||||
animation-duration: 11s; |
||||
} |
||||
|
||||
@keyframes animate { |
||||
0%{ |
||||
transform: translateY(0) rotate(0deg); |
||||
opacity: 1; |
||||
border-radius: 0; |
||||
} |
||||
|
||||
100%{ |
||||
transform: translateY(-1000px) rotate(720deg); |
||||
opacity: 0; |
||||
border-radius: 50%; |
||||
} |
||||
} |
||||
|
||||
</style> |
||||
</head> |
||||
<body> |
||||
<header> |
||||
<form name="search" method="GET" action="search.php"> |
||||
<h1><?php echo _('Yo!') ?></h1> |
||||
<input type="text" name="q" placeholder="<?php echo $placeholder ?>" value="" /> |
||||
<button type="submit"> |
||||
<sub> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-search" viewBox="0 0 16 16"> |
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/> |
||||
</svg> |
||||
</sub> |
||||
|
||||
<?php echo _('Search'); ?> |
||||
</button> |
||||
</form> |
||||
</header> |
||||
<!-- css animation : begin --> |
||||
<main> |
||||
<ul> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
<li></li> |
||||
</ul> |
||||
</main> |
||||
<!-- css animation : end --> |
||||
<footer> |
||||
<?php foreach ($config->webui->footer->links as $i => $link) { ?> |
||||
<?php if ($i) echo '|' ?> |
||||
<a <?php foreach ($link->attributes as $name => $value) { echo sprintf(' %s="%s"', $name, $value); } ?>> |
||||
<?php echo _($link->text) ?> |
||||
</a> |
||||
<?php foreach ($link->index as $index) { ?> |
||||
<a rel="nofollow" href="<?php echo $index ?>" title="<?php echo sprintf(_('Download %s database'), $link->text) ?>"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 16 16"> |
||||
<path d="M12.5 9a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7m.354 5.854 1.5-1.5a.5.5 0 0 0-.708-.708l-.646.647V10.5a.5.5 0 0 0-1 0v2.793l-.646-.647a.5.5 0 0 0-.708.708l1.5 1.5a.5.5 0 0 0 .708 0ZM8 1c-1.573 0-3.022.289-4.096.777C2.875 2.245 2 2.993 2 4s.875 1.755 1.904 2.223C4.978 6.711 6.427 7 8 7s3.022-.289 4.096-.777C13.125 5.755 14 5.007 14 4s-.875-1.755-1.904-2.223C11.022 1.289 9.573 1 8 1"/> |
||||
<path d="M2 7v-.839c.457.432 1.004.751 1.49.972C4.722 7.693 6.318 8 8 8s3.278-.307 4.51-.867c.486-.22 1.033-.54 1.49-.972V7c0 .424-.155.802-.411 1.133a4.51 4.51 0 0 0-4.815 1.843A12.31 12.31 0 0 1 8 10c-1.573 0-3.022-.289-4.096-.777C2.875 8.755 2 8.007 2 7m6.257 3.998L8 11c-1.682 0-3.278-.307-4.51-.867-.486-.22-1.033-.54-1.49-.972V10c0 1.007.875 1.755 1.904 2.223C4.978 12.711 6.427 13 8 13h.027a4.552 4.552 0 0 1 .23-2.002m-.002 3L8 14c-1.682 0-3.278-.307-4.51-.867-.486-.22-1.033-.54-1.49-.972V13c0 1.007.875 1.755 1.904 2.223C4.978 15.711 6.427 16 8 16c.536 0 1.058-.034 1.555-.097a4.507 4.507 0 0 1-1.3-1.905"/> |
||||
</svg> |
||||
</a> |
||||
<?php } ?> |
||||
<?php } ?> |
||||
</footer> |
||||
</body> |
||||
</html> |
@ -1,514 +0,0 @@
@@ -1,514 +0,0 @@
|
||||
<?php |
||||
|
||||
// Debug |
||||
ini_set('display_errors', '1'); |
||||
ini_set('display_startup_errors', '1'); |
||||
error_reporting(E_ALL); |
||||
|
||||
// Load dependencies |
||||
require_once __DIR__ . '/../../vendor/autoload.php'; |
||||
|
||||
// Init config |
||||
$config = json_decode( |
||||
file_get_contents( |
||||
__DIR__ . '/../../config.json' |
||||
) |
||||
); |
||||
|
||||
// Init |
||||
$client = new \Manticoresearch\Client( |
||||
[ |
||||
'host' => $config->manticore->server->host, |
||||
'port' => $config->manticore->server->port, |
||||
] |
||||
); |
||||
|
||||
// Init index |
||||
$index = $client->index( |
||||
$config->manticore->index->document->name |
||||
); |
||||
|
||||
// Get totals |
||||
$total = $index->search('') |
||||
->option('cutoff', 0) |
||||
->limit(0) |
||||
->get() |
||||
->getTotal(); |
||||
|
||||
$placeholder = sprintf( |
||||
_('Search in %s documents %s'), |
||||
number_format( |
||||
$total |
||||
), |
||||
$config->webui->search->index->request->url->enabled ? _('or enter new address to crawl...') : false |
||||
); |
||||
|
||||
$response = false; |
||||
|
||||
// Request |
||||
$q = !empty($_GET['q']) ? trim($_GET['q']) : ''; |
||||
$p = !empty($_GET['p']) ? (int) $_GET['p'] : 1; |
||||
|
||||
// Register new URL by request on enabled |
||||
if ($config->webui->search->index->request->url->enabled && filter_var($q, FILTER_VALIDATE_URL)) |
||||
{ |
||||
if (preg_match($config->webui->search->index->request->url->regex, $q)) |
||||
{ |
||||
// Prepare URL |
||||
$url = $q; |
||||
$crc32url = crc32($url); |
||||
|
||||
// Check URL for exist |
||||
$exist = $index->search('') |
||||
->filter('id', $crc32url) |
||||
->limit(1) |
||||
->get() |
||||
->getTotal(); |
||||
|
||||
if ($exist) |
||||
{ |
||||
/* disable as regular search request possible |
||||
$response = sprintf( |
||||
_('URL "%s" exists in search index'), |
||||
htmlentities($q) |
||||
); |
||||
*/ |
||||
} |
||||
|
||||
// Add URL |
||||
else |
||||
{ |
||||
// @TODO check http code |
||||
|
||||
$index->addDocument( |
||||
[ |
||||
'url' => $url, |
||||
'rank' => (int) mb_strlen( |
||||
(string) |
||||
urldecode( |
||||
(string) |
||||
parse_url( |
||||
$url, |
||||
PHP_URL_PATH |
||||
) |
||||
) |
||||
) |
||||
], |
||||
$crc32url |
||||
); |
||||
|
||||
$response = sprintf( |
||||
_('URL "%s" added to the crawl queue!'), |
||||
htmlentities($q) |
||||
); |
||||
} |
||||
} |
||||
|
||||
else { |
||||
$response = sprintf( |
||||
_('URL "%s" does not match node settings!'), |
||||
htmlentities($q) |
||||
); |
||||
} |
||||
} |
||||
|
||||
// Extended corrections |
||||
switch (true) |
||||
{ |
||||
// Empty query |
||||
case empty($q): |
||||
|
||||
$query = $index->search('')->sort('RAND()'); |
||||
|
||||
break; |
||||
|
||||
// URL request |
||||
case filter_var($q, FILTER_VALIDATE_URL): |
||||
|
||||
$query = $index->search('')->filter('id', crc32($q)); |
||||
|
||||
break; |
||||
|
||||
default: |
||||
|
||||
// Allow raw requests on extended syntax mode requested |
||||
// http://sphinxsearch.com/docs/current/extended-syntax.html |
||||
if (isset($_GET['e']) && $config->webui->search->extended->enabled) |
||||
{ |
||||
$query = $index->search($q); |
||||
} |
||||
|
||||
// Regular request |
||||
else |
||||
{ |
||||
$query = $index->search( |
||||
@\Manticoresearch\Utils::escape( |
||||
$q |
||||
) |
||||
); |
||||
} |
||||
} |
||||
|
||||
// Apply search options (e.g. field_weights) |
||||
foreach ($config->webui->search->options as $key => $value) |
||||
{ |
||||
if (is_int($value) || is_string($value)) |
||||
{ |
||||
$query->option( |
||||
$key, |
||||
$value |
||||
); |
||||
} |
||||
|
||||
else |
||||
{ |
||||
$query->option( |
||||
$key, |
||||
(array) $value |
||||
); |
||||
} |
||||
} |
||||
|
||||
// Apply highlight options |
||||
if ($config->webui->search->highlight->fields) |
||||
{ |
||||
$query->highlight( |
||||
(array) $config->webui->search->highlight->fields, |
||||
(array) $config->webui->search->highlight->options |
||||
); |
||||
} |
||||
|
||||
// Get found |
||||
$found = empty($q) ? $total : $query->get()->getTotal(); |
||||
|
||||
// Search request begin |
||||
$results = $query->offset($p * $config->webui->pagination->limit - $config->webui->pagination->limit) |
||||
->limit($config->webui->pagination->limit) |
||||
->get(); |
||||
|
||||
?> |
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="<?php echo _('en-US'); ?>"> |
||||
<head> |
||||
<title><?php echo sprintf(_('Yo! %s'), htmlentities($q)) ?></title> |
||||
<meta charset="utf-8" /> |
||||
<meta name="keywords" content="<?php echo htmlentities($q) ?>" /> |
||||
<style> |
||||
|
||||
* { |
||||
border: 0; |
||||
margin: 0; |
||||
padding: 0; |
||||
font-family: Sans-serif; |
||||
color: #ccc; |
||||
} |
||||
|
||||
body { |
||||
background-color: #2e3436; |
||||
word-break: break-word; |
||||
} |
||||
|
||||
header { |
||||
background-color: #34393b; |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
right: 0; |
||||
z-index: 2; |
||||
} |
||||
|
||||
main { |
||||
margin-top: 80px; |
||||
margin-bottom: 76px; |
||||
padding: 0 32px; |
||||
} |
||||
|
||||
main > div { |
||||
border-top: 1px #000 dashed; |
||||
font-size: 14px; |
||||
margin: 0 auto; |
||||
max-width: 620px; |
||||
padding: 8px 0; |
||||
position: relative; |
||||
} |
||||
|
||||
main > div > img { |
||||
left: -24px; |
||||
position: absolute; |
||||
top: 18px; |
||||
|
||||
} |
||||
|
||||
main > div > div { |
||||
padding: 8px 0; |
||||
line-height: 16px; |
||||
} |
||||
|
||||
main > div > div > a { |
||||
font-size: 12px; |
||||
} |
||||
|
||||
h1 { |
||||
position: fixed; |
||||
top: 2px; |
||||
left: 24px; |
||||
} |
||||
|
||||
h1 > a, |
||||
h1 > a:visited, |
||||
h1 > a:active, |
||||
h1 > a:hover { |
||||
color: #fff; |
||||
font-weight: normal; |
||||
font-size: 22px; |
||||
margin: 0; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
h2 { |
||||
display: block; |
||||
font-size: 15px; |
||||
font-weight: normal; |
||||
color: #fff; |
||||
} |
||||
|
||||
form { |
||||
display: block; |
||||
max-width: 678px; |
||||
margin: 0 auto; |
||||
text-align: center; |
||||
} |
||||
|
||||
input[type="checkbox"] { |
||||
accent-color: #3394fb; |
||||
} |
||||
|
||||
input[type="text"], |
||||
input[type="text"]:-webkit-autofill, |
||||
input[type="text"]:-webkit-autofill:focus { |
||||
transition: background-color 0s 600000s, color 0s 600000s; /* chrome */ |
||||
width: 100%; |
||||
margin: 12px 0; |
||||
padding: 6px 0; |
||||
border-radius: 32px; |
||||
background-color: #000; |
||||
color: #fff; |
||||
font-size: 15px; |
||||
text-align: center; |
||||
} |
||||
|
||||
input[type="text"]:hover { |
||||
background-color: #111 |
||||
} |
||||
|
||||
input[type="text"]:focus { |
||||
outline: none; |
||||
background-color: #111 |
||||
} |
||||
|
||||
input[type="text"]:focus::placeholder { |
||||
color: #090808 |
||||
} |
||||
|
||||
label { |
||||
font-size: 14px; |
||||
position: absolute; |
||||
right: 80px; |
||||
top: 18px; |
||||
} |
||||
|
||||
label > input { |
||||
width: auto; |
||||
margin: 0 4px; |
||||
} |
||||
|
||||
button { |
||||
padding: 6px 12px; |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
background-color: #3394fb; |
||||
color: #fff; |
||||
font-size: 14px; |
||||
position: fixed; |
||||
top: 12px; |
||||
right: 24px; |
||||
} |
||||
|
||||
button:hover { |
||||
background-color: #4b9df4; |
||||
} |
||||
|
||||
a, a:visited, a:active { |
||||
color: #9ba2ac; |
||||
} |
||||
|
||||
a:hover { |
||||
color: #54a3f7; |
||||
} |
||||
|
||||
span { |
||||
display: block; |
||||
margin: 8px 0; |
||||
} |
||||
|
||||
.text-warning { |
||||
color: #db6161; |
||||
fill: #db6161; |
||||
} |
||||
|
||||
</style> |
||||
</head> |
||||
<body> |
||||
<header> |
||||
<form name="search" method="GET" action="search.php"> |
||||
<h1><a href="./"><?php echo _('Yo!') ?></a></h1> |
||||
<input type="text" name="q" placeholder="<?php echo $placeholder ?>" value="<?php echo htmlentities($q) ?>" /> |
||||
<?php if ($config->webui->search->extended->enabled) { ?> |
||||
<label for="e"> |
||||
<input type="checkbox" name="e" id="e" value="true" <?php echo isset($_GET['e']) ? 'checked="checked"': false ?>/> |
||||
<?php echo _('Extended') ?> |
||||
</label> |
||||
<?php } ?> |
||||
<button type="submit"> |
||||
<sub> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-search" viewBox="0 0 16 16"> |
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/> |
||||
</svg> |
||||
</sub> |
||||
</button> |
||||
</form> |
||||
</header> |
||||
<main> |
||||
<?php if (isset($_GET['e']) && $config->webui->search->extended->enabled) { ?> |
||||
<div> |
||||
<p> |
||||
<?php echo _('Extended syntax enabled, follow') ?> |
||||
<a href="http://sphinxsearch.com/docs/current/extended-syntax.html" rel="nofollow" target="_blank"><?php echo _('Documentation') ?></a> |
||||
<sub> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" fill="currentColor" viewBox="0 0 16 16"> |
||||
<path fill-rule="evenodd" d="M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5"/> |
||||
<path fill-rule="evenodd" d="M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0z"/> |
||||
</svg> |
||||
</sub> |
||||
</p> |
||||
<p> |
||||
<?php echo _('Available fields:') ?> |
||||
<i>@title</i> |
||||
<i>@description</i> |
||||
<i>@keywords</i> |
||||
<i>@mime</i> |
||||
<i>@url</i> |
||||
</p> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if ($response) { ?> |
||||
<div> |
||||
<?php echo $response ?> |
||||
</div> |
||||
<?php } ?> |
||||
<div> |
||||
<?php echo sprintf(_('Found: %s'), number_format($found)) ?> |
||||
</div> |
||||
<?php foreach ($results as $result) { ?> |
||||
<div> |
||||
<?php |
||||
|
||||
$hostname = parse_url( |
||||
$result->url, |
||||
PHP_URL_HOST |
||||
); |
||||
|
||||
$identicon = new \Jdenticon\Identicon(); |
||||
|
||||
$identicon->setValue( |
||||
$hostname |
||||
); |
||||
|
||||
$identicon->setSize(14); |
||||
|
||||
$identicon->setStyle( |
||||
[ |
||||
'backgroundColor' => 'rgba(255, 255, 255, 0)', |
||||
'padding' => 0 |
||||
] |
||||
); |
||||
|
||||
$icon = $identicon->getImageDataUri('webp'); |
||||
|
||||
?> |
||||
<img src="<?php echo $icon ?>" title="<?php echo $hostname ?>" alt="identicon" /> |
||||
<?php if (!empty($result->getHighlight()['title'])) { ?> |
||||
<div> |
||||
<h2> |
||||
<?php foreach ($result->getHighlight()['title'] as $title) { ?> |
||||
<p><?php echo $title ?></p> |
||||
<?php } ?> |
||||
</h2> |
||||
</div> |
||||
<?php } else if (!empty($result->title)) { ?> |
||||
<div> |
||||
<h2><?php echo $result->title ?></h2> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if (!empty($result->getHighlight()['description'])) { ?> |
||||
<div> |
||||
<?php foreach ($result->getHighlight()['description'] as $description) { ?> |
||||
<p><?php echo $description ?></p> |
||||
<?php } ?> |
||||
</div> |
||||
<?php } else if (!empty($result->description)) { ?> |
||||
<div> |
||||
<?php echo $result->description ?> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if (!empty($result->getHighlight()['keywords'])) { ?> |
||||
<div> |
||||
<?php foreach ($result->getHighlight()['keywords'] as $keywords) { ?> |
||||
<p><?php echo $keywords ?></p> |
||||
<?php } ?> |
||||
</div> |
||||
<?php } else if (!empty($result->keywords)) { ?> |
||||
<div> |
||||
<?php echo $result->keywords ?> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if (!empty($result->getHighlight()['body'])) { ?> |
||||
<div> |
||||
<?php foreach ($result->getHighlight()['body'] as $body) { ?> |
||||
<p><?php echo $body ?></p> |
||||
<?php } ?> |
||||
</div> |
||||
<?php } ?> |
||||
<div> |
||||
<?php if (!empty($result->getHighlight()['url'])) { ?> |
||||
<?php foreach ($result->getHighlight()['url'] as $url) { ?> |
||||
<a href="<?php echo $result->url ?>"><?php echo urldecode($url) ?></a> |
||||
<?php } ?> |
||||
<?php } else if (!empty($result->title)) { ?> |
||||
<a href="<?php echo $result->url ?>"><?php echo htmlentities(urldecode($result->url)) ?></a> |
||||
<?php } ?> |
||||
<?php if (!in_array($result->get('code'), [0, 200])) { ?> |
||||
<small>•</small> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" class="text-warning" viewBox="0 0 16 16"> |
||||
<path d="m9.97 4.88.953 3.811C10.159 8.878 9.14 9 8 9c-1.14 0-2.158-.122-2.923-.309L6.03 4.88C6.635 4.957 7.3 5 8 5s1.365-.043 1.97-.12m-.245-.978L8.97.88C8.718-.13 7.282-.13 7.03.88L6.275 3.9C6.8 3.965 7.382 4 8 4c.618 0 1.2-.036 1.725-.098zm4.396 8.613a.5.5 0 0 1 .037.96l-6 2a.5.5 0 0 1-.316 0l-6-2a.5.5 0 0 1 .037-.96l2.391-.598.565-2.257c.862.212 1.964.339 3.165.339s2.303-.127 3.165-.339l.565 2.257 2.391.598"/> |
||||
</svg> |
||||
<small><?php echo $result->get('code') ?></small> |
||||
<?php } ?> |
||||
<small>•</small> |
||||
<a rel="nofollow" href="explore.php?i=<?php echo $result->getId() ?>"><?php echo _('explore') ?></a> |
||||
</div> |
||||
</div> |
||||
<?php } ?> |
||||
<?php if ($p * $config->webui->pagination->limit <= $results->getTotal()) { ?> |
||||
<div> |
||||
<div> |
||||
<a href="search.php?q=<?php echo urlencode(htmlentities($q)) ?>&p=<?php echo $p + 1 ?>"> |
||||
<?php echo _('More') ?> |
||||
</a> |
||||
</div> |
||||
</div> |
||||
<?php } ?> |
||||
</main> |
||||
</body> |
||||
</html> |
Loading…
Reference in new issue