diff --git a/mastblocksdump/mastblocksmerge.wip.sh b/mastblocksdump/mastblocksmerge.wip.sh new file mode 100755 index 0000000..f1bbbac --- /dev/null +++ b/mastblocksdump/mastblocksmerge.wip.sh @@ -0,0 +1,237 @@ +#!/bin/bash + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +MASTHOME='/var/lib/mastodon' +MASTENVFP="$MASTHOME/live/.env.production" +SISTERSFP="istanzesorelle" +LOCAL=0 +INTERACTIVE=0 + +HELP="SINTASSI + mastblocksmerge.sh [opzioni] +DESCRIZIONE + Questo script integra i dati di una o più blocklist esterne nella + tabella domain_blocks di mastodon. + Legge i domini delle istanze di cui recuperare la blocklist da un file + di inizializzazione, per default \"$SISTERSP\" (formato del file: + un dominio per riga), prova a recuperare ciascuna blocklist da + https://[dominio]/domain_blocks.txt, costruisce dalle liste recuperate + un\'unica lista senza duplicati, si collega al db di mastodon e scrive + nella tabella domain_blocks i dati relativi alle istanze bloccate che + non sono già presenti nella tabella stessa. + Per la connessione al db di mastodon legge i dati necessari dal file + di configurazione di mastodon, per default + \"$MASTENVFP\" + È pensato per essere eseguito periodicamente da un cron job, come + utente mastodon oppure root oppure altro utente che abbia accesso in + lettura al file di configurazione di mastodon. +OPZIONI + -H, --home + Definisce la home di mastodon (per default \"$MASTHOME\") + e di conseguenza il percorso del suo file di configurazione + (per default \"$MASTENVFP\"). + È comunque possibile specificare individualmente il percorso + del file di configurazione di mastodon con l\'opzione che segue. + -e, --envfp + Definisce il percorso del file di configurazione di mastodon in uso. + -s, --sistersfp + Definisce il percorso del file di inizializzazione da cui leggere + la lista dei domini delle istanze sorelle. + -l, --local + Interpreta il file di inizializzazione come lista di file locali + contenenti blacklist (formato: un file per riga). + -i, --interactive + Modalità interattiva: se vengono nelle blocklist vengono trovate + istanze ancora non presenti nel database di mastodon, viene chiesto + per ciascuna se aggiungerla o meno. + -h, --help + Mostra questo aiuto ed esce." + +args=("$@") +i=0 +while [ $i -lt ${#args[@]} ]; do + if [ "${args[$i]:0:1}" == "-" ]; then + case "${args[$i]}" in + "-H" | "--home" ) + if [ -z "${args[$i+1]}" ]; then + echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." + exit 1 + else + ((i++)) + MASTHOME=$(echo "${args[$i]}" | sed -e 's/\/$//') + MASTENVFP="$MASTHOME/live/.env.production" + fi + ;; + "-e" | "--envfp" ) + if [ -z "${args[$i+1]}" ]; then + echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." + exit 1 + else + ((i++)) + MASTENVFP="${args[$i]}" + fi + ;; + "-s" | "--sistersfp" ) + if [ -z "${args[$i+1]}" ]; then + echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." + exit 1 + else + ((i++)) + SISTERSFP="${args[$i]}" + fi + ;; + "-l" | "--local" ) + LOCAL=1 + ;; + "-i" | "--interactive" ) + INTERACTIVE=1 + ;; + "-h" | "--help" ) + echo "$HELP" + exit 0 + ;; + *) + echo "\"${args[$i]}\": opzione sconosciuta (usa \"-h\" per l'aiuto)." + exit 1 + ;; + esac + else + echo "\"${args[$i]}\": opzione sconosciuta (usa \"-h\" per l'aiuto)." + exit 1 + fi + ((i++)) +done + +[ ! -e "$MASTENVFP" ] && echo "\"$MASTENVFP\" non esiste, muoio (usa \"-h\" per l'aiuto)." && exit 1 +[ ! -f "$MASTENVFP" ] && echo "\"$MASTENVFP\" non è un file, muoio (usa \"-h\" per l'aiuto)." && exit 1 +[ ! -r "$MASTENVFP" ] && echo "\"$MASTENVFP\" non è leggibile, muoio (usa \"-h\" per l'aiuto)." && exit 1 + +[ ! -e "$SISTERSFP" ] && echo "\"$SISTERSFP\" non esiste, muoio (usa \"-h\" per l'aiuto)." && exit 1 +[ ! -f "$SISTERSFP" ] && echo "\"$SISTERSFP\" non è un file, muoio (usa \"-h\" per l'aiuto)." && exit 1 +[ ! -r "$SISTERSFP" ] && echo "\"$SISTERSFP\" non è leggibile, muoio (usa \"-h\" per l'aiuto)." && exit 1 + +DB_HOST=`grep 'DB_HOST' "$MASTENVFP"|sed -e 's/[^=]*=//'` +DB_PORT=`grep 'DB_PORT' "$MASTENVFP"|sed -e 's/[^=]*=//'` +DB_NAME=`grep 'DB_NAME' "$MASTENVFP"|sed -e 's/[^=]*=//'` +DB_USER=`grep 'DB_USER' "$MASTENVFP"|sed -e 's/[^=]*=//'` +DB_PASS=`grep 'DB_PASS' "$MASTENVFP"|sed -e 's/[^=]*=//'` + +IFS=$'\n' + +function decode { + #dominio + record[0]=$(echo "$1" | sed -e 's/\t.*//') + #data creazione + record[1]=$(echo "$1" | sed -e 's/^[^\t]*\t\([^\t]*\).*/\1/') + #data ultima modifica + record[2]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') + #tipo di blocco + record[3]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') + #rifiuto media + record[4]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') + #rifiuto reports + record[5]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') + #commento pubblico + record[6]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') + if [ "${record[4]}" == "f" ]; then + record[4]="No" + elif [ "${record[4]}" == "t" ]; then + record[4]="Si" + fi + if [ "${record[5]}" == "f" ]; then + record[5]="No" + elif [ "${record[5]}" == "t" ]; then + record[5]="Si" + fi + if [ "${record[3]}" == "0" ]; then + record[3]="Silenziata" + elif [ "${record[3]}" == "1" ]; then + record[3]="Sospesa" + elif [ "${record[3]}" == "2" ]; then + record[3]="Nessuno" + fi +} + +for sisdom in $(grep -P '^[^#]+[^\s]+' "$SISTERSFP"); do + if [ $LOCAL -eq 0 ]; then + blocks+="$(curl --connect-timeout 3 -s "https://$sisdom/domain_blocks.txt" | grep -P '^[^#]+[^\s]+')$IFS" + else + blocks+="$(cat "$sisdom" | grep -P '^[^#]+[^\s]+')$IFS" + fi +done +blocks=$(echo "$blocks" | head -n -1 | sort -u) +echo "$blocks" +echo "~~~~~~~~~~~~~~~~~~~~" +okblocks='' +for line in $blocks; do + dom=$(echo "$line" | sed -e 's/\t.*//' -e 's/\./\\./g') + echo "$okblocks" | grep -P "^$dom\t" + if [ $? -ne 0 ]; then + entries=$(echo "$blocks" | grep -P "^$dom\t") + howmany=$(echo "$entries" | wc -l) + if [ $howmany -gt 1 ]; then + if [ $INTERACTIVE -eq 1 ]; then + i=0 + for entry in $entries; do + ((i++)) + echo "$i: $entry" + done + read + else + # qui ci vorrebbe codice "intelligente" che sceglie la entry più recente, ma per ora così + okblocks+="$line$IFS" + fi + fi + fi +done +okblocks=$(echo "$okblocks" | head -n -1 | sort) +echo "$okblocks" +echo "~~~~~~~~~~~~~~~~~~~~" + +exit + + + + +blocks=$(PGPASSWORD="$DB_PASS" psql -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -c 'SELECT domain, updated_at, severity, public_comment FROM domain_blocks' -A -t -F $'\t') + +i=0 +for line in $allblocks; do + dom=$(echo "$line" | sed -e 's/\t.*//' -e 's/\./\\./g') + echo "$blocks" | grep -P "^$dom\t" &>/dev/null + [ $? -ne 0 ] && newblocks+="$line$IFS" && ((i++)) +done +newblocks=$(echo "$newblocks" | head -n -1 | sort) + +[ $i -eq 0 ] && echo "Non ho trovato nessuna nuova istanza bloccata." && exit 0 + +echo "Ho trovato $i istanza/e bloccata da aggiungere." + +if [ $INTERACTIVE -eq 1 ]; then + for line in $newblocks; do + decode "$line" + echo "Dominio: ${record[0]}; Data creaz.: ${record[1]}; Data ult. mod.: ${record[2]}; Tipo blocco: ${record[3]}; Rifiuto media: ${record[4]}; Rifiuto reports: ${record[5]}; Commento pub.: ${record[6]}" + ask=1 + while [ $ask -eq 1 ]; do + read -p "Vuoi aggiungere questa istanza alla tabella delle istanze bloccate? [S/n] " inp + echo "$inp" | grep -P '^[sSnN]{0,1}$' &>/dev/null + [ $? -eq 0 ] && ask=0 + done + if [ "$inp" == "" ] || [ "$inp" == "s" ] || [ "$inp" == "S" ]; then + buf+="$line$IFS" + fi + done + newblocks=$(echo "$buf" | head -n -1) +fi + +echo "$newblocks" | PGPASSWORD="$DB_PASS" psql -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -A -t -c "COPY domain_blocks ( domain, created_at, updated_at, severity, reject_media, reject_reports, public_comment ) FROM STDIN WITH ( FORMAT text, DELIMITER ' ' )" diff --git a/mastblocksdump/php/domblocks.php b/mastblocksdump/php/domblocks.php new file mode 100644 index 0000000..8fc6311 --- /dev/null +++ b/mastblocksdump/php/domblocks.php @@ -0,0 +1,38 @@ +null, + 'DB_PORT'=>null, + 'DB_NAME'=>null, + 'DB_USER'=>null, + 'DB_PASS'=>null +); + +$confa=file($conffp,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); + +foreach ($confa as $line) { + if (preg_match('/^([A-Z_]+)=(.*)$/',$line,$buf)===1 && array_key_exists($buf[1],$conf)) + $conf[$buf[1]]=$buf[2]; +} + +$dbconn=pg_connect('host='.$conf['DB_HOST'].' port='.$conf['DB_PORT'].' dbname='.$conf['DB_NAME'].' user='.$conf['DB_USER'].' password='.$conf['DB_PASS']) + or die('Connessione fallita: '.pg_last_error()); + +$res=pg_query('SELECT domain, created_at, updated_at, severity, reject_media, reject_reports, public_comment FROM domain_blocks') + or die('Query fallita: '.pg_last_error()); + +while ($row=pg_fetch_assoc($res)) + $domblocks[]=$row; + +pg_free_result($res); +pg_close($dbconn); + +echo(json_encode($domblocks)); + +exit(0); + +?> diff --git a/web/admin/crawler/.htaccess b/web/admin/crawler/.htaccess new file mode 100644 index 0000000..93169e4 --- /dev/null +++ b/web/admin/crawler/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all diff --git a/web/admin/crawler/blacklist_bida.txt b/web/admin/crawler/blacklist_bida.txt deleted file mode 100644 index 7dfe535..0000000 --- a/web/admin/crawler/blacklist_bida.txt +++ /dev/null @@ -1,36 +0,0 @@ -anitwitter.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -anitwitter.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -babymetal.party 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -baraag.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -bsd.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://mastodon.bida.im/@Ca_Gi/101270762003908554 -ediot.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -freespeechextremist.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -freespeech.firedragonstudios.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://mastodon.bida.im/@Ca_Gi/101344114624456297 -freezepeach.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -gorf.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -gs.smuglo.li 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -humblr.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f https://mastodon.bida.im/@cirku17/101399587014096355 -ika.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -mastodon.starrevolution.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://a.nom.pl/notice/450131 -mobile.co 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://mastodon.bida.im/@Ca_Gi/101355947506820592 -neckbeard.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f Instance suspended: neckbeard.xyz - anime nazi shit, irony bro admin -newjack.city 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -noagendasocial.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -pawoo.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -pl.smuglo.li 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -porntoot.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -preteengirls.biz 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -quodverum.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://mastodon.bida.im/@Ca_Gi/101514801964087604 -sealion.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -shitposter.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -shitposter.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f https://mastodon.bida.im/@Ca_Gi/101270762003908554 -social.au2pb.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -social.heldscal.la 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -social.imirhil.fr 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -social.quodverum.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f Razzisti -social.targaryen.house 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -switter.at 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f https://mastodon.bida.im/@jops/101404791975700441 -toot.love 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 0 f f -unsafe.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -woofer.alfter.us 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f -wrongthink.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:05.111111 1 f f diff --git a/web/admin/crawler/blacklist_cagi.txt b/web/admin/crawler/blacklist_cagi.txt deleted file mode 100644 index b8f989e..0000000 --- a/web/admin/crawler/blacklist_cagi.txt +++ /dev/null @@ -1,157 +0,0 @@ -2.distsn.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Spam -2hu.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -anitwitter.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -anitwitter.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -ap.torlipen.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -ap.uwu.st 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -babymetal.party 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -baraag.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -beehub.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -blob.cat 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -bodybuilding.im 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -bofa.lol 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -bsd.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -carnal-gabhub.protohype.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -civiq.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -cofe.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -comm.network 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -community.halle-leaks.de 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -community.highlandarrow.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -counter.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -cryzed.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -cyzed.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -daffodil-11.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Malicious site -dev.civiq.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -develop.gab.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -dickshow.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -djitter.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -ediot.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -ediot.socialsilence 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -ekrem.develop.gab.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -exited.eu 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -explosion.party 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Conspiracy theories -fedichive.tk 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -feminism.lgbt 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -freefedifollowers.ga 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -freehold.earth 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -freespeechextremist.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -freespeech.firedragonstudios.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -freespeech.host 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -freevoice.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -freezepeach.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.ai 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gabble.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gabfed.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.io 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.polaris-1.work 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.protohype.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gab.sleek.eu 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gameliberty.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -gasthe.lgbt 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gnusocial.no 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -goldandblack.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gorf.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -gorf.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -gs.archae.me 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gs.kawa-kun.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gs.mon5t3r.info 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -gs.smuglo.li 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -hakui.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -homura.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -ika.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -impeccable.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -inditoot.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -jabb.in 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Conspiracy theories -juche.town 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -karolat.press 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -kawaiistu.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -kawen.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -kazvam.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -kipper.im 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -kiwifarms.cc 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -kneegrows.top 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -kowai.youkai.town 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -kyot.me 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -liberdon.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -libertarianism.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -libre.tube 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -loli.estate 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -lolis.world 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -manx.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -mastodon.loliandstuff.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -mastodon.starrevolution.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -mast.wholemars.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -melalandia.tk 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -me.nooruul.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -mobile.co 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -neckbeard.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -neenster.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -newjack.city 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Spam -niu.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -noagendasocial.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -not-develop.gab.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -not.phrack.fyi 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Conspiracy theories -npf.mlpol.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -pawoo.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -pleroma.cucked.me 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -pleroma.rareome.ga 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Malicious site -pleroma.soykaf.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -pleroma.wolfie.pw 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -pleroma.yorha.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -pleville.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -pl.smuglo.li 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -porntoot.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -preteen.biz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -preteengirls.bi 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -preteengirls.biz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -pridelands.io 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -qoto.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -quey.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -quitter.pw 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -quodverum.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -rainbowdash.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -rapefeminists.network 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -sealion.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -shitasstits.life 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -shitposter.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.allthefallen.ninja 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -social.au2pb.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.guizzyordi.info 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.heldscal.la 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.hidamari.blue 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -social.homunyan.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -social.i2p.rocks 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.imirhil.fr 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -social.louisoft01.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Conspiracy theories -social.lucci.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Conspiracy theories -social.quodverum.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -social.raptorengineering.io 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Advertisement -social.sunshinegardens.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -social.super-niche.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -social.targaryen.house 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -social.wiuwiu.de 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -socnet.supes.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -spinster.dev 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -spinster.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -sunshinegardens.org 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -thechad.zone 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -the.hedgehoghunter.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -toot.love 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Bad Moderation -unsafe.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -vampire.estate 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -video.halle-leaks.de 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f -vipgirlfriend.xxx 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Unflagged porn -voluntaryism.club 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -wagesofsinisdeath.com 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -waifu.social 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -warc.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -weeaboo.space 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -weedis.life 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f -wogan.im 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -woofer.alfter.us 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech -wrongthink.net 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 0 f f Fascism – Hatespeech -wxw.moe 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -yiff.rocks 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Harassment or abuse -youkai.town 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Pedo – Loli -zerohack.xyz 2019-12-11 18:44:05.111111 2019-12-11 18:44:06.710862 1 f f Fascism – Hatespeech diff --git a/web/admin/crawler/crawler.php b/web/admin/crawler/crawler.php index f51b933..59b9c74 100755 --- a/web/admin/crawler/crawler.php +++ b/web/admin/crawler/crawler.php @@ -18,118 +18,38 @@ define('N',"\n"); -$inifp=null; +declare(ticks=1); +pcntl_signal(SIGTERM,'signalHandler');// Termination ('kill' was called) +pcntl_signal(SIGHUP,'signalHandler');// Terminal log-out +pcntl_signal(SIGINT,'signalHandler');// Interrupted (Ctrl-C is pressed) +function signalHandler($signal) { + global $link, $logf, $jsonf; + lecho(N.'Sono stato interrotto.'.N); + if ($link) { + lecho('La connessione MySQL è aperta, la chiudo.'.N); + mysqli_close($link); + } + if ($jsonf) { + echo('Il file di dump json è aperto, lo chiudo.'.N); + fwrite($jsonf,'"Fine?": true'.N.'}'.N); + fclose($jsonf); + } + if ($logf) { + echo('Il file di log è aperto, lo chiudo.'.N); + fclose($logf); + } + exit(2); +} $opts=array( - 'excludeafter'=>60*60*24*30, - 'startinstancesfp'=>null, - 'loadbiglist'=>true, - 'onlinecheck'=>true, - 'timeout'=>5, - 'biglistfp'=>null, - 'prodlistfp'=>null, - 'blacklists'=>array(), - 'whitelists'=>array() + 'timeout'=>3, + 'log'=>true, + 'jsonfp'=>'instances.json', + 'jsonwrite'=>true, + 'jsonread'=>false ); -$help='DESCRIZIONE - Questo script parte da una selezione di istanze Mastodon («istanze - di partenza»), ciascuna con una relativa lista di istanze da essa - bloccate (che può anche essere omessa), e genera/aggiorna due liste: - una che conterrà i dati di tutte le istanze di partenza e delle istanze - ad esse note (comprese quelle bloccate, escluse soltanto quelle che non - rispondono da un lasso di tempo impostabile), e una che conterrà solo - le istanze non bloccate, la cui piattaforma è mastodon, che danno - possibilità di iscrizione di nuovi utenti, il cui numero di utenti - è compreso tra 11 e 30000, che conoscono almeno altre 500 istanze, - che hanno avuto almeno 10 utenti attivi nell\'ultimo mese o, se questo - dato non è disponibile, la cui media di toot per utente è maggiore - o uguale a 10. -SINTASSI - crawler.php -i | -s -b -p [altre opzioni] -OPZIONI - -i, --inifp - Imposta un file di configurazione da cui leggere le opzioni. - Il formato di questo file è semplice: una opzione per riga in formato - =, dove «opzione» è una qualsiasi tra le opzioni - descritte qui nel suo formato lungo, tranne «inifp» e «help». - Esempio: «startinstancesfp=startinstances.txt». - Il file di configurazione può non contenere tutte le opzioni - disponibili. - Nota bene: tutte le opzioni impostate da riga di comando, che siano - specificate prima o dopo questa, hanno la precedenza su quelle - definite nel file di configurazione. - -s, --startinstancesfp - DEVE essere specificata. - Imposta il file da cui leggere le istanze di partenza e le relative - liste di istanze sospese-silenziate. - Il formato del file è questo: per ogni riga: - |[uri della relativa lista di istanze - bloccate] - Ogni riga vuota o che cominci con il carattere «#» sarà ignorata. - Il formato del file delle istanze bloccate è questo: per ogni riga: - |||| - - Esempio di : «2019-12-11 18:44:06.710862» - : «0» per silenziata, «1» per sospesa, «2» per "solo - file media e rapporti". - -b, --biglistfp - DEVE essere specificata. - Imposta il file da cui leggere le istanze già testate in passato - (se il file esiste e non è specificata l’opzione «-d», vedi sotto) - e in cui scrivere tutti i dati recuperabili delle istanze testate. - -p, --prodlistfp - DEVE essere specificata. - Imposta il file da cui leggere (se esiste) e in cui scrivere i dati - relativi alle istanze corrispondenti ai criteri di selezione descritti - nel paragrafo «DESCRIZIONE». - -B, --blacklistfp - Imposta un eventuale file di istanze bloccate aggiuntivo. Per il - formato di questi file vedi sopra il paragrafo relativo nella - descrizione dell\'opzione «-s, --startinstancesfp». Questa opzione può - essere utilizzata più volte per specificare più file di istanze - bloccate. Nel file di configurazione ha un formato particolare: - «blacklistfp=file1[,file2[,file3[...]]]». - -w, --whitelistfp - Imposta un eventuale file di istanze da non scartare mai, nemmeno - se fanno parte di una delle blacklist utilizzato o non corrispondono - ai criteri di filtraggio. Il formato di questi file è semplice: - un dominio per riga (le righe vuote o che cominciano con il carattere - «#» vengono ignorate. Questa opzione può essere utilizzata più volte - per specificare più whitelist. Nel file di configurazione - ha un formato particolare: «whitelistfp=file1[,file2[,file3[...]]]». - -t, --timeout - Imposta il timeout delle richieste http(s) in secondi. - DEFAULT: '.$opts['timeout'].' secondi. - -e, --excludeafter - Imposta il lasso di tempo dopo il quale un’istanza che non risponde - viene eliminata dal listone di tutte le istanze testate. - «tempo» deve essere specificato come un numero, seguito eventualmente - da un carattere che ne indica l’unità di misura: «s» o nessun - carattere per secondi, «m» per minuti, «o» per ore, «g» per giorni, - «S» per settimane, «M» per mesi (30 giorni), «A» per anni. - DEFAULT: 1 mese. - -l, --loadbiglist - Dice al programma se caricare o meno il listone delle istanze già - testate in passato. - DEFAULT: «si». - -c, --onlinecheck - Dice al programma se interrogare o meno le istanze note. - Se impostato a «no» forza a «si» «loadbiglist» (vedi opzione - precedente). - DEFAULT: «si». - -h, --help - Mostra questo aiuto ed esce. - - This program comes with ABSOLUTELY NO WARRANTY; for details see - the source. - This is free software, and you are welcome to redistribute it under - certain conditions; see for details.'.N; - -function mexit($msg,$code) { - echo($msg); - exit($code); -} +use function mysqli_real_escape_string as myesc; function tosec($str) { if (preg_match('/^([0-9]+)([smogSMA]?)/',$str,$buf)===1) { @@ -162,441 +82,377 @@ function tosec($str) { } } -for ($i=1; $i<$argc; $i++) { - if ($argv[$i]=='-i' || $argv[$i]=='--inifp') { - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede di specificare un file di configurazione (usa «-h» per vedere la guida).'.N,1); - $i++; - $inifp=$argv[$i]; +function mexit($msg,$code,$closemy=false) { + global $link; + lecho($msg); + if ($closemy) + mysqli_close($link); + if ($logf) + fclose($logf); + exit($code); +} + +function lecho($msg,$logonly=false) { + global $opts, $logf; + if (!$logonly) + echo($msg); + if ($opts['log']) + fwrite($logf,$msg); +} + +$logfp='crawler.log'; +if ($opts['log']) { + $logf=@fopen(__DIR__.'/'.$logfp,'w') + or mexit('Non ho potuto aprire in scrittura il file di log «'.$logfp.'».',1); +} + +$inifp='../sec/mastostartadmin.ini'; +$iniarr=parse_ini_file($inifp) + or mexit('Impossibile aprire il file di configurazione «'.$inifp.'»'.N,1); +$link=mysqli_connect($iniarr['db_host'],$iniarr['db_admin_name'],$iniarr['db_admin_password'],$iniarr['db_name'],$iniarr['db_port'],$iniarr['db_socket']) + or mexit(mysqli_error($link).N,1); +mysqli_set_charset($link,'utf8'); + +$contextopts=array( + 'http'=>array( + 'timeout'=>$opts['timeout'] + ), + 'socket'=>array( + 'tcp_nodelay'=>true + ) +); +$context=stream_context_create($contextopts); + +$blacklist=array(); +lecho('Carico la blacklist dal database...'.N); +$res=mysqli_query($link,'SELECT * FROM Blacklist') + or mexit(mysqli_error($link).N,3,true); +lecho(mysqli_num_rows($res).' istanze nella blacklist.'.N); +while($row=mysqli_fetch_assoc($res)) { + $blacklist[$row['Domain']]=$row; +} + +function pgdatetomy($pgdate) { + if (preg_match('/^(\d+)-(\d+)-(\d+)[ T]{1}(\d+):(\d+):(\d+)\.(\d+)Z?$/',$pgdate,$buf)===1) { + return(mktime($buf[4],$buf[5],$buf[6],$buf[2],$buf[3],$buf[1])+floatval('0.'.$buf[7])); + } else { + return(false); } } -if (!is_null($inifp)) { - $buf=@parse_ini_file($inifp); +function blpgdumplinetomy($line) { + $truefalse=array('f'=>0,'t'=>1); + $row=explode("\t",$line); + $row=array('Domain'=>$row[0], + 'CreatedAt'=>pgdatetomy($row[1]), + 'ModifiedAt'=>pgdatetomy($row[2]), + 'Severity'=>$row[3], + 'RejectMedia'=>$truefalse[$row[4]], + 'RejectReports'=>$truefalse[$row[5]], + 'PublicComment'=>$row[6]); + return($row); +} + +$blacklistnew=array(); +$insts=array(); +lecho('Carico le istanze di partenza...'.N); +$res=mysqli_query($link,'SELECT Domain FROM StartNodes') + or mexit(mysqli_error($link).N,3,true); +lecho(mysqli_num_rows($res).' istanze di partenza.'.N); +while($row=mysqli_fetch_assoc($res)) { + $insts[$row['Domain']]=null; + lecho('Recupero la lista delle istanze note a «'.$row['Domain'].'» ... '); + $buf=@file_get_contents('https://'.$row['Domain'].'/api/v1/instance/peers',false,$context); if ($buf!==false) { - foreach ($buf as $key=>$val) { - if (array_key_exists($key,$opts)) { - if ($key=='excludeafter') { - $opts['excludeafter']=tosec($val); - if ($opts['excludeafter']===false) - mexit('L’opzione «excludeafter» specificata in «'.$inifp.'» non è in un formato corretto (usa «-h» per vedere la guida).'.N,1); - } elseif ($key=='blacklists') { - $opts['blacklists']=explode(',',$val); - } elseif ($key=='whitelists') { - $opts['whitelists']=explode(',',$val); - } else { - $opts[$key]=$val; - } - } else { - echo('Attenzione: l’opzione «'.$key.'» in «'.$inifp.'» è sconosciuta e sarà ignorata.'.N); + lecho('OK :-)'.N); + $peers=json_decode($buf,true); + foreach ($peers as $pdom) { + if (!array_key_exists($pdom,$insts) && strlen($pdom)<=64) { + $insts[$pdom]=null; } } } else { - mexit('Attenzione: non ho potuto leggere la configurazione dal file «'.$inifp.'».'.N,1); + lecho('ERRORE :-('.N); } -} - -for ($i=1; $i<$argc; $i++) { - if (substr($argv[$i],0,1)=='-') { - switch($argv[$i]) { - case '-i': - case '--inifp': - $i++; - break; - case '-e': - case '--excludeafter': - if ($i+1>=$argc) - $i++; - $opts['excludeafter']=tosec($argv[$i]); - if ($opts['excludeafter']===false) - mexit('Opzione «'.$argv[$i].'»: formato non corretto (usa «-h» per vedere la guida).'.N,1); - break; - case '-t': - case '--timeout': - if ($i+1>=$argc || preg_match('/^[0-9]+$/',$argv[$i+1])!==1) - mexit('L’opzione «'.$argv[$i].'» richiede un parametro numerico intero (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['timeout']=$argv[$i]; - break; - case '-b': - case '--biglistfp': - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['biglistfp']=$argv[$i]; - break; - case '-p': - case '--prodlistfp': - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['prodlistfp']=$argv[$i]; - break; - case '-s': - case '--startinstancesfp': - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['startinstancesfp']=$argv[$i]; - break; - case '-B': - case '--blacklistfp': - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['blacklists'][]=$argv[$i]; - break; - case '-w': - case '--whitelistfp': - if ($i+1>=$argc || $argv[$i+1]=='') - mexit('L’opzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['whitelists'][]=$argv[$i]; - break; - case '-l': - case '--loadbiglist': - if ($i+1>=$argc || ($argv[$i+1]!='si' && $argv[$i+1]!='no')) - mexit('L’opzione «'.$argv[$i].'» richiede un parametro («si/no») (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['loadbiglist']=true; - if ($argv[$i]=='no') $opts['loadbiglist']=false; - break; - case '-c': - case '--onlinecheck': - if ($i+1>=$argc || ($argv[$i+1]!='si' && $argv[$i+1]!='no')) - mexit('L’opzione «'.$argv[$i].'» richiede un parametro («si/no») (usa «-h» per vedere la guida).'.N,1); - $i++; - $opts['onlinecheck']=true; - if ($argv[$i]=='no') $opts['onlinecheck']=false; - break; - case '-h': - case '--help': - mexit($help,1); - break; - default: - mexit('Opzione «'.$argv[$i].'» sconosciuta (usa «-h» per vedere la guida).'.N,1); - break; - } - } else { - mexit('Opzione «'.$argv[$i].'» sconosciuta (usa «-h» per vedere la guida).'.N,1); - } -} - -$buf=null; -if (is_null($opts['startinstancesfp'])) - $buf.='- Non hai specificato il file delle istanze di partenza («-s/--startinstancesfp»)'.N; -if (is_null($opts['biglistfp'])) - $buf.='- Non hai specificato il file da cui leggere e in cui salvare i dati di tutte le istanze testate («-b/--biglistfp»)'.N; -if (is_null($opts['prodlistfp'])) - $buf.='- Non hai specificato il file da cui leggere e in cui salvare i dati di tutte le istanze testate che corrispondono ai criteri di selezione («-p/--prodlistfp»)'.N; -if (!is_null($buf)) - mexit('ERRORI'.N.$buf.'Usa «-h/--help» per leggere la guida.'.N,1); - -if (!$opts['onlinecheck']) - $opts['loadbiglist']=true; - -$biglist=array(); -$ibiglistc=0; -if ($opts['loadbiglist']) { - if (file_exists($opts['biglistfp']) && is_file($opts['biglistfp']) && is_readable($opts['biglistfp'])) { - echo('Carico la listona pre-esistente («'.$opts['biglistfp'].'») ... '); - $buf=@file_get_contents($opts['biglistfp']); - if ($buf!==false) { - echo('OK :-)'.N); - $biglist=json_decode($buf,true); - $ibiglistc=count($biglist); - } else { - echo('ERRORE :-('.N); - } - } -} - -$blinstances=array(); -$wlinstances=array(); - -function loadblacklist($bluri) { - global $blinstances, $opts; - $context=stream_context_create(array('http'=>array('timeout'=>$opts['timeout']))); - $f=@fopen($bluri,'r',false,$context); - if ($f!==false) { - $i=0; - while (!feof($f)) { - $lin=fgets($f); -//bsd.moe|2019-12-11 18:44:06.710862|1|https://mastodon.bida.im/@Ca_Gi/101270762003908554 - if (preg_match('/^([^#\|]{1}[^\|]+)\|{1}([^\|]+)\|{1}([012]{1})\|{1}(.*)$/',$lin,$buf)===1 && !in_array($buf[1],$blinstances) ) { - $i++; - $blinstances[]=$buf[1]; - } - } - fclose($f); - echo('OK :-) (+'.$i.' istanze bloccate caricate; totale: '.count($blinstances).')'.N); - } else { - mexit('ERRORE :-('.N,1); - } -} - -$startinstances=array(); -echo('Carico il file delle istanze di partenza («'.$opts['startinstancesfp'].'») ... '); -$buf=@file_get_contents($opts['startinstancesfp']); -if ($buf!==false) { - echo('OK :-)'.N); - $buf=explode(N,$buf); - foreach ($buf as $val) { - if ($val!='' && $val[0]!='#') { - $kv=explode('|',$val); - if ($kv[1]=='') $kv[1]=null; - $startinstances[$kv[0]]=$kv[1]; - } - } -} else { - mexit(N.'Non ho potuto caricare il file delle istanze di partenza «'.$opts['startinstancesfp'].'», muoio.'.N,1); -} -if (count($startinstances)<1) - mexit('Il file delle istanze di partenza «'.$opts['startinstancesfp'].'» non contiene alcuna voce, muoio.'.N,1); - -foreach ($startinstances as $dom=>$bluri) { - if (!is_null($bluri)) { - echo('Recupero la lista delle istanze bloccate da «'.$dom.'» («'.$bluri.'») ... '); - loadblacklist($bluri); - } else { - echo('NON recupero la lista delle istanze bloccate da «'.$dom.'»: la uri della stessa non è definita.'.N); - } -} -foreach ($opts['blacklists'] as $bluri) { - echo('Carico la lista delle istanze bloccate dall\'URI «'.$bluri.'» ... '); - loadblacklist($bluri); -} -sort($blinstances); -echo(count($blinstances).' istanze bloccate.'.N); - -foreach ($opts['whitelists'] as $wluri) { - echo('Carico la whitelist delle istanze dall\'URI «'.$wluri.'» ... '); - $buf=@file_get_contents($wluri); + lecho('Recupero la blacklist di «'.$row['Domain'].'» ... '); + $buf=@file_get_contents('https://'.$row['Domain'].'/domain_blocks.txt',false,$context); if ($buf!==false) { - echo('OK :-)'.N); + lecho('OK :-)'.N); $buf=explode(N,$buf); - foreach ($buf as $val) { - if ($val!='' && $val[0]!='#' && !in_array($val,$wlinstances)) - $wlinstances[]=$val; + foreach ($buf as $line) { + if (preg_match('/(^#.*$)|(^\s*$)/',$line)===0) { + $brow=blpgdumplinetomy($line); + if (!array_key_exists($brow['Domain'],$blacklist)) { + $blacklistnew[$brow['Domain']]=$brow; + } + $blacklist[$brow['Domain']]=$brow; + } } } else { - mexit(N.'Non ho potuto caricare la whitelist delle istanze «'.$wluri.'», muoio.'.N,1); + lecho('ERRORE :-('.N); } } -sort($wlinstances); -echo(count($wlinstances).' istanze whitelistate.'.N); +//lecho('Carico le istanze note dal DB e aggiungo alla lista di quelle da controllare quelle che non ci sono già.'.N); +$res=mysqli_query($link,'SELECT URI FROM Instances') + or mexit(mysqli_error($link).N,3,true); +while($row=mysqli_fetch_assoc($res)) { + if (!array_key_exists($row['URI'],$insts)) + $insts[$row['URI']]=null; +} +ksort($insts); +ksort($blacklist); +ksort($blacklistnew); +lecho('Istanze recuperate: '.count($insts).N); +lecho('Istanze blacklistate: '.count($blacklist).', di cui '.count($blacklistnew).' nuove da aggiungere al DB.'.N); -if ($opts['onlinecheck']) { +foreach ($blacklistnew as $row) { + foreach($row as $key=>$val) + $row[$key]=myesc($link,$val); + mysqli_query($link,'INSERT INTO Blacklist (ID, Domain, CreatedAt, ModifiedAt, Severity, RejectMedia, RejectReports, PrivateComment, PublicComment) VALUES (NULL, \''.$row['Domain'].'\', \''.$row['CreatedAt'].'\', \''.$row['ModifiedAt'].'\', \''.$row['Severity'].'\', \''.$row['RejectMedia'].'\', \''.$row['RejectReports'].'\', NULL, \''.$row['PublicComment'].'\')') + or mexit(mysqli_error($link).N,3,true); +} - $context=stream_context_create(array('http'=>array('timeout'=>$opts['timeout']))); +//INSERT INTO `Instances` (`ID`, `New`, `Chosen`, `Visible`, `BlackListed`, `URI`, `Title`, `ShortDesc`, `LongDesc`, `OurDesc`, `PlaceID`, `Email`, `Software`, `Version`, `UserCount`, `StatusCount`, `DomainCount`, `ActiveUsersMonth`, `ActiveUsersHalfYear`, `Thumb`, `RegOpen`, `RegReqApproval`, `MaxTootChars`, `AdmAccount`, `AdmDisplayName`, `AdmCreatedAt`, `AdmNote`, `AdmURL`, `AdmAvatar`, `AdmHeader`) VALUES (NULL, '1', '0', '0', '0', 'pantagruel.dnsup.net', 'Pantagruel', 'Descrizione breve', 'Descrizione lunga', 'Istanza molto carina senza soffitto, senza cucina', '1', 'Graume ', 'mastodon', '3.0.1', '2', '12', '345', '5', '10', 'http://www.iedm.it', '1', '0', '540', 'admin', 'Admin', '2019-12-11', 'Note \'admin\'', 'https://rame.altervista.org', 'http://www.iedm.it', 'http://www.iedm.it'); - foreach ($startinstances as $dom=>$bluri) { - if (!array_key_exists($dom,$biglist)) - $biglist[$dom]=null; - echo('Recupero la lista delle istanze note a «'.$dom.'» ... '); - $buf=@file_get_contents('https://'.$dom.'/api/v1/instance/peers',false,$context); - if ($buf!==false) { - echo('OK :-)'.N); - $peers=json_decode($buf,true); - foreach ($peers as $pdom) { - if (!array_key_exists($pdom,$biglist)) { - $biglist[$pdom]=null; - } - } - } else { - echo('ERRORE :-('.N); - } +function b2i($bool) { + if ($bool) + return(1); + else + return(0); +} + +//array key exists and value is not null +function akeavinn($key,&$arr) { + if (array_key_exists($key,$arr) && !is_null($arr[$key])) + return(true); + else + return(false); +} + +function nempty($str) { + if (preg_match('/^\s*$/',$str)===1) + return(null); + else + return($str); +} + +function subarim($glue,$key,&$arr) { + $str=''; + $i=1; + $carr=count($arr); + foreach ($arr as $inarr) { + $str.=$inarr[$key]; + if ($i<$carr) + $str.=$glue; + $i++; } - ksort($biglist); - $diff=count($biglist)-$ibiglistc; - if ($diff>=0) $diff='+'.$diff; - echo('Totale istanze note: '.count($biglist).' ('.$diff.' rispetto all\'ultima volta).'.N); + return($str); } -$prodlist=array(); -$iprodlistc=0; -$buf=@file_get_contents($opts['prodlistfp']); -if ($buf!==false) { - $prodlist=json_decode($buf,true); - $iprodlistc=count($prodlist); +function notify($msg,$sev) { + global $link; + mysqli_query($link,'INSERT INTO Notifications (ID, Notification, Severity, Microtime) VALUES (NULL, \''.myesc($link,$msg).'\', '.$sev.', '.microtime().')') + or mexit(mysqli_error($link).N,3,true); } -$newbiglist=array(); +/* + * Nodeinfo ('https://'.$dom.'/nodeinfo/2.0') è stato aggiunto nella 3.0.0 + * Trends ('https://'.$dom.'/api/v1/trends') è stato aggiunto nella 3.0.0 + * Activity ('https://'.$dom.'/api/v1/instance/activity') è stato aggiunto nella 2.1.2 +*/ + +if ($opts['jsonwrite']) { + $jsonf=@fopen(__DIR__.'/'.$opts['jsonfp'],'w') + or mexit('Non ho potuto aprire in scrittura il file di dump delle info json «'.$opts['jsonfp'].'».',1); + fwrite($jsonf,'{'.N); +} +$cinsts=count($insts); $i=0; -$biglistc=count($biglist); -foreach ($biglist as $dom=>$oinfo) { +$ok=0; +foreach ($insts as $dom=>$row) { $i++; - echo('~~~~~~'.N); - if ($opts['onlinecheck']) { - - echo('Recupero le informazioni su «'.$dom.'» ('.$i.'/'.$biglistc.' - '.round(100/$biglistc*$i).'%)'.N); - - echo('Recupero le informazioni Nodeinfo ... '); - $ninfo=null; - $buf=@file_get_contents('https://'.$dom.'/nodeinfo/2.0',false,$context); - if ($buf!==false) { - echo('OK :-)'.N); - $ninfo=json_decode($buf,true); - } else { - echo('ERRORE :-('.N); - } - - echo('Recupero le informazioni API sull\'attività dell\'istanza ... '); - $activity=null; - $buf=@file_get_contents('https://'.$dom.'/api/v1/instance/activity',false,$context); - if ($buf!==false) { - echo('OK :-)'.N); - $activity=json_decode($buf,true); - } else { - echo('ERRORE :-('.N); - } - - echo('Recupero le informazioni API sull\'istanza ... '); - $info=null; - $buf=@file_get_contents('https://'.$dom.'/api/v1/instance',false,$context); - if ($buf!==false) { - echo('OK :-)'.N); - $info=json_decode($buf,true); - if (!is_null($oinfo) && array_key_exists('X-Checks',$oinfo)) - $info['X-Checks']=$oinfo['X-Checks']; - $info['X-Checks'][]=array('time'=>time(),'ok'=>true); - if (!is_null($ninfo)) { - if (array_key_exists('usage',$ninfo) && array_key_exists('users',$ninfo['usage'])) { - if (array_key_exists('activeMonth',$ninfo['usage']['users'])) - $info['X-ActiveUsersPerMonth']=$ninfo['usage']['users']['activeMonth']; - if (array_key_exists('activeHalfyear',$ninfo['usage']['users'])) - $info['X-ActiveUsersPerHalfYear']=$ninfo['usage']['users']['activeHalfyear']; - } - if (array_key_exists('software',$ninfo)) { - if (array_key_exists('name',$ninfo['software'])) - $info['X-Software']=$ninfo['software']['name']; - if (array_key_exists('version',$ninfo['software'])) - $info['X-Version']=$ninfo['software']['version']; + $info=null; + lecho('~~~~~~~~~~~~~~~'.N); + lecho('Provo a recuperare info su «'.$dom.'» ['.$i.'/'.$cinsts.' ('.$ok.' OK) - '.round(100/$cinsts*$i).'%]'.N); + lecho('Provo a recuperare le informazioni API sull’istanza ... '); + $buf=@file_get_contents('https://'.$dom.'/api/v1/instance',false,$context); + if ($buf!==false) { + $ok++; + lecho('OK :-)'.N); + $info=json_decode($buf,true); + if (array_key_exists('version',$info)) { + if ($info['version']>='2.1.2') { + lecho('Provo a recuperare le informazioni API sull’attività dell’istanza ... '); + $buf=@file_get_contents('https://'.$dom.'/api/v1/instance/activity',false,$context); + if ($buf!==false) { + lecho('OK :-)'.N); + $info['x-activity']=json_decode($buf,true); + } else { + lecho('ERRORE :-('.N); } } - if (!is_null($activity)) - $info['X-Activity']=$activity; - $newbiglist[$dom]=$info; - } else { - echo('ERRORE :-( ... '); - $lastokk=null; - if (!is_null($oinfo) && array_key_exists('X-Checks',$oinfo)) { - foreach ($oinfo['X-Checks'] as $key=>$val) - if ($val['ok']) $lastokk=$key; + if ($info['version']>='3.0.0') { + lecho('Provo a recuperare le informazioni Nodeinfo sull’istanza ... '); + $buf=@file_get_contents('https://'.$dom.'/nodeinfo/2.0',false,$context); + if ($buf!==false) { + lecho('OK :-)'.N); + $info['x-nodeinfo']=json_decode($buf,true); + } else { + lecho('ERRORE :-('.N); + } + lecho('Provo a recuperare le informazioni API sui trends dell’istanza ... '); + $buf=@file_get_contents('https://'.$dom.'/api/v1/trends',false,$context); + if ($buf!==false) { + lecho('OK :-)'.N); + $info['x-trends']=json_decode($buf,true); + } else { + lecho('ERRORE :-('.N); + } } - if (is_null($oinfo) || is_null($lastokk) || time()-$oinfo['X-Checks'][$lastokk]['time']<=$opts['excludeafter']) { - echo('ma riproveremo...'.N); - $oinfo['X-Checks'][]=array('time'=>time(),'ok'=>false); - $newbiglist[$dom]=$oinfo; - } else { - echo('e non riproveremo...'.N); - $oinfo=null; - } - $info=$oinfo; } } else { - $info=$oinfo; + lecho('ERRORE :-('.N); } - $whynot=array(); - if (array_key_exists('uri',$info)) { - if (!in_array($dom,$wlinstances)) { - if (in_array($dom,$blinstances)) - $whynot[]='Istanza blacklistata'; - if (array_key_exists('X-Software',$info) && !in_array($info['X-Software'],array('mastodon','corgidon'))) - $whynot[]='Il software non è Mastodon (ma '.$info['X-Software'].')'; - if (!array_key_exists('registrations',$info)) - $whynot[]='Stato delle registrazioni non disponibile'; - elseif ($info['registrations']==false) - $whynot[]='Registrazioni chiuse'; - if (!array_key_exists('stats',$info)) { - $whynot[]='Stats non disponibili'; - } else { - if (!array_key_exists('user_count',$info['stats'])) - $whynot[]='Numero utenti non disponibile'; - elseif ($info['stats']['user_count']<10 || $info['stats']['user_count']>30000) - $whynot[]='Numero utenti ('.$info['stats']['user_count'].') non compreso tra 10 e 30000'; - if (!array_key_exists('domain_count',$info['stats'])) - $whynot[]='Numero istanze conosciute non disponibile'; - elseif ($info['stats']['domain_count']<500) - $whynot[]='Numero istanze conosciute minore di 500'; - /* if (!array_key_exists('status_count',$info['stats'])) - $whynot[]='Numero di toots non disponibile'; - elseif ($info['stats']['status_count']/$info['stats']['user_count']<10) - $whynot[]='Media dei toots per utente minore di 10';*/ + if (!is_null($info) && akeavinn('uri',$info) && !is_null(nempty($info['uri']))) { + lecho(json_encode($info,JSON_PRETTY_PRINT).N,true); + if ($opts['jsonwrite']) + fwrite($jsonf,'"'.$info['uri'].'": '.json_encode($info,JSON_PRETTY_PRINT).','.N); +//INSERT INTO `Instances` (`ID`, `New`, `Chosen`, `Visible`, `BlackListed`, `URI`, `Title`, `ShortDesc`, `LongDesc`, `OurDesc`, `PlaceID`, `Email`, `Software`, `Version`, `UserCount`, `StatusCount`, `DomainCount`, `ActiveUsersMonth`, `ActiveUsersHalfYear`, `Thumb`, `RegOpen`, `RegReqApproval`, `MaxTootChars`, `AdmAccount`, `AdmDisplayName`, `AdmCreatedAt`, `AdmNote`, `AdmURL`, `AdmAvatar`, `AdmHeader`) VALUES (NULL, '1', '0', '0', '0', 'pantagruel.dnsup.net', 'Pantagruel', 'Descrizione breve', 'Descrizione lunga', 'Istanza molto carina senza soffitto, senza cucina', '1', 'Graume ', 'mastodon', '3.0.1', '2', '12', '345', '5', '10', 'http://www.iedm.it', '1', '0', '540', 'admin', 'Admin', '2019-12-11', 'Note \'admin\'', 'https://rame.altervista.org', 'http://www.iedm.it', 'http://www.iedm.it'); + $instrow=array('ID'=>null, 'New'=>0, 'Chosen'=>0, 'Visible'=>0, 'BlackListed'=>0, 'URI'=>null, 'Title'=>null, 'ShortDesc'=>null, 'LongDesc'=>null, 'OurDesc'=>null, 'PlaceID'=>null, 'Email'=>null, 'Software'=>null, 'Version'=>null, 'UserCount'=>null, 'StatusCount'=>null, 'DomainCount'=>null, 'ActiveUsersMonth'=>null, 'ActiveUsersHalfYear'=>null, 'Thumb'=>null, 'RegOpen'=>null, 'RegReqApproval'=>null, 'MaxTootChars'=>null, 'AdmAccount'=>null, 'AdmDisplayName'=>null, 'AdmCreatedAt'=>null, 'AdmNote'=>null, 'AdmURL'=>null, 'AdmAvatar'=>null, 'AdmHeader'=>null); + if (array_key_exists($info['uri'],$blacklist)) + $instrow['BlackListed']=1; + $instrow['URI']=nempty($info['uri']); + if (akeavinn('title',$info)) + $instrow['Title']=nempty($info['title']); + if (akeavinn('short_description',$info)) + $instrow['ShortDesc']=nempty($info['short_description']); + if (akeavinn('description',$info)) + $instrow['LongDesc']=nempty($info['description']); + if (akeavinn('email',$info)) + $instrow['Email']=nempty($info['email']); + if (akeavinn('version',$info)) + $instrow['Version']=nempty($info['version']); + if (akeavinn('stats',$info)) { + if (akeavinn('user_count',$info['stats'])) + $instrow['UserCount']=$info['stats']['user_count']; + if (akeavinn('status_count',$info['stats'])) + $instrow['StatusCount']=$info['stats']['status_count']; + if (akeavinn('domain_count',$info['stats'])) + $instrow['DomainCount']=$info['stats']['domain_count']; + } + if (akeavinn('thumbnail',$info)) + $instrow['Thumb']=nempty($info['thumbnail']); + if (akeavinn('max_toot_chars',$info)) + $instrow['MaxTootChars']=$info['max_toot_chars']; + if (akeavinn('registrations',$info)) + $instrow['RegOpen']=b2i($info['registrations']); + if (akeavinn('approval_required',$info)) + $instrow['RegReqApproval']=b2i($info['approval_required']); + if (akeavinn('contact_account',$info)) { + if (akeavinn('acct',$info['contact_account'])) + $instrow['AdmAccount']=nempty($info['contact_account']['acct']); + if (akeavinn('display_name',$info['contact_account'])) + $instrow['AdmDisplayName']=nempty($info['contact_account']['display_name']); + if (akeavinn('created_at',$info['contact_account'])) + $instrow['AdmCreatedAt']=pgdatetomy($info['contact_account']['created_at']); + if (akeavinn('note',$info['contact_account'])) + $instrow['AdmNote']=nempty(strip_tags($info['contact_account']['note'],'')); + if (akeavinn('url',$info['contact_account'])) + $instrow['AdmURL']=nempty($info['contact_account']['url']); + if (akeavinn('avatar',$info['contact_account'])) + $instrow['AdmAvatar']=nempty($info['contact_account']['avatar']); + if (akeavinn('header',$info['contact_account'])) + $instrow['AdmHeader']=nempty($info['contact_account']['header']); + } + if (akeavinn('x-nodeinfo',$info)) { + if (akeavinn('software',$info['x-nodeinfo']) && akeavinn('name',$info['x-nodeinfo']['software'])) + $instrow['Software']=nempty($info['x-nodeinfo']['software']['name']); + if (akeavinn('usage',$info['x-nodeinfo']) && akeavinn('users',$info['x-nodeinfo']['usage'])) { + if (akeavinn('activeMonth',$info['x-nodeinfo']['usage']['users'])) + $instrow['ActiveUsersMonth']=$info['x-nodeinfo']['usage']['users']['activeMonth']; + if (akeavinn('activeHalfyear',$info['x-nodeinfo']['usage']['users'])) + $instrow['ActiveUsersHalfYear']=$info['x-nodeinfo']['usage']['users']['activeHalfyear']; } - if (array_key_exists('X-ActiveUsersPerMonth',$info)) { - if ($info['X-ActiveUsersPerMonth']<10) - $whynot[]='Numero utenti attivi nell\'ultimo mese minore di 10'; - } elseif (array_key_exists('stats',$info) && array_key_exists('status_count',$info['stats']) && array_key_exists('user_count',$info['stats']) && $info['stats']['user_count']>0 && $info['stats']['status_count']/$info['stats']['user_count']<10) { - $whynot[]='Media dei toots per utente minore di 10'; + } + $res=mysqli_query($link,'SELECT * FROM Instances WHERE URI=\''.myesc($link,$instrow['URI']).'\'') + or mexit(mysqli_error($link).N,3,true); + if (mysqli_num_rows($res)>0) { + lecho('«'.$instrow['URI'].'» è già presente nel DB, la aggiorno...'.N); + $oldinstrow=mysqli_fetch_assoc($res); + $query='UPDATE Instances SET '; + foreach ($instrow as $field=>$value) { + if (!is_null($value)) + $query.=$field.'=\''.myesc($link,$value).'\', '; + else + $query.=$field.'=\'NULL\', '; } - if (!array_key_exists('contact_account',$info) || is_null($info['contact_account'])) { - $whynot[]='Informazioni sull\'account admin principale non disponibili'; - }/* else { - if (!array_key_exists('created_at',$info['contact_account'])) - $whynot[]='Data di creazione dell\'account admin principale non disponibile'; - elseif (time()-strtotime($info['contact_account']['created_at'])<6*31*24*60*60) - $whynot[]='L\'account admin principale risulta esser stato creato meno di 6 mesi fa'; + $query=substr($query,0,-2).' WHERE Instances.ID='.$oldinstrow['ID']; + echo('QUERONA DI UPDATE: «'.$query.'».'.N); +/* $res=mysql_query($link,'SELECT InstID, LangID, Pos, Code FROM InstLangs LEFT JOIN Languages ON Languages.ID=LangID WHERE InstID='.$oldinstrow['ID'].' ORDER BY Pos ASC') + or mexit(mysqli_error($link).N,3,true); + $oldinstlangs=array(); + while ($row=mysql_fetch_assoc($res)) + $oldinstlangs[]=$row; + if (akeavinn('languages',$info)) { + $instlangs=array(); + $pos=0; + foreach ($info['languages'] as $lang) { + $res=mysqli_query($link,'SELECT * FROM Languages WHERE Code=\''.myesc($link,$lang).'\'') + or mexit(mysqli_error($link).N,3,true); + if (mysqli_num_rows($res)<1) { + mysqli_query($link,'INSERT INTO Languages (ID, Code, Name) VALUES (NULL, \''.myesc($link,$lang).'\', NULL)') + or mexit(mysqli_error($link).N,3,true); + $langid=mysqli_insert_id($link); + notify('L’aggiornamento dei dati relativi all’istanza «'.$info['URI'].'» ha aggiunto un codice lingua non ancora noto, «'.$lang.'», di cui non conosco il nome per esteso. Puoi editarlo qui.',1); + } else { + $row=mysqli_fetch_assoc($res); + $langid=$row['ID']; + } + $pos++; + $instlangs[]=array('InstID'=>$oldinstrow['ID'],'LangID'=>$langid,'Pos'=>$pos,'Code'=>$lang); + } + print_r($instlangs); + print_r($oldinstlangs); + if ($instlangs!=$oldinstlangs) { + notify('La lista delle lingue utilizzate dichiarate dall’istanza «'.$info['URI'].'» è cambiata da «'.subarim(', ','Code',$oldinstlangs).'» a «'.subarim(', ','Code',$oldinstlangs).'».',1); + mysqli_query($link,'DELETE FROM InstLangs WHERE InstID='.$oldinstrow['ID']) + or mexit(mysqli_error($link).N,3,true); + foreach ($instlangs as $row) { + mysqli_query($link,'INSERT INTO InstLangs (InstID, LangID, Pos) VALUES ('.$row['InstID'].', '.$row['LangID'].', '.$row['Pos'].')') + or mexit(mysqli_error($link).N,3,true); + } + } }*/ } else { - echo('«'.$dom.'» è whitelistata, la teniamo a prescindere.'.N); - } - } elseif (!array_key_exists($dom,$prodlist)) { - $whynot[]='Info non disponibili, e l\'istanza non era già presente nella lista delle istanze occhei'; - } - if (count($whynot)==0) { - if (array_key_exists($dom,$prodlist)) { - if (array_key_exists('short_description',$info) && (!array_key_exists('short_description',$prodlist[$dom]) || $prodlist[$dom]['short_description']!=$info['short_description'])) { - $info['X-ShortDescriptionChanged']=true; - $info['X-PrevShortDescription']=$prodlist[$dom]['short_description']; - } else { - $info['X-ShortDescriptionChanged']=false; + lecho('«'.$info['uri'].'» non è già presente nel DB, la aggiungo...'.N); + $instrow['New']=1; + $fields=array(); + $values=''; + foreach ($instrow as $field=>$value) { + $fields[]=$field; + if (!is_null($value)) + $values.='\''.myesc($link,$value).'\', '; + else + $values.='NULL, '; } - if (array_key_exists('description',$info) && (!array_key_exists('description',$prodlist[$dom]) || $prodlist[$dom]['description']!=$info['description'])) { - $info['X-DescriptionChanged']=true; - $info['X-PrevDescription']=$prodlist[$dom]['description']; - } else { - $info['X-DescriptionChanged']=false; - } - echo('«'.$dom.'» era nella lista delle istanze occhei ed è stata AGGIORNATA! :-)'.N); - if (array_key_exists('X-Show',$prodlist[$dom])) - $info['X-Show']=$prodlist[$dom]['X-Show']; - else - $info['X-Show']=-1; - } else { - $info['X-ShortDescriptionChanged']=false; - $info['X-DescriptionChanged']=false; - $info['X-Show']=-1; - echo('«'.$dom.'» non era nella lista delle istanze occhei ed è stata AGGIUNTA! :-)'.N); + $values=substr($values,0,-2); + $query='INSERT INTO Instances ('.implode(', ',$fields).') VALUES ('.$values.')'; + echo('QUERONA DI INSERT: «'.$query.'»'.N); } - $prodlist[$dom]=$info; - } else { - if (array_key_exists($dom,$prodlist)) { - unset($prodlist[$dom]); - echo('«'.$dom.'» era nella lista delle istanze occhei ma è stata SCARTATA! :-('.N); - } else { - echo('«'.$dom.'» non era nella lista delle istanze occhei e NON CI È ENTRATA! :-('.N); - } - echo('Motivazioni: '.implode('; ',$whynot).'.'.N); +// var_dump($instrow); } } -echo('~~~~~~'.N); +mysqli_close($link); -if ($opts['onlinecheck']) { - $json=json_encode($newbiglist,JSON_PRETTY_PRINT); - file_put_contents($opts['biglistfp'],$json); - $newbiglistc=count($newbiglist); - $diff=$newbiglistc-$ibiglistc; - if ($diff>=0) $diff='+'.$diff; - echo('Totale istanze nella listona: '.$newbiglistc.' ('.$diff.' rispetto all\'ultima volta)'.N); -} else { - echo('Totale istanze nella listona: '.count($biglist).N); +if ($opts['jsonwrite']) { + fwrite($jsonf,'"Fine?": true'.N.'}'.N); + fclose($jsonf); } -$json=json_encode($prodlist,JSON_PRETTY_PRINT); -file_put_contents($opts['prodlistfp'],$json); -$diff=count($prodlist)-$iprodlistc; -if ($diff>=0) $diff='+'.$diff; -echo('Totale istanze nella listina di quelle occhei: '.count($prodlist).' ('.$diff.' rispetto all\'ultima volta)'.N); + +if ($opts['log']) + fclose($logf); + +exit(0); ?> diff --git a/web/admin/crawler/crawler_pant.ini b/web/admin/crawler/crawler_pant.ini deleted file mode 100644 index 190070f..0000000 --- a/web/admin/crawler/crawler_pant.ini +++ /dev/null @@ -1,9 +0,0 @@ -excludeafter=1M -startinstancesfp=istanzesorelle_pant -loadbiglist=true -onlinecheck=true -timeout=5 -biglistfp=biglist_pant.json -prodlistfp=prodlist_pant.json -blacklists=blacklist_cagi.txt -whitelists=whitelist_sorellanza.txt diff --git a/web/admin/crawler/crawler_sorellanza.ini b/web/admin/crawler/crawler_sorellanza.ini deleted file mode 100644 index 9d82098..0000000 --- a/web/admin/crawler/crawler_sorellanza.ini +++ /dev/null @@ -1,9 +0,0 @@ -excludeafter=1M -startinstancesfp=istanzesorelle -loadbiglist=true -onlinecheck=true -timeout=3 -biglistfp=biglist.json -prodlistfp=prodlist.json -blacklists=blacklist_cagi.txt -whitelists=whitelist_sorellanza.txt diff --git a/web/admin/crawler/istanzesorelle b/web/admin/crawler/istanzesorelle deleted file mode 100644 index 06acaac..0000000 --- a/web/admin/crawler/istanzesorelle +++ /dev/null @@ -1,5 +0,0 @@ -mastodon.bida.im|blacklist_bida.txt -mastodon.cisti.org| -nebbia.fail| -stereodon.social| -snapj.saja.freemyip.com| diff --git a/web/admin/crawler/istanzesorelle_pant b/web/admin/crawler/istanzesorelle_pant deleted file mode 100644 index 8b56c12..0000000 --- a/web/admin/crawler/istanzesorelle_pant +++ /dev/null @@ -1 +0,0 @@ -pantagruel.dnsup.net|blacklist_bida.txt diff --git a/web/admin/favicon.ico b/web/admin/favicon.ico new file mode 100644 index 0000000..c03b1b9 Binary files /dev/null and b/web/admin/favicon.ico differ diff --git a/web/admin/imgs/icona-180.png b/web/admin/imgs/icona-180.png new file mode 100644 index 0000000..b4b0ed6 Binary files /dev/null and b/web/admin/imgs/icona-180.png differ diff --git a/web/admin/imgs/icona-192.png b/web/admin/imgs/icona-192.png new file mode 100644 index 0000000..a654000 Binary files /dev/null and b/web/admin/imgs/icona-192.png differ diff --git a/web/admin/imgs/icona-32.png b/web/admin/imgs/icona-32.png new file mode 100644 index 0000000..b9b903e Binary files /dev/null and b/web/admin/imgs/icona-32.png differ diff --git a/web/admin/imgs/icona-512.png b/web/admin/imgs/icona-512.png new file mode 100644 index 0000000..9ad6300 Binary files /dev/null and b/web/admin/imgs/icona-512.png differ diff --git a/web/admin/include/connuser.php b/web/admin/include/connuser.php new file mode 100644 index 0000000..553b365 --- /dev/null +++ b/web/admin/include/connuser.php @@ -0,0 +1,10 @@ +Login.',true); +$user=mysqli_fetch_assoc($res); + +?> diff --git a/web/admin/include/glob.php b/web/admin/include/glob.php new file mode 100644 index 0000000..af9f50c --- /dev/null +++ b/web/admin/include/glob.php @@ -0,0 +1,10 @@ + diff --git a/web/admin/include/menu.php b/web/admin/include/menu.php new file mode 100644 index 0000000..c6927a5 --- /dev/null +++ b/web/admin/include/menu.php @@ -0,0 +1,52 @@ +array('liadd'=>null, 'href'=>'istanze.php', 'title'=>'Istanze', 'selected'=>false, 'submenu'=> + array( + 'aggiungi'=>array('liadd'=>'onclick="golang(\'en\')" onmouseover="this.style.cursor=\'pointer\'"', 'href'=>null, 'title'=>'English', 'selected'=>false, 'submenu'=>null), + 'italiano'=>array('liadd'=>'onclick="golang(\'it\')" onmouseover="this.style.cursor=\'pointer\'"', 'href'=>null, 'title'=>'Italiano', 'selected'=>false, 'submenu'=>null) + ) + ), + 'boh'=>array('liadd'=>null, 'href'=>'#', 'title'=>'Non saprei', 'selected'=>false, 'submenu'=>null), + 'vedremo'=>array('liadd'=>null, 'href'=>'#', 'title'=>'Vedremo', 'selected'=>false, 'submenu'=>null), + 'forse'=>array('liadd'=>null, 'href'=>'#', 'title'=>'Forse', 'selected'=>false, 'submenu'=>null) +); + + +/* +
  • Guide
  • +
  • Instances
  • +
  • About us
  • +
  • Language + +
  • +*/ + +$menuout=''; + +function buildmenu($menu) { + global $menuout; + foreach ($menu as $key=>$arr) { + $menuout.=''.$arr['title'].''; + else + $menuout.=$arr['title']; + if (!is_null($arr['submenu'])) { +// qui bisognerebbe aggiungere che a seconda del "livello" imposta class giusta: ula, oppure ulb per livello > 1 + $menuout.=N.'
      '.N; + buildmenu($arr['submenu']); + $menuout.='
    '.N; + } + $menuout.=''.N; + } +} + +?> diff --git a/web/admin/include/muoribene.php b/web/admin/include/muoribene.php new file mode 100644 index 0000000..20927a8 --- /dev/null +++ b/web/admin/include/muoribene.php @@ -0,0 +1,31 @@ + + + +Mastodon Startpage Admin - Errori + + + + + + + + + + +
    +
    +

    '.$msg.'

    +
    +
    + + +'); + exit(1); +} + +?> diff --git a/web/admin/include/myconn.php b/web/admin/include/myconn.php new file mode 100644 index 0000000..945b5cd --- /dev/null +++ b/web/admin/include/myconn.php @@ -0,0 +1,9 @@ +'.$btl,false); +$link=mysqli_connect($iniarr['db_host'],$iniarr['db_admin_name'],$iniarr['db_admin_password'],$iniarr['db_name'],$iniarr['db_port'],$iniarr['db_socket']) + or muoribene('Impossibile connettersi al database: '.mysqli_connect_error().' ['.mysqli_connect_errno().']',false); +mysqli_set_charset($link,'utf8'); + +?> diff --git a/web/admin/include/sessionstart.php b/web/admin/include/sessionstart.php new file mode 100644 index 0000000..fa820ca --- /dev/null +++ b/web/admin/include/sessionstart.php @@ -0,0 +1,12 @@ +Torna alla pagina di accesso.',false); +} + +?> diff --git a/web/admin/index.php b/web/admin/index.php new file mode 100644 index 0000000..2c229ff --- /dev/null +++ b/web/admin/index.php @@ -0,0 +1,59 @@ + + + + +Mastodon Startpage Admin Login + + + + + + + + + + + + +
    +
    +
    +Mastodon Startpage Admin Login +
    +
    +
    + + + + + +
    Nome:
    Password:
    Password dimenticata?
    +
    +
    +
    +
    + + + diff --git a/web/admin/instances.php b/web/admin/instances.php new file mode 100644 index 0000000..033802e --- /dev/null +++ b/web/admin/instances.php @@ -0,0 +1,90 @@ +'.$btl,false); +mysqli_close($link); +if (mysqli_num_rows($res)<1) { + $out='

    Nessuna istanza da mostrare.

    '.N; +} else { + $out=''.N; + while ($row=mysqli_fetch_assoc($res)) { + $out.=''.N; + } + $out.='
    '.$row['URI'].'
    '.N; +} + + +?> + + + +Mastodon Startpage Admin - Main Menu + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + diff --git a/web/admin/js/alerta.js b/web/admin/js/alerta.js new file mode 100644 index 0000000..b0bc995 --- /dev/null +++ b/web/admin/js/alerta.js @@ -0,0 +1,4 @@ +function alerta(msg) { + document.getElementById('popupcont').innerHTML='

    Attenzione

    '+msg+''; + document.getElementById('popup').style.display='table'; +} diff --git a/web/admin/login.php b/web/admin/login.php new file mode 100644 index 0000000..7c7df0b --- /dev/null +++ b/web/admin/login.php @@ -0,0 +1,36 @@ +Torna al login'; + +$errs=''; + +if (!array_key_exists('username',$_POST) || $_POST['username']=='') + $errs.='Non hai specificato il nome
    '.N; +if (!array_key_exists('password',$_POST) || $_POST['password']=='') + $errs.='Non hai specificato la password
    '.N; +if ($errs!='') muoribene($errs.$btl,false); + +$iniarr=parse_ini_file('sec/mastostartadmin.ini') + or muoribene('Impossibile aprire il file di configurazione.
    '.$btl,false); +$link=mysqli_connect($iniarr['db_host'],$iniarr['db_admin_name'],$iniarr['db_admin_password'],$iniarr['db_name'],$iniarr['db_port'],$iniarr['db_socket']) + or muoribene('Impossibile connettersi al database: '.mysqli_connect_error().' ['.mysqli_connect_errno().']',false); +mysqli_set_charset($link,'utf8'); +$res=mysqli_query($link,'SELECT * FROM Admins WHERE Username=\''.mysqli_real_escape_string($link,$_POST['username']).'\'') + or muoribene(mysqli_error($link).'
    '.$btl,true); +mysqli_close($link); +if (mysqli_num_rows($res)>1) + muoribene('Record admin duplicato.
    '.$btl,false); +$row=mysqli_fetch_assoc($res); +if (mysqli_num_rows($res)<1 || !password_verify($_POST['password'],$row['Password'])) + muoribene('Nome admin e/o password sbagliati.
    '.$btl,false); + +session_name('mastostartadmin'); +session_start(); +$_SESSION['id']=$row['ID']; + +header('Location: instances.php'); + +?> diff --git a/web/admin/sec/.htaccess b/web/admin/sec/.htaccess new file mode 100644 index 0000000..93169e4 --- /dev/null +++ b/web/admin/sec/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all diff --git a/web/admin/sec/mastostartadmin.ini b/web/admin/sec/mastostartadmin.ini new file mode 100644 index 0000000..b634513 --- /dev/null +++ b/web/admin/sec/mastostartadmin.ini @@ -0,0 +1,6 @@ +db_host=localhost +db_port=3306 +db_socket=/run/mysqld/mysqld.sock +db_name=mastostart +db_admin_name=MastoStartAdmin +db_admin_password=MastoStartAdmin diff --git a/web/admin/theme.css b/web/admin/theme.css new file mode 100644 index 0000000..3aa981d --- /dev/null +++ b/web/admin/theme.css @@ -0,0 +1,213 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} +html { + scroll-behavior: smooth; + height: 100% +} +body { + background-color: white; + color: black; + font-family: Arial, Helvetica, Sans-Serif, sans; + font-size: 14pt; + margin: 0; + padding: 5px; + height: 100% +} +h1,h2,h3,h4,h5,h6 { + text-align: center; +} +a { + text-decoration: none; + color: red; +} +a:hover { + text-decoration: underline; +} +ul { + list-style-type: disc; + padding-left: 0; + margin-left: 14pt; +} +#fullscreen, #fullscreenm { + width: 100%; + height: 100%; + display: table; +} +#fullscreenm { + padding-top: 40px; +} +#middlerow { + display: table-cell; + vertical-align: middle; + text-align: center; +} +#centertit, #centerbox { + font-size: 12pt; + margin-right: auto; + margin-left: auto; + width: 320px; + padding: 5px; +} +#centertit { + font-size: 13pt; + padding: 8px; + background-color: #916f6f; + color: white; + text-shadow: 1px 1px 2px black; + font-weight: bold; + text-align: center; + border-radius: 9px 9px 0 0; +} +#centerbox { + background-color: lightgrey; + border-radius: 0 0 9px 9px; +} +#logintable { + width: 100%; +} +#logintable td { + text-align: right; + width: 1%; +} +#logintable .rtd { + text-align: left; + width: 99%; +} +#logintable .tiptd { + font-size: 10pt; + text-align: center; + width: 100%; + padding-top:10px; + padding-bottom: 10px; +} +input { + width: 100%; + font-size: 11pt; + padding-top: 2px; + padding-bottom: 2px; +} +.button { + font-size: 11pt; + height: 40px; +} +#popup { + z-index: 1; + display: none; + top: 0px; + position: fixed; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.75); + color: white; + padding: 0; + font-size: 12pt; +} +#inpopup { + display: table-cell; + vertical-align: middle; +} +#popupcont { + position: relative; + margin-left: auto; + margin-right: auto; + border: 1px solid gray; + width: 200px; + background-color: white; + border-radius: 9px; + color: black; + padding: 5px; + text-align: left; +} +#footer { + color: white; + position: fixed; + height: 40px; + width: 100%; + bottom: 0; + left: 0; + background-color: rgba(0,0,0,0.85); + line-height: 40px; + vertical-align: middle; +} + + +#hmenu { + font-size: 14pt; + background-color: rgba(0,0,0,0.85); + color: white; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 40px; + margin: 0; + padding: 0; + /*box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4);*/ + /*padding-left: 40px;*/ + z-index: 2; + /*display: none;*/ +} +#hmenu ul { + list-style-type: none; + margin: 0; + padding: 0; + overflow: visible; +} +#hmenu ul li { + width: 80pt; + height: 40px; + text-align: center; + display: table-cell; + vertical-align: middle; + color: #3088D4; +} +#hmenu ul li:hover { + background-color: rgba(255,255,255,0.10); + cursor: default; +} +#hmenu ul li a { + width: 80pt; + line-height: 40px; + display: block; + color: #3088D4; +} +#hmenu .ula { + position: absolute; + top: 40px; + background-color: rgba(0,0,0,0.85); + display: none; +} +#hmenu .ulb { + background-color: rgba(0,0,0,0.85); + left: 80pt; + position: relative; + top: -40px; + display: none; +} +#hmenu .ula li, .ulb li { + width: 80pt; + height: 40px; + display: block; + float: none; + text-align: center; + line-height: 40px; + vertical-align: middle; +} +#hmenu .ula li:hover, .ulb li:hover { + text-decoration: underline; +} +#hmenu .hil { + background-color: rgba(255,255,255,0.10); + color: #97C3E9; +} +#hmenu .hil:hover { + cursor: default; + text-decoration: none; +} +#hmenu .ula li.hil:hover, .ulb li.hil:hover { + text-decoration: none; +} + diff --git a/web/favicon.ico b/web/favicon.ico index 79000c9..f4ac4da 100644 Binary files a/web/favicon.ico and b/web/favicon.ico differ diff --git a/web/imgs/ClosedPadlock.png b/web/imgs/ClosedPadlock.png index 255738b..7eb4fc3 100644 Binary files a/web/imgs/ClosedPadlock.png and b/web/imgs/ClosedPadlock.png differ diff --git a/web/imgs/Earth.png b/web/imgs/Earth.png index 041722b..ac34dc6 100644 Binary files a/web/imgs/Earth.png and b/web/imgs/Earth.png differ diff --git a/web/imgs/OpenPadlock.png b/web/imgs/OpenPadlock.png index d3291aa..12603fc 100644 Binary files a/web/imgs/OpenPadlock.png and b/web/imgs/OpenPadlock.png differ diff --git a/web/imgs/TrendingHashtags.png b/web/imgs/TrendingHashtags.png index d7bc99e..e16900e 100644 Binary files a/web/imgs/TrendingHashtags.png and b/web/imgs/TrendingHashtags.png differ diff --git a/web/imgs/icona-180.png b/web/imgs/icona-180.png new file mode 100644 index 0000000..e277cd2 Binary files /dev/null and b/web/imgs/icona-180.png differ diff --git a/web/imgs/icona-192.png b/web/imgs/icona-192.png new file mode 100644 index 0000000..bf98cd1 Binary files /dev/null and b/web/imgs/icona-192.png differ diff --git a/web/imgs/icona-32.png b/web/imgs/icona-32.png new file mode 100644 index 0000000..11680a1 Binary files /dev/null and b/web/imgs/icona-32.png differ diff --git a/web/imgs/icona-512.png b/web/imgs/icona-512.png new file mode 100644 index 0000000..ee1f239 Binary files /dev/null and b/web/imgs/icona-512.png differ diff --git a/web/index.php b/web/index.php index 53e7d06..c3a3763 100644 --- a/web/index.php +++ b/web/index.php @@ -1,6 +1,6 @@ array('liadd'=>null, 'href'=>$instpath, 'title'=>'Guide', 'selected'=>false, 'submenu'=>null), + 'guide'=>array('liadd'=>null, 'href'=>$instpath.'/', 'title'=>'Guide', 'selected'=>false, 'submenu'=>null), 'instances'=>array('liadd'=>null, 'href'=>$instpath.'/instances', 'title'=>'Instances', 'selected'=>false, 'submenu'=>null), 'about'=>array('liadd'=>null, 'href'=>$instpath.'/about', 'title'=>'About', 'selected'=>false, 'submenu'=>null), 'language'=>array('liadd'=>null, 'href'=>null, 'title'=>'Language', 'selected'=>false, 'submenu'=>array( @@ -25,7 +25,7 @@ function tradmenu($lang) { switch ($lang) { case 'it': $menu['guide']['title']='Guida'; - $menu['guide']['href'].='/it'; + $menu['guide']['href'].='it'; $menu['instances']['title']='Istanze'; $menu['instances']['href'].='/it'; $menu['about']['title']='Info'; @@ -42,6 +42,7 @@ switch($path) { 'fp'=>'home_en.php', 'lang'=>'en', 'atit'=>' - Guide', + 'desc'=>'A thorough introduction to Mastodon', 'js'=>array('shsum','guideanchors','scrolltrack') ); $menu['guide']['liadd']='onclick="shsum()" onmouseover="this.style.cursor=\'pointer\'; this.style.textDecoration=\'underline\'" onmouseout="this.style.textDecoration=\'none\'"'; @@ -56,6 +57,7 @@ switch($path) { 'fp'=>'home_it.php', 'lang'=>'it', 'atit'=>' - Guida', + 'desc'=>'Una approfondita introduzione a Mastodon', 'js'=>array('shsum','guideanchors','scrolltrack') ); tradmenu('it'); @@ -71,6 +73,7 @@ switch($path) { 'fp'=>'instances_en.php', 'lang'=>'en', 'atit'=>' - Instances', + 'desc'=>'Recommended Mastodon Instances', 'js'=>array() ); $menu['instances']['href']=null; @@ -84,6 +87,7 @@ switch($path) { 'fp'=>'instances_it.php', 'lang'=>'it', 'atit'=>' - Istanze', + 'desc'=>'Istanze Mastodon consigliate', 'js'=>array() ); tradmenu('it'); @@ -98,6 +102,7 @@ switch($path) { 'fp'=>'about_en.php', 'lang'=>'en', 'atit'=>' - About us', + 'desc'=>'Infos about Mastodon Startpage’s authors, contributors, license', 'js'=>array() ); $menu['about']['href']=null; @@ -111,6 +116,7 @@ switch($path) { 'fp'=>'about_it.php', 'lang'=>'it', 'atit'=>' - Info', + 'desc'=>'Informazioni sugli autori, i collaboratori e la licenza di Mastodon Startpage', 'js'=>array() ); tradmenu('it'); @@ -125,6 +131,7 @@ switch($path) { 'fp'=>'404.php', 'lang'=>'en', 'atit'=>' - 404', + 'desc'=>'Page not found', 'js'=>array() ); break; @@ -178,9 +185,12 @@ $cjrand=rand(0,999999); Mastodon Startpage<?php echo($cont['atit']); ?> - + - + + + +