718 lines
35 KiB
PHP
718 lines
35 KiB
PHP
<?php
|
||
|
||
$bt=microtime(true);
|
||
|
||
$dlanguc=strtoupper($dlang);
|
||
|
||
require('mustard/include/n2es.php');
|
||
require('mustard/include/gracetime.php');
|
||
require('lib/fnum.php');
|
||
|
||
use function mysqli_real_escape_string as myesc;
|
||
/*$dlang='fr';
|
||
$dtzbl=array('ca'=>'Europe/Madrid','en'=>'Europe/London','es'=>'Europe/Madrid','fr'=>'Europe/Paris','it'=>'Europe/Rome');
|
||
date_default_timezone_set($dtzbl[$dlang]);*/
|
||
|
||
$debug='';
|
||
$debug.='REQUEST_URI: '.$_SERVER['REQUEST_URI'].N;
|
||
$debug.='$_GET: '.print_r($_GET,1);
|
||
$debug.='LOCALE: '.$locale.N;
|
||
|
||
// an instance is displayed as "New" if its age, relative to the InsertTS field, is less or equal than this (currently 31 days)
|
||
$oldline=31*24*60*60;
|
||
|
||
// an instance is considered dead if the last time it responded is before the graceline (see code below)
|
||
// $gracetime is defined in mustard/include/gracetime.php
|
||
$graceline=time()-$gracetime;
|
||
|
||
if (array_key_exists('id',$_GET) && preg_match('/^\d+$/',$_GET['id'])) {
|
||
$_GET['id']+=0;
|
||
$single=true;
|
||
} else {
|
||
$single=false;
|
||
}
|
||
|
||
//$getc=count($_GET);
|
||
//forzo $getc a 1 per non mostrare mai la spiega di come funziona il motore di ricerca
|
||
$getc=1;
|
||
|
||
if (array_key_exists('advc',$_GET)) {
|
||
($_GET['advc']=='1') ? $_GET['advc']=1 : $_GET['advc']=0;
|
||
} else {
|
||
$_GET['advc']=0;
|
||
}
|
||
|
||
$minudef=10;
|
||
$minumax=10000000000;
|
||
$maxudef=30000;
|
||
$maxumax=10000000000;
|
||
$minaudef=10;
|
||
$minaumax=10000000;
|
||
|
||
echo('</nav>
|
||
<div id="popupback">
|
||
<div id="fseenhelp" class="dhelp">
|
||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||
</div>
|
||
</div>
|
||
<div class="scrwide">
|
||
<div class="scrwidein">
|
||
<section class="sectcontm">
|
||
<img src="'.$prepath.'imgs/helpbutti.svg" id="helpbutt" class="helpb" onmouseover="swhelpi(true);" onmouseout="swhelpi(false);" onclick="swhelp();">
|
||
<h3>'._('Instances').'</h3>
|
||
<script language="JavaScript">
|
||
let mctrlsh=false;
|
||
function shmctrl() {
|
||
let mctrl=document.getElementById("mctrl");
|
||
let mctrlb=document.getElementById("mctrlb");
|
||
let advc=document.getElementById("advc");
|
||
if (mctrlsh) {
|
||
//mctrl.style.display="none";
|
||
mctrl.style.height="0px";
|
||
//mctrlb.className="litbut";
|
||
mctrlb.value="'._('Show advanced criteria').'";
|
||
advc.value=0;
|
||
mctrlsh=false;
|
||
} else {
|
||
//mctrl.style.display="block";
|
||
mctrl.style.height=mctrl.scrollHeight+"px";
|
||
//mctrlb.className="litbuta";
|
||
mctrlb.value="'._('Hide advanced criteria').'";
|
||
advc.value=1;
|
||
mctrlsh=true;
|
||
}
|
||
}
|
||
let helpsh='.(($getc==0) ? 'false' : 'true').';
|
||
function swhelp() {
|
||
let hdiv=document.getElementById("help");
|
||
let himg=document.getElementById("helpbutt");
|
||
if (helpsh) {
|
||
//hdiv.style.display="none";
|
||
hdiv.style.height="0px";
|
||
himg.title="'._('Show introduction').'";
|
||
himg.src="'.$prepath.'imgs/helpbutti.svg";
|
||
helpsh=false;
|
||
} else {
|
||
//hdiv.style.display="block";
|
||
hdiv.style.height=hdiv.scrollHeight+"px";
|
||
himg.title="'._('Hide introduction').'";
|
||
himg.src="'.$prepath.'imgs/helpbutta.svg";
|
||
helpsh=true;
|
||
}
|
||
}
|
||
function swhelpi(over) {
|
||
let himg=document.getElementById("helpbutt"), ia;
|
||
if (helpsh) {
|
||
(over) ? ia="i" : ia="a";
|
||
} else {
|
||
(over) ? ia="a" : ia="i";
|
||
}
|
||
himg.src="'.$prepath.'imgs/helpbutt"+ia+".svg";
|
||
}
|
||
function swp(pn) {
|
||
document.curvf.p.value=pn;
|
||
document.curvf.submit();
|
||
}
|
||
function sethid(obj) {
|
||
if (document.getElementById("cb"+obj).checked)
|
||
document.getElementById(obj).value=1;
|
||
else
|
||
document.getElementById(obj).value=0;
|
||
ckadvcri();
|
||
}
|
||
|
||
let advcri=true;
|
||
|
||
function ckadvcri() {
|
||
if (document.getElementById("minu").value!='.$minudef.' ||
|
||
document.getElementById("maxu").value!='.$maxudef.' ||
|
||
document.getElementById("minau").value!='.$minaudef.' ||
|
||
document.getElementById("cbnoxious").checked==false ||
|
||
document.getElementById("cbcreg").checked==false ||
|
||
document.getElementById("cbappr").checked==true ||
|
||
document.getElementById("cblcok").checked==true) {
|
||
|
||
document.getElementById("disadvcrib").value="'._('Reset all advanced criteria to default').'";
|
||
advcri=false;
|
||
} else {
|
||
document.getElementById("disadvcrib").value="'._('Disable all advanced criteria').'";
|
||
advcri=true;
|
||
}
|
||
}
|
||
|
||
function endisadvcri() {
|
||
if (advcri) {
|
||
document.getElementById("minu").value="";
|
||
document.getElementById("maxu").value="";
|
||
document.getElementById("minau").value="";
|
||
document.getElementById("cbnoxious").checked=false;
|
||
document.getElementById("noxious").value=0;
|
||
document.getElementById("cbcreg").checked=false;
|
||
document.getElementById("creg").value=0;
|
||
document.getElementById("cbappr").checked=false;
|
||
document.getElementById("appr").value=0;
|
||
document.getElementById("cblcok").checked=false;
|
||
document.getElementById("lcok").value=0;
|
||
} else {
|
||
document.getElementById("minu").value='.$minudef.';
|
||
document.getElementById("maxu").value='.$maxudef.';
|
||
document.getElementById("minau").value='.$minaudef.';
|
||
document.getElementById("cbnoxious").checked=true;
|
||
document.getElementById("noxious").value=1;
|
||
document.getElementById("cbcreg").checked=true;
|
||
document.getElementById("creg").value=1;
|
||
document.getElementById("cbappr").checked=false;
|
||
document.getElementById("appr").value=0;
|
||
document.getElementById("cblcok").checked=false;
|
||
document.getElementById("lcok").value=0;
|
||
}
|
||
ckadvcri();
|
||
}
|
||
|
||
function presub() {
|
||
document.getElementById("p").value=1;
|
||
if (document.getElementById("ord").value=="noxd") {
|
||
document.getElementById("cbnoxious").checked=false;
|
||
document.getElementById("noxious").value=0;
|
||
}
|
||
}
|
||
|
||
</script>
|
||
'.N);
|
||
|
||
function nullemp($inp) {
|
||
if (is_null($inp) || preg_match('/^\s*$/',$inp)===1) return(true);
|
||
return(false);
|
||
}
|
||
function ldate($ts,$dateonly=false) {
|
||
if (nullemp($ts)) return(null);
|
||
$ts=round($ts);
|
||
if (!$dateonly)
|
||
return(gmdate('d/m/Y H:i:s e',$ts));
|
||
else
|
||
return(gmdate('d/m/Y e',$ts));
|
||
}
|
||
function hspech($str) {
|
||
if (nullemp($str)) return(null);
|
||
return(htmlspecialchars($str,ENT_QUOTES|ENT_HTML5,'UTF-8'));
|
||
}
|
||
function muorimeglio($msg,$close) {
|
||
global $link;
|
||
if ($close)
|
||
mysqli_close($link);
|
||
echo('<p>'.$msg.'</p>'.N.'</section>'.N.'</div>'.N.'</div>'.N.'</body>'.N);
|
||
exit(2);
|
||
}
|
||
function nully($str) {
|
||
// "Not available" in singular form - translators, please omit "{singular}" from translation,
|
||
// it's there just to diversify this "Not available" from the next one
|
||
if (nullemp($str)) return('<span class="null">'._('Not available{singular}').'</span>');
|
||
return($str);
|
||
}
|
||
function nullyp($str) {
|
||
// "Not available" in plural form - translators, please omit "{plural}" from translation,
|
||
// it's there just to diversify this "Not available" from the previous one
|
||
if (nullemp($str)) return('<span class="null">'._('Not available{plural}').'</span>');
|
||
return($str);
|
||
}
|
||
function strip($str,$uri) {
|
||
if (nullemp($str)) return(null);
|
||
$str=preg_replace('#<style( [^>]*)?>.*</style>#is','',$str);
|
||
$str=preg_replace('#<a href="(?![a-zA-Z]+://)([^"]+)#i','<a href="https://'.$uri.'$1>',$str);
|
||
$str=preg_replace(['#<h[1-9][^>]*>#i','#</h[1-9]>#i'],['<p class="exh">','</p>'],$str);
|
||
$str=preg_replace(['#</p><br>#i','#</li><br>#i','#</ul><br>#i','#<ul><br>#i'],['</p>','</li>','</ul>','<ul>'],$str);
|
||
$str=preg_replace(['#<b>#i','#</b>#i','#<i>#i','#</i>#i'],['<strong>','</strong>','<em>','</em>'],$str);
|
||
$str=preg_replace('#<p>\s*</p>#is','',$str);
|
||
$str=strip_tags($str,'<a><br><ol><ul><li><p><div><strong><em><small><img>');
|
||
// all this part below is to try and assign the css "nobott" css class to a possible closing <p>/<ol>/<ul>/<div>,
|
||
// to avoid the useless and UGLY last bottom-margin :-))
|
||
$str=preg_replace('#^\s*#m','',$str);// strip all spaces from empty lines
|
||
$str=preg_replace('#[\r\n]#',' ',$str);// strip all "wrap chars"
|
||
$str=preg_replace('#(</p>|</ol>|</ul>|</div>)#i','$1'.N,$str);// now add a newline after every </p> and so on
|
||
$str=rtrim($str);// trim the newline at the end of the whole text block in order for the next preg_replace to match against $ as end of the whole text block
|
||
$str=preg_replace(['#<p[^>]*>(.*)</p>$#i', '#<ol[^>]*>(.*)</ol>$#i', '#<ul[^>]*>(.*)</ul>$#i', '#<div[^>]*>(.*)</div>$#i'],['<p class="nobott">$1</p>', '<ol class="nobott">$1</ol>', '<ul class="nobott">$1</ul>', '<div class="nobott">$1</div>'],$str);
|
||
return($str);
|
||
}
|
||
|
||
$link=mysqli_connect($conf['db_host'],$conf['db_user_name'],$conf['db_user_password'],$conf['db_name'],$conf['db_port'],$conf['db_socket']) or muorimeglio(_('Couldn’t connect to database: ').mysqli_connect_error().' ['.mysqli_connect_errno().']',false);
|
||
mysqli_set_charset($link,'utf8mb4');
|
||
|
||
$res=mysqli_query($link,'SELECT COUNT(ID) AS tinsts, SUM(UserCount) AS tusers, SUM(StatusCount) AS tstatuses, SUM(ActiveUsersMonth) AS tactusers FROM Instances WHERE Instances.IsMastodon=1 AND Instances.FirstSeen IS NOT NULL AND Instances.LastOkCheckTS>='.$graceline) or muorimeglio(__LINE__.': '.mysqli_error($link),true);
|
||
$row=mysqli_fetch_assoc($res);
|
||
echo(_('<div id="help" class="helpd"><p class="intro">This is our search engine for Mastodon instances. It works this way: data of already indexed instances gets updated every night, and a shuffling occurs for the “random ordering”; also, once a week, during the night between Tuesday and Wednesday, new instances get searched for and added to the database.</p><p class="intro">Advanced search criteria are customizable, but by default they reflect our fondness for a decentralized and egalitarian Fediverse, and we try to exclude instances accepting fascist, racist, sexist, ableist, sovereignist contents.</p></div>').N);
|
||
printf(_('<p class="introe">We currently count <span class="statd">%s</span> Mastodon instances, with <span class="statd">%s</span> users (<span class="statd">%s</span> active during last month) and <span class="statd">%s</span> published statuses.</p>').N, fnum($row['tinsts'],0,$dlang), fnum($row['tusers'],0,$dlang), fnum($row['tactusers'],0,$dlang), fnum($row['tstatuses'],0,$dlang));
|
||
|
||
// <p class="intro">Nella prima versione stabile daremo a* admin delle istanze compatibili con questa politica la possibilità di descrivere ulteriormente la propria istanza con questi campi, tutti facoltativi: “Descrizione in inglese” (per le istanze la cui descrizione è in altre lingue), “Località” (se l’istanza è particolarmente legata a un territorio), “Lingue” (se le lingue utilizzate prevalentemente sull’istanza non corrispondono a quelle rilevate automaticamente dal nostro crawler), “Modalità di copertura dei costi” (per esempio “Autonoma”, “Sottoscrizioni volontarie degli utenti”, “Iniziative benefit”), “Regole sui contenuti” (per esempio “Tag NSFW per i nudi”, “No link a siti di partiti politici”, “No pubblicità”, “Content Warning prima degli spoiler”), e “Categorie” (per esempio “Generalista”, “Astronomia”, “Politica”, “Musica folk”).</p>
|
||
// daremo la possibilità di segnalarci le istanze su cui sono accettati contenuti di questo tipo
|
||
// Le istanze che non rispondono da più di due mesi vengono dichiarate “morte” nel database e non vengono più mostrate tra i risultati della ricerca, ma una volta all’anno, nella notte di Halloween (31 ottobre), vengono nuovamente controllate e, se rispondono, “resuscitate”
|
||
|
||
if ((array_key_exists('noxious',$_GET) && $_GET['noxious']=='1') || !array_key_exists('noxious',$_GET)) {
|
||
$_GET['cbnoxious']=' checked';
|
||
$_GET['noxious']=1;
|
||
} else {
|
||
$_GET['cbnoxious']='';
|
||
$_GET['noxious']=0;
|
||
}
|
||
//echo('<p>noxious: '.$_GET['noxious'].'</p>');
|
||
|
||
if ((array_key_exists('creg',$_GET) && $_GET['creg']=='1') || !array_key_exists('creg',$_GET)) {
|
||
$_GET['cbcreg']=' checked';
|
||
$_GET['creg']=1;
|
||
} else {
|
||
$_GET['cbcreg']='';
|
||
$_GET['creg']=0;
|
||
}
|
||
|
||
if (array_key_exists('appr',$_GET) && $_GET['appr']=='1') {
|
||
$_GET['cbappr']=' checked';
|
||
$_GET['appr']=1;
|
||
} else {
|
||
$_GET['cbappr']='';
|
||
$_GET['appr']=0;
|
||
}
|
||
|
||
if (array_key_exists('lcok',$_GET) && $_GET['lcok']=='1') {
|
||
$_GET['cblcok']=' checked';
|
||
$_GET['lcok']=1;
|
||
} else {
|
||
$_GET['cblcok']='';
|
||
$_GET['lcok']=0;
|
||
}
|
||
|
||
if (array_key_exists('lang',$_GET)) {
|
||
if (preg_match('#^[0-9]+$#',$_GET['lang'])===1)
|
||
$_GET['lang']=$_GET['lang']+0;
|
||
else
|
||
$_GET['lang']=0;
|
||
} else {
|
||
$res=mysqli_query($link,'SELECT ID FROM Languages WHERE Code="'.$dlang.'"') or muorimeglio(__LINE__.': '.mysqli_error($link),true);
|
||
if (mysqli_num_rows($res)>0) {
|
||
$row=mysqli_fetch_assoc($res);
|
||
$_GET['lang']=$row['ID'];
|
||
} else {
|
||
$_GET['lang']=0;
|
||
}
|
||
}
|
||
if ($_GET['lang']>5000000000) $_GET['lang']=0;
|
||
|
||
if (array_key_exists('desc',$_GET) && preg_match('#^.+$#',$_GET['lang'])===1)
|
||
$_GET['desc']=trim(n2es($_GET['desc']));
|
||
else
|
||
$_GET['desc']='';
|
||
if (mb_strlen($_GET['desc'])>64) $_GET['desc']='';
|
||
|
||
function ckgnum($key,$def,$max) {
|
||
if (array_key_exists($key,$_GET)) {
|
||
$_GET[$key]=trim($_GET[$key]);
|
||
if (preg_match('#^[0-9]+$#',$_GET[$key])===1) {
|
||
$_GET[$key]=$_GET[$key]+0;
|
||
if ($_GET[$key]>$max) $_GET[$key]=$max;
|
||
} elseif ($_GET[$key]!='') {
|
||
$_GET[$key]=$def;
|
||
}
|
||
} else {
|
||
$_GET[$key]=$def;
|
||
}
|
||
}
|
||
|
||
ckgnum('minu',$minudef,$minumax);
|
||
ckgnum('maxu',$maxudef,$maxumax);
|
||
if (is_int($_GET['maxu']) && is_int($_GET['minu']) && $_GET['maxu']<$_GET['minu']) $_GET['maxu']=$_GET['minu'];
|
||
ckgnum('minau',$minaudef,$minaumax);
|
||
|
||
$order=array(
|
||
'rand'=>array('t'=>_('Random, recommended first'),'q'=>'Instances.Priority DESC, Instances.RPos ASC'),
|
||
'invold'=>array('t'=>_('By users’ involvement (active users / users), descending'),'q'=>'(Instances.ActiveUsersMonth / Instances.UserCount) DESC'),
|
||
'invola'=>array('t'=>_('By users’ involvement (active users / users), ascending'),'q'=>'(Instances.ActiveUsersMonth / Instances.UserCount) ASC'),
|
||
'fseend'=>array('t'=>_('By date and time of first sighting, descending'),'q'=>'Instances.FirstSeen DESC'),
|
||
'fseena'=>array('t'=>_('By date and time of first sighting, ascending'),'q'=>'Instances.FirstSeen ASC'),
|
||
'tusersd'=>array('t'=>_('By number of users, descending'),'q'=>'Instances.UserCount DESC'),
|
||
'tusersa'=>array('t'=>_('By number of users, ascending'),'q'=>'Instances.UserCount ASC'),
|
||
'ausersd'=>array('t'=>_('By number of active users, descending'),'q'=>'Instances.ActiveUsersMonth DESC'),
|
||
'ausersa'=>array('t'=>_('By number of active users, ascending'),'q'=>'Instances.ActiveUsersMonth ASC'),
|
||
'charsd'=>array('t'=>_('By maximum number of characters per toot, descending'),'q'=>'Instances.MaxTootChars DESC'),
|
||
// 'charsa'=>array('t'=>_('By maximum number of characters per toot, ascending'),'q'=>'Instances.MaxTootChars ASC'),
|
||
'noxd'=>array('t'=>_('Noxious first (switches off “Exclude noxious”)'),'q'=>'Instances.Noxious DESC')
|
||
);
|
||
if (!(array_key_exists('ord',$_GET) && array_key_exists($_GET['ord'],$order)))
|
||
$_GET['ord']='rand';
|
||
if ($_GET['lang']==0) $order['rand']=array('t'=>_('Random'),'q'=>'Instances.RPos ASC');
|
||
|
||
$p=1;
|
||
if (array_key_exists('p',$_GET) && preg_match('#^[0-9]+$#',$_GET['p'])===1) $p=$_GET['p']+0;
|
||
|
||
echo('<form method="get" id="curvf" name="curvf">
|
||
<input name="advc" type="hidden" value="'.$_GET['advc'].'">
|
||
<input name="noxious" type="hidden" value="'.$_GET['noxious'].'">
|
||
<input name="creg" type="hidden" value="'.$_GET['creg'].'">
|
||
<input name="appr" type="hidden" value="'.$_GET['appr'].'">
|
||
<input name="lcok" type="hidden" value="'.$_GET['lcok'].'">
|
||
<input name="lang" type="hidden" value="'.$_GET['lang'].'">
|
||
<input name="desc" type="hidden" value="'.htmlentities($_GET['desc']).'">
|
||
<input name="minu" type="hidden" value="'.$_GET['minu'].'">
|
||
<input name="maxu" type="hidden" value="'.$_GET['maxu'].'">
|
||
<input name="minau" type="hidden" value="'.$_GET['minau'].'">
|
||
<input name="ord" type="hidden" value="'.$_GET['ord'].'">
|
||
<input name="p" type="hidden" value="'.$p.'">
|
||
</form>'.N);
|
||
($_GET['lang']==0) ? $selected=' selected' : $selected='';
|
||
echo('<form method="get" id="searchf" class="sdbox" onsubmit="presub();">
|
||
<div class="sdtit">'._('Search criteria').'</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="lang" title="'._('Include only instances where the most used language is the one selected here').'">'._('Most used language is').'</label></div>
|
||
<div class="sdinput">
|
||
<select id="lang" name="lang" class="sselect">
|
||
<option value="0"'.$selected.'>'._('Irrelevant').'</option>'.N);
|
||
$res=mysqli_query($link,'SELECT Languages.ID AS Lid, CONCAT(Name'.$dlanguc.', \' [\', Code, \'] (\', COUNT(Languages.ID), \')\') AS Txt FROM InstOurLangs LEFT JOIN Languages ON Languages.ID=OurLangID LEFT JOIN Instances ON Instances.ID=InstOurLangs.InstID WHERE Instances.LastOkCheckTS>='.$graceline.' AND Instances.IsMastodon=1 AND InstOurLangs.Pos=1 GROUP BY Languages.ID ORDER BY Name'.$dlanguc.' ASC') or muorimeglio(__LINE__.': '.mysqli_error($link),true);
|
||
//$res=mysqli_query($link,'SELECT Languages.ID AS Lid, CONCAT(Name'.$dlanguc.', \' (\', Code, \')\') AS Txt FROM InstOurLangs LEFT JOIN Languages ON Languages.ID=OurLangID LEFT JOIN Instances ON Instances.ID=InstOurLangs.InstID WHERE Instances.LastOkCheckTS>='.$graceline.' AND Instances.IsMastodon=1 AND InstOurLangs.Pos=1 GROUP BY Languages.ID ORDER BY Name'.$dlanguc.' ASC') or muorimeglio(__LINE__.': '.mysqli_error($link),true);
|
||
while ($row=mysqli_fetch_assoc($res)) {
|
||
($_GET['lang']==$row['Lid']) ? $selected=' selected' : $selected='';
|
||
echo('<option value="'.$row['Lid'].'"'.$selected.'>'.$row['Txt'].'</option>'.N);
|
||
}
|
||
echo('</select>
|
||
</div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="desc" title="'._('Include only instances whose URI, name or description (short or long) contains the specified expression').'">'._('URI, name or descriptions contains').'</label></div>
|
||
<div class="sdinput"><input type="text" id="desc" name="desc" class="sinput" maxlength="64" value="'.hspech($_GET['desc']).'"></div>
|
||
</div>
|
||
|
||
<div id="mctrl">
|
||
<div class="sdrow">
|
||
<input type="button" class="litbut" id="disadvcrib" value="'._('Disable all advanced criteria').'" onclick="endisadvcri();">
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="minu" title="'._('Include only instances which have at least this number of users (set to empty to disable this criterion)').'">'._('Minimum number of users is').'</label></div>
|
||
<div class="sdinput"><input type="number" id="minu" name="minu" min="0" max="'.$minumax.'" class="sinput" value="'.$_GET['minu'].'" onchange="ckadvcri();"></div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="maxu" title="'._('Include only instances which have at most this number of users (set to empty to disable this criterion)').'">'._('Maximum number of users is').'</label></div>
|
||
<div class="sdinput"><input type="number" id="maxu" name="maxu" min="0" max="'.$maxumax.'" class="sinput" value="'.$_GET['maxu'].'" onchange="ckadvcri();"></div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="minau" title="'._('Include only instances which had at least this number of active users during the last 30 days (set to empty to disable this criterion)').'">'._('Minimum number of active users is').'</label></div>
|
||
<div class="sdinput"><input type="number" id="minau" name="minau" min="0" max="'.$minaumax.'" class="sinput" value="'.$_GET['minau'].'" onchange="ckadvcri();"></div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="cbnoxious" title="'._('Exclude noxious instances').'">'._('Exclude noxious').'</label></div>
|
||
<div class="sdinput">
|
||
<input type="checkbox" class="sckbox" id="cbnoxious" value="1"'.$_GET['cbnoxious'].' onchange="sethid(\'noxious\');">
|
||
<input type="hidden" id="noxious" name="noxious" value="'.$_GET['noxious'].'">
|
||
</div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="cbcreg" title="'._('Exclude instances which don’t accept new registrations').'">'._('Exclude if registrations are closed').'</label></div>
|
||
<div class="sdinput">
|
||
<input type="checkbox" class="sckbox" id="cbcreg" value="1"'.$_GET['cbcreg'].' onchange="sethid(\'creg\');">
|
||
<input type="hidden" id="creg" name="creg" value="'.$_GET['creg'].'">
|
||
</div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="cbappr" title="'._('Exclude instances on which admin approval is required for registration').'">'._('Exclude if registration requires approval').'</label></div>
|
||
<div class="sdinput">
|
||
<input type="checkbox" class="sckbox" id="cbappr" value="1"'.$_GET['cbappr'].' onchange="sethid(\'appr\');">
|
||
<input type="hidden" id="appr" name="appr" value="'.$_GET['appr'].'">
|
||
</div>
|
||
</div>
|
||
<div class="sdrow">
|
||
<div class="sdlabel"><label for="cblcok" title="'._('Exclude instances which didn’t respond to last check').'">'._('Exclude if offline on last check').'</label></div>
|
||
<div class="sdinput">
|
||
<input type="checkbox" class="sckbox" id="cblcok" value="1"'.$_GET['cblcok'].' onchange="sethid(\'lcok\');">
|
||
<input type="hidden" id="lcok" name="lcok" value="'.$_GET['lcok'].'">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script language="JavaScript">
|
||
ckadvcri();
|
||
</script>
|
||
|
||
<div class="sdcrow">
|
||
<input type="button" class="litbut" id="mctrlb" value="'._('Advanced criteria').'" onclick="shmctrl()">
|
||
</div>
|
||
|
||
<div class="sdtitb">'._('Order of results').'</div>
|
||
|
||
<div class="sdcrow">
|
||
<select id="ord" name="ord" class="sselect100">'.N);
|
||
foreach ($order as $key=>$buf) {
|
||
($key!=$_GET['ord']) ? $selected='' : $selected=' selected';
|
||
echo('<option value="'.$key.'"'.$selected.'>'.$buf['t'].'</option>'.N);
|
||
}
|
||
echo('</select>
|
||
</div>
|
||
|
||
<div class="sdlrow">
|
||
<input type="submit" value="'._('Search').'" class="ssubmit">
|
||
</div>
|
||
|
||
<div class="sdlcrow">
|
||
<input type="button" class="litbut" value="'._('Reset search').'" onclick="document.location.href=document.location.href.replace(/\\?.*$/,\'\')">
|
||
</div>
|
||
|
||
<input type="hidden" id="advc" name="advc" value="'.$_GET['advc'].'">
|
||
<input type="hidden" id="p" name="p" value="'.$p.'">
|
||
</form>
|
||
|
||
<script language="JavaScript">
|
||
mctrlsh='.(($_GET['advc']==1) ? 'false' : 'true').';
|
||
shmctrl();
|
||
swhelp();
|
||
</script>'.N);
|
||
$joins=array();
|
||
$wheres=array();
|
||
$wheres[]='Instances.LastOkCheckTS>='.$graceline.' AND Instances.IsMastodon=1 AND Instances.FirstSeen IS NOT NULL';
|
||
if ($_GET['noxious']==1) $wheres[]='Instances.Noxious=0';
|
||
if ($_GET['creg']==1) $wheres[]='Instances.RegOpen=1';
|
||
if ($_GET['appr']==1) $wheres[]='Instances.RegReqApproval=0';
|
||
if ($_GET['lcok']==1) $wheres[]='Instances.WasLastCheckOk=1';
|
||
/*if ($_GET['lcok']==1) {
|
||
$joins[]='LEFT JOIN InstChecks AS InstChecks ON InstChecks.InstID=Instances.ID AND InstChecks.Time=(SELECT MAX(InstChecks.Time) AS MaxTime FROM InstChecks WHERE InstChecks.InstID=Instances.ID)';
|
||
$wheres[]='InstChecks.Status=1';
|
||
}*/
|
||
if ($_GET['lang']>0) {
|
||
$joins[]='LEFT JOIN InstOurLangs ON InstOurLangs.InstID=Instances.ID';
|
||
$wheres[]='(InstOurLangs.OurLangID='.$_GET['lang'].' AND InstOurLangs.Pos=1)';
|
||
}
|
||
$buf=preg_replace('#%#','\%',myesc($link,$_GET['desc']));
|
||
if ($_GET['desc']!='') $wheres[]='(Instances.URI LIKE "%'.$buf.'%" OR Instances.Title LIKE "%'.$buf.'%" OR Instances.ShortDesc LIKE "%'.$buf.'%" OR Instances.LongDesc LIKE "%'.$buf.'%")';
|
||
if ($_GET['minu']!='') $wheres[]='Instances.UserCount>='.$_GET['minu'];
|
||
if ($_GET['maxu']!='') $wheres[]='Instances.UserCount<='.$_GET['maxu'];
|
||
if ($_GET['minau']!='') $wheres[]='Instances.ActiveUsersMonth>='.$_GET['minau'];
|
||
$joins=implode(' ',$joins);
|
||
$wheres='WHERE '.implode(' AND ',$wheres);
|
||
if (!$single)
|
||
$que='SELECT * FROM Instances '.$joins.' '.$wheres.' ORDER BY '.$order[$_GET['ord']]['q'];
|
||
else
|
||
$que='SELECT * FROM Instances WHERE ID='.$_GET['id'];
|
||
$debug.='QUERY: «'.$que.'»'.N;
|
||
$qbt=microtime(true);
|
||
$res=mysqli_query($link,$que) or muorimeglio(__LINE__.': '.mysqli_error($link),true);
|
||
$debug.='MAIN QUERY EXEC TIME: '.(microtime(true)-$qbt).' sec.'.N;
|
||
$itot=mysqli_num_rows($res);
|
||
$debug.='RESULTS: '.$itot.N;
|
||
$ipp=10;// istanze per pagina
|
||
$if=$ipp*($p-1);
|
||
if ($if>=$itot) {
|
||
$if=0;
|
||
$p=1;
|
||
}
|
||
$il=$if+$ipp;
|
||
|
||
function tquery($query,$line) {
|
||
global $link, $debug;
|
||
$bt=microtime(true);
|
||
$res=mysqli_query($link,$query) or muorimeglio($line.': '.mysqli_error($link),true);
|
||
$debug.=(microtime(true)-$bt).' secs. for query «'.$query.'»'.N;
|
||
return($res);
|
||
}
|
||
|
||
mysqli_data_seek($res,$if);
|
||
while ($if<$il && $row=mysqli_fetch_assoc($res)) {
|
||
$if++;
|
||
$out='<div class="ihead"><a href="https://'.hspech($row['URI']).'" title="'._('Go to instance').'">'.hspech($row['URI']).'</a>';
|
||
if (!$single) $out.=' <a href="'.$conf['baseurl'].'/instances?id='.$row['ID'].'" title="'._('Direct link to this instance’s card').'">('.$if.'/'.$itot.')</a>';
|
||
$out.='</div>'.N.'<div class="ibody">'.N;
|
||
$qbt=microtime(true);
|
||
$rres=tquery('SELECT CONCAT(Languages.Name'.$dlanguc.'," (",Languages.Code,")") AS Lang FROM InstOurLangs LEFT JOIN Languages ON Languages.ID=InstOurLangs.OurLangID WHERE InstOurLangs.InstID='.$row['ID'].' ORDER BY InstOurLangs.Pos ASC',__LINE__);
|
||
$buf=array();
|
||
while ($rrow=mysqli_fetch_assoc($rres))
|
||
$buf[]=hspech($rrow['Lang']);
|
||
($row['Thumb']=='unavailable') ? $thumb=$prepath.'imgs/InstThumbUnavailable.svg' : $thumb=$row['Thumb'];
|
||
$out.='<div class="iimgc"><a href="https://'.hspech($row['URI']).'" title="'._('Go to instance').'"><img class="iimg" src="'.$thumb.'"></a>';
|
||
// if (!is_null($row['Priority'])) $out.='<img src="'.$prepath.'imgs/featured-it.svg" class="ifeat">';
|
||
if (!is_null($row['Priority'])) $out.='<div class="dfeat">'._('Recommended').'</div>';
|
||
if ($row['Thumb']=='unavailable' && $row['WasLastCheckOk']==1) $out.='<div class="unavmsg">'._('It seems like this instance’s server thumbnail’s URL points to a non existent file. This is usually easily fixeable by admins by uploading again the server thumbnail. Note that if you do it, the change won’t be displayed here before the daily automatic update of this instance’s infos occurs.').'</div>';
|
||
$out.='</div>'.N;
|
||
$out.='<div class="icol">'.N;
|
||
$out.='<div><span class="ilab">'._('Name').'</span> <a href="https://'.hspech($row['URI']).'" title="'._('Go to instance').'">'.nully(hspech($row['Title'])).'</a></div>'.N;
|
||
/*$out.='<div><span class="ilab">'._('Consigliata').'</span> ';
|
||
(!is_null($row['Priority'])) ? $out.='<span class="ivgood">'._('Si!').'</span>' : $out.=_('No');
|
||
$out.='</div>'.N;*/
|
||
$out.='<div><span class="ilab">'._('Languages').'</span> '.nully(implode(', ',$buf)).'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Users').'</span> '.nully(fnum($row['UserCount'],0,$dlang)).'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Active users (last month)').'</span> '.nully(fnum($row['ActiveUsersMonth'],0,$dlang)).'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Active users (last six months)').'</span> '.nully(fnum($row['ActiveUsersHalfYear'],0,$dlang)).'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Characters per toot (max)').'</span> ';
|
||
if (nullemp(fnum($row['MaxTootChars'],0,$dlang)))
|
||
$out.='<span class="null">500</span>';
|
||
else
|
||
$out.=$row['MaxTootChars'];
|
||
$out.='</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Known instances').'</span> '.nully(fnum($row['DomainCount'],0,$dlang)).'</div>'.N;
|
||
$out.='</div>'.N;
|
||
|
||
$out.='<div class="icol">'.N;
|
||
if (is_null($row['FirstSeen'])) {// can't currently happen, because main query excludes on FirstSeen = null; but we put it there in any event
|
||
$fseen='<span class="null">'._('Not available{singular}').'</span>';
|
||
} elseif ($row['FirstSeen']<1602626400) {// 1602626400 is October 14, 2020, 0:0:0 - we have FirstSeen only since October 13, 2020, so...
|
||
$fseen='<span class="nulltip" title="'._('We record this value only since October 14, 2020 ;-)').'">'._('Before October 14, 2020').'</span>';
|
||
} else {
|
||
$fseen=ldate($row['FirstSeen'],true);
|
||
}
|
||
$out.='<div><span class="ilab">'._('First sight').'</span> '.$fseen.'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Last successful check').'</span> '.nully(ldate($row['LastOkCheckTS'],true)).'</div>'.N;
|
||
$out.='<div><span class="ilab">'._('Noxious').'</span> ';
|
||
($row['Noxious']==1) ? $out.='<span class="ibad">'._('Yes (see why below)').'</span>' : $out.='<span class="igood">'._('No').'</span>';
|
||
$out.='</div>'.N;
|
||
$out.='<div><span class="ilab">'._('New').'</span> ';
|
||
($bt-$row['InsertTS']<=$oldline) ? $out.='<span class="ivgood">'._('Yes!').'</span>' : $out.=_('No');
|
||
$out.='</div>'.N;
|
||
$software='';
|
||
if (!is_null($row['Software'])) $software.=ucfirst($row['Software']);
|
||
if (!is_null($row['Version'])) $software.=' '.$row['Version'];
|
||
$out.='<div><span class="ilab">'._('Software').'</span> '.nully(hspech($software)).'</div>'.N;
|
||
|
||
$out.='<div><span class="ilab">'._('Registrations').'</span> ';
|
||
($row['RegReqApproval']==1) ? $buf=' <span class="iwarn">('._('by admin approval').')</span>' : $buf='';
|
||
if (nullemp($row['RegOpen']))
|
||
$out.='<span class="null">'._('Not available{singular}').'</span>';
|
||
elseif ($row['RegOpen']==1)
|
||
$out.='<span class="igood">'._('Open').'</span>'.$buf;
|
||
else
|
||
$out.='<span class="iwarn">'._('Closed').'</span>';
|
||
$out.='</div>'.N;
|
||
$out.='<div><span class="ilab">'._('E-mail').'</span> ';
|
||
if (nullemp($row['Email']))
|
||
$out.='<span class="null">'._('Not available{singular}').'</span>';
|
||
else
|
||
$out.='<a href="mailto:'.$row['Email'].'">'.$row['Email'].'</a>';
|
||
$out.='</div>'.N;
|
||
$out.='</div>'.N;
|
||
|
||
$out.='<div><span class="ilab">'._('Most used hashtags (last week)').'</span> ';
|
||
$rres=tquery('SELECT * FROM InstTrends WHERE InstID='.$row['ID'].' ORDER BY Pos ASC',__LINE__);
|
||
if (mysqli_num_rows($rres)>0) {
|
||
$buf=array();
|
||
while ($rrow=mysqli_fetch_assoc($rres))
|
||
$buf[]='<a href="'.hspech($rrow['URL']).'">'.hspech($rrow['Name']).'</a>';
|
||
$out.=implode(', ',$buf);
|
||
} else {
|
||
$out.='<span class="null">'._('Not available{plural}').'</span>';
|
||
}
|
||
$out.='</div>'.N;
|
||
|
||
if ($row['Noxious']) {
|
||
$out.='<div><div class="noxlab">'._('Why we consider this instance noxious').'</div><div class="noxreas">'.nully(strip($row['NoxReason'],$row['URI'])).'</div></div>'.N;
|
||
}
|
||
|
||
$out.='<div><div class="idlab">'._('Short description').'</div><div class="idesc">'.nully(strip($row['ShortDesc'],$row['URI'])).'</div></div>'.N;
|
||
$out.='<div><div class="idlab">'._('Long description').'</div><div class="idesc">'.nully(strip($row['LongDesc'],$row['URI'])).'</div></div>'.N;
|
||
|
||
$out.='<div><div class="idlab">'._('Server rules').'</div><div class="idesc">';
|
||
$rres=tquery('SELECT Text FROM InstRules WHERE InstID='.$row['ID'],__LINE__);
|
||
if (mysqli_num_rows($rres)>0) {
|
||
$out.='<ol class="nobott">'.N;
|
||
while ($rrow=mysqli_fetch_assoc($rres))
|
||
$out.='<li>'.hspech($rrow['Text']).'</li>'.N;// no strip, do hspech, because server rules don’t support html nor markdown in mastodon
|
||
$out.='</ol>'.N;
|
||
} else {
|
||
$out.='<span class="null">'._('Not available{plural}').'</span>';
|
||
}
|
||
$out.='</div></div>'.N;
|
||
|
||
$out.='<div><div class="idlab">'._('Moderated servers').'</div><div class="idesc">';
|
||
$sevmap=['silence'=>_('silenced'), 'suspend'=>_('suspended')];
|
||
$rres=tquery('SELECT Domain, Severity, Comment FROM InstBlocks WHERE InstID='.$row['ID'],__LINE__);
|
||
if (mysqli_num_rows($rres)>0) {
|
||
$out.='<ul class="nobott">'.N;
|
||
while ($rrow=mysqli_fetch_assoc($rres)) {
|
||
$out.='<li><strong>'.hspech($rrow['Domain']).'</strong>: '.$sevmap[$rrow['Severity']];
|
||
if (!is_null($rrow['Comment'])) $out.=' - '.hspech($rrow['Comment']);// no strip, do hspech, because moredated server comments don’t support html nor markdown in mastodon
|
||
$out.='</li>'.N;
|
||
}
|
||
$out.='</ul>'.N;
|
||
} else {
|
||
$out.='<span class="null">'._('Not available{plural}').'</span>';
|
||
}
|
||
$out.='</div></div>'.N;
|
||
|
||
$admacc=nully(null);
|
||
$thumb=$prepath.'imgs/AdmAccThumbUnavailable.svg';
|
||
if (!is_null($row['AdmAccount']) && $row['AdmAccount']!='OPTED OUT') {
|
||
$admacc='<a href="https://'.hspech($row['URI']).'/@'.hspech($row['AdmAccount']).'">'.hspech($row['AdmAccount']).'@'.hspech($row['URI']).'</a>';
|
||
if ($row['AdmAvatar']!='unavailable') $thumb=$row['AdmAvatar'];
|
||
} elseif ($row['AdmAccount']=='OPTED OUT') {
|
||
$admacc='<span class="null">'._('Opted out of search engines indexing').'</span>';
|
||
}
|
||
$out.='<div class="abox"><img class="aimg" src="'.$thumb.'"><div><span class="ilab">'._('Admin account').'</span> '.$admacc.'</div><div><span class="ilab">'._('Date of creation').'</span> '.nully(ldate($row['AdmCreatedAt'],true)).'</div><div><span class="ilab">'._('Display name').'</span> '.nully(hspech($row['AdmDisplayName'])).'</div><div><div class="idlab">'._('Bio').'</div><div class="inote">'.nully(strip($row['AdmNote'],$row['URI'])).'</div>'.N;
|
||
$out.='</div></div>';
|
||
|
||
$out.='<div class="ghost"><div class="idlab">'._('Stats').'</div><div class="istat">';
|
||
|
||
$rres=tquery('SELECT COUNT(InstID) AS cnt, SUM(Statuses) AS tstatuses, SUM(Logins) AS tlogins, SUM(Registrations) AS tregs FROM InstActivity WHERE InstID='.$row['ID'],__LINE__);
|
||
$out.='<div class="dida">'._('Last 12 weeks activity');
|
||
if (mysqli_num_rows($rres)>0) {
|
||
$rrow=mysqli_fetch_assoc($rres);
|
||
if ($rrow['cnt']>0)
|
||
$out.=' ('._('totals:').' '.$rrow['tstatuses'].' '._('statuses').', '.$rrow['tlogins'].' '._('logins').', '.$rrow['tregs'].' '._('registrations').')';
|
||
}
|
||
$out.='</div>'.N;
|
||
$rres=tquery('SELECT * FROM InstActivity WHERE InstID='.$row['ID'].' ORDER BY Week ASC',__LINE__);
|
||
$out.='<table class="abar"><tr>';
|
||
$tot=mysqli_num_rows($rres);
|
||
if ($tot>0) {
|
||
while ($rrow=mysqli_fetch_assoc($rres))
|
||
// initials for Statuses, Logins, Registrations
|
||
$out.='<td width="'.(100/$tot).'%">'._('S').': '.$rrow['Statuses'].'<br>'._('L').': '.$rrow['Logins'].'<br>'._('R').': '.$rrow['Registrations'].'</td>';
|
||
} else {
|
||
$out.='<td><span class="null">'._('Not available{singular}').'</span></td>';
|
||
}
|
||
$out.='</tr></table>'.N;
|
||
|
||
$rres=tquery('SELECT * FROM InstChecks WHERE InstID='.$row['ID'].' ORDER BY Time DESC LIMIT 0,8',__LINE__);
|
||
$tot=mysqli_num_rows($rres);
|
||
$buf=array();
|
||
while ($rrow=mysqli_fetch_assoc($rres)) $buf[]=$rrow;
|
||
$out.='<div class="dida">'._('Last checks (green: OK; red: KO)').'</div><table class="cbar"><tr>';
|
||
for ($i=$tot-1; $i>=0; $i--) {
|
||
$out.='<td width="'.(100/$tot).'%"';
|
||
if ($buf[$i]['Status']==1) $out.=' class="cbarok"';
|
||
$out.='>'.ldate($buf[$i]['Time']).'</td>';
|
||
}
|
||
$out.='</tr></table>'.N;
|
||
|
||
$out.='</div></div>'.N;
|
||
|
||
$out.='</div>'.N;
|
||
echo($out);
|
||
}
|
||
mysqli_close($link);
|
||
|
||
echo('</section>'.N);
|
||
|
||
$ptot=ceil($itot/$ipp);
|
||
if ($ptot>1) {
|
||
echo('<div id="footmarg"></div>'.N);
|
||
echo('<div id="bmenu">'.N);
|
||
$pnav='<table id="pnav"><tr>';
|
||
if ($p>1)
|
||
$pnav.='<td><img src="'.$prepath.'imgs/nav_first.svg" onclick="swp(1);" class="hov" title="'._('Go to first page').'"></td><td><img src="'.$prepath.'imgs/nav_prev.svg" onclick="swp('.($p-1).');" class="hov" title="'._('Go to previous page').'"></td>';
|
||
else
|
||
$pnav.='<td><img src="'.$prepath.'imgs/nav_first_off.svg"></td><td><img src="'.$prepath.'imgs/nav_prev_off.svg"></td>';
|
||
//$pnav.='<td>Page '.$p.'/'.$ptot.'</td>';
|
||
$pnav.='<td><select id="pagesel" onchange="swp(this.value);" title="'._('Select page').'">'.N;
|
||
for ($i=1; $i<=$ptot; $i++) {
|
||
($i!=$p) ? $selected='' : $selected=' selected';
|
||
$li=$i*$ipp;
|
||
if ($li>$itot) $li=$itot;
|
||
//page number prefix
|
||
$pnav.='<option value="'.$i.'"'.$selected.'>'._('Page').' '.$i.' '._('of').' '.$ptot.' ('._('instances').': '.(($i-1)*$ipp+1).'-'.$li.'/'.$itot.')</option>'.N;
|
||
}
|
||
$pnav.='</select></td>'.N;
|
||
if ($p<$ptot)
|
||
$pnav.='<td><img src="'.$prepath.'imgs/nav_next.svg" onclick="swp('.($p+1).');" class="hov" title="'._('Go to next page').'"></td><td><img src="'.$prepath.'imgs/nav_last.svg" onclick="swp('.($ptot).');" class="hov" title="'._('Go to last page').'"></td>';
|
||
else
|
||
$pnav.='<td><img src="'.$prepath.'imgs/nav_next_off.svg"></td><td><img src="'.$prepath.'imgs/nav_last_off.svg"></td>';
|
||
$pnav.='</tr></table>'.N;
|
||
echo($pnav);
|
||
echo('</div>'.N);
|
||
}
|
||
|
||
echo('</div>'.N);
|
||
echo('</div>'.N);
|
||
|
||
$debug.='TOTAL RENDERING TIME: '.(microtime(true)-$bt).N;
|
||
if (array_key_exists('debug',$_GET) && $_GET['debug']=='1') echo('<!--'.N.'--- DEBUG INFO ---'.N.$debug.'//-->'.N);
|
||
|
||
?>
|