Merge branch 'dev' into dev

This commit is contained in:
mjfriaza 2020-09-03 19:36:05 +02:00
commit a86f312c2f
43 changed files with 1083 additions and 628 deletions

View file

@ -65,7 +65,7 @@ Switch the verification on/off (1/0)
## What the script will do for you...
+ install everything required by your Zot hub/instance, basically a web server (Apache), PHP, a database (MySQL), certbot,...
+ install everything required by your Zot hub/instance, basically a web server (Apache or Nginx), PHP, a database (MySQL), certbot,...
+ create a database
+ run certbot to have everything for a secure connection (httpS)
+ create a script for daily maintenance
@ -142,5 +142,5 @@ DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
## Reminder for Different Web Wervers
For those of you who feel adventurous enough to use a different web server (Nginx, Lighttpd...), don't forget that this script will install Apache and that you can only have one web server listening to ports 80 & 443. Also, don't forget to tweak your daily shell script in /var/www/ accordingly.
For those of you who feel adventurous enough to use a different web server (i.e. Lighttpd...), don't forget that this script will install Apache or Nginx and that you can only have one web server listening to ports 80 & 443. Also, don't forget to tweak your daily shell script in /var/www/ accordingly.

View file

@ -0,0 +1,144 @@
##
# Hubzilla/Zap/Mistpark/Osada Nginx block configuration template
# based on the example created by Olaf Conradi
#
# The files generated with this template will be added to
# /etc/nginx/sites-available & /etc/nginx/sites-enabled (symlink)
##
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
#
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
##
##
# This configuration assumes
# You filled the zotserver-config.txt file
# Your domain/subdomain is functionnal
# You want all traffic to be https
# You have PHP FastCGI Process Manager (php-fpm) running on localhost
##
server {
listen 80;
server_name SERVER_NAME;
# HTTP > HTTPS #
return 301 https://$server_name$request_uri;
}
##
# Configure Red with SSL
#
# All requests are routed to the front controller
# except for certain known file types like images, css, etc.
# Those are served statically whenever possible with a
# fall back to the front controller (needed for avatars, for example)
##
server {
listen 443 ssl;
server_name SERVER_NAME;
ssl on;
ssl_certificate /etc/letsencrypt/live/SERVER_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/SERVER_NAME/privkey.pem;
ssl_session_timeout 5m;
# DO WE NEED TO REVIEW THE FOLLOWING SETTINGS?
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
ssl_prefer_server_ciphers on;
fastcgi_param HTTPS on;
charset utf-8;
root INSTALL_PATH;
index index.php;
access_log /var/log/nginx/ZOTSERVER_LOG;
#Uncomment the following line to include a standard configuration file
#Note that the most specific rule wins and your standard configuration
#will therefore *add* to this file, but not override it.
#include standard.conf
# allow uploads up to 20MB in size
client_max_body_size 20m;
client_body_buffer_size 128k;
include mime.types;
# rewrite to front controller as default rule
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?req=$1;
}
}
# make sure webfinger and other well known services aren't blocked
# by denying dot files and rewrite request to the front controller
location ^~ /.well-known/ {
allow all;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?req=$1;
}
}
# statically serve these file types when possible
# otherwise fall back to front controller
# allow browser to cache them
# added .htm for advanced source code editor library
# location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|map|ttf|woff|woff2|svg)$ {
# expires 30d;
# try_files $uri /index.php?req=$uri&$args;
# }
# SHOULD WE UNCOMMENT THE ABOVE LINES ?
# block these file types
location ~* \.(tpl|md|tgz|log|out)$ {
deny all;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
# or a unix socket
location ~* \.php$ {
# IS THE FOLLOWING STILL RELEVANT AS OF AUGUST 2020?
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this
# server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
# another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# With php-fpm:
fastcgi_pass unix:PHP_FPM_SOCK;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# deny access to all dot files
location ~ /\. {
deny all;
}
#deny access to store
location ~ /store {
deny all;
}
}

View file

@ -29,6 +29,18 @@ db_pass=
le_domain=
le_email=
###############################################
### OPTIONAL - Webserver choice ###############
#
# Please indicate if you want to choose Nginx
# or Apache as your web server
#
# Valid strings are nginx or apache (lower case),
# any other will stop the setup script.
#
webserver=apache
###############################################
### OPTIONAL - selfHOST - dynamic IP address ##
#

View file

@ -8,6 +8,7 @@
# - zap: https://zotlabs.com/zap/
# - misty : https://zotlabs.com/misty/
# - osada : https://codeberg.org/zot/osada
# - redmatrix : https://codeberg.org/zot/redmatrix
# under Debian Linux "Buster"
#
# 1) Copy the file "zotserver-config.txt.template" to "zotserver-config.txt"
@ -60,7 +61,7 @@
#
# The script makes a (daily) backup of all relevant files
# - /var/lib/mysql/ > database
# - /var/www/ > hubzilla/zap/misty from github
# - /var/www/ > hubzilla/zap/misty from git repository
# - /etc/letsencrypt/ > certificates
#
# The backup will be written on an external disk compatible to LUKS+ext4 (see zotserver-config.txt)
@ -209,8 +210,15 @@ function print_warn {
}
function stop_zotserver {
print_info "stopping apache webserver..."
systemctl stop apache2
if [ $webserver = "nginx" ]
then
print_info "stopping nginx webserver..."
systemctl stop nginx
elif [ $webserver = "apache" ]
then
print_info "stopping apache webserver..."
systemctl stop apache2
fi
print_info "stopping mysql db..."
systemctl stop mariadb
}
@ -222,8 +230,14 @@ function install_apache {
systemctl restart apache2
}
function install_nginx {
print_info "installing nginx..."
nocheck_install "nginx"
systemctl restart nginx
}
function add_vhost {
print_info "adding vhost"
print_info "adding apache vhost"
echo "<VirtualHost *:80>" >> "/etc/apache2/sites-available/${le_domain}.conf"
echo "ServerName ${le_domain}" >> "/etc/apache2/sites-available/${le_domain}.conf"
echo "DocumentRoot $install_path" >> "/etc/apache2/sites-available/${le_domain}.conf"
@ -231,6 +245,12 @@ function add_vhost {
a2ensite $le_domain
}
function add_nginx_block {
print_info "adding nginx block"
sed "s|SERVER_NAME|${le_domain}|g;s|INSTALL_PATH|${install_path}|g;s|ZOTSERVER_LOG|${install_folder}-${zotserver}.log|;s|PHP_FPM_SOCK|$(ls /var/run/php/*sock)|;" nginx-zotserver.conf.template >> /etc/nginx/sites-enabled/${le_domain}.conf
ln -s /etc/nginx/sites-enabled/${le_domain}.conf /etc/nginx/sites-available/
}
function install_imagemagick {
print_info "installing imagemagick..."
nocheck_install "imagemagick"
@ -254,9 +274,18 @@ function install_sendmail {
function install_php {
# openssl and mbstring are included in libapache2-mod-php
print_info "installing php..."
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/apache2/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/apache2/php.ini
if [ $webserver = "nginx" ]
then
nocheck_install "php php-pear php-curl php-gd php-mbstring php-xml php-zip php-fpm"
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/fpm/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/fpm/php.ini
systemctl reload php7.3-fpm
elif [ $webserver = "apache" ]
then
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/apache2/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/apache2/php.ini
fi
}
function install_mysql {
@ -452,10 +481,20 @@ function install_letsencrypt {
then
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
fi
nocheck_install "certbot python-certbot-apache"
print_info "run certbot ..."
if [ $webserver = "nginx" ]
then
nocheck_install "certbot"
print_info "run certbot..."
systemctl stop nginx
certbot certonly --standalone -d $le_domain -m $le_email --agree-tos --non-interactive
systemctl start nginx
elif [ $webserver = "apache" ]
then
nocheck_install "certbot python-certbot-apache"
print_info "run certbot ..."
certbot --apache -w $install_path -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
service apache2 restart
service apache2 restart
fi
}
function check_https {
@ -483,8 +522,11 @@ function zotserver_name {
elif git remote -v | grep -i "origin.*osada.*"
then
zotserver=osada
elif git remote -v | grep -i "origin.*redmatrix.*"
then
zotserver=redmatrix
else
die "neither osada,misty, zap nor hubzilla repository > did not install osada/misty/zap/hubzilla"
die "neither redmatrix, osada, misty, zap nor hubzilla repository > did not install redmatrix/osada/misty/zap/hubzilla"
fi
}
@ -507,8 +549,12 @@ function install_zotserver {
then
print_info "osada"
util/add_addon_repo https://codeberg.org/zot/osada-addons.git oaddons
elif [ $zotserver = "redmatrix" ]
then
print_info "redmatrix"
util/add_addon_repo https://codeberg.org/zot/redmatrix-addons.git raddons
else
die "neither osada, misty, zap nor hubzilla repository > did not install addons or osada/misty/zap/hubzilla"
die "neither redmatrix, osada, misty, zap nor hubzilla repository > did not install addons or redmatrix/osada/misty/zap/hubzilla"
fi
mkdir -p "cache/smarty3"
mkdir -p "store"
@ -533,6 +579,22 @@ function install_cryptosetup {
nocheck_install "cryptsetup"
}
function configure_zotserverdaily {
echo "#!/bin/sh" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "# update of $le_domain Zot hub/instance" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$zotserverdaily
echo "echo \"reaching git repository for $le_domain $zotserver hub/instance...\"" >> /var/www/$zotserverdaily
echo "(cd $install_path ; util/udall)" >> /var/www/$zotserverdaily
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$zotserverdaily
if [ $webserver = "apache" ]
then
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$zotserverdaily
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$zotserverdaily
fi
chmod a+x /var/www/$zotserverdaily
}
function configure_cron_daily {
print_info "configuring cron..."
# every 10 min for poller.php
@ -541,99 +603,105 @@ function configure_cron_daily {
echo "*/10 * * * * www-data cd $install_path; php Zotlabs/Daemon/Run.php Cron >> /dev/null 2>&1" >> /etc/crontab
fi
# Run external script daily at 05:30
# - stop apache and mysql-server
# - stop apache/nginx and mysql-server
# - renew the certificate of letsencrypt
# - backup db, files ($install_path), certificates if letsencrypt
# - update zotserver core and addon
# - update and upgrade linux
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
echo "#!/bin/sh" > /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "echo \" \"" >> /var/www/$zotserverdaily
echo "echo \"+++ \$(date) +++\"" >> /var/www/$zotserverdaily
echo "echo \" \"" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$zotserverdaily
echo "certbot renew --noninteractive" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$zotserverdaily
echo "service apache2 stop" >> /var/www/$zotserverdaily
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "# backup" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$zotserverdaily
echo "backup_device_name=$backup_device_name" >> /var/www/$zotserverdaily
echo "backup_device_pass=$backup_device_pass" >> /var/www/$zotserverdaily
echo "backup_mount_point=$backup_mount_point" >> /var/www/$zotserverdaily
echo "device_mounted=0" >> /var/www/$zotserverdaily
echo "if [ -n \"$backup_device_name\" ]" >> /var/www/$zotserverdaily
echo "then" >> /var/www/$zotserverdaily
echo " if blkid | grep $backup_device_name" >> /var/www/$zotserverdaily
echo " then" >> /var/www/$zotserverdaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"decrypting backup device...\"" >> /var/www/$zotserverdaily
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$zotserverdaily
fi
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$zotserverdaily
echo " then" >> /var/www/$zotserverdaily
echo " mkdir $backup_mount_point" >> /var/www/$zotserverdaily
echo " fi" >> /var/www/$zotserverdaily
echo " echo \"mounting backup device...\"" >> /var/www/$zotserverdaily
if [ -n "$backup_device_pass" ]
then
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$zotserverdaily
else
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$zotserverdaily
fi
echo " then" >> /var/www/$zotserverdaily
echo " device_mounted=1" >> /var/www/$zotserverdaily
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$zotserverdaily
echo " rsync -a --delete /var/lib/mysql/ /media/zotserver_backup/mysql" >> /var/www/$zotserverdaily
echo " rsync -a --delete /var/www/ /media/zotserver_backup/www" >> /var/www/$zotserverdaily
echo " rsync -a --delete /etc/letsencrypt/ /media/zotserver_backup/letsencrypt" >> /var/www/$zotserverdaily
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$zotserverdaily
echo " df -h" >> /var/www/$zotserverdaily
echo " echo \"\$(date) - db size...\"" >> /var/www/$zotserverdaily
echo " du -h $backup_mount_point | grep mysql/zotserver" >> /var/www/$zotserverdaily
echo " echo \"unmounting backup device...\"" >> /var/www/$zotserverdaily
echo " umount $backup_mount_point" >> /var/www/$zotserverdaily
echo " else" >> /var/www/$zotserverdaily
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$zotserverdaily
echo " fi" >> /var/www/$zotserverdaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"closing decrypted backup device...\"" >> /var/www/$zotserverdaily
echo " cryptsetup luksClose cryptobackup" >> /var/www/$zotserverdaily
fi
echo " fi" >> /var/www/$zotserverdaily
echo "fi" >> /var/www/$zotserverdaily
echo "if [ \$device_mounted == 0 ]" >> /var/www/$zotserverdaily
echo "then" >> /var/www/$zotserverdaily
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$zotserverdaily
echo "fi" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - db size...\"" >> /var/www/$zotserverdaily
echo "du -h /var/lib/mysql/ | grep mysql/zotserver" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "# update" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$zotserverdaily
echo "(cd $install_path/ ; util/udall)" >> /var/www/$zotserverdaily
echo "chown -R www-data:www-data $install_path/ # make all accessable for the webserver" >> /var/www/$zotserverdaily
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$zotserverdaily
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$zotserverdaily
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$zotserverdaily
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$zotserverdaily
echo "#" >> /var/www/$zotserverdaily
echo "shutdown -r now" >> /var/www/$zotserverdaily
if [ -z "`grep '$zotserverdaily' /etc/crontab`" ]
echo "#!/bin/sh" > /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "echo \" \"" >> /var/www/$zotcron
echo "echo \"+++ \$(date) +++\"" >> /var/www/$zotcron
echo "echo \" \"" >> /var/www/$zotcron
echo "echo \"\$(date) - stopping $webserver and mysql...\"" >> /var/www/$zotcron
if [ $webserver = "nginx" ]
then
echo "30 05 * * * root /bin/bash /var/www/$zotserverdaily >> $install_path/${install_folder}-${zotserver}-daily.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm $install_path/${install_folder}-${zotserver}-daily.log" >> /etc/crontab
echo "systemctl stop nginx" >> /var/www/$zotcron
elif [ $webserver = "apache" ]
then
echo "service apache2 stop" >> /var/www/$zotcron
fi
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$zotcron
echo "certbot renew --noninteractive" >> /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "# backup" >> /var/www/$zotcron
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$zotcron
echo "backup_device_name=$backup_device_name" >> /var/www/$zotcron
echo "backup_device_pass=$backup_device_pass" >> /var/www/$zotcron
echo "backup_mount_point=$backup_mount_point" >> /var/www/$zotcron
echo "device_mounted=0" >> /var/www/$zotcron
echo "if [ -n \"\$backup_device_name\" ]" >> /var/www/$zotcron
echo "then" >> /var/www/$zotcron
echo " if blkid | grep $backup_device_name" >> /var/www/$zotcron
echo " then" >> /var/www/$zotcron
if [ -n "$backup_device_pass" ]
then
echo " echo \"decrypting backup device...\"" >> /var/www/$zotcron
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$zotcron
fi
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$zotcron
echo " then" >> /var/www/$zotcron
echo " mkdir $backup_mount_point" >> /var/www/$zotcron
echo " fi" >> /var/www/$zotcron
echo " echo \"mounting backup device...\"" >> /var/www/$zotcron
if [ -n "$backup_device_pass" ]
then
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$zotcron
else
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$zotcron
fi
echo " then" >> /var/www/$zotcron
echo " device_mounted=1" >> /var/www/$zotcron
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$zotcron
echo " rsync -a --delete /var/lib/mysql/ /media/zotserver_backup/mysql" >> /var/www/$zotcron
echo " rsync -a --delete /var/www/ /media/zotserver_backup/www" >> /var/www/$zotcron
echo " rsync -a --delete /etc/letsencrypt/ /media/zotserver_backup/letsencrypt" >> /var/www/$zotcron
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$zotcron
echo " df -h" >> /var/www/$zotcron
echo " echo \"\$(date) - db size...\"" >> /var/www/$zotcron
echo " du -h $backup_mount_point | grep mysql/zotserver" >> /var/www/$zotcron
echo " echo \"unmounting backup device...\"" >> /var/www/$zotcron
echo " umount $backup_mount_point" >> /var/www/$zotcron
echo " else" >> /var/www/$zotcron
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$zotcron
echo " fi" >> /var/www/$zotcron
if [ -n "$backup_device_pass" ]
then
echo " echo \"closing decrypted backup device...\"" >> /var/www/$zotcron
echo " cryptsetup luksClose cryptobackup" >> /var/www/$zotcron
fi
echo " fi" >> /var/www/$zotcron
echo "fi" >> /var/www/$zotcron
echo "if [ \$device_mounted == 0 ]" >> /var/www/$zotcron
echo "then" >> /var/www/$zotcron
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$zotcron
echo "fi" >> /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "echo \"\$(date) - db size...\"" >> /var/www/$zotcron
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "cd /var/www" >> /var/www/$zotcron
echo "for f in *-daily.sh; do \"./\${f}\"; done" >> /var/www/$zotcron
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$zotcron
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$zotcron
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$zotcron
echo "#" >> /var/www/$zotcron
echo "shutdown -r now" >> /var/www/$zotcron
# If global cron job does not exist we add it to /etc/crontab
if grep -q $zotcron /etc/crontab
then
echo "cron job already in /etc/crontab"
else
echo "30 05 * * * root /bin/bash /var/www/$zotcron >> /var/www/zot-daily.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm /var/www/zot-daily.log" >> /etc/crontab
fi
# This is active after either "reboot" or "/etc/init.d/cron reload"
# This is active after either "reboot" or cron reload"
systemctl restart cron
print_info "configured cron for updates/upgrades"
}
@ -641,7 +709,6 @@ echo "shutdown -r now" >> /var/www/$zotserverdaily
# START OF PROGRAM
########################################################################
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
check_sanity
zotserver_name
@ -655,8 +722,9 @@ source $configfile
selfhostdir=/etc/selfhost
selfhostscript=selfhost-updater.sh
zotcron="zotcron.sh"
zotserverdaily="${install_folder}-${zotserver}-daily.sh"
backup_mount_point="/media/${install_folder}-${zotserver}_backup"
backup_mount_point="/media/zotserver_backup"
#set -x # activate debugging from here
@ -666,15 +734,32 @@ update_upgrade
install_curl
install_wget
install_sendmail
install_apache
if [ "$install_path" != "/var/www/html" ]
if [ $webserver = "nginx" ]
then
add_vhost
install_nginx
elif [ $webserver = "apache" ]
then
install_apache
else
die "Failed to install a Web server: 'webserver' not set to \"apache\" or \"nginx\" in $configfile"
fi
install_imagemagick
install_php
if [ $webserver = "nginx" ]
then
add_nginx_block
elif [ $webserver = "apache" ]
then
if [ "$install_path" != "/var/www/html" ]
then
add_vhost
fi
fi
install_mysql
if [ $webserver = "apache" ]
then
install_adminer
fi
create_zotserver_db
run_freedns
install_run_selfhost
@ -692,6 +777,8 @@ fi
install_zotserver
configure_zotserverdaily
configure_cron_daily
if [ "$le_domain" != "localhost" ]
@ -704,5 +791,3 @@ fi
#set +x # stop debugging from here

View file

@ -43,13 +43,6 @@ class Cron {
require_once('include/sharedwithme.php');
apply_updates();
// expire any expired mail
q("delete from mail where expires > '%s' and expires < %s ",
dbesc(NULL_DATE),
db_utcnow()
);
// expire any expired items
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s

View file

@ -2,6 +2,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzotdir;
use Zotlabs\Lib\Libzot;
class Cron_daily {
@ -14,12 +15,15 @@ class Cron_daily {
*
*/
Libzotdir::check_upstream_directory();
// make sure our own site record is up to date
Libzot::import_site(Libzot::site_info(true));
// Fire off the Cron_weekly process if it's the correct day.
$d3 = intval(datetime_convert('UTC','UTC','now','N'));
if($d3 == 7) {
if ($d3 == 7) {
Run::Summon(array('Cron_weekly'));
}
@ -71,15 +75,16 @@ class Cron_daily {
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
$dirmode = get_config('system','directory_mode');
// $dirmode = get_config('system','directory_mode');
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
Libzotdir::sync_directories($dirmode);
}
// if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
// Libzotdir::sync_directories($dirmode);
// }
Run::Summon(array('Expire'));
Run::Summon(array('Cli_suggest'));
// Run::Summon(array('Cli_suggest'));
// remove xchan photos that were stored in the DB ine earlier versions
// and were migrated to filesystem storage.

View file

@ -13,30 +13,28 @@ class Directory {
static public function run($argc,$argv) {
if($argc < 2)
if ($argc < 2) {
return;
}
$force = false;
$pushall = true;
$pushed = false;
if($argc > 2) {
if($argv[2] === 'force')
if ($argc > 2) {
if ($argv[2] === 'force') {
$force = true;
if($argv[2] === 'nopush')
}
if ($argv[2] === 'nopush') {
$pushall = false;
}
}
logger('directory update', LOGGER_DEBUG);
$dirmode = get_config('system','directory_mode');
if($dirmode === false)
$dirmode = DIRECTORY_MODE_NORMAL;
$channel = channelx_by_n($argv[1]);
if(! $channel)
if (! $channel) {
return;
}
// update the local directory - was optional, but now done regardless
@ -48,56 +46,8 @@ class Directory {
);
// Now update all the connections
if($pushall) {
if ($pushall) {
Run::Summon(array('Notifier','refresh_all',$channel['channel_id']));
$pushed = true;
}
// if applicable send the changes upstream
$directory = Libzotdir::find_upstream_directory($dirmode);
if(! $directory) {
logger('no directory');
return;
}
$url = $directory['url'] . '/zot';
// ensure the upstream directory is updated
$packet = Libzot::build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
$z = Libzot::zot($url,$packet,$channel);
// re-queue if unsuccessful
if(! $z['success']) {
/** @FIXME we aren't updating channel_dirdate if we have to queue
* the directory packet. That means we'll try again on the next poll run.
*/
$hash = new_uuid();
Queue::insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $url,
'notify' => $packet,
));
}
else {
q("update channel set channel_dirdate = '%s' where channel_id = %d",
dbesc(datetime_convert()),
intval($channel['channel_id'])
);
}
// Now update all the connections
if($pushall && (! $pushed))
Run::Summon(array('Notifier','refresh_all',$channel['channel_id']));
}
}

View file

@ -38,7 +38,7 @@ class Onepoll {
return;
}
$contact = $contacts[0];
$contact = array_shift($contacts);
$t = $contact['abook_updated'];
@ -159,13 +159,15 @@ class Onepoll {
} // end USE_OUTBOX
// update the poco details for this connection
if($contact['xchan_connurl']) {
$r = q("SELECT xlink_id from xlink
where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
intval($contact['xchan_hash']),
db_utcnow(), db_quoteinterval('1 DAY')
db_utcnow(), db_quoteinterval('7 DAY')
);
if(! $r) {
poco_load($contact['xchan_hash'],$contact['xchan_connurl']);

View file

@ -1787,7 +1787,15 @@ class Activity {
}
}
$about = ((isset($person_obj['summary'])) ? html2bbcode($person_obj['summary']) : EMPTY_STR);
$about = ((isset($person_obj['summary'])) ? html2bbcode(purify_html($person_obj['summary'])) : EMPTY_STR);
$p = q("select * from xchan where xchan_url = '%s' and xchan_network = 'zot6' limit 1",
dbesc($url)
);
if ($p) {
set_xconfig($url,'system','protocols','zot6,activitypub');
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($url)
@ -1803,6 +1811,7 @@ class Activity {
'xchan_url' => $profile,
'xchan_name' => $name,
'xchan_hidden' => intval($hidden),
'xchan_updated' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
'xchan_network' => 'activitypub',
'xchan_photo_date' => datetime_convert('UTC','UTC','1968-01-01'),
@ -1824,7 +1833,8 @@ class Activity {
}
// update existing record
$u = q("update xchan set xchan_name = '%s', xchan_pubkey = '%s', xchan_network = '%s', xchan_name_date = '%s', xchan_hidden = %d where xchan_hash = '%s'",
$u = q("update xchan set xchan_updated = '%s', xchan_name = '%s', xchan_pubkey = '%s', xchan_network = '%s', xchan_name_date = '%s', xchan_hidden = %d where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($name),
dbesc($pubkey),
dbesc('activitypub'),

View file

@ -130,8 +130,14 @@ class Enotify {
logger('notification: mail');
$subject = sprintf( t('[$Projectname:Notify] New mail received at %s'),$sitename);
$preamble = sprintf( t('%1$s sent you a new private message at %2$s.'), $sender['xchan_name'],$sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
if ($params['item']['mid'] === $params['item']['parent_mid']) {
$preamble = sprintf( t('%1$s sent you a new private message at %2$s.'), $sender['xchan_name'],$sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
}
else {
$preamble = sprintf( t('%1$s replied to a private message at %2$s.'), $sender['xchan_name'],$sitename);
$epreamble = sprintf( t('%1$s replied to %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
}
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/display/' . gen_link_id($params['item']['mid']) );

View file

@ -47,6 +47,10 @@ class Img_cache {
$x = z_fetch_url($url,true,$redirects,[ 'filep' => $fp, 'novalidate' => true ]);
fclose($fp);
// $file *should* exist. The existence check was added because in at least one case
// this code was reached and $file did not exist. Go figure...
if ($x['success'] && file_exists($file)) {
$i = @getimagesize($file);
if ($i && $i[2]) { // looking for non-zero imagetype

View file

@ -1157,6 +1157,7 @@ class Libsync {
$xv['xchan_guid_sig'] = $sig;
$xv['xchan_hash'] = $hash;
$xv['xchan_pubkey'] = $channel['channel_pubkey'];
$xv['xchan_updated'] = datetime_convert();
xchan_store_lowlevel($xv);
$newxchan = $xv;
}

View file

@ -781,6 +781,16 @@ class Libzot {
del_xconfig($xchan_hash,'system','protocols');
}
}
$collections = [];
if (isset($arr['primary_location']['following'])) {
$collections['following'] = $arr['primary_location']['following'];
}
if (isset($arr['primary_location']['followers'])) {
$collections['followers'] = $arr['primary_location']['followers'];
}
if ($collections) {
set_xconfig($xchan_hash,'activitypub','collections',$collections);
}
if (($r[0]['xchan_name_date'] != $arr['name_updated'])
|| ($r[0]['xchan_connurl'] != $arr['primary_location']['connections_url'])
@ -788,10 +798,12 @@ class Libzot {
|| ($r[0]['xchan_follow'] != $arr['primary_location']['follow_url'])
|| ($r[0]['xchan_connpage'] != $arr['connect_url'])
|| ($r[0]['xchan_url'] != $arr['primary_location']['url'])
|| ($r[0]['xchan_updated'] < datetime_convert('UTC','UTC','now - 7 days'))
|| $hidden_changed || $adult_changed || $deleted_changed || $type_changed ) {
$rup = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',
$rup = q("update xchan set xchan_updated = '%s', xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',
xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_type = %d,
xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc(($arr['name']) ? escape_tags($arr['name']) : '-'),
dbesc($arr['name_updated']),
dbesc($arr['primary_location']['connections_url']),
@ -851,6 +863,7 @@ class Libzot {
'xchan_connpage' => $arr['connect_url'],
'xchan_name' => (($arr['name']) ? escape_tags($arr['name']) : '-'),
'xchan_network' => 'zot6',
'xchan_updated' => datetime_convert(),
'xchan_photo_date' => $arr['photo_updated'],
'xchan_name_date' => $arr['name_updated'],
'xchan_hidden' => intval(1 - intval($arr['searchable'])),
@ -921,8 +934,9 @@ class Libzot {
if ($photos[4]) {
// importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
// This often happens when somebody joins the matrix with a bad cert.
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
$r = q("update xchan set xchan_updated = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@ -931,9 +945,10 @@ class Libzot {
);
}
else {
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
$r = q("update xchan set xchan_updated = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
dbesc(datetime_convert()),
dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@ -970,15 +985,15 @@ class Libzot {
// Are we a directory server of some kind?
$other_realm = false;
$realm = get_directory_realm();
if (array_key_exists('site',$arr)
&& array_key_exists('realm',$arr['site'])
&& (strpos($arr['site']['realm'],$realm) === false))
$other_realm = true;
// $other_realm = false;
// $realm = get_directory_realm();
// if (array_key_exists('site',$arr)
// && array_key_exists('realm',$arr['site'])
// && (strpos($arr['site']['realm'],$realm) === false))
// $other_realm = true;
if ($dirmode != DIRECTORY_MODE_NORMAL) {
// if ($dirmode != DIRECTORY_MODE_NORMAL) {
// We're some kind of directory server. However we can only add directory information
// if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
@ -1002,7 +1017,7 @@ class Libzot {
dbesc($xchan_hash)
);
}
}
// }
if (array_key_exists('site',$arr) && is_array($arr['site'])) {
$profile_changed = self::import_site($arr['site']);
@ -3079,10 +3094,12 @@ class Libzot {
$ret['id_sig'] = self::sign($e['xchan_guid'], $e['channel_prvkey']);
$ret['primary_location'] = [
'address' => $e['xchan_addr'],
'url' => $e['xchan_url'],
'connections_url' => $e['xchan_connurl'],
'follow_url' => $e['xchan_follow'],
'address' => $e['xchan_addr'],
'url' => $e['xchan_url'],
'connections_url' => $e['xchan_connurl'],
'follow_url' => $e['xchan_follow'],
'followers' => z_root() . '/followers/' . $e['channel_address'],
'following' => z_root() . '/following/' . $e['channel_address']
];
$ret['public_key'] = $e['xchan_pubkey'];
@ -3098,6 +3115,9 @@ class Libzot {
$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
$ret['channel_type'] = $channel_type;
$ret['protocols'] = [ 'zot6' ];
if (get_pconfig($e['channel_id'],'system','activitypub',get_config('system','activitypub',true))) {
$ret['protocols'][] = 'activitypub';
}
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
@ -3170,7 +3190,7 @@ class Libzot {
}
static function site_info() {
static function site_info($force = false) {
$signing_key = get_config('system','prvkey');
$sig_method = get_config('system','signature_algorithm','sha256');
@ -3208,7 +3228,7 @@ class Libzot {
// hide detailed site information if you're off the grid
if ($dirmode != DIRECTORY_MODE_STANDALONE) {
if ($dirmode != DIRECTORY_MODE_STANDALONE || $force) {
$register_policy = intval(get_config('system','register_policy'));
@ -3237,10 +3257,6 @@ class Libzot {
$ret['site']['access_policy'] = 'tiered';
}
$ret['site']['accounts'] = account_total();
$ret['site']['channels'] = channel_total();
$ret['site']['admin'] = get_config('system','admin_email');
$visible_plugins = [];

View file

@ -188,6 +188,11 @@ class Libzotdir {
static function sync_directories($dirmode) {
// !!!!!!!!!
return;
// !!!!!!!!!
if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL)
return;

View file

@ -338,26 +338,16 @@ class Acl extends Controller {
$address = true;
}
$remote_dir = false;
if (($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if (! $url) {
$directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
$remote_dir = true;
}
$url = z_root() . '/dirsearch';
$results = [];
$results2 = [];
$token = get_config('system','realm_token');
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
if ($url) {
$query = $url . '?f=' . (($token) ? '&t=' . urlencode($token) : '');
$query = $url . '?f=';
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
$x = z_fetch_url($query);
@ -369,35 +359,6 @@ class Acl extends Controller {
}
}
}
if ($remote_dir) {
$query = z_root() . '/dirsearch' . '?f=&navsearch=1' . (($token) ? '&t=' . urlencode($token) : '');
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
$x = z_fetch_url($query);
if ($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if ($j && $j['results']) {
$results2 = $j['results'];
}
}
}
if ($results2) {
foreach ($results2 as $x) {
$found = false;
foreach ($results as $y) {
if ($y['url'] === $x['url']) {
$found = true;
}
}
if (! $found) {
$x['local'] = true;
$results[] = $x;
}
}
}
return $results;
}
}

View file

@ -54,6 +54,7 @@ class Site {
$mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
$directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : '');
$force_publish = ((x($_POST,'publish_all')) ? True : False);
$block_public_dir = ((x($_POST,'block_public_directory')) ? True : False);
$disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True);
$site_firehose = ((x($_POST,'site_firehose')) ? True : False);
$open_pubstream = ((x($_POST,'open_pubstream')) ? True : False);
@ -63,6 +64,7 @@ class Site {
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
$max_imported_follow = ((x($_POST,'max_imported_follow')) ? intval(trim($_POST['max_imported_follow'])) : 10);
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
@ -114,7 +116,8 @@ class Site {
set_config('system', 'show_like_counts', $show_like_counts);
set_config('system', 'pubstream_incl',$pub_incl);
set_config('system', 'pubstream_excl',$pub_excl);
set_config('system', 'block_public_directory', $block_public_dir);
set_config('system', 'max_imported_follow', $max_imported_follow);
if ($directory_server) {
set_config('system','directory_server',$directory_server);
@ -320,14 +323,16 @@ class Site {
'$frontpage' => [ 'frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.") ],
'$mirror_frontpage' => [ 'mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting') ],
'$abandon_days' => [ 'abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.') ],
'$block_public_dir' => [ 'block_public_directory', t('Block directory from visitors'), get_config('system','block_public_directory',true), t('Only allow authenticated access to directory.') ],
'$verify_email' => [ 'verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).") ],
'$force_publish' => [ 'publish_all', t("Force publish in directory"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.") ],
'$disable_discover_tab' => [ 'disable_discover_tab', t('Public stream'), $discover_tab, t('Provide access to public content from other sites. Warning: this content is unmoderated.') ],
'$site_firehose' => [ 'site_firehose', t('Site only Public ttream'), get_config('system','site_firehose'), t('Provide access to public content originating only from this site if Public stream is disabled.') ],
'$site_firehose' => [ 'site_firehose', t('Site only Public stream'), get_config('system','site_firehose'), t('Provide access to public content originating only from this site if Public stream is disabled.') ],
'$open_pubstream' => [ 'open_pubstream', t('Allow anybody on the internet to access the Public stream'), get_config('system','open_pubstream',0), t('Default is to only allow viewing by site members. Warning: this content is unmoderated.') ],
'$show_like_counts' => [ 'show_like_counts', t('Show numbers of likes and dislikes in conversations'), get_config('system','show_like_counts',1), t('If disabled, the presence of likes and dislikes will be shown, but without totals.') ],
'$incl' => [ 'pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ],
'$excl' => [ 'pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ],
'$max_imported_follow' => [ 'max_imported_follow', t('Maximum number of imported friends of friends'), get_config('system','max_imported_follow',10), t('Warning: higher numbers will improve the quality of friend suggestions and directory results but can exponentially increase resource usage') ],
'$login_on_homepage' => [ 'login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.") ],
'$enable_context_help' => [ 'enable_context_help', t("Enable context help"),((intval($enable_context_help) === 1 || $enable_context_help === false) ? 1 : 0) , t("Display contextual help for the current page when the help button is pressed.") ],
'$reply_address' => [ 'reply_address', t('Reply-to email address for system generated email.'), get_config('system','reply_address','noreply@' . \App::get_hostname()),'' ],

View file

@ -83,9 +83,9 @@ class Directory extends Controller {
$observer = get_observer_hash();
if (get_config('system','block_public_directory',false) && (! $observer)) {
if (get_config('system','block_public_directory',true) && (! $observer)) {
notice( t('Public access denied.') . EOL);
return;
return login(false);
}
$globaldir = Libzotdir::get_directory_setting($observer, 'globaldir');
@ -130,7 +130,8 @@ class Directory extends Controller {
// only works if the suggestion query and the directory query have the
// same number of results
$r = suggestion_query(local_channel(),get_observer_hash(),0,DIRECTORY_PAGESIZE);
App::set_pager_itemspage(60);
$r = suggestion_query(local_channel(),get_observer_hash(),App::$pager['start'],DIRECTORY_PAGESIZE);
if (! $r) {
notice( t('No default suggestions were found.') . EOL);
@ -142,14 +143,14 @@ class Directory extends Controller {
$common = array();
$index = 0;
foreach ($r as $rr) {
$common[$rr['xchan_addr']] = ((intval($rr['total']) > 0) ? intval($rr['total']) - 1 : 0);
$addresses[$rr['xchan_addr']] = $index++;
$common[$rr['xchan_hash']] = ((intval($rr['total']) > 0) ? intval($rr['total']) - 1 : 0);
$addresses[$rr['xchan_hash']] = $index++;
}
// Build query to get info about suggested people
$advanced = '';
foreach (array_keys($addresses) as $address) {
$advanced .= "address=\"$address\" ";
$advanced .= "xhash=\"$address\" ";
}
// Remove last space in the advanced query
$advanced = rtrim($advanced);
@ -162,23 +163,10 @@ class Directory extends Controller {
$directory_admin = false;
if (($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
if (is_site_admin()) {
$directory_admin = true;
}
$url = z_root() . '/dirsearch';
if (is_site_admin()) {
$directory_admin = true;
}
if (! $url) {
$directory = Libzotdir::find_upstream_directory($dirmode);
if ((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url'])) {
logger('CRITICAL: No directory server URL');
}
$url = $directory['url'] . '/dirsearch';
}
$token = get_config('system','realm_token');
logger('mod_directory: URL = ' . $url, LOGGER_DEBUG);
$contacts = array();
@ -305,14 +293,7 @@ class Directory extends Controller {
$page_type = '';
$rating_enabled = get_config('system','rating_enabled');
if ($rr['total_ratings'] && $rating_enabled) {
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
}
else {
$total_ratings = '';
}
$total_ratings = '';
$profile = $rr;
@ -322,9 +303,6 @@ class Directory extends Controller {
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False);
if ($about && $safe_mode) {
$about = html2plain($about);
}
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
@ -379,6 +357,8 @@ class Directory extends Controller {
'total_ratings' => $total_ratings,
'viewrate' => true,
'canrate' => (($rating_enabled && local_channel()) ? true : false),
// 'network' => network_to_name($rr['network']),
// 'network_label' => t('Network:'),
'pdesc' => $pdesc,
'pdesc_label' => t('Description:'),
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
@ -399,9 +379,9 @@ class Directory extends Controller {
'keywords' => $out,
'ignlink' => $suggest ? z_root() . '/directory?ignore=' . $rr['hash'] : '',
'ignore_label' => t('Don\'t suggest'),
'common_friends' => (($common[$rr['address']]) ? intval($common[$rr['address']]) : ''),
'common_label' => t('Common connections (estimated):'),
'common_count' => intval($common[$rr['address']]),
'common_friends' => (($common[$rr['hash']]) ? intval($common[$rr['hash']]) : ''),
'common_label' => t('Suggestion ranking:'),
'common_count' => intval($common[$rr['hash']]),
'safe' => $safe_mode
];
@ -450,7 +430,7 @@ class Directory extends Controller {
else {
$maxheight = 94;
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
$dirtitle = (($globaldir) ? t('Network Directory (channels known to this site)') : t('Local Directory'));
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['req'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, [
@ -507,7 +487,7 @@ class Directory extends Controller {
$out = [];
foreach ($suggests as $k => $v) {
foreach ($results as $rv) {
if ($k == $rv['address']) {
if ($k == $rv['hash']) {
$out[intval($v)] = $rv;
break;
}

View file

@ -20,38 +20,24 @@ class Dirsearch extends Controller {
function get() {
$ret = array('success' => false);
$ret = [ 'success' => false ];
// logger('request: ' . print_r($_REQUEST,true));
$dirmode = intval(get_config('system','directory_mode'));
if ($dirmode == DIRECTORY_MODE_NORMAL && ! intval($_REQUEST['navsearch'])) {
$ret['message'] = t('This site is not a directory server');
json_return_and_die($ret);
}
$network = ((intval($_REQUEST['navsearch'])) ? EMPTY_STR : " AND xchan_network = 'zot6' ");
$access_token = $_REQUEST['t'];
$token = get_config('system','realm_token');
if ($token && $access_token != $token) {
$ret['message'] = t('This directory server requires an access token');
json_return_and_die($ret);
}
if (argc() > 1 && argv(1) === 'sites') {
$ret = $this->list_public_sites();
json_return_and_die($ret);
}
$dirmode = intval(get_config('system','directory_mode'));
$network = EMPTY_STR;
$sql_extra = '';
$tables = [ 'name', 'address', 'locale', 'region', 'postcode',
$tables = [ 'name', 'address', 'xhash', 'locale', 'region', 'postcode',
'country', 'gender', 'marital', 'sexual', 'keywords' ];
// parse advanced query if present
@ -65,6 +51,8 @@ class Dirsearch extends Controller {
$sql_extra .= $this->dir_query_build($adv['logic'],'xchan_name',$adv['value']);
elseif ($adv['field'] === 'address')
$sql_extra .= $this->dir_query_build($adv['logic'],'xchan_addr',$adv['value']);
elseif ($adv['field'] === 'xhash')
$sql_extra .= $this->dir_query_build($adv['logic'],'xchan_hash',$adv['value']);
else
$sql_extra .= $this->dir_query_build($adv['logic'],'xprof_' . $adv['field'],$adv['value']);
}
@ -140,6 +128,9 @@ class Dirsearch extends Controller {
if ($address) {
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
}
if ($hash) {
$sql_extra .= $this->dir_query_build($joiner,'xchan_hash',$hash);
}
if ($locale) {
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$locale);
}
@ -173,12 +164,7 @@ class Dirsearch extends Controller {
$sql_extra .= " AND xprof_age >= " . intval($agege) . ") ";
}
if($hash) {
$sql_extra = " AND xchan_hash like '" . dbesc($hash) . protect_sprintf('%') . "' ";
}
$perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 60);
$page = (($_REQUEST['p']) ? intval($_REQUEST['p'] - 1) : 0);
$startrec = (($page+1) * $perpage) - $perpage;
@ -195,7 +181,7 @@ class Dirsearch extends Controller {
// If &limit=n, return at most n entries
// If &return_total=1, we count matching entries and return that as 'total_items' for use in pagination.
// By default we return one page (default 80 items maximum) and do not count total entries
// By default we return one page (default 60 items maximum) and do not count total entries
$logic = ((strlen($sql_extra)) ? 'false' : 'true');
@ -246,58 +232,6 @@ class Dirsearch extends Controller {
$order = " order by xchan_name_date desc ";
if ($sync) {
// generate sync packet for directory mirrors
$spkt = array('transactions' => [] );
$r = q("select * from updates where ud_date >= '%s' and ud_guid != '' order by ud_date desc",
dbesc($sync)
);
if ($r) {
foreach ($r as $rr) {
$flags = [];
if ($rr['ud_flags'] & UPDATE_FLAGS_DELETED)
$flags[] = 'deleted';
if ($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
$flags[] = 'forced';
if ($rr['ud_flags'] & UPDATE_FLAGS_CENSORED)
$flags[] = 'censored';
$spkt['transactions'][] = [
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
'transaction_id' => $rr['ud_guid'],
'timestamp' => $rr['ud_date'],
'flags' => $flags
];
}
}
// sync ratings - not currently used
$r = q("select * from xlink where xlink_static = 1 and xlink_updated >= '%s' ",
dbesc($sync)
);
if ($r) {
$spkt['ratings'] = [];
foreach ($r as $rr) {
$spkt['ratings'][] = [
'type' => 'rating',
'encoding' => 'zot',
'channel' => $rr['xlink_xchan'],
'target' => $rr['xlink_link'],
'rating' => intval($rr['xlink_rating']),
'rating_text' => $rr['xlink_rating_text'],
'signature' => $rr['xlink_sig'],
'edited' => $rr['xlink_updated']
];
}
}
json_return_and_die($spkt);
}
// normal directory query
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
@ -313,18 +247,24 @@ class Dirsearch extends Controller {
$entries = [];
foreach ($r as $rr) {
// We need a better way to do this than one query for every
// AP record. Leaving this for the moment because it produces
// the desired results of not having duplicate entries for
// a channel that has multiple identities across multiple
// networks.
if ($rr['xchan_network'] === 'activitypub') {
$z = q("select xchan_hash from xchan where xchan_url = '%s' and xchan_network = 'zot6' limit 1",
dbesc($rr['xchan_url'])
);
if ($z) {
continue;
}
}
$entry = [];
$pc = q("select count(xlink_rating) as total_ratings from xlink where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 group by xlink_rating",
dbesc($rr['xchan_hash'])
);
if ($pc)
$entry['total_ratings'] = intval($pc[0]['total_ratings']);
else
$entry['total_ratings'] = 0;
$entry['name'] = $rr['xchan_name'];
$entry['hash'] = $rr['xchan_hash'];
$entry['censored'] = $rr['xchan_censored'];
@ -334,6 +274,7 @@ class Dirsearch extends Controller {
$entry['photo_l'] = $rr['xchan_photo_l'];
$entry['photo'] = $rr['xchan_photo_m'];
$entry['address'] = $rr['xchan_addr'];
$entry['network'] = $rr['xchan_network'];
$entry['description'] = $rr['xprof_desc'];
$entry['locale'] = $rr['xprof_locale'];
$entry['region'] = $rr['xprof_region'];
@ -445,25 +386,16 @@ class Dirsearch extends Controller {
$rand = db_getfunc('rand');
$realm = get_directory_realm();
if ($realm == DIRECTORY_REALM) {
$r = q("select * from site where site_access != 0 and site_register !=0 and ( site_realm = '%s' or site_realm = '') and site_type = %d and site_dead = 0 order by $rand",
dbesc($realm),
$r = q("select * from site where site_type = %d and site_dead = 0",
intval(SITE_TYPE_ZOT)
);
}
else {
$r = q("select * from site where site_access != 0 and site_register !=0 and site_realm = '%s' and site_type = %d and site_dead = 0 order by $rand",
dbesc($realm),
intval(SITE_TYPE_ZOT)
);
}
);
$ret = array('success' => false);
if ($r) {
$ret['success'] = true;
$ret['sites'] = array();
$insecure = array();
foreach ($r as $rr) {
@ -483,13 +415,8 @@ class Dirsearch extends Controller {
else
$register = 'closed';
if (strpos($rr['site_url'],'https://') !== false)
$ret['sites'][] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']);
else
$insecure[] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']);
}
if ($insecure) {
$ret['sites'] = array_merge($ret['sites'],$insecure);
$ret['sites'][] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']);
}
}
return $ret;

View file

@ -225,6 +225,7 @@ class Import extends Controller {
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_name' => $channel['channel_name'],
'xchan_network' => 'zot6',
'xchan_updated' => datetime_convert(),
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert()
]
@ -255,7 +256,8 @@ class Import extends Controller {
if ($xchan['xchan_hash'] === $channel['channel_hash']) {
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
$r = q("update xchan set xchan_updated = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']),
@ -272,7 +274,8 @@ class Import extends Controller {
$photodate = $xchan['xchan_photo_date'];
}
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
$r = q("update xchan set xchan_updated = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),

View file

@ -350,7 +350,6 @@ class Item extends Controller {
$api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
$consensus = intval($_REQUEST['consensus']);
$nocomment = intval($_REQUEST['nocomment']);
$is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false);
@ -698,7 +697,6 @@ class Item extends Controller {
$item_unseen = $orig_post['item_unseen'];
$item_starred = $orig_post['item_starred'];
$item_uplink = $orig_post['item_uplink'];
$item_consensus = $orig_post['item_consensus'];
$item_wall = $orig_post['item_wall'];
$item_thread_top = $orig_post['item_thread_top'];
$item_notshown = $orig_post['item_notshown'];
@ -823,6 +821,33 @@ class Item extends Controller {
$str_contact_deny = $gacl['deny_cid'];
$str_group_deny = $gacl['deny_gid'];
// if the acl contains a single contact and it's a group, add a mention. This is for compatibility
// with other groups implementations which require a mention to trigger group delivery.
if (($str_contact_allow) && (! $str_group_allow) && (! $str_contact_deny) && (! $str_group_deny)) {
$cida = expand_acl($str_contact_allow);
if (count($cida) === 1) {
$netgroups = get_forum_channels($profile_uid,1);
if ($netgroups) {
foreach($netgroups as $ng) {
if ($ng['xchan_hash'] == $cida[0]) {
if (! isset($post_tags)) {
$post_tags = [];
}
$post_tags[] = array(
'uid' => $profile_uid,
'ttype' => TERM_MENTION,
'otype' => TERM_OBJ_POST,
'term' => $ng['xchan_name'],
'url' => $ng['xchan_url']
);
}
}
}
}
}
$groupww = false;
// if this is a wall-to-wall post to a group, turn it into a direct message
@ -1096,7 +1121,6 @@ class Item extends Controller {
$item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
$item_wall = (($post_type === 'wall' || $post_type === 'wall-comment') ? 1 : 0);
$item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
@ -1197,15 +1221,8 @@ class Item extends Controller {
}
}
if($webpage == ITEM_TYPE_MAIL) {
$plink = z_root() . '/mail/' . $channel['channel_address'] . '/' . substr($mid,-16);
}
if ((! $plink) && ($item_thread_top)) {
// $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
// $plink = substr($plink,0,190);
$plink = z_root() . '/item/' . $uuid;
}
@ -1251,7 +1268,7 @@ class Item extends Controller {
$datarray['item_unseen'] = intval($item_unseen);
$datarray['item_starred'] = intval($item_starred);
$datarray['item_uplink'] = intval($item_uplink);
$datarray['item_consensus'] = intval($item_consensus);
$datarray['item_consensus'] = 0;
$datarray['item_notshown'] = intval($item_notshown);
$datarray['item_nsfw'] = intval($item_nsfw);
$datarray['item_relay'] = intval($item_relay);
@ -1326,7 +1343,7 @@ class Item extends Controller {
if($z) {
$datarray['cancel'] = 1;
notice( t('Duplicate post suppressed.') . EOL);
logger('Duplicate post. Faking plugin cancel.');
logger('Duplicate post. Cancelled.');
}
}
@ -1362,19 +1379,6 @@ class Item extends Controller {
$datarray['id'] = $post_id;
$x = item_store_update($datarray,$execflag);
// We only need edit activities for other federated protocols
// which do not support edits natively. While this does federate
// edits, it presents a number of issues locally - such as #757 and #758.
// The SQL check for an edit activity would not perform that well so to fix these issues
// requires an additional item flag (perhaps 'item_edit_activity') that we can add to the
// query for searches and notifications.
// For now we'll just forget about trying to make edits work on network protocols that
// don't support them.
// item_create_edit_activity($x);
if(! $parent) {
$r = q("select * from item where id = %d",
intval($post_id)
@ -1417,10 +1421,10 @@ class Item extends Controller {
if(local_channel())
retain_item($parent);
// only send comment notification if this is a wall-to-wall comment,
// only send comment notification if this is a wall-to-wall comment and not a DM,
// otherwise it will happen during delivery
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall'])) && intval($datarray['item_private']) != 2) {
Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'from_xchan' => $datarray['author_xchan'],

View file

@ -1,98 +0,0 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Libzotdir;
class Pubsites extends \Zotlabs\Web\Controller {
function get() {
$dirmode = intval(get_config('system','directory_mode'));
if (($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if (! $url) {
$directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}
$url .= '/sites';
$o .= '<div class="generic-content-wrapper">';
$o .= '<div class="section-title-wrapper"><h2>' . t('Public Hubs') . '</h2></div>';
$o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
t('The listed hubs allow public registration for the zot network - which may include webapps such as zap, misty (Mistpark 2020), and hubzilla. All hubs in the network are interlinked so membership on any of them conveys membership in the network as a whole. Some hubs may require subscription or provide tiered service plans. The hub itself <strong>may</strong> provide additional details.') . '</div>' . EOL;
$ret = z_fetch_url($url);
if($ret['success']) {
$j = json_decode($ret['body'],true);
if($j) {
if($j['sites']) {
$projects = $this->sort_sites($j['sites']);
foreach($projects as $p => $v) {
if (ucfirst($p) === 'Osada') {
// deprecated
continue;
}
$o .= '<strong>' . ucfirst($p) . '</strong>' . EOL;
$o .= '<table class="table table-striped table-hover"><tr><td>' . t('Hub URL') . '</td><td>' . t('Access Type') . '</td><td>' . t('Registration Policy') . '</td><td>' . t('Software') . '</td>';
$o .= '</tr>';
usort($v, [ $this, 'sort_versions' ]);
foreach ($v as $jj) {
if(strpos($jj['version'],' ')) {
$x = explode(' ', $jj['version']);
if($x[1])
$jj['version'] = $x[1];
}
$m = parse_url($jj['url']);
$host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
$location = '';
if(!empty($jj['location'])) {
$location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</p>';
}
else {
$location = '<br>&nbsp;';
}
$urltext = str_replace(array('https://'), '', $jj['url']);
$o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="fa fa-link"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
$o .= '</tr>';
}
$o .= '</table>';
$o .= '<br><br>';
}
}
$o .= '</div></div>';
}
}
return $o;
}
function sort_sites($a) {
$ret = [];
if($a) {
foreach($a as $e) {
$projectname = explode(' ',$e['project']);
$ret[$projectname[0]][] = $e;
}
}
$projects = array_keys($ret);
$newret = [];
foreach($projects as $p) {
$newret[$p] = $ret[$p];
}
return $newret;
}
function sort_versions($a,$b) {
return version_compare($b['version'],$a['version']);
}
}

View file

@ -195,31 +195,30 @@ class Register extends Controller {
function get() {
$registration_is = '';
$other_sites = '';
$registration_is = EMPTY_STR;
$other_sites = false;
if (intval(get_config('system','register_policy')) === REGISTER_CLOSED) {
notice( t('Registration on this website is disabled.') . EOL);
if (intval(get_config('system','directory_mode')) === DIRECTORY_MODE_STANDALONE) {
notice( t('Registration on this hub is disabled.') . EOL);
return;
return EMPTY_STR;
}
else {
$other_sites = true;
}
$mod = new Pubsites();
return $mod->get();
}
if (intval(get_config('system','register_policy')) == REGISTER_APPROVE) {
$registration_is = t('Registration on this hub is by approval only.');
$other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
$registration_is = t('Registration on this website is by approval only.');
$other_sites = true;
}
$invitations = false;
if (intval(get_config('system','invitation_only'))) {
$invitations = true;
$registration_is = t('Registration on this hub is by invitation only.');
$other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>');
$registration_is = t('Registration on this site is by invitation only.');
$other_sites = true;
}
$max_dailies = intval(get_config('system','max_daily_registrations'));
@ -255,38 +254,36 @@ class Register extends Controller {
}
else {
$age = get_config('system','minimum_age');
if (!$age) {
if (! $age) {
$age = 13;
}
$label_tos = sprintf( t('I am over %s years of age and accept the %s for this website'), $age, $toslink);
}
$enable_tos = 1 - intval(get_config('system','no_termsofservice'));
$enable_tos = 1 - intval(get_config('system','no_termsofservice'));
$email = array('email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : ""));
$password = array('password', t('Choose a password'), '');
$password2 = array('password2', t('Please re-enter your password'), '');
$invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : ""));
$name = array('name', t('Your Name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real names are preferred.'));
$nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub));
$role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role for your usage needs and privacy requirements.'),$perm_roles);
$tos = array('tos', $label_tos, '', '', array(t('no'),t('yes')));
$email = [ 'email', t('Your email address'), ((x($_REQUEST,'email')) ? strip_tags(trim($_REQUEST['email'])) : "")];
$password = [ 'password', t('Choose a password'), '' ];
$password2 = [ 'password2', t('Please re-enter your password'), '' ];
$invite_code = [ 'invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : "")];
$name = [ 'name', t('Your Name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real names are preferred.') ];
$nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl'));
$nickname = [ 'nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub)];
$role = ['permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role for your usage needs and privacy requirements.'),$perm_roles];
$tos = [ 'tos', $label_tos, '', '', [ t('no'), t('yes') ] ];
$auto_create = (get_config('system','auto_channel_create') ? true : false);
$default_role = get_config('system','default_permissions_role');
$email_verify = get_config('system','verify_email');
require_once('include/bbcode.php');
$o = replace_macros(get_markup_template('register.tpl'), array(
$o = replace_macros(get_markup_template('register.tpl'), [
'$form_security_token' => get_form_security_token("register"),
'$title' => t('Registration'),
'$reg_is' => $registration_is,
'$registertext' => bbcode(get_config('system','register_text')),
'$other_sites' => $other_sites,
'$other_sites' => (($other_sites) ? t('<a href="sites">Show affiliated sites - some of which may allow registration.</a>') : EMPTY_STR),
'$invitations' => $invitations,
'$invite_code' => $invite_code,
'$auto_create' => $auto_create,
@ -301,7 +298,7 @@ class Register extends Controller {
'$pass2' => $password2,
'$submit' => t('Register'),
'$verify_note' => (($email_verify) ? t('This site requires email verification. After completing this form, please check your email for further instructions.') : ''),
));
] );
return $o;

105
Zotlabs/Module/Sites.php Normal file
View file

@ -0,0 +1,105 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Libzotdir;
class Sites extends \Zotlabs\Web\Controller {
function get() {
$o .= '<div class="generic-content-wrapper">';
$o .= '<div class="section-title-wrapper"><h2>' . t('Affiliated Sites') . '</h2></div>';
$o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
t('This page provides information about related projects and websites that are currently known to this system. These are a small fraction of the thousands of affiliated fediverse websites.') . '</div>' . EOL;
$j = [];
$r = q("select * from site where site_type = %d and site_flags != 256 and site_dead = 0",
intval(SITE_TYPE_ZOT)
);
if ($r) {
foreach ($r as $rr) {
if ($rr['site_access'] == ACCESS_FREE)
$access = 'free';
elseif ($rr['site_access'] == ACCESS_PAID)
$access = 'paid';
elseif ($rr['site_access'] == ACCESS_TIERED)
$access = 'tiered';
else
$access = 'private';
if ($rr['site_register'] == REGISTER_OPEN)
$register = 'open';
elseif ($rr['site_register'] == REGISTER_APPROVE)
$register = 'approve';
else
$register = 'closed';
$j[] = [ 'url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version'] ];
}
}
if ($j) {
$projects = $this->sort_sites($j);
foreach ($projects as $p => $v) {
if (! $p) {
continue;
}
$o .= '<strong>' . ucfirst($p) . '</strong>' . EOL;
$o .= '<table class="table table-striped table-hover"><tr><td style="width: 50%;">' . t('URL') . '</td><td style="width: 15%;">' . t('Access Type') . '</td><td style="width: 15%;">' . t('Registration Policy') . '</td><td style="width: 20%">' . t('Software') . '</td>';
$o .= '</tr>';
usort($v, [ $this, 'sort_versions' ]);
foreach ($v as $jj) {
if (strpos($jj['version'],' ')) {
$x = explode(' ', $jj['version']);
if ($x[1]) {
$jj['version'] = $x[1];
}
}
$m = parse_url($jj['url']);
$host = strtolower($m['host']);
$location = '<br>&nbsp;';
if (!empty($jj['location'])) {
$location = '<br><span title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</span>';
}
$disabled = (($jj['access'] === 'private') ? true : false);
$o .= '<tr><td>' . (($disabled) ? '' : '<a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="fa fa-link"></i> ') . $host . (($disabled) ? '' : '</a>') . $location . '</td><td>' . $jj['access'] . '</td><td>' . (($disabled) ? '&nbsp;' : $jj['register']) . '</td><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
$o .= '</tr>';
}
$o .= '</table>';
$o .= '<br><br>';
}
}
$o .= '</div></div>';
return $o;
}
function sort_sites($a) {
$ret = [];
if($a) {
foreach($a as $e) {
$projectname = explode(' ',$e['project']);
$ret[$projectname[0]][] = $e;
}
}
$projects = array_keys($ret);
rsort($projects);
$newret = [];
foreach($projects as $p) {
$newret[$p] = $ret[$p];
}
return $newret;
}
function sort_versions($a,$b) {
return version_compare($b['version'],$a['version']);
}
}

View file

@ -9,6 +9,26 @@ class Xp extends Controller {
if (argc() > 1) {
$path = 'cache/xp/' . substr(argv(1),0,2) . '/' . substr(argv(1),2,2) . '/' . argv(1);
if (! file_exists($path)) {
// no longer cached for some reason, perhaps expired
$resolution = substr(argv(1),(-2),2);
if ($resolution && substr($resolution,0,1) === '-') {
switch (substr($resolution,1,1)) {
case '4':
$path = get_default_profile_photo();
break;
case '5':
$path = get_default_profile_photo(80);
break;
case '6':
$path = get_default_profile_photo(48);
break;
default:
break;
}
}
}
if (! file_exists($path)) {
http_status_exit(404,'Not found');
}

46
Zotlabs/Update/_1242.php Normal file
View file

@ -0,0 +1,46 @@
<?php
namespace Zotlabs\Update;
class _1242 {
function run() {
q("START TRANSACTION");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE xchan ADD xchan_updated timestamp NOT NULL DEFAULT '0001-01-01 00:00:00' ");
$r2 = q("create index \"xchan_updated_idx\" on xchan (\"xchan_updated\")");
$r = ($r1 && $r2);
}
else {
$r = q("ALTER TABLE `xchan` ADD `xchan_updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' ,
ADD INDEX `xchan_updated` (`xchan_updated`)");
}
if($r) {
q("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
function verify() {
$columns = db_columns('xchan');
if(in_array('xchan_updated',$columns)) {
return true;
}
return false;
}
}

View file

@ -1,16 +0,0 @@
<?php
namespace Zotlabs\Widget;
class Pubsites {
// used by site ratings pages to provide a return link
function widget($arr) {
if(\App::$poi)
return;
return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>';
}
}

View file

@ -16,10 +16,10 @@ use Zotlabs\Daemon\Run;
* @brief This file defines some global constants and includes the central App class.
*/
define ( 'STD_VERSION', '20.08.26' );
define ( 'STD_VERSION', '20.09.03' );
define ( 'ZOT_REVISION', '6.0' );
define ( 'DB_UPDATE_VERSION', 1241 );
define ( 'DB_UPDATE_VERSION', 1242 );
define ( 'PLATFORM_NAME', 'zap' );
define ( 'PLATFORM_ARCHITECTURE', 'zap' );
@ -1602,9 +1602,6 @@ function login($register = false, $form_id = 'main-login', $hiddens = false, $lo
// Register links are enabled on the site home page and login page and navbar.
// They are not shown by default on other pages which may require login.
// If the register link is enabled and registration is closed, the request is directed
// to /pubsites. If registration is allowed, /register is the default destination
// system.register_link can over-ride the default behaviour and redirect to an arbitrary
// webpage for paid/custom or organisational registrations, regardless of whether
// registration is allowed.
@ -1627,7 +1624,7 @@ function login($register = false, $form_id = 'main-login', $hiddens = false, $lo
$register_policy = get_config('system','register_policy');
$reglink = get_config('system', 'register_link', z_root() . '/' . ((intval($register_policy) === REGISTER_CLOSED) ? 'pubsites' : 'register'));
$reglink = get_config('system', 'register_link', z_root() . '/register');
if($reglink !== 'none') {
$reg = [

BIN
images/redmatrix-64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
images/redmatrix.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

85
images/redmatrix.svg Normal file
View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="200"
height="200"
id="svg3053"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="redmatrix.svg">
<defs
id="defs3055" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="35.049163"
inkscape:cy="27.799654"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1871"
inkscape:window-height="1056"
inkscape:window-x="49"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata3058">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Laag 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-315.00002,-392.36223)"
style="display:inline">
<g
id="g2985"
transform="matrix(4.7619048,0,0,4.7619048,-1370.7143,-2042.6958)">
<path
style="fill:#c60032;fill-opacity:1"
d="m 218.0851,397.84091 c 0,12.77893 -10.00215,23.1383 -22.34043,23.1383 -12.33827,0 -22.34042,-10.35937 -22.34042,-23.1383 0,-12.77893 10.00215,-23.1383 22.34042,-23.1383 12.33828,0 22.34043,10.35937 22.34043,23.1383 z"
sodipodi:ry="23.138298"
sodipodi:rx="22.340425"
sodipodi:cy="397.84091"
sodipodi:cx="195.74467"
id="path3028-4-5-3"
sodipodi:type="arc"
transform="matrix(0.94,0,0,0.9075862,191.00001,171.28726)" />
<g
id="text3003-0-4-0"
style="font-size:46px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
transform="translate(52.138256,-208.57143)">
<path
inkscape:connector-curvature="0"
id="path3008"
style="font-size:45.09999847px;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ffffff;font-family:generic;-inkscape-font-specification:generic Bold"
d="m 322.85053,756.03406 4.7355,0 1.3079,-7.9827 4.8708,0 0,-4.4649 -4.1492,0 1.0373,-6.4944 4.9159,0 0,-4.4649 -4.1492,0 1.1275,-7.0356 -4.7355,0 -1.1275,7.0356 -5.1865,0 1.1275,-7.0356 -4.7355,0 -1.1275,7.0356 -5.0963,0 0,4.4649 4.3296,0 -1.0373,6.4944 -5.0963,0 0,4.4649 4.3747,0 -1.3079,7.9827 4.7355,0 1.3079,-7.9827 5.1865,0 -1.3079,7.9827 m 2.0295,-12.4476 -5.1865,0 1.0373,-6.4944 5.1865,0 -1.0373,6.4944" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -90,6 +90,15 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
}
}
$forums = get_forum_channels(local_channel(),1);
if($forums) {
foreach($forums as $f) {
$selected = (($single_group && $f['hash'] === $allow_cid[0]) ? ' selected = "selected" ' : '');
$groups .= '<option id="^' . $f['abook_id'] . '" value="^' . $f['xchan_hash'] . '"' . $selected . '>' . $f['xchan_name'] . '</option>' . "\r\n";
}
}
$tpl = get_markup_template("acl_selector.tpl");
$o = replace_macros($tpl, array(
'$showall' => $showall_caption,

View file

@ -372,6 +372,7 @@ function create_identity($arr) {
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
'xchan_name' => $ret['channel']['channel_name'],
'xchan_network' => 'zot6',
'xchan_updated' => datetime_convert(),
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
'xchan_system' => $system
@ -617,6 +618,7 @@ function change_channel_keys($channel) {
$xv['xchan_guid_sig'] = $sig;
$xv['xchan_hash'] = $hash;
$xv['xchan_pubkey'] = $key['pubkey'];
$xv['xchan_updated'] = datetime_convert();
xchan_store_lowlevel($xv);
$newxchan = $xv;
}
@ -2350,6 +2352,7 @@ function anon_identity_init($reqvars) {
'xchan_name' => $anon_name,
'xchan_url' => $anon_url,
'xchan_network' => 'anon',
'xchan_updated' => datetime_convert(),
'xchan_name_date' => datetime_convert()
]);
@ -2362,7 +2365,8 @@ function anon_identity_init($reqvars) {
$photo = z_root() . '/' . get_default_profile_photo(300);
$photos = import_remote_xchan_photo($photo,$hash);
if ($photos) {
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'anon' ",
$r = q("update xchan set xchan_updated = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'anon' ",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),

View file

@ -1003,6 +1003,7 @@ function import_author_unknown($x) {
'xchan_hash' => $x['url'],
'xchan_guid' => $x['url'],
'xchan_url' => $x['url'],
'xchan_updated' => datetime_convert(),
'xchan_name' => (($name) ? $name : t('(Unknown)')),
'xchan_name_date' => datetime_convert(),
'xchan_network' => 'unknown'
@ -1014,7 +1015,8 @@ function import_author_unknown($x) {
$photos = import_remote_xchan_photo($x['photo']['src'],$x['url']);
if($photos) {
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' and xchan_network = 'unknown'",
$r = q("update xchan set xchan_updated = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' and xchan_network = 'unknown'",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
@ -2401,12 +2403,21 @@ function send_status_notifications($post_id,$item) {
if($y)
$notify = false;
if (intval($item['item_private']) === 2) {
$notify_type = NOTIFY_MAIL;
}
else {
$notify_type = NOTIFY_COMMENT;
}
if(! $notify)
return;
Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'type' => $notify_type,
'from_xchan' => $item['author_xchan'],
'to_xchan' => $r[0]['channel_hash'],
'item' => $item,
@ -2487,8 +2498,11 @@ function tag_deliver($uid, $item_id) {
return;
}
// send mail (DM) notifications here, but only for top level posts.
// followups will be processed by send_status_notifications()
$mail_notify = false;
if ((! intval($item['item_wall'])) && intval($item['item_private']) === 2) {
if ((! $item['item_wall']) && intval($item['item_thread_top']) && $item['author_xchan'] !== $u['channel_hash'] && intval($item['item_private']) === 2) {
Enotify::submit(array(
'to_xchan' => $u['channel_hash'],
'from_xchan' => $item['author_xchan'],

View file

@ -1769,3 +1769,5 @@ function get_request_string($url) {
return '/' . ((count($a) > 3) ? $a[3] : EMPTY_STR);
}

View file

@ -3,6 +3,7 @@
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libzotdir;
use Zotlabs\Lib\Zotfinger;
use Zotlabs\Lib\ASCollection;
/**
* poco_load
@ -25,8 +26,13 @@ use Zotlabs\Lib\Zotfinger;
* @param string $xchan
* @param string $url
*/
function poco_load($xchan = '', $url = null) {
if (ap_poco_load($xchan)) {
return;
}
if($xchan && ! $url) {
$r = q("select xchan_connurl from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan)
@ -41,6 +47,12 @@ function poco_load($xchan = '', $url = null) {
return;
}
$max = intval(get_config('system','max_imported_follow',10));
if (! intval($max)) {
return;
}
$url = $url . '?f=&fields=displayName,hash,urls,photos' ;
logger('poco_load: ' . $url, LOGGER_DEBUG);
@ -104,6 +116,7 @@ function poco_load($xchan = '', $url = null) {
return;
}
$total = 0;
foreach($j['entry'] as $entry) {
@ -113,7 +126,8 @@ function poco_load($xchan = '', $url = null) {
$name = '';
$hash = '';
$rating = 0;
$network = '';
$name = $entry['displayName'];
$hash = $entry['hash'];
@ -123,7 +137,7 @@ function poco_load($xchan = '', $url = null) {
$profile_url = $url['value'];
continue;
}
if(in_array($url['type'], ['zot','zot6'] )) {
if(in_array($url['type'], ['zot6','activitypub'] )) {
$network = $url['type'];
$address = str_replace('acct:' , '', $url['value']);
continue;
@ -139,12 +153,18 @@ function poco_load($xchan = '', $url = null) {
}
}
if (! in_array($network, ['zot6' , 'activitypub'])) {
continue;
}
if((! $name) || (! $profile_url) || (! $profile_photo) || (! $hash) || (! $address)) {
logger('poco_load: missing data');
logger('poco_load: ' . print_r($entry,true), LOGGER_DATA);
continue;
}
$x = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
$x = q("select xchan_hash from xchan where ( xchan_hash = '%s' or xchan_url = '%s' ) order by xchan_network desc limit 1",
dbesc($hash),
dbesc($hash)
);
@ -152,13 +172,16 @@ function poco_load($xchan = '', $url = null) {
if(($x !== false) && (! count($x))) {
if($address) {
if(in_array($network, ['zot6'])) {
if(in_array($network, ['zot6' , 'activitypub'])) {
$wf = discover_by_webbie($profile_url);
if ($wf) {
$x = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
$x = q("select xchan_hash from xchan where ( xchan_hash = '%s' or xchan_url = '%s') order by xchan_network desc limit 1",
dbesc($wf),
dbesc($wf)
);
$hash = $wf;
if ($x) {
$hash = $x[0]['xchan_hash'];
}
}
if(! $x) {
continue;
@ -193,17 +216,126 @@ function poco_load($xchan = '', $url = null) {
intval($r[0]['xlink_id'])
);
}
$total ++;
if ($total > $max) {
break;
}
}
logger("poco_load: loaded $total entries",LOGGER_DEBUG);
q("delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - INTERVAL %s and xlink_static = 0",
dbesc($xchan),
db_utcnow(), db_quoteinterval('2 DAY')
db_utcnow(), db_quoteinterval('7 DAY')
);
}
function ap_poco_load($xchan) {
$max = intval(get_config('system','max_imported_follow',10));
if (! intval($max)) {
return;
}
if($xchan) {
$cl = get_xconfig($xchan,'activitypub','collections');
if (is_array($cl) && $cl) {
$url = ((array_key_exists('following',$cl)) ? $cl['following'] : '');
}
else {
return false;
}
}
if (! $url) {
logger('ap_poco_load: no url');
return;
}
$obj = new ASCollection($url, '', 0, $max);
$friends = $obj->get();
if (! $friends) {
return;
}
foreach($friends as $entry) {
$hash = EMPTY_STR;
$x = q("select xchan_hash from xchan where (xchan_hash = '%s' or xchan_url = '%s') order by xchan_network desc limit 1",
dbesc($entry),
dbesc($entry)
);
if ($x) {
$hash = $x[0]['xchan_hash'];
}
else {
// We've never seen this person before. Import them.
$wf = discover_by_webbie($entry);
if ($wf) {
$x = q("select xchan_hash from xchan where (xchan_hash = '%s' or xchan_url = '%s') order by xchan_network desc limit 1",
dbesc($wf),
dbesc($wf)
);
if ($x) {
$hash = $x[0]['xchan_hash'];
}
}
}
if (! $hash) {
continue;
}
$total ++;
$r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 0 limit 1",
dbesc($xchan),
dbesc($hash)
);
if(! $r) {
q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 0 ) ",
dbesc($xchan),
dbesc($hash),
intval(0),
dbesc(''),
dbesc(''),
dbesc(datetime_convert())
);
}
else {
q("update xlink set xlink_updated = '%s' where xlink_id = %d",
dbesc(datetime_convert()),
intval($r[0]['xlink_id'])
);
}
}
logger("ap_poco_load: loaded $total entries", LOGGER_DEBUG);
q("delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - INTERVAL %s and xlink_static = 0",
dbesc($xchan),
db_utcnow(),
db_quoteinterval('7 DAY')
);
return true;
}
function count_common_friends($uid,$xchan) {
$r = q("SELECT count(xlink_id) as total from xlink where xlink_xchan = '%s' and xlink_static = 0 and xlink_link in
@ -262,28 +394,8 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) {
intval($start)
);
if($r && count($r) >= ($limit -1))
return $r;
return (($r) ? $r : []);
$r2 = q("SELECT count(xlink_link) as total, xchan.* from xchan
left join xlink on xlink_link = xchan_hash
where xlink_xchan = ''
and not xlink_link in ( select abook_xchan from abook where abook_channel = %d )
and not xlink_link in ( select xchan from xign where uid = %d )
and xchan_hidden = 0
and xchan_deleted = 0
and xlink_static = 0
group by xchan_hash order by total desc limit %d offset %d ",
intval($uid),
intval($uid),
intval($limit),
intval($start)
);
if(is_array($r) && is_array($r2))
return array_merge($r,$r2);
return array();
}
// This function fetches a number of sitenames from the directory and searches them
@ -295,6 +407,19 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) {
function update_suggestions() {
// this function is no longer used
// remove any existing entries it once created
//
$r = q("delete from xlink where xlink_xchan = '' and xlink_static = 0",
db_utcnow(), db_quoteinterval('7 DAY')
);
// !!!!!
return;
// !!!!!
$dirmode = get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL);
if ($dirmode == DIRECTORY_MODE_STANDALONE) {

View file

@ -21,6 +21,7 @@ function xchan_store_lowlevel($arr) {
'xchan_connpage' => ((array_key_exists('xchan_connpage',$arr)) ? $arr['xchan_connpage'] : ''),
'xchan_name' => ((array_key_exists('xchan_name',$arr)) ? $arr['xchan_name'] : ''),
'xchan_network' => ((array_key_exists('xchan_network',$arr)) ? $arr['xchan_network'] : ''),
'xchan_updated' => ((array_key_exists('xchan_updated',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_updated']) : datetime_convert()),
'xchan_photo_date' => ((array_key_exists('xchan_photo_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_photo_date']) : NULL_DATE),
'xchan_name_date' => ((array_key_exists('xchan_name_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_name_date']) : NULL_DATE),
'xchan_hidden' => ((array_key_exists('xchan_hidden',$arr)) ? intval($arr['xchan_hidden']) : 0),
@ -102,6 +103,7 @@ function xchan_store($arr) {
$x['xchan_' . $k] = escape_tags($v);
}
$x['xchan_updated'] = datetime_convert();
$x['xchan_name_date'] = datetime_convert();
$x['xchan_photo_date'] = datetime_convert();
$x['xchan_system'] = false;
@ -128,7 +130,8 @@ function xchan_store($arr) {
if($update_photo && $arr['photo']) {
$photos = import_remote_xchan_photo($arr['photo'],$arr['hash']);
if ($photos) {
$x = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
$x = q("update xchan set xchan_updated = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
@ -139,7 +142,8 @@ function xchan_store($arr) {
}
}
if($update_name && $arr['name']) {
$x = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
$x = q("update xchan set xchan_updated = '%s', xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc(escape_tags($arr['name'])),
dbesc(datetime_convert()),
dbesc($arr['hash'])

View file

@ -1300,6 +1300,7 @@ CREATE TABLE IF NOT EXISTS `xchan` (
`xchan_connpage` char(191) NOT NULL DEFAULT '',
`xchan_name` char(191) NOT NULL DEFAULT '',
`xchan_network` char(191) NOT NULL DEFAULT '',
`xchan_updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`xchan_photo_date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`xchan_name_date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`xchan_hidden` tinyint(1) NOT NULL DEFAULT 0 ,
@ -1322,6 +1323,7 @@ CREATE TABLE IF NOT EXISTS `xchan` (
KEY `xchan_censored` (`xchan_censored`),
KEY `xchan_selfcensored` (`xchan_selfcensored`),
KEY `xchan_system` (`xchan_system`),
KEY `xchan_updated` (`xchan_updated`),
KEY `xchan_type` (`xchan_type`),
KEY `xchan_deleted` (`xchan_deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View file

@ -1283,6 +1283,7 @@ CREATE TABLE "xchan" (
"xchan_connpage" text NOT NULL DEFAULT '',
"xchan_name" text NOT NULL DEFAULT '',
"xchan_network" text NOT NULL DEFAULT '',
"xchan_updated" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
"xchan_photo_date" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
"xchan_name_date" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
"xchan_hidden" smallint NOT NULL DEFAULT '0',
@ -1299,6 +1300,7 @@ create index "xchan_addr" on xchan ("xchan_addr");
create index "xchan_name" on xchan ("xchan_name");
create index "xchan_network" on xchan ("xchan_network");
create index "xchan_url" on xchan ("xchan_url");
create index "xchan_updated" on xchan ("xchan_updated");
create index "xchan_connurl" on xchan ("xchan_connurl");
create index "xchan_follow" on xchan ("xchan_follow");
create index "xchan_hidden" on xchan ("xchan_hidden");

View file

@ -14,6 +14,9 @@ function ACL(backend_url) {
that.group_uids = [];
that.group_ids = [];
that.contact_uids = [];
that.contact_ids = [];
that.selected_id = '';
that.info = $("#acl-info");
@ -148,14 +151,28 @@ ACL.prototype.on_showall = function(event) {
ACL.prototype.on_showgroup = function(event) {
var xid = that.acl_select.children(":selected").val();
var cid = '';
if(xid.length && xid.substr(0,1) == '^') {
cid = xid.slice(1);
xid = '';
}
// preventDefault() isn't called here as we want state changes from update_view() to be applied to the radiobutton
event.stopPropagation();
that.allow_cid = [];
that.allow_gid = [xid];
that.deny_cid = [];
that.deny_gid = [];
if (xid.length) {
that.allow_cid = [];
that.allow_gid = [xid];
that.deny_cid = [];
that.deny_gid = [];
}
else {
that.allow_cid = [cid];
that.allow_gid = [];
that.deny_cid = [];
that.deny_gid = [];
}
that.update_view();
that.on_submit();
@ -307,6 +324,17 @@ ACL.prototype.update_view = function(value) {
$('#dbtn-jotnets').hide();
$('.profile-jot-net input').attr('disabled', 'disabled');
}
else if (that.allow_gid.length === 0 && that.allow_cid.length === 1 && that.deny_gid.length === 0 && that.deny_cid.length === 0 && value !== 'custom') {
that.list.hide(); //hide acl-list
that.info.hide(); //show acl-info
that.selected_id = that.contact_ids[that.allow_cid[0]];
that.update_select(that.selected_id);
/* jot acl */
$('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock');
$('#dbtn-jotnets').hide();
$('.profile-jot-net input').attr('disabled', 'disabled');
}
else {
that.list.show(); //show acl-list
@ -382,6 +410,21 @@ ACL.prototype.update_view = function(value) {
bthide.removeClass("btn-outline-danger").addClass("btn-danger");
$(this).removeClass("groupshow");
}
$(that.contact_uids[id]).each(function(i, v) {
if(uclass == "grouphide")
// we need attr selection here because the id can include an @ (diaspora/friendica xchans)
$('[id="g' + v + '"]').removeClass("groupshow");
if(uclass !== "") {
var cls = $('[id="g' + v + '"]').attr('class');
if( cls === undefined)
return true;
var hiding = cls.indexOf('grouphide');
if(hiding == -1)
$('[id="g' + v + '"]').addClass(uclass);
}
});
break;
}
});
}

View file

@ -67,9 +67,6 @@
{{include file="field_checkbox.tpl" field=$mirror_frontpage}}
{{include file="field_checkbox.tpl" field=$login_on_homepage}}
{{include file="field_checkbox.tpl" field=$enable_context_help}}
{{if $directory_server}}
{{include file="field_select.tpl" field=$directory_server}}
{{/if}}
<div class="settings-submit-wrapper" >
<button type="submit" name="page_site" class="btn btn-primary" value="1" >{{$submit}}</button>
</div>
@ -114,6 +111,7 @@
{{include file="field_checkbox.tpl" field=$verify_email}}
{{include file="field_checkbox.tpl" field=$show_like_counts}}
{{include file="field_checkbox.tpl" field=$ap_contacts}}
{{include file="field_checkbox.tpl" field=$block_public_dir}}
{{include file="field_checkbox.tpl" field=$force_publish}}
{{include file="field_checkbox.tpl" field=$disable_discover_tab}}
{{include file="field_checkbox.tpl" field=$site_firehose}}
@ -138,6 +136,7 @@
<div class="section-content-tools-wrapper">
{{include file="field_input.tpl" field=$imagick_path}}
{{include file="field_checkbox.tpl" field=$cache_images}}
{{include file="field_input.tpl" field=$max_imported_follow}}
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}
{{include file="field_input.tpl" field=$timeout}}

View file

@ -28,6 +28,13 @@
</div>
</div>
<div class="contact-info">
{{if $entry.network}}
<div class="contact-info-element">
<span class="contact-info-label">{{$entry.network_label}}</span> {{$entry.network}}
</div>
{{/if}}
{{if $entry.common_friends}}
<div id="dir-common" class="contact-info-element">
<span class="contact-info-label">{{$entry.common_label}}</span> {{$entry.common_count}}

View file

@ -86,12 +86,8 @@
</div>
<div id="profile-jot-submit-wrapper" class="clearfix p-2 jothidden">
<div id="profile-jot-submit-left" class="btn-toolbar float-left">
{{if $bbcode}}
<button id="jot-markup-toggle" class="btn btn-outline-secondary btn-sm" title="{{$text_style}}" onclick="openClose('jot-markup'); return false;">
<i class="fa fa-fw fa-chevron-right jot-icons"></i>
</button>
<div id="jot-markup" class="btn-group mr-2" style="display: none;">
{{if $bbcode}}
<div id="jot-markup" class="btn-group mr-2">
<button id="main-editor-bold" class="btn btn-outline-secondary btn-sm" title="{{$bold}}" onclick="inserteditortag('b', 'profile-jot-text'); return false;">
<i class="fa fa-bold jot-icons"></i>
</button>

View file

@ -6,6 +6,5 @@
{{/foreach}}
{{/if}}
<div class="clear"></div>
<!--disabled the more link until the zot and zot6 directories are merged due to conflicting results -->
<!--div class="suggest-widget-more"><a href="suggestions">{{$more}}</a></div-->
<div class="suggest-widget-more"><a href="suggestions">{{$more}}</a></div>
</div>