1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/hubzilla_ynh.git synced 2024-09-03 19:26:21 +02:00

Updated Hubzilla core and addons to v2.0.7. Updated installation scripts to support latest YunoHost.

This commit is contained in:
Andrew Manning 2017-02-05 10:11:01 -05:00
parent b1b31c03a2
commit 9f9d78396e
10820 changed files with 222588 additions and 1534961 deletions

View file

@ -1,8 +1,14 @@
# YunoHost App for Hubzilla Hub #
# YunoHost App for Hubzilla Hub
## Hubzilla
[Hubzilla](http://hubzilla.org) is a powerful platform for creating interconnected websites featuring a decentralized identity, communications, and permissions framework built using common webserver technology.
Current snapshot in *sources*:
* https://github.com/redmatrix/hubzilla: 2.0.7
* https://github.com/redmatrix/hubzilla-addons: >2.0 (commit 33a9a7f971097bcf14228b626bfb127559e47830)
## Notes
Before installing, read the [Hubzilla installation instructions](https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt) for important information about
@ -12,7 +18,38 @@ Before installing, read the [Hubzilla installation instructions](https://github.
- Required packages (all of these are not yet installed by this YunoHost installer package)
Current snapshot in *sources*:
* https://github.com/redmatrix/hubzilla: 1.8
* https://github.com/redmatrix/hubzilla-addons: 1.8
## Installation
### Register a new domain and add it to YunoHost
Hubzilla requires a dedicated domain, so obtain one and add it using the [YunoHost admin](https://reticu.li/yunohost/admin) panel. **Domains -> Add domain**
Once you have added the new domain to YunoHost, SSH into your YunoHost server and perform the following steps:
1. Install [certbot](https://certbot.eff.org/) to make installing free SSL certificates from Let's Encrypt simple.
1. Stop nginx
service nginx stop
1. Run the **certbot** utility with the **certonly** option
certbot certonly
1. Copy the generated certificate and key into the appropriate location for YunoHost to use
cp /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem /etc/yunohost/certs/YOUR_DOMAIN/crt.pem
cp /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem /etc/yunohost/certs/YOUR_DOMAIN/key.pem
1. Restart nginx
service nginx start
### Install the Hubzilla application
Use the [YunoHost admin](https://reticu.li/yunohost/admin) panel to install Hubzilla by entering the GitHub repo address in the custom app URL
https://github.com/YunoHost-Apps/hubzilla-yunohost
Make sure to select your domain from the previous section as the application domain. Also set the application to Public.
When installation is complete, you will need to visit your new hub and register a new account using the email address you specified in the app installation form. You should then be able to log in and create your first channel.

View file

@ -1,24 +0,0 @@
;; Test complet
auto_remove=1
; Manifest
domain="domain.tld" (DOMAIN)
admin="john" (USER)
adminemail="johndoe@example.com"
is_public="Yes" (PUBLIC|public=Yes|private=No)
; Checks
pkg_linter=1
setup_sub_dir=1
setup_root=1
setup_nourl=0
setup_private=1
setup_public=1
upgrade=1
backup_restore=1
multi_instance=0
wrong_user=1
wrong_path=1
incorrect_path=1
corrupt_source=0
fail_download_source=0
port_already_use=0
final_path_already_use=0

View file

@ -1,7 +1,7 @@
location YNH_WWW_PATH {
# Path to source
alias YNH_WWW_ALIAS/ ;
alias YNH_WWW_ALIAS ;
# Force https
if ($scheme = http) {
@ -25,9 +25,13 @@ location YNH_WWW_PATH {
location ~ "(^|/)\.git" { return 403; }
location ~ "(^|/)store" { return 403; }
autoindex off;
location / { if (!-e $request_filename){ rewrite ^(.*)$ /index.php?q=$1; } }
location ~ \.(out|log|gz)$ { deny all; }
location / {
rewrite ^/\.well\-known/.* /index.php?q=$1;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?q=$1;
}
}
# Include SSOWAT user panel.
include conf.d/yunohost_panel.conf.inc;
# include conf.d/yunohost_panel.conf.inc;
}

View file

@ -1,46 +1,50 @@
{
"name": "Hubzilla",
"packaging_format": 1,
"id": "hubzilla",
"name": "Hubzilla",
"description": {
"en": "Hubzilla is a decentralized publication platform and social network."
},
"licence": "CopyLeft",
"developer": {
"name": "Mike Macgirvin",
"email": "",
"url": "https://github.com/redmatrix/hubzilla"
"url": "https://github.com/redmatrix/hubzilla",
"license": "MIT",
"version": "2.0.7",
"maintainer": {
"name": "Andrew Manning",
"email": "andrew@reticu.li"
},
"multi_instance": false,
"services": [
"nginx",
"php5-fpm",
"mysql"
],
"requirements": {
"yunohost": ">= 2.4.0"
},
"multi_instance": "false",
"arguments": {
"install" : [
{
"name": "domain",
"type": "domain",
"ask": {
"en": "Choose a domain for your Hubzilla hub. Hubzilla must run in the root of this domain."
},
"example": "hub.example.com"
}
},
{
"name": "admin",
"type": "user",
"ask": {
"en": "Choose an admin user"
},
"example": "johndoe"
"en": "Choose the Hubzilla administrator (must be an existing YunoHost user)",
"fr": "Choisissez l'administrateur de Hubzilla (doit être un utilisateur YunoHost existant)"
}
},
{
"name": "adminemail",
"name": "email",
"ask": {
"en": "Email address for the Hubzilla hub admin"
},
"example": "johndoe@example.com"
},
{
"name": "is_public",
"ask": {
"en": "Is it a public application ?"
},
"choices": ["Yes", "No"],
"default": "Yes"
"example": "peter@example.com",
"optional": false
}
]
}

View file

@ -1,77 +1,95 @@
#!/bin/bash
app=hubzilla
#set -eu
# Retrieve arguments
domain=$1
admin=$2
adminemail=$3
is_public=$4
email=$3
app="hubzilla"
path="/"
# Save app settings
sudo yunohost app setting $app admin -v "$admin"
sudo yunohost app setting $app is_public -v "$is_public"
# Source app helpers
source /usr/share/yunohost/helpers
# Check user parameter
ynh_user_exists "$admin" \
|| ynh_die "The chosen admin user does not exist."
ynh_app_setting_set $app admin_user $admin
# Check destination directory
final_path="/var/www/$app"
[[ -d $final_path ]] && ynh_die \
"The destination directory '$DESTDIR' already exists.\
You should safely delete it before installing this app."
sudo yunohost app setting $app is_public -v "Yes"
# Check domain/path availability
sudo yunohost app checkurl $domain$path -a "$app"
if [[ ! $? -eq 0 ]]; then
exit 1
fi
sudo yunohost app checkurl "${domain}${path}" -a "$app" \
|| ynh_die "The path ${domain}${path} is not available for app installation."
# Install dependencies
sudo apt-get install -y -qq php5-cli php5-imagick php5-gd php5-mcrypt
# Generate random password
db_pwd=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d '[A-Za-z0-9]' | sed -n 's/\(.\{24\}\).*/\1/p')
# Use 'hubzilla' as database name and user
db_user=$app
db_name=$app
# Generate random password
dbpass=$(ynh_string_random)
# Initialize database and store mysql password for upgrade
sudo yunohost app initdb $db_user -p $db_pwd
sudo yunohost app setting $app mysqlpwd -v $db_pwd
sudo yunohost app initdb $db_user -p $dbpass
sudo yunohost app setting $app mysqlpwd -v $dbpass
#ynh_app_setting_set "$app" mysqlpwd "$dbpass"
# Copy source files
final_path=/var/www/$app
sudo mkdir -p $final_path
sudo rsync -va ../sources/ $final_path/
sudo mkdir -p "$final_path/store/[data]/smarty3"
sudo chmod -R 777 $final_path/store
# Import database schema
sudo mysql -u $db_user -p$db_pwd $db_user < $final_path/install/schema_mysql.sql
sudo mysql -u$db_user -p$dbpass $db_name < $final_path/install/schema_mysql.sql
# Copy the template install/htconfig.sample.php to .htconfig.php
sudo cp $final_path/install/htconfig.sample.php $final_path/.htconfig.php
# Use sed to add the database information to .htconfig.php
sudo sed -i "s/your.mysqlhost.com/localhost/g" $final_path/.htconfig.php
sudo sed -i "s/mysqlpassword/$db_pwd/g" $final_path/.htconfig.php
sudo sed -i "s/mysqlpassword/$dbpass/g" $final_path/.htconfig.php
sudo sed -i "s/mysqlusername/$db_user/g" $final_path/.htconfig.php
sudo sed -i "s/mysqldatabasename/$db_user/g" $final_path/.htconfig.php
sudo sed -i "s/myredsite.example/$domain/g" $final_path/.htconfig.php
sudo sed -i "s/[\'admin_email\'] = \'\';/[\'admin_email\'] = \'$adminemail\';/g" $final_path/.htconfig.php
sudo sed -i "s/if the auto install failed, put a unique random string here/$db_pwd$db_pwd$db_pwd/g" $final_path/.htconfig.php
sudo sed -i "s/mysqldatabasename/$db_name/g" $final_path/.htconfig.php
sudo sed -i "s/mysite.example/$domain/g" $final_path/.htconfig.php
sudo sed -i "s/if the auto install failed, put a unique random string here/$(ynh_string_random)$(ynh_string_random)$(ynh_string_random)/g" $final_path/.htconfig.php
sudo sed -i "s/ADMIN_EMAIL_REPLACE/$email/g" $final_path/.htconfig.php
# Set www-data to owner
sudo chown -R www-data: $final_path
# Set up poller
sed -i "s@YNH_WWW_PATH@$final_path@g" ../conf/poller-cron
sudo cp ../conf/poller-cron /etc/cron.d/poller-cron
# Modify Nginx configuration file and copy it to Nginx conf directory
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf
# If app is public, add url to SSOWat conf as skipped_uris
if [ "$is_public" = "Yes" ];
then
sudo yunohost app setting $app skipped_uris -v "/"
fi
# Modify php.ini to allow exec() function and increase the upload size limits
sudo sed -i 's/,pcntl_exec//g' /etc/php5/fpm/php.ini
sudo sed -i 's/^post_max_size =.*$/post_max_size = 256M/' /etc/php5/fpm/php.ini
sudo sed -i 's/^upload_max_filesize =.*$/upload_max_filesize = 256M/' /etc/php5/fpm/php.ini
sudo sed -i 's/^max_file_uploads =.*$/max_file_uploads = 50/' /etc/php5/fpm/php.ini
# Restart services
sudo service nginx reload
sudo yunohost app ssowatconf
# Set SSOwat rules
ynh_app_setting_set "$app" skipped_uris "/"
# Reload services
sudo service php5-fpm restart || true
sudo service nginx reload || true
# Set up poller
sed -i "s@YNH_WWW_PATH@$final_path@g" ../conf/poller-cron
sudo cp ../conf/poller-cron /etc/cron.d/$app

View file

@ -1,2 +0,0 @@
# Disable LF normalization for all files
* -text

View file

@ -1,70 +0,0 @@
## Ignore tmp, backup, logs and other junk files
*~
*.gz
*.out
*.bak
*.swp
*.log
*.lock
*.kate-swp
#Ignore emacs tempfiles
\#*
# patch attempts
*.orig
*.rej
# OSX .DS_Store files
.DS_Store
# version scripts (repo master only)
.version*
Thumbs.db
## Ignore RedMatrix site specific files and folders
.htconfig.php
favicon.*
addon/
custom/
/store/
# site apps
apps/
# default startpage
home.html
# page header plugin
pageheader.html
# Ignore site TOS
doc/SiteTOS.md
# themes except for redbasic
view/theme/*
! view/theme/redbasic
# site theme schemas
view/theme/redbasic/schema/default.php
# Doxygen API documentation, run 'doxygen util/Doxyfile' to generate it
doc/html/
# zotsh configuration files
.zotshrc
# external repositories for themes/addons
extend/
## exclude IDE files
# config files and folders from Eclipse
.project
.buildpath
.externalToolBuilders
.settings/
# NetBeans project folder
nbproject/
# Kdevelop project files
*.kdev4
# PHPStorm
.idea/
# composer files (at the moment composer is not officially supported and only used to add SabreDAV, we should add these)
composer.*
# When we include composer we should exclude vendor/
#vendor/
# Exclude at least some vendor test files, examples, etc.
vendor/sabre/*/tests/
vendor/sabre/*/examples/

View file

@ -1,164 +0,0 @@
# Hubzilla at Home next to your Router
Run hubzilla-setup.sh for an unattended installation of hubzilla.
The script is known to work with Debian 8.3 stable (Jessie)
+ Home-PC (Debian-8.3.0-amd64)
+ DigitalOcean droplet (Debian 8.3 x64 / 512 MB Memory / 20 GB Disk / NYC3)
# Step-by-Step Overwiew
## Preconditions
Hardware
+ Internet connection and router at home
+ Mini-pc connected to your router
+ USB drive for backups
Software
+ Fresh installation of Debian on your mini-pc
+ Router with open ports 80 and 443 for your Debian
## The basic steps (quick overview)
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your new debian (server)
- apt-get install git
- mkdir -p /var/www/html
- cd /var/www/html
- git clone https://github.com/redmatrix/hubzilla.git .
- cp .homeinstall/hubzilla-config.txt.template .homeinstall/hubzilla-config.txt
- nano .homeinstall/hubzilla-config.txt
- Enter your values there: db pass, domain, values for dyn DNS
- hubzilla-setup.sh as root
- ... wait, wait, wait until the script is finised
- reboot
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
# Step-by-Step in Detail
## Preparations Hardware
### Mini-PC
### Recommended: USB Drive for Backups
The installation will create a daily backup.
If the backup process does not find an external device than the backup goes to
the internal disk.
The USB drive must be compatible with an encrpyted filesystem LUKS + ext4.
## Preparations Software
### Install Debian Linux on the Mini-PC
Download the stable Debian at https://www.debian.org/
Create bootable USB drive with Debian on it. You could use the programm
unetbootin, https://en.wikipedia.org/wiki/UNetbootin
Switch of your mini pc, plug in your USB drive and start the mini pc from the
stick. Install Debian. Follow the instructions of the installation.
### Configure your Router
Open the ports 80 and 443 on your router for your Debian
## Preparations Dynamic IP Address
Your Hubzilla must be reachable by a domain that you can type in your browser
cooldomain.org
You can use subdomains as well
my.cooldomain.org
There are two way to get a domain
- buy a domain (recommended) or
- register a free subdomain
### Method 1: Get yourself an own Domain (recommended)
...for example at selfHOST.de
### Method 2 Register a (free) Subdomain
Register a free subdomain for example at
- freeDNS
- selfHOST
WATCH THIS: A free subdomain is not the prefered way to get a domain name. Why?
Let's encrpyt issues a limited number of certificates each
day. Possibly other users of this domain will try to issue a certificate
at the same day as you do. So make sure you choose a domain with as less subdomains as
possible.
## Install Hubzilla on your Debian
Login to your debian
(Provided your username is "you" and the name of the mini pc is "debian". You
could take the IP address instead of "debian")
ssh -X you@debian
Change to root user
su -l
Install git
apt-get install git
Make the directory for apache and change diretory to it
mkdir /var/www
cd /var/www/
Clone hubzilla from git ("git pull" will update it later)
git clone https://github.com/redmatrix/hubzilla html
Change to the install script
cd html/.homeinstall/
Copy the template file
cp hubzilla-config.txt.template hubzilla-config.txt
Change the file "hubzilla-config.txt". Read the instructions there and enter your values.
nano hubzilla-config.txt
Run the script
./hubzilla-setup.sh
Wait... The script should not finish with an error message.
In a webbrowser open your domain.
Expected: A test page of hubzilla is shown. All checks there shoulg be
successfull. Go on...
Expected: A page for the Hubzilla server configuration shows up.
Leave db server name "127.0.0.1" and port "0" untouched.
Enter
- DB user name = hubzilla
- DB pass word = This is the password you entered in "hubzilla-config.txt"
- DB name = hubzilla
Leave db type "MySQL" untouched.
Follow the instructions in the next pages.

View file

@ -1,177 +0,0 @@
###############################################
### MANDATORY - database password #############
#
# Please give your database password
# Example: db_pass=pass_word_with_no_blanks_in_it
# Example: db_pass="this password has blanks in it"
db_pass=
###############################################
### MANDATORY - let's encrypt #################
#
# Hubilla requires encrypted communication via secure HTTP (HTTPS).
# This script automates installation of an SSL certificate from
# Let's Encrypt (https://letsencrypt.org)
#
# Please give the domain name of your hub
#
# Example: my.cooldomain.org
# Example: cooldomain.org
#
# Email is optional
#
#
le_domain=
le_email=
###############################################
### OPTIONAL - selfHOST - dynamic IP address ##
#
# 1. Register a domain at selfhost.de
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 08.01.2016
# 2. Get your configuration for dynamic IP update
# - Log in at selfhost.de
# - go to "DynDNS Accounte"
# - klick "Details" of your (freshly) registered domain
# - You will find the configuration there
# - Benutzername (user name) > use this for "selfhost_user="
# - Passwort (pass word) > use this for "selfhost_pass="
#
#
selfhost_user=
selfhost_pass=
###############################################
### OPTIONAL - FreeDNS - dynamic IP address ###
#
# Please give the alpha-numeric-key of freedns
#
# Get a free subdomain from freedns and use it for your dynamic ip address
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
#
# - Register for a Free domain at http://freedns.afraid.org/signup/
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
# possible. Why? Let's encrpyt issues a limited count of certificates each
# day. Possible other users of this domain will try to issue a certificate
# at the same day.
# - Logon to FreeDNS (where you just registered)
# - Goto http://freedns.afraid.org/dynamic/
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
# - You should notice a large and unique alpha-numeric key in the URL
#
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
#
# Provided your url from freedns is
#
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
# Then you have to provide
#
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
#
#freedns_key=
###############################################
### OPTIONAL - Backup to external device ######
#
# The script can use an external device for the daily backup.
# The file system of the device (USB stick for example) must be compatible
# with encrypted LUKS + ext4
#
# You should test to mount the device befor you run the script
# (hubzilla-setup.sh).
# How to find your (pluged-in) devices?
#
# fdisk -l
#
# Provided your device was listed as is /dev/sdb1. You could check with:
#
# blkid | grep /dev/sdb1
#
# Try to decrypt
# (You might install cryptsetup befor using apt-get install.
#
# apt-get install cryptsetup
# cryptsetup luksOpen /dev/sdb1 cryptobackup
#
# Try to mount
# You might create the directory /media/hubzilla_backup it it does not exist
# using mkdir.
#
# mkdir /media/hubzilla_backup
# mount /dev/mapper/cryptobackup /media/hubzilla_backup
#
# Unmounting device goes like this
#
# umount /media/hubzilla_backup
# cryptsetup luksClose cryptobackup
#
# To check if still mounted
#
# lsof /media/hubzilla_backup
#
# If you leave the following parameters
# - "backup_device_name" and
# - "backup_device_pass"
# empty the script will create daily backups on the internal disk (which could
# save you as well).
#
# Example: backup_device_name=/dev/sdc1
#
backup_device_name=
backup_device_pass=
###############################################
### OPTIONAL - Owncloud - deprecated ##########
#
# To install owncloud: owncloud=y
# Leave empty if you don't want to install owncloud
#
#owncloud=
###############################################
### OPTIONAL - do not mess with things below ##
# (...if you are not certain)
#
# Usually you are done here
# Everything below is OPTIONAL
#
###############################################
#
# Database for hubzilla
hubzilla_db_name=hubzilla
hubzilla_db_user=hubzilla
hubzilla_db_pass=$db_pass
#
#
# Password for package mysql-server
# Example: mysqlpass=aberhallo
# Example: mysqlpass="aber hallo has blanks in it"
#
mysqlpass=$db_pass
# Password for package phpmyadmin
# Example: phpmyadminpass=aberhallo
# Example: phpmyadminpass="aber hallo has blanks in it"
phpmyadminpass=$db_pass
# TODO Prepare hubzilla for programmers
# - install eclipse and plugins
# - install xdebug to debug the php with eclipse
# - weaken permissions on /var/www/html
# - manual steps after this script
# * in eclipse: install plugins for php git hub
# * in eclipse: configure firefox (chrome,...) as browser to run with the php debuger
# * in eclipse: switch php debugger from zend to xdebug
# * in eclipse: add local hubzilla github repository
#
# Which user will use eclipse?
# Leave this empty if you do not want to prepare hubzilla for debugging
#
#developer_name=

View file

@ -1,949 +0,0 @@
#!/bin/bash
#
# How to use
# ----------
#
# This file automates the installation of hubzilla under Debian Linux
#
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
# Follow the instuctions there
#
# 2) Switch to user "root" by typing "su -"
#
# 3) Run with "./hubzilla-setup.sh"
# If this fails check if you can execute the script.
# - To make it executable type "chmod +x hubzilla-setup.sh"
# - or run "bash hubzilla-setup.sh"
#
#
# What does this script do basically?
# -----------------------------------
#
# This file automates the installation of hubzilla under Debian Linux
# - install
# * apache webserer,
# * php,
# * mysql - the database for hubzilla,
# * phpmyadmin,
# * git to download and update hubzilla itself
# - download hubzilla core and addons
# - configure cron
# * "poller.php" for regular background prozesses of hubzilla
# * to_do "apt-get update" and "apt-get dist-upgrade" to keep linux
# up-to-date
# * to_do backup hubzillas database and files (rsnapshot)
# - configure dynamic ip with cron
# - to_do letsencrypt
# - to_do redirection to https
#
#
# Discussion
# ----------
#
# Security - password is the same for mysql-server, phpmyadmin and hubzilla db
# - The script runs into installation errors for phpmyadmin if it uses
# different passwords. For the sake of simplicity one singel password.
#
# Security - suhosin for PHP
# - The script does not install suhosin.
# - Is the security package suhosin usefull or not usefull?
#
# Hubzilla - email verification
# - The script switches off email verification off in all htconfig.tpl.
# Example: /var/www/html/view/en/htconfig.tpl
# - Is this a silly idea or not?
#
#
# Remove Hubzilla (for a fresh start using the script)
# ----------------------------------------------------
#
# You could use /var/www/hubzilla-remove.sh
# that is created by hubzilla-setup.sh.
#
# The script will remove (almost everything) what was installed by the script.
# After the removal you could run the script again to have a fresh install
# of all applications including hubzilla and its database.
#
# How to restore from backup
# --------------------------
#
# Daily backup
# - - - - - -
#
# The installation
# - writes a script /var/www/hubzilla-daily.sh
# - creates a daily cron that runs the hubzilla-daily.sh
#
# hubzilla-daily.sh makes a (daily) backup of all relevant files
# - /var/lib/mysql/ > hubzilla database
# - /var/www/html/ > hubzilla from github
# - /var/www/letsencrypt/ > certificates
#
# hubzilla-daily.sh writes the backup
# - either to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
# - or to /var/cache/rsnapshot in case the external disk is not plugged in
#
# Restore backup
# - - - - - - -
#
# This was not tested yet.
# Bacically you can copy the files from the backup to the server.
#
# Credits
# -------
#
# The script is based on Thomas Willinghams script "debian-setup.sh"
# which he used to install the red#matrix.
#
# The script uses another script from https://github.com/lukas2511/letsencrypt.sh
#
# The documentation for bash is here
# https://www.gnu.org/software/bash/manual/bash.html
#
function check_sanity {
# Do some sanity checking.
print_info "Sanity check..."
if [ $(/usr/bin/id -u) != "0" ]
then
die 'Must be run by root user'
fi
if [ -f /etc/lsb-release ]
then
die "Distribution is not supported"
fi
if [ ! -f /etc/debian_version ]
then
die "Ubuntu is not supported"
fi
}
function check_config {
print_info "config check..."
# Check for required parameters
if [ -z "$db_pass" ]
then
die "db_pass not set in $configfile"
fi
if [ -z "$le_domain" ]
then
die "le_domain not set in $configfile"
fi
# backup is important and should be checked
if [ -n "$backup_device_name" ]
then
device_mounted=0
if fdisk -l | grep -i "$backup_device_name.*linux"
then
print_info "ok - filesystem of external device is linux"
if [ -n "$backup_device_pass" ]
then
echo "$backup_device_pass" | cryptsetup luksOpen $backup_device_name cryptobackup
if [ ! -d /media/hubzilla_backup ]
then
mkdir /media/hubzilla_backup
fi
if mount /dev/mapper/cryptobackup /media/hubzilla_backup
then
device_mounted=1
print_info "ok - could encrypt and mount external backup device"
umount /media/hubzilla_backup
else
print_warn "backup to external device will fail because encryption failed"
fi
cryptsetup luksClose cryptobackup
else
if mount $backup_device_name /media/hubzilla_backup
then
device_mounted=1
print_info "ok - could mount external backup device"
umount /media/hubzilla_backup
else
print_warn "backup to external device will fail because mount failed"
fi
fi
else
print_warn "backup to external device will fail because filesystem is either not linux or 'backup_device_name' is not correct in $configfile"
fi
if [ $device_mounted == 0 ]
then
die "backup device not ready"
fi
fi
}
function die {
echo "ERROR: $1" > /dev/null 1>&2
exit 1
}
function update_upgrade {
print_info "updated and upgrade..."
# Run through the apt-get update/upgrade first. This should be done before
# we try to install any package
apt-get -q -y update && apt-get -q -y dist-upgrade
print_info "updated and upgraded linux"
}
function check_install {
if [ -z "`which "$1" 2>/dev/null`" ]
then
# export DEBIAN_FRONTEND=noninteractive ... answers from the package
# configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $2
print_info "installed $2 installed for $1"
else
print_warn "$2 already installed"
fi
}
function nocheck_install {
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
print_info "installed $1"
}
function print_info {
echo -n -e '\e[1;34m'
echo -n $1
echo -e '\e[0m'
}
function print_warn {
echo -n -e '\e[1;31m'
echo -n $1
echo -e '\e[0m'
}
function stop_hubzilla {
if [ -d /etc/apache2 ]
then
print_info "stopping apache webserver..."
service apache2 stop
fi
if [ -f /etc/init.d/mysql ]
then
print_info "stopping mysql db..."
/etc/init.d/mysql stop
fi
}
function install_apache {
print_info "installing apache..."
nocheck_install "apache2 apache2-utils"
}
function install_curl {
print_info "installing curl..."
nocheck_install "curl"
}
function install_sendmail {
print_info "installing sendmail..."
nocheck_install "sendmail sendmail-bin"
}
function install_php {
# openssl and mbstring are included in libapache2-mod-php5
# to_to: php5-suhosin
print_info "installing php..."
nocheck_install "libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd"
php5enmod mcrypt
}
function install_mysql {
# http://www.microhowto.info/howto/perform_an_unattended_installation_of_a_debian_package.html
#
# To determine the required package name, key and type you can perform
# a trial installation then search the configuration database.
#
# debconf-get-selections | grep mysql-server
#
# The command debconf-get-selections is provided by the package
# debconf-utils, which you may need to install.
#
# apt-get install debconf-utils
#
# If you want to supply an answer to a configuration question but do not
# want to be prompted for it then this can be arranged by preseeding the
# DebConf database with the required information.
#
# echo mysql-server-5.5 mysql-server/root_password password xyzzy | debconf-set-selections
# echo mysql-server-5.5 mysql-server/root_password_again password xyzzy | debconf-set-selections
#
print_info "installing mysql..."
if [ -z "$mysqlpass" ]
then
die "mysqlpass not set in $configfile"
fi
echo mysql-server-5.5 mysql-server/root_password password $mysqlpass | debconf-set-selections
echo mysql-server-5.5 mysql-server/root_password_again password $mysqlpass | debconf-set-selections
nocheck_install "php5-mysql mysql-server mysql-client"
php5enmod mcrypt
}
function install_phpmyadmin {
print_info "installing phpmyadmin..."
if [ -z "$phpmyadminpass" ]
then
die "phpmyadminpass not set in $configfile"
fi
echo phpmyadmin phpmyadmin/setup-password password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/app-pass password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/app-password-confirm password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/admin-pass password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/password-confirm password $phpmyadminpass | debconf-set-selections
echo phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2 | debconf-set-selections
nocheck_install "phpmyadmin"
# It seems to be not neccessary to check rewrite.load because it comes
# with the installation. To be sure you could check this manually by:
#
# nano /etc/apache2/mods-available/rewrite.load
#
# You should find the content:
#
# LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
a2enmod rewrite
if [ ! -f /etc/apache2/apache2.conf ]
then
die "could not find file /etc/apache2/apache2.conf"
fi
sed -i \
"s/AllowOverride None/AllowOverride all/" \
/etc/apache2/apache2.conf
if [ -z "`grep 'Include /etc/phpmyadmin/apache.conf' /etc/apache2/apache2.conf`" ]
then
echo "Include /etc/phpmyadmin/apache.conf" >> /etc/apache2/apache2.conf
fi
service apache2 restart
}
function create_hubzilla_db {
print_info "creating hubzilla database..."
if [ -z "$hubzilla_db_name" ]
then
die "hubzilla_db_name not set in $configfile"
fi
if [ -z "$hubzilla_db_user" ]
then
die "hubzilla_db_user not set in $configfile"
fi
if [ -z "$hubzilla_db_pass" ]
then
die "hubzilla_db_pass not set in $configfile"
fi
Q1="CREATE DATABASE IF NOT EXISTS $hubzilla_db_name;"
Q2="GRANT USAGE ON *.* TO $hubzilla_db_user@localhost IDENTIFIED BY '$hubzilla_db_pass';"
Q3="GRANT ALL PRIVILEGES ON $hubzilla_db_name.* to $hubzilla_db_user@localhost identified by '$hubzilla_db_pass';"
Q4="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}"
mysql -uroot -p$phpmyadminpass -e "$SQL"
}
function run_freedns {
print_info "run freedns (dynamic IP)..."
if [ -z "$freedns_key" ]
then
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
else
if [ -n "$selfhost_user" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
wget --no-check-certificate -O - https://freedns.afraid.org/dynamic/update.php?$freedns_key
fi
}
function install_run_selfhost {
print_info "install and start selfhost (dynamic IP)..."
if [ -z "$selfhost_user" ]
then
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
else
if [ -n "$freedns_key" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
if [ -z "$selfhost_pass" ]
then
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
fi
if [ ! -d $selfhostdir ]
then
mkdir $selfhostdir
fi
# the old way
# https://carol.selfhost.de/update?username=123456&password=supersafe
#
# the prefered way
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
echo "router" > $selfhostdir/device
echo "$selfhost_user" > $selfhostdir/user
echo "$selfhost_pass" > $selfhostdir/pass
bash $selfhostdir/$selfhostscript update
fi
}
function ping_domain {
print_info "ping domain $domain..."
# Is the domain resolved? Try to ping 6 times à 10 seconds
COUNTER=0
for i in {1..6}
do
print_info "loop $i for ping -c 1 $domain ..."
if ping -c 4 -W 1 $le_domain
then
print_info "$le_domain resolved"
break
else
if [ $i -gt 5 ]
then
die "Failed to: ping -c 1 $domain not resolved"
fi
fi
sleep 10
done
sleep 5
}
function configure_cron_freedns {
print_info "configure cron for freedns..."
if [ -z "$freedns_key" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
then
echo "@reboot root https://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
echo "*/30 * * * * root wget --no-check-certificate -O - https://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for freedns was configured already"
fi
fi
}
function configure_cron_selfhost {
print_info "configure cron for selfhost..."
if [ -z "$selfhost_user" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
then
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for selfhost was configured already"
fi
fi
}
function install_git {
print_info "installing git..."
nocheck_install "git"
}
function install_letsencrypt {
print_info "installing let's encrypt ..."
# check if user gave domain
if [ -z "$le_domain" ]
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
fi
# configure apache
apache_le_conf=/etc/apache2/sites-available/le-default.conf
if [ -f $apache_le_conf ]
then
print_info "$apache_le_conf exist already"
else
cat > $apache_le_conf <<END
# letsencrypt default Apache configuration
Alias /.well-known/acme-challenge /var/www/letsencrypt
<Directory /var/www/letsencrypt>
Options FollowSymLinks
Allow from all
</Directory>
END
a2ensite le-default.conf
service apache2 restart
fi
# download the shell script
if [ -d $le_dir ]
then
print_info "letsenrypt exists already (nothing downloaded > no certificate created and registered)"
return 0
fi
git clone https://github.com/lukas2511/letsencrypt.sh $le_dir
cd $le_dir
# create config file for letsencrypt.sh
echo "WELLKNOWN=$le_dir" > $le_dir/config.sh
if [ -n "$le_email" ]
then
echo "CONTACT_EMAIL=$le_email" >> $le_dir/config.sh
fi
# create domain file for letsencrypt.sh
# WATCH THIS:
# - It did not work wit "sub.domain.org www.sub.domain.org".
# - So just use "sub.domain.org" only!
echo "$le_domain" > $le_dir/domains.txt
# test apache config for letsencrpyt
url_http=http://$le_domain/.well-known/acme-challenge/domains.txt
wget_output=$(wget -nv --spider --max-redirect 0 $url_http)
if [ $? -ne 0 ]
then
die "Failed to load $url_http"
fi
# run letsencrypt.sh
#
./letsencrypt.sh --cron
}
function configure_apache_for_https {
print_info "configuring apache to use httpS ..."
# letsencrypt.sh
#
# "${BASEDIR}/certs/${domain}/privkey.pem"
# "${BASEDIR}/certs/${domain}/cert.pem"
# "${BASEDIR}/certs/${domain}/fullchain.pem"
#
SSLCertificateFile=${le_dir}/certs/${le_domain}/cert.pem
SSLCertificateKeyFile=${le_dir}/certs/${le_domain}/privkey.pem
SSLCertificateChainFile=${le_dir}/certs/${le_domain}/fullchain.pem
if [ ! -f $SSLCertificateFile ]
then
print_warn "Failed to configure apache for httpS: Missing certificate file $SSLCertificateFile"
return 0
fi
# make sure that the ssl mode is enabled
print_info "...configuring apache to use httpS - a2enmod ssl ..."
a2enmod ssl
# modify apach' ssl conf file
if grep -i "ServerName" $sslconf
then
print_info "seems that apache was already configered to use httpS with $sslconf"
else
sed -i "s/ServerAdmin.*$/ServerAdmin webmaster@localhost\\n ServerName ${le_domain}/" $sslconf
fi
sed -i s#/etc/ssl/certs/ssl-cert-snakeoil.pem#$SSLCertificateFile# $sslconf
sed -i s#/etc/ssl/private/ssl-cert-snakeoil.key#$SSLCertificateKeyFile# $sslconf
sed -i s#/etc/apache2/ssl.crt/server-ca.crt#$SSLCertificateChainFile# $sslconf
sed -i s/#SSLCertificateChainFile/SSLCertificateChainFile/ $sslconf
# apply changes
a2ensite default-ssl.conf
service apache2 restart
}
function check_https {
print_info "checking httpS > testing ..."
url_https=https://$le_domain
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
if [ $? -ne 0 ]
then
print_warn "check not ok"
else
print_info "check ok"
fi
}
function install_hubzilla {
print_info "installing hubzilla..."
# rm -R /var/www/html/ # for "stand alone" usage
cd /var/www/
# git clone https://github.com/redmatrix/hubzilla html # for "stand alone" usage
cd html/
git clone https://github.com/redmatrix/hubzilla-addons addon
mkdir -p "store/[data]/smarty3"
chmod -R 777 store
touch .htconfig.php
chmod ou+w .htconfig.php
install_hubzilla_plugins
cd /var/www/
chown -R www-data:www-data html
chown root:www-data /var/www/html/
chown root:www-data /var/www/html/.htaccess
chmod 0644 /var/www/html/.htaccess
# try to switch off email registration
sed -i "s/verify_email.*1/verify_email'] = 0/" /var/www/html/view/*/ht*
if [ -n "`grep -r 'verify_email.*1' /var/www/html/view/`" ]
then
print_warn "Hubzillas registration prozess might have email verification switched on."
fi
print_info "installed hubzilla"
}
function install_hubzilla_plugins {
print_info "installing hubzilla plugins..."
cd /var/www/html
plugin_install=.homeinstall/plugin_install.txt
theme_install=.homeinstall/theme_install.txt
# overwrite script to update the plugin and themes
rm -f $plugins_update
echo "cd /var/www/html" >> $plugins_update
###################
# write plugin file
if [ ! -f "$plugin_install" ]
then
echo "# To install a plugin" >> $plugin_install
echo "# 1. add the plugin in a new line and run" >> $plugin_install
echo "# 2. run" >> $plugin_install
echo "# cd /var/www/html/.homeinstall" >> $plugin_install
echo "# ./hubzilla-setup.sh" >> $plugin_install
echo "https://gitlab.com/zot/ownmapp.git ownMapp" >> $plugin_install
echo "https://gitlab.com/zot/hubzilla-chess.git chess" >> $plugin_install
fi
# install plugins
while read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
p_url=$(echo $line | awk -F' ' '{print $1}')
p_name=$(echo $line | awk -F' ' '{print $2}')
# basic check of format
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
then
# install addon
util/add_addon_repo $line
util/update_addon_repo $p_name # not sure if this line is neccessary
echo "util/update_addon_repo $p_name" >> $plugins_update
else
print_info "skipping installation of a plugin from file $plugin_install - something wrong with format in line: $line"
fi
done < "$plugin_install"
###################
# write theme file
if [ ! -f "$theme_install" ]
then
echo "# To install a theme" >> $theme_install
echo "# 1. add the theme in a new line and run" >> $theme_install
echo "# 2. run" >> $theme_install
echo "# cd /var/www/html/.homeinstall" >> $theme_install
echo "# ./hubzilla-setup.sh" >> $theme_install
echo "https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes" >> $theme_install
fi
# install plugins
while read -r line; do
[[ "$line" =~ ^#.*$ ]] && continue
p_url=$(echo $line | awk -F' ' '{print $1}')
p_name=$(echo $line | awk -F' ' '{print $2}')
# basic check of format
if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ]
then
# install addon
util/add_theme_repo $line
util/update_theme_repo $p_name # not sure if this line is neccessary
echo "util/update_theme_repo $p_name" >> $plugins_update
else
print_info "skipping installation of a theme from file $theme_install - something wrong with format in line: $line"
fi
done < "$theme_install"
print_info "installed hubzilla plugins and themes"
}
function rewrite_to_https {
print_info "configuring apache to redirect http to httpS ..."
htaccessfile=/var/www/html/.htaccess
if grep -i "https" $htaccessfile
then
print_info "...configuring apache to redirect http to httpS was already done in $htaccessfile"
else
sed -i "s#QSA]#QSA]\\n RewriteCond %{SERVER_PORT} !^443$\\n RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]#" $htaccessfile
fi
service apache2 restart
}
function install_owncloud {
if [ -z "$owncloud" ]
then
print_info "Do not install owncloud"
return 0
fi
if [ -f /etc/apt/sources.list.d/owncloud.list ]
then
print_info "owncloud is already installed and is left untouched"
return 0
fi
print_info "installing owncloud..."
# add the repository key to apt
wget -nv https://download.owncloud.org/download/repositories/stable/Debian_8.0/Release.key -O Release.key
apt-key add - < Release.key
# add the repository and install from there
sh -c "echo 'deb http://download.owncloud.org/download/repositories/stable/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud.list"
apt-get update
nocheck_install "owncloud"
chown -R www-data:www-data /var/www/owncloud/
# set strong permissions
ocpath='/var/www/owncloud'
htuser='www-data'
htgroup='www-data'
rootuser='root' # On QNAP this is admin
find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750
chown -R ${rootuser}:${htgroup} ${ocpath}/
chown -R ${htuser}:${htgroup} ${ocpath}/apps/
chown -R ${htuser}:${htgroup} ${ocpath}/config/
chown -R ${htuser}:${htgroup} ${ocpath}/data/
chown -R ${htuser}:${htgroup} ${ocpath}/themes/
chown ${rootuser}:${htgroup} ${ocpath}/.htaccess
chown ${rootuser}:${htgroup} ${ocpath}/data/.htaccess
chmod 0644 ${ocpath}/.htaccess
chmod 0644 ${ocpath}/data/.htaccess
}
# This will allways overwrite both config files
# - internal disk
# - external disk (LUKS + ext4)
# of rsnapshot for hubzilla
function install_rsnapshot {
print_info "installing rsnapshot..."
nocheck_install "rsnapshot"
# internal disk
cp -f /etc/rsnapshot.conf $snapshotconfig
sed -i "/hourly/s/retain/#retain/" $snapshotconfig
sed -i "/monthly/s/#retain/retain/" $snapshotconfig
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig
sed -i "s/^backup/#backup/" $snapshotconfig
if [ -z "`grep 'letsencrypt' $snapshotconfig`" ]
then
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
fi
# external disk
if [ -n "$backup_device_name" ] && [ -n "$backup_device_pass" ]
then
cp -f /etc/rsnapshot.conf $snapshotconfig_external_device
sed -i "s#snapshot_root.*#snapshot_root $backup_mount_point#" $snapshotconfig_external_device
sed -i "/hourly/s/retain/#retain/" $snapshotconfig_external_device
sed -i "/monthly/s/#retain/retain/" $snapshotconfig_external_device
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig_external_device
sed -i "s/^backup/#backup/" $snapshotconfig_external_device
if [ -z "`grep 'letsencrypt' $snapshotconfig_external_device`" ]
then
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig_external_device
echo "backup /var/www/html/ localhost/" >> $snapshotconfig_external_device
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig_external_device
fi
else
print_info "No backup configuration (rsnapshot) for external device configured. Reason: backup_device_name and/or backup_device_pass not given in $configfile"
fi
}
function install_cryptosetup {
print_info "installing cryptsetup..."
nocheck_install "cryptsetup"
}
function configure_cron_daily {
print_info "configuring cron..."
# every 10 min for poller.php
if [ -z "`grep 'poller.php' /etc/crontab`" ]
then
echo "*/10 * * * * www-data cd /var/www/html; php include/poller.php >> /dev/null 2>&1" >> /etc/crontab
fi
# Run external script daily at 05:30
# - stop apache and mysql-server
# - backup hubzilla
# - update hubzilla core and addon
# - update and upgrade linux
# - reboot
echo "#!/bin/sh" > /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "echo \" \"" >> /var/www/$hubzilladaily
echo "echo \"+++ \$(date) +++\"" >> /var/www/$hubzilladaily
echo "echo \" \"" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - renew certificat if 30 days old...\"" >> /var/www/$hubzilladaily
echo "bash /var/www/letsencrypt/letsencrypt.sh --cron" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "# stop hubzilla" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - stoping apaache and mysql...\"" >> /var/www/$hubzilladaily
echo "service apache2 stop" >> /var/www/$hubzilladaily
echo "/etc/init.d/mysql stop # to avoid inconsistancies" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "# backup" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$hubzilladaily
echo "backup_device_name=$backup_device_name" >> /var/www/$hubzilladaily
echo "backup_device_pass=$backup_device_pass" >> /var/www/$hubzilladaily
echo "backup_mount_point=$backup_mount_point" >> /var/www/$hubzilladaily
echo "device_mounted=0" >> /var/www/$hubzilladaily
echo "if [ -n \"$backup_device_name\" ]" >> /var/www/$hubzilladaily
echo "then" >> /var/www/$hubzilladaily
echo " if blkid | grep $backup_device_name" >> /var/www/$hubzilladaily
echo " then" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"decrypting backup device...\"" >> /var/www/$hubzilladaily
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$hubzilladaily
fi
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$hubzilladaily
echo " then" >> /var/www/$hubzilladaily
echo " mkdir $backup_mount_point" >> /var/www/$hubzilladaily
echo " fi" >> /var/www/$hubzilladaily
echo " echo \"mounting backup device...\"" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$hubzilladaily
else
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hubzilladaily
fi
echo " then" >> /var/www/$hubzilladaily
echo " device_mounted=1" >> /var/www/$hubzilladaily
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device daily" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device weekly" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig_external_device monthly" >> /var/www/$hubzilladaily
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
echo " df -h" >> /var/www/$hubzilladaily
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
echo " du -h $backup_mount_point | grep mysql/hubzilla" >> /var/www/$hubzilladaily
echo " echo \"unmounting backup device...\"" >> /var/www/$hubzilladaily
echo " umount $backup_mount_point" >> /var/www/$hubzilladaily
echo " else" >> /var/www/$hubzilladaily
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$hubzilladaily
echo " fi" >> /var/www/$hubzilladaily
if [ -n "$backup_device_pass" ]
then
echo " echo \"closing decrypted backup device...\"" >> /var/www/$hubzilladaily
echo " cryptsetup luksClose cryptobackup" >> /var/www/$hubzilladaily
fi
echo " fi" >> /var/www/$hubzilladaily
echo "fi" >> /var/www/$hubzilladaily
echo "if [ \$device_mounted == 0 ]" >> /var/www/$hubzilladaily
echo "then" >> /var/www/$hubzilladaily
echo " echo \"device could not be mounted $backup_device_name. Using internal disk for backup...\"" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig daily" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig weekly" >> /var/www/$hubzilladaily
echo " rsnapshot -c $snapshotconfig monthly" >> /var/www/$hubzilladaily
echo "fi" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
echo "du -h /var/cache/rsnapshot/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "# update" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating letsencrypt.sh...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/letsencrypt/ pull" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating hubhilla core...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/html/ pull" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating hubhilla addons...\"" >> /var/www/$hubzilladaily
echo "git -C /var/www/html/addon/ pull" >> /var/www/$hubzilladaily
echo "bash /var/www/html/$plugins_update" >> /var/www/$hubzilladaily
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
echo "apt-get -q -y update && apt-get -q -y dist-upgrade # update linux and upgrade" >> /var/www/$hubzilladaily
echo "echo \"\$(date) - Backup hubzilla and update linux finished. Rebooting...\"" >> /var/www/$hubzilladaily
echo "#" >> /var/www/$hubzilladaily
echo "reboot" >> /var/www/$hubzilladaily
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
then
echo "30 05 * * * root /bin/bash /var/www/$hubzilladaily >> /var/www/html/hubzilla-daily.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm /var/www/html/hubzilla-daily.log" >> /etc/crontab
fi
# This is active after either "reboot" or "/etc/init.d/cron reload"
print_info "configured cron for updates/upgrades"
}
function write_uninstall_script {
print_info "writing uninstall script..."
cat > /var/www/hubzilla-remove.sh <<END
#!/bin/sh
#
# This script removes Hubzilla.
# You might do this for a fresh start using the script.
# The script will remove (almost everything) what was installed by the script,
# all applications including hubzilla and its database.
#
# Backup the certificates of letsencrypt (you never know)
cp -a /var/www/letsencrypt/ ~/backup_le_certificats
#
# Removal
apt-get remove apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
apt-get purge apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
apt-get autoremove
apt-get clean
rm /etc/rsnapshot_hubzilla.conf
rm /etc/rsnapshot_hubzilla_external_device.conf
rm -R /etc/apache2/
rm -R /var/lib/mysql/
rm -R /var/www
rm -R /etc/selfhost/
# uncomment the next line if you want to remove the backups
# rm -R /var/cache/rsnapshot
nano /etc/crontab # remove entries there manually
END
chmod -x /var/www/hubzilla-remove.sh
}
########################################################################
# START OF PROGRAM
########################################################################
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
check_sanity
# Read config file edited by user
configfile=hubzilla-config.txt
source $configfile
selfhostdir=/etc/selfhost
selfhostscript=selfhost-updater.sh
hubzilladaily=hubzilla-daily.sh
plugins_update=.homeinstall/plugins_update.sh
snapshotconfig=/etc/rsnapshot_hubzilla.conf
snapshotconfig_external_device=/etc/rsnapshot_hubzilla_external_device.conf
backup_mount_point=/media/hubzilla_backup
le_dir=/var/www/letsencrypt
sslconf=/etc/apache2/sites-available/default-ssl.conf
#set -x # activate debugging from here
check_config
stop_hubzilla
update_upgrade
install_curl
install_sendmail
install_apache
install_php
install_mysql
install_phpmyadmin
create_hubzilla_db
run_freedns
install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
install_git
install_letsencrypt
configure_apache_for_https
check_https
install_hubzilla
rewrite_to_https
# install_owncloud # deprecated
install_rsnapshot
configure_cron_daily
install_cryptosetup
write_uninstall_script
#set +x # stop debugging from here

View file

@ -1,34 +0,0 @@
Options -Indexes
AddType application/x-java-archive .jar
AddType audio/ogg .oga
#SSLCipherSuite HIGH:AES256-SHA:AES128-SHA:RC4:!aNULL:!eNULL:!EDH
# don't allow any web access to logfiles, even after rotation/compression
<FilesMatch "\.(out|log|gz)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine on
# Protect repository directory from browsing
RewriteRule "(^|/)\.git" - [F]
RewriteRule "(^|/)store" - [F]
# Rewrite current-style URLs of the form 'index.php?q=x'.
# Also place auth information into REMOTE_USER for sites running
# in CGI mode.
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
</IfModule>

View file

@ -1,94 +0,0 @@
#Hubzilla on OpenShift
You will notice a new .openshift folder when you fetch from upstream, i.e. from https://github.com/redmatrix/hubzilla.git , which contains a deploy script to set up Hubzilla on OpenShift.
Create an account on OpenShift, then use the registration e-mail and password to create your first Hubzilla instance. Install git and RedHat's command line tools - rhc - if you have not already done so.
```
rhc app-create your_app_name php-5.4 mysql-5.5 cron phpmyadmin --namespace your_domain --from-code https://github.com/redmatrix/hubzilla.git -l your@email.address -p your_account_password
```
Make a note of the database username and password OpenShift creates for your instance, and use these at https://your_app_name-your_domain.rhcloud.com/ to complete the setup.
NOTE: PostgreSQL is NOT supported by the deploy script yet.
Update
To update, consider your own workflow first. I have forked Hubzilla code into my GitHub account to be able to try things out, this remote repo is called origin. Here is how I fetch new code from upstream, merge into my local repo, then push the updated code both into origin and the remote repo called openshift.
```
git fetch upstream;git checkout master;git merge upstream/master;git push origin;git push openshift HEAD
```
##Administration
Symptoms of need for MySQL database administration are:
- you can visit your domain and see the Hubzilla frontpage, but trying to login throws you back to login. This can mean your session table is marked as crashed.
- you can login, but your channel posts are not visible. This can mean your item table is marked as crashed.
- you can login and you can see your channel posts, but apparently nobody is getting your posts, comments, likes and so on. This can mean your outq table is marked as crashed.
You can check your OpenShift logs by doing
```
rhc tail -a your_app_name -n your_domain -l your@email.address -p your_account_password
```
and you might be able to confirm the above suspicions about crashed tables, or other problems you need to fix.
###How to fix crashed tables in MySQL
Using MySQL and the MyISAM database engine can result in table indexes coming out of sync, and you have at least two options for fixing tables marked as crashed.
- Use the database username and password OpenShift creates for your instance at https://your_app_name-your_domain.rhcloud.com/phpmyadmin/ to login via the web into your phpMyAdmin web interface, click your database in the left column, in the right column scroll down to the bottom of the list of tables and click the checkbox for marking all tables, then select Check tables from the drop down menu. This will check the tables for problems, and you can then checkmark only those tables with problems, and select Repair table from the same drop down menu at the bottom.
- You can login to your instance with SSH - see OpenShift for details - then
```
cd mysql/data/your_database
myisamchk -r *.MYI
```
or if you get
```
Can't create new tempfile
```
check your OpenShift's gear quota with
```
quota -gus
```
and if you are short on space, then locally (not SSH) do
```
rhc app-tidy your_app_name -l your_login -p your_password
```
to have rhc delete temporary files and OpenShift logs to free space first, then check the size of your local repo dir and execute
```
git gc
```
against it and check the size again, and then to minimize your remote repo connect via SSH to your application gear and execute the same command against it by changing to the remote repo directory - your repo should be in
```
~/git/your_app_name.git
```
(if not, do find -size +1M to find it), then do
```
cd ~/mysql/data/yourdatabase
myisamchk -r -v -f*.MYI
```
and hopefully your database tables are now okay.
##NOTES
Note 1: definitely DO turn off feeds and discovery by default if you are on the Free or Bronze plan on OpenShift with a single 1Gb gear by visiting https://your-app-name.rhcloud.com/admin/site when logged in as administrator of your Hubzilla site.
Note 2: DO add the above defaults into the deploy script.
Note 3: DO add git gc to the deploy script to clean up git.
Note 4: MAYBE DO add myisamchk - only checking? to the end of the deploy script.
The OpenShift `php` cartridge documentation can be found at:
http://openshift.github.io/documentation/oo_cartridge_guide.html#php
For information about .openshift directory, consult the documentation:
http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory

View file

@ -1,3 +0,0 @@
For information about action hooks, consult the documentation:
http://openshift.github.io/documentation/oo_user_guide.html#action-hooks

View file

@ -1,218 +0,0 @@
#!/bin/bash
# This deploy hook gets executed after dependencies are resolved and the
# build hook has been run but before the application has been started back
# up again. This script gets executed directly, so it could be python, php,
# ruby, etc.
# Bash help: http://www.panix.com/~elflord/unix/bash-tute.html
# For information about action hooks supported by OpenShift, consult the documentation:
# http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory
####
# Hubzilla specific deploy script
# Place this file in /.openshift/action_hooks/ (The .openshift folder will be in the root of your repo)
# The file name should be "deploy" such that you have:
# .openshift/action_hooks/deploy
# Conventions: Vars in curley braces have the slash after implied so no need to add it.
# e.g. ${OPENSHIFT_REPO_DIR}php/foobar = /repo/php/foobar
# See all OpenShift vars here:
# https://www.openshift.com/developers/openshift-environment-variables
# HME - NOTE - leftover from original openshift-drupal-deploy
# In config.php you can leverage the enviroment variables like this:
# // Define env vars.
# if (array_key_exists('OPENSHIFT_APP_NAME', $_SERVER)) {
# $src = $_SERVER;
# } else {
# $src = $_ENV;
# }
#
# $conf["file_private_path"] = $src['OPENSHIFT_DATA_DIR'] . "private";
# $conf["file_temporary_path"] = $src['OPENSHIFT_DATA_DIR'] . "tmp";
####
# Start Deploy
echo "Starting Deploy..."
# Let's create the Hubzilla files directory in the Openshift data folder ($OPENSHIFT_DATA_DIR).
echo "Check for the files directory called store, if not created - create it"
if [ ! -d ${OPENSHIFT_DATA_DIR}store ]; then
mkdir -p ${OPENSHIFT_DATA_DIR}"store/[data]/smarty3"
echo "Done creating files directory"
else
echo "The files directory called store already exists"
fi
####
# Set permissions on the files directory.
echo "Now chmod 777 -R files"
chmod -R 777 ${OPENSHIFT_DATA_DIR}store
echo "chmod done, permissions set to 777"
####
# Symlink our files folder to the repo.
# Note the "php" directory below seems to be the best way to serve OpenShift files.
# This is good as that allows us for directories one level above such as tmp and private
echo "Create sym links for writeable directories"
ln -sf ${OPENSHIFT_DATA_DIR}store ${OPENSHIFT_REPO_DIR}store
echo "Files sym links created"
####
# Copy .htconfig.php from the repo, rename it and place it in the data directory.
# if it's there already, skip it.
if [ ! -f ${OPENSHIFT_DATA_DIR}.htconfig.php ];
then
cp ${OPENSHIFT_REPO_DIR}.htconfig.php ${OPENSHIFT_DATA_DIR}.htconfig.php
echo ".htconfig.php copied."
else
echo "Looks like the .htconfig.php file is already there, we won't overwrite it."
fi
####
# symlink the .htconfig.php file.
echo "Create sym link for .htconfig.php"
ln -sf ${OPENSHIFT_DATA_DIR}.htconfig.php ${OPENSHIFT_REPO_DIR}.htconfig.php
echo ".htconfig.php symlink created"
####
# Copy .htaccess from the repo, rename it and place it in the data directory.
# if it's there already, skip it.
if [ ! -f ${OPENSHIFT_DATA_DIR}.htaccess ];
then
cp ${OPENSHIFT_REPO_DIR}.htaccess ${OPENSHIFT_DATA_DIR}.htaccess
echo ".htaccess copied."
else
echo "Looks like the .htaccess file is already there, we won't overwrite it."
fi
####
# symlink the .htaccess file.
echo "Create sym link for .htaccess"
ln -sf ${OPENSHIFT_DATA_DIR}.htaccess ${OPENSHIFT_REPO_DIR}.htaccess
echo ".htaccess symlink created"
####
echo "Check for the poller at .openshift/cron/minutely/poller , if not created - create it"
if [ ! -f ${OPENSHIFT_REPO_DIR}.openshift/cron/minutely/poller ]; then
printf '%s\n' '#!/bin/bash' 'if [ ! -f $OPENSHIFT_DATA_DIR/last_run ]; then' ' touch $OPENSHIFT_DATA_DIR/last_run' 'fi' 'if [[ $(find $OPENSHIFT_DATA_DIR/last_run -mmin +9) ]]; then #run every 10 mins' ' rm -f $OPENSHIFT_DATA_DIR/last_run' ' touch $OPENSHIFT_DATA_DIR/last_run' ' # The command(s) that you want to run every 10 minutes' 'cd /var/lib/openshift/${OPENSHIFT_APP_UUID}/app-root/repo; /opt/rh/php54/root/usr/bin/php include/poller.php' 'fi' >${OPENSHIFT_REPO_DIR}.openshift/cron/minutely/poller
echo "Done creating file .openshift/cron/minutely/poller"
else
echo "The poller already exists"
fi
####
# Set permissions on the poller script to make it executable.
echo "Now chmod 777 -R poller"
chmod -R 777 ${OPENSHIFT_REPO_DIR}.openshift/cron/minutely/poller
echo "chmod done, permissions set to 777 on poller script."
####
### echo "Check for the hot deploy marker at .openshift/markers/hot_deploy , if not created - create it"
### if [ ! -f ${OPENSHIFT_REPO_DIR}.openshift/markers/hot_deploy ]; then
### touch ${OPENSHIFT_REPO_DIR}.openshift/markers/hot_deploy
### echo "Done creating file .openshift/markers/hot_deploy"
### else
### echo "The hot deploy marker already exists"
### fi
####
# Hubzilla configuration - changes to default settings
# to make Hubzilla on OpenShift a more pleasant experience
echo "Changing default configuration to conserve space and autocreate a social private channel upon account registration"
cd ${OPENSHIFT_REPO_DIR}
util/config system auto_channel_create
util/config system default_permissions_role social_private
util/config system workflow_channel_next channel
util/config system expire_delivery_reports 3
util/config system feed_contacts 0
util/config system diaspora_enabled 0
util/config system disable_discover_tab 1
util/config directory safemode 0
util/config directory globaldir 1
util/config directory pubforums 0
# Hubzill addons
echo "Try to add or update Hubzilla addons"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git HubzillaAddons
# Hubzilla themes - unofficial repo
echo "Try to add or update Hubzilla themes - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_theme_repo https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes insecure
# Hubzilla ownMapp - unofficial repo
echo "Try to add or update Hubzilla ownMapp - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/ownmapp.git ownMapp insecure
# Hubzilla Chess - unofficial repo
echo "Try to add or update Hubzilla chess - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/hubzilla-chess.git Chess insecure
# Hubzilla Hubsites - unofficial repo
echo "Try to add or update Hubzilla Hubsites - unofficial repo"
cd ${OPENSHIFT_REPO_DIR}
util/add_addon_repo https://gitlab.com/zot/hubsites.git Hubsites insecure

View file

@ -1,27 +0,0 @@
Run scripts or jobs on a periodic basis
=======================================
Any scripts or jobs added to the minutely, hourly, daily, weekly or monthly
directories will be run on a scheduled basis (frequency is as indicated by the
name of the directory) using run-parts.
run-parts ignores any files that are hidden or dotfiles (.*) or backup
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved}
The presence of two specially named files jobs.deny and jobs.allow controls
how run-parts executes your scripts/jobs.
jobs.deny ===> Prevents specific scripts or jobs from being executed.
jobs.allow ===> Only execute the named scripts or jobs (all other/non-named
scripts that exist in this directory are ignored).
The principles of jobs.deny and jobs.allow are the same as those of cron.deny
and cron.allow and are described in detail at:
http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-Automating_System_Tasks.html#s2-autotasks-cron-access
See: man crontab or above link for more details and see the the weekly/
directory for an example.
PLEASE NOTE: The Cron cartridge must be installed in order to run the configured jobs.
For more information about cron, consult the documentation:
http://openshift.github.io/documentation/oo_cartridge_guide.html#cron
http://openshift.github.io/documentation/oo_user_guide.html#cron

View file

@ -1,16 +0,0 @@
Run scripts or jobs on a weekly basis
=====================================
Any scripts or jobs added to this directory will be run on a scheduled basis
(weekly) using run-parts.
run-parts ignores any files that are hidden or dotfiles (.*) or backup
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} and handles
the files named jobs.deny and jobs.allow specially.
In this specific example, the chronograph script is the only script or job file
executed on a weekly basis (due to white-listing it in jobs.allow). And the
README and chrono.dat file are ignored either as a result of being black-listed
in jobs.deny or because they are NOT white-listed in the jobs.allow file.
For more details, please see ../README.cron file.

View file

@ -1 +0,0 @@
Time And Relative D...n In Execution (Open)Shift!

View file

@ -1,3 +0,0 @@
#!/bin/bash
echo "`date`: `cat $(dirname \"$0\")/chrono.dat`"

View file

@ -1,12 +0,0 @@
#
# Script or job files listed in here (one entry per line) will be
# executed on a weekly-basis.
#
# Example: The chronograph script will be executed weekly but the README
# and chrono.dat files in this directory will be ignored.
#
# The README file is actually ignored due to the entry in the
# jobs.deny which is checked before jobs.allow (this file).
#
chronograph

View file

@ -1,7 +0,0 @@
#
# Any script or job files listed in here (one entry per line) will NOT be
# executed (read as ignored by run-parts).
#
README

View file

@ -1,4 +0,0 @@
For information about markers, consult the documentation:
http://openshift.github.io/documentation/oo_user_guide.html#markers
http://openshift.github.io/documentation/oo_cartridge_guide.html#php-markers

View file

@ -1,46 +0,0 @@
# see http://about.travis-ci.org/docs/user/languages/php/ for more hints
language: php
# list any PHP version you want to test against
php:
# using major version aliases
# aliased to a recent 5.4.x version
- 5.4
# aliased to a recent 5.5.x version
- 5.5
# aliased to a recent 5.6.x version
- 5.6
# aliased to a recent 7.x version
- 7.0
# aliased to a recent hhvm version
- hhvm
# optionally specify a list of environments, for example to test different RDBMS
#env:
# - DB=mysql
# - DB=pgsql
# optionally set up exclutions and allowed failures in the matrix
matrix:
# exclude:
# - php: hhvm
# env: DB=pgsql # PDO driver for pgsql is unsupported by HHVM (3rd party install for support)
allow_failures:
- php: 7.0
- php: hhvm
# execute any number of scripts before the test run, custom env's are available as variables
#before_script:
# - if [[ "$DB" == "pgsql" ]]; then psql -c "DROP DATABASE IF EXISTS hello_world_test;" -U postgres; fi
# - if [[ "$DB" == "pgsql" ]]; then psql -c "create database hello_world_test;" -U postgres; fi
# - if [[ "$DB" == "mysql" ]]; then mysql -e "create database IF NOT EXISTS hello_world_test;" -uroot; fi
# omitting "script:" will default to phpunit
# use the $DB env variable to determine the phpunit.xml to use
script: phpunit tests/*php
# configure notifications (email, IRC, campfire etc)
notifications:
# irc: "irc.freenode.org#yourfavouriteroomfortravis"
# a plugin/script to post to a hubzilla channel would be neat here

View file

@ -1,293 +0,0 @@
Hubzilla 1.8
Administration:
Cleanup and resolve some edge cases with addon repository manager
Provide sort field and direction on all fields of account and channel administration tables
Rename 'user' administration to account administration to reflect its true purpose
'safemode' tool to quickly disable and re-enable addons during a hypothetical upgrade crisis
Security:
Edited comments to private posts could lose their privacy settings under some circumstances
Provide zot-finger signatures to prevent a possible but rare exploit involving DNS spoofing and phishing
ACL selections:
Various improvements to the ACL editor to further simplify the concepts and make it more intuitive
Chat:
Notifications of chatroom activity using standard browser notification interfaces.
Themes:
Allow a theme:schema string to represent a valid theme name. This fixes issues with setting schemas on site themes.
Pubsites:
Show server role (identify UNO or basic sites as opposed to hubzilla pro) and link to statistics
Documentation:
Clarify privacy rights of commenters w/r/t conversation owners, as this policy is network dependent.
Wiki (Git backed):
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
Account Cloning:
Regression on clone channel creation created a new channel name each time.
New issue (fixed) with directory creation on cloned file content
Content Rendering:
Add inline code (in addition to the existing code blocks) to BBcode
Add emoji reactions
Add emojis as extended smilies with auto-complete support
Emoji added as feature so it can be enabled/disabled and locked
Ability to configure the standard reactions available on a site basis
Disable 'convenience' ajax autoload on pgdn key, as it could lead to premature memory exhaustion
Photos:
Change album sort ordering, allow widgets and plugins to define other orderings
Apps:
Synchronise app list with changes to system apps
Preserve existing app categories on app updates/edits
Regression: fixed translated system app names
Architecture:
Provide autoloaded class files and libraries for plugins.
Further refactoring of session driver to sort out some cookie anomolies
Experimental PDO database driver
Creation of Daemon Master class and port all daemon (background task) interfaces to use it
Create separate class for each of 'Cron', 'Cron daily', and 'Cron weekly'.
Always run a Cron maintenance task if not run in the last four hours
Refactor the template classes
Refactor the ConversationItem mess into ThreadItem and ThreadStream
Refactor Apps, Enotify, and Chat library code
Refactor the various Config libraries (Config, PConfig, XConfig, AConfig, AbConfig, and IConfig)
Created WebServer class for top level
Remove mcrypt dependencies (deprecated in PHP 7.1)
Remove all reserved (including merely 'not recommended') words as DB table column names
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
Bugfixes:
Remove db_close function on page end - not needed and will not work with persistent DB connections.
Undefined ref_session_write
Some session functions needed to be static to work with CalDAV/CardDAV
CLI interface: argc and argv were reversed
HTML entities double encoded in edited titles
Prevent delivering to empty recipients
Sabre library setting some security headers for SAML after we've emitted HTML content
Always initialise miniApp (caused obscure warning message if not set)
Block 'sys' channels from being 'random profile' candidates
DB update failed email could be sent in the wrong language under rare circumstances
Openid remote authentication used incorrect namespace
URL attached to profile "things" was not linked, always showing the "thing" manage page
New connection wasn't added to default privacy group when "auto-accept" was enabled
Regression: iconfig sharing wasn't working properly
Plugins:
CalDAV/CardDAV plugin provided
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
Allow 'superblock' to work across API calls from third party clients
statistics.json: use 'zot' as protocol
Issues fixed during testing of ability to follow Diaspora tags
Parse issue with Diaspora reshare content
Chess: moved to main repo, ported to 1.8
Hubzilla 1.6
Cleanup and standardise the interfaces to the "jot" editor
Router re-written to support calling class object methods as controllers
All existing modules (160+) re-written as object classes
Plugin hook interface adapted to call static class methods
Context help improved dramatically with content for the most accessed pages.
Reverted a compatibility change to support GNU-social events. We copied their feed format and their feed format is wrong (XML namespace collisions).
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
Fix javascript detection and allow either positive or negative detection.
Refactor the plugin hook registration procedure, provide 'unregister all' ability.
Fix RSD (Real Simple Discovery) which has been broken for some time.
Update smarty library to 3.1.29
Update jquery.textcomplete to 1.3.4
Update font-awesome to 4.6.1
Update SabreDAV to 3.0 (PHP version requirements prevent us from pushing it further at this time)
Help text added to cmdline utilities config and pconfig
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
Implement singleton delivery (emulate nomadic identity to singleton networks and services)
Fix empty album name in photo activities when photo is stored in top level folder.
Allow engineering units to be used in service class data size restrictions (400M, 1G, etc.)
Lots of work on bbcode auto-completion
Admin interface provided to manage external resource repositories
Oembed security reworked. Now all sources are filtered by default unless blocked.
Remove the date-string version and use only STD_VERSION
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
Ensure the ability to translate names of all system apps (except those provided in addons)
Provide ability to add categories to content from channel sources
Lots of work on the presentation of the ACL widget to enhance usability and intuitiveness
Allow somebody to follow a channel from a pasted redress containing a Unicode lookalike of the @ sign.
Add conditional syntax to Comanche (if/then/else)
Convert Comanche to an object class
Removed IE6 compatibility code
Explicitly close DB on shutdown/exit instead of allowing it to close naturally
Allowed delayed publish of webpages
Show current repository versions of master and dev on admin page and warn if your installation has fallen behind master
Provide some extra security checks to import data and files to prevent mischief
Block CalDAV/CardDAV namespace reserved words from being used as a channel nickname/redress since Sabre is somewhat inflexible in this regard
Plugins:
Diaspora
markdown translator work needed to eradicate the Diaspora Comment Virus.
upgrade all inbound paths with the most recent protocol changes (several of these)
convert 'diaspora_meta' (Diaspora Comment Virus) to iconfig and eradicate from sites with Diaspora disabled
implement social relay and allow following tags
upgrade statistics.json to NodeInfo. Currently hubzilla sites are tagged as 'redmatrix' because the NodeInfo schema lacks extensibility and project names are used to designate protocol compatibility rather than protocol names.
Std-embeds
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
Various:
upgrade font-awesome icons and adapt a few addons to Objects and the new hook interface and new controller interface
Hubzilla 1.4
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
of the internal code structure to gain long-term performance and stability and provide a standard
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
improved protocol federation potential to other networks by virtue of removing nomadic identity
(which is not possible to model or work around using other network protocols).]
Implement channel move operation for UNO configuration
Remove bookmark references in UNO (which has no bookmarks by default)
UI cleanup profiles/chat/manage
Refactor webfinger probes and salmon backend for GNU-social federation
SECURITY: DAV authentication exploit
Context help added
More help pages
Provide 'posts only' feed
Refactor App to remove globals
Refactor Session to remove globals
provide a fullscreen mode for selected modules and functions
Regression: some addon routes broken
fix "remember me"
Autocomplete tool extended to bbcode/comanche
Clone sync of file/photo updates
system rename (e.g. http to https or DNS name change) missing some connection photos
calendar module not blocked to public whhen block_public enabled
Use timeago.js in reshare content so that timestamps will be correct on federated reshares
Rework detection of JavaScript to avoid reload penalty under normal operation
Changed primary directory server to a hubzilla server
Plugins:
Diaspora - switch to alternate XML parser to avoid storing compound objects
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
Friendica - Initial federation work (not yet published)
Hubzilla 1.3
Admin Security configuration page created which consolidates several previously hidden settings:
Communication white/black lists
Channel white/black lists
OEmbed white/black lists
Admin Profile Fields page created which manages the availability and order of standard profile fields and allows new fields to be created/managed
"Poke" module reworked - page UI updated and "poke basic" setting introduced which limits the available poke "verbs".
"Mood" module UI reworked
"profile_photo" module UI reworked
"cover_photo" module UI reworked
"new_channel" module UI reworked
"register" module UI reworked
"pubsites" module UI reworked
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
A number of fixes to "readmore" to fix page jumping
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
Siteinfo incorrectly identifying secondary directory servers
Allow admin to set and lock features when UNO is configured
Atom feeds: alter how events are formatted to be compatible with GNU-social
Allow guest/visitor access to view personal calendar
Moved several more classes to "composer format" and provided an autoloader.
Bugfix: require existing password to change password
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
Plugin API: add "requires" keyword to module header to indicate dependent addons
ActivityStreams improvements and cleanup: photo and file activities
UI cleanup for editing profile when multiple profiles enabled
Removed the "markdown" feature as there are numerous issues and no maintainer.
Provide "footer" bbcode to ease theming of post footer content
Bugfix: install issues caused by composer code refactor and typo in postgres load file
Plugins:
keepout - "block public on steroids"
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
GNUsocial protocol - under development
Diaspora protocol - some work to ease migration to the new signing format
Diaspost - disabled; numerous issues and no maintainer
smileybutton - theme work and fixed compatibility with other jot-tools plugins
Hubzilla 1.2
Provide extra HTTP security headers (several of them).
Allow a site to disable delivery reports if disk space is limited
Regression: Wrong theme when viewing single post as non-member
Some Diaspora profile photos use relative URLs - force absolute
Add locked features to siteinfo report to aid remote debugging
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
Account config storage
Provide optional integrated registration and channel create form
cli utility for managing addons
issue with sharing photo "items"
cover photo manager: upload, crop, and store
cover photo widget created
rework the connections list page and provide a few management features there
fixed issue with Comanche layout definitions loaded by plugins
provide ability to separate delivery functions from item_store() and item_store_update() - some forum messages were being redelivered when cloned.
call build_sync_packet() on pdledit changes
Abstract the project name and version so these can be customised or removed
Allow hiding the ratings links on a per-site basis
db_type not present in international setup templates - was unable to choose postgres.
item_photo_menu logically divided into a) actions on the post, b) actions related to the author
bug: default channel not reset to 0 when last channel removed
create widget containing only the contact block
regression: public forums granted send stream permissions to connections
workaround Firefox's refusal to honour disabling autocomplete of passwords
regression: photo's uploaded to a channel by a guest (with file write permissions) not saved correctly.
provide mechanisms for custom .well-known handlers (needed for LetsEncrypt ownership verification)
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
Delegation section of Channel Manager was missing names and contained useless notification icons.
Change "expire" channel setting to show system limit if there is one.
Regression: provide a one-click ignore of pending connection
Config to control directory keyword generation on client and server.
"Collections" renamed to "Privacy Groups", documentation improved
widget_item - allow use of page title instead of message id
Add site black/white list checking to all .well-known services
reduce incidents of screen jumping when "showmore" is activated
add oembed provider for photos
Addons:
CSS theming of pageheader plugin
xmpp addon ported from Friendica
Diaspora private mail issues after the third reply
Occasional issue with Diaspora connection requests
Add notification email to Diaspora PMs
Allow anonymising platform and version for statistics
msgfooter addon created
removed embedly plugin
sync clones after superblock addition
"keepout" plugin created
Hubzilla 1.1
Rewrote and simplified the Queue manager and delivery system
Rewrote and simplified the outer layers of the Zot protocol
Use a standard version numbering scheme in addition to the snapshot tags
Provide a channel blacklist for blocking channels with abusive or illegal content at the hub level
Make the black/white lists pluggable
Update template library
Support for letsencrypt certs in various places
Cleanup of login and register pages
Better error responses for permission denied on channel file repositories
Disabled the public stream by default for new installs (can be enabled if desired)
Cleanup of API authentication and rework the old OAuth1 stuff
Add API "status with media" support compatible with Twitter and conflicting method for GNU-social
Rework photo ActivityStreams objects to align better with ActivityStreams producers/consumers
Several minor API fixes to work better with AndStatus client
Invitation only site - experimental support added, needs more work
Fix delivery loop condition due to corrupted data which resulted in recursive upstream delivery
Provide more support for external (git) widget collections.
Extend the Queue API to 3rd-party network addons which have experienced downtime recently.
Regression: Inherited permissions were not explicitly set
Regression: "Xyz posted on your wall" notification sent when creating webpages at another channel
Regression: Custom permissions not pre-populated on channel creation with named role.
Provide "Public" string when a post can be made public, instead of "visible to default audience"
Allow hub admin to specify a default role type for the first channel created, reducing complexity
Ability for a hub admin to set feature defaults and lock them, reducing complexity
Change default expiration of delivery reports to 10 days to accomodate sites with reduced resources
Addons/Plugins:
Pageheader addon ported from Friendica
Hubwall (allow admin to send email to all accounts on this hub) created
GNU-social - queueing added
Diaspora - fixes for various failures to update profile photos, updates to queue API
Cross Domain Authenticated Chess (Andrew Manning's repository)
And... the normal "lots of bugs fixed, translations updated, and documentation improved"

View file

@ -1,20 +0,0 @@
Copyright (c) 2010-2016 the Hubzilla Community
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -1,50 +0,0 @@
![Hubzilla](images/hubzilla-banner.png)
Hubzilla - Community Server
===========================
Groupware re-imagined and re-invented.
--------------------------------------
Connect and link decentralised web communities.
-----------------------------------------------
<p align="center" markdown="1">
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
</p>
**What are Hubz?**
Hubz are independent general-purpose websites that not only connect with their associated members and viewers, but also connect together to exchange personal communications and other information with each other.
This allows hub members on any hub to securely and privately share anything; with anybody, on any hub - anywhere; or share stuff publicly with anybody on the internet if desired.
**Hubzilla** is the server software which makes this possible. It is a sophisticated and unique combination of an open source content management system and a decentralised identity, communications, and permissions framework and protocol suite, built using common webserver technology (PHP/MySQL/Apache and popular variants). The end result is a level of systems integration, privacy control, and communications features that you wouldn't think are possible in either a content management system or a decentralised communications network. It also brings a new level of cooperation and privacy to the web and introduces the concept of personally owned "single sign-on" to web services across the entire internet.
Hubzilla hubz are
* decentralised
* inherently social
* optionally inter-networked with other hubz
* privacy-enabled (privacy exclusions work across the entire internet to any registered identity on any compatible hubz)
Possible website applications include
* decentralised social networking nodes
* personal cloud storage
* file dropboxes
* managing organisational communications and activities
* collaboration and community decision-making
* small business websites
* public and private media/file libraries
* blogs
* event promotion
* feed aggregation and republishing
* forums
* dating websites
* pretty much anything you can do on a traditional blog or community website, but that you could do better if you could easily connect it with other websites or privately share things across website boundaries.
<p align="center" markdown="1">
<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
</p>
[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla)

View file

@ -1,92 +0,0 @@
<?php
namespace Zotlabs\Access;
class AccessList {
private $allow_cid;
private $allow_gid;
private $deny_cid;
private $deny_gid;
/* indicates if we are using the default constructor values or values that have been set explicitly. */
private $explicit;
function __construct($channel) {
if($channel) {
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
$this->deny_gid = $channel['channel_deny_gid'];
}
else {
$this->allow_cid = '';
$this->allow_gid = '';
$this->deny_cid = '';
$this->deny_gid = '';
}
$this->explicit = false;
}
function get_explicit() {
return $this->explicit;
}
/**
* Set AccessList from strings such as those in already
* existing stored data items
*/
function set($arr,$explicit = true) {
$this->allow_cid = $arr['allow_cid'];
$this->allow_gid = $arr['allow_gid'];
$this->deny_cid = $arr['deny_cid'];
$this->deny_gid = $arr['deny_gid'];
$this->explicit = $explicit;
}
/**
* return an array consisting of the current
* access list components where the elements
* are directly storable.
*/
function get() {
return array(
'allow_cid' => $this->allow_cid,
'allow_gid' => $this->allow_gid,
'deny_cid' => $this->deny_cid,
'deny_gid' => $this->deny_gid,
);
}
/**
* Set AccessList from arrays, such as those provided by
* acl_selector(). For convenience, a string (or non-array) input is
* assumed to be a comma-separated list and auto-converted into an array.
*/
function set_from_array($arr,$explicit = true) {
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
? $arr['contact_allow'] : explode(',',$arr['contact_allow']));
$this->allow_gid = perms2str((is_array($arr['group_allow']))
? $arr['group_allow'] : explode(',',$arr['group_allow']));
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
? $arr['contact_deny'] : explode(',',$arr['contact_deny']));
$this->deny_gid = perms2str((is_array($arr['group_deny']))
? $arr['group_deny'] : explode(',',$arr['group_deny']));
$this->explicit = $explicit;
}
function is_private() {
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
}
}

View file

@ -1,107 +0,0 @@
<?php
namespace Zotlabs\Extend;
class Hook {
static public function register($hook,$file,$function,$version = 1,$priority = 0) {
if(is_array($function)) {
$function = serialize($function);
}
$r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `fn` = '%s' and priority = %d and hook_version = %d LIMIT 1",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
if($r)
return true;
// To aid in upgrade and transition, remove old settings for any registered hooks that match in all respects except
// for priority or hook_version
$r = q("DELETE FROM `hook` where `hook` = '%s' and `file` = '%s' and `fn` = '%s'",
dbesc($hook),
dbesc($file),
dbesc($function)
);
$r = q("INSERT INTO `hook` (`hook`, `file`, `fn`, `priority`, `hook_version`) VALUES ( '%s', '%s', '%s', %d, %d )",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
return $r;
}
static public function unregister($hook,$file,$function,$version = 1,$priority = 0) {
if(is_array($function)) {
$function = serialize($function);
}
$r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `fn` = '%s' and priority = %d and hook_version = %d",
dbesc($hook),
dbesc($file),
dbesc($function),
intval($priority),
intval($version)
);
return $r;
}
// unregister all hooks with this file component.
// Useful for addon upgrades where you want to clean out old interfaces.
static public function unregister_by_file($file) {
$r = q("DELETE FROM hook WHERE `file` = '%s' ",
dbesc($file)
);
return $r;
}
/**
* @brief Inserts a hook into a page request.
*
* Insert a short-lived hook into the running page request.
* Hooks are normally persistent so that they can be called
* across asynchronous processes such as delivery and poll
* processes.
*
* insert_hook lets you attach a hook callback immediately
* which will not persist beyond the life of this page request
* or the current process.
*
* @param string $hook
* name of hook to attach callback
* @param string $fn
* function name of callback handler
* @param int $version
* hook interface version, 0 uses two callback params, 1 uses one callback param
* @param int $priority
* currently not implemented in this function, would require the hook array to be resorted
*/
static public function insert($hook, $fn, $version = 0, $priority = 0) {
if(is_array($fn)) {
$fn = serialize($fn);
}
if(! is_array(App::$hooks))
App::$hooks = array();
if(! array_key_exists($hook, App::$hooks))
App::$hooks[$hook] = array();
App::$hooks[$hook][] = array('', $fn, $priority, $version);
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace Zotlabs\Identity\BasicId;
class BasicId {
private $name;
private $profile_photo;
private $profile_url;
private $address;
private $protocol;
}

View file

@ -1,16 +0,0 @@
<?php
namespace Zotlabs\Identity\ProfilePhoto;
class ProfilePhoto {
private $photo_large_url;
private $photo_medium_url;
private $photo_small_url;
private $photo_mimetype;
private $photo_updated;
}

View file

@ -1,25 +0,0 @@
<?php
namespace Zotlabs\Lib;
// account configuration storage is built on top of the under-utilised xconfig
class AConfig {
static public function Load($account_id) {
return XConfig::Load('a_' . $account_id);
}
static public function Get($account_id,$family,$key) {
return XConfig::Get('a_' . $account_id,$family,$key);
}
static public function Set($account_id,$family,$key,$value) {
return XConfig::Get('a_' . $account_id,$family,$key,$value);
}
static public function Delete($account_id,$family,$key) {
return XConfig::Delete('a_' . $account_id,$family,$key);
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace Zotlabs\Lib;
class AbConfig {
static public function Load($chash,$xhash) {
$r = q("select * from abconfig where chan = '%s' and xchan = '%s'",
dbesc($chash),
dbesc($xhash)
);
return $r;
}
static public function Get($chash,$xhash,$family,$key) {
$r = q("select * from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
dbesc($chash),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
if($r) {
return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
}
return false;
}
static public function Set($chash,$xhash,$family,$key,$value) {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(self::Get($chash,$xhash,$family,$key) === false) {
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( '%s', '%s', '%s', '%s', '%s' ) ",
dbesc($chash),
dbesc($xhash),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
}
else {
$r = q("update abconfig set v = '%s' where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
dbesc($dbvalue),
dbesc($chash),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
}
if($r)
return $value;
return false;
}
static public function Delete($chash,$xhash,$family,$key) {
$r = q("delete from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
dbesc($chash),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
return $r;
}
}

View file

@ -1,708 +0,0 @@
<?php /** @file */
namespace Zotlabs\Lib;
/**
* Apps
*
*/
require_once('include/plugin.php');
require_once('include/channel.php');
class Apps {
static public $installed_system_apps = null;
static public function get_system_apps($translate = true) {
$ret = array();
if(is_dir('apps'))
$files = glob('apps/*.apd');
else
$files = glob('app/*.apd');
if($files) {
foreach($files as $f) {
$x = self::parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
}
}
$files = glob('addon/*/*.apd');
if($files) {
foreach($files as $f) {
$n = basename($f,'.apd');
if(plugin_is_installed($n)) {
$x = self::parse_app_description($f,$translate);
if($x) {
$ret[] = $x;
}
}
}
}
return $ret;
}
static public function import_system_apps() {
if(! local_channel())
return;
$apps = self::get_system_apps(false);
self::$installed_system_apps = q("select * from app where app_system = 1 and app_channel = %d",
intval(local_channel())
);
if($apps) {
foreach($apps as $app) {
$id = self::check_install_system_app($app);
// $id will be boolean true or false to install an app, or an integer id to update an existing app
if($id === false)
continue;
if($id !== true) {
// if we already installed this app, but it changed, preserve any categories we created
$s = '';
$r = q("select * from term where otype = %d and oid = d",
intval(TERM_OBJ_APP),
intval($id)
);
if($r) {
foreach($r as $t) {
if($s)
$s .= ',';
$s .= $t['term'];
}
$app['categories'] = $s;
}
}
$app['uid'] = local_channel();
$app['guid'] = hash('whirlpool',$app['name']);
$app['system'] = 1;
self::app_install(local_channel(),$app);
}
}
}
/**
* Install the system app if no system apps have been installed, or if a new system app
* is discovered, or if the version of a system app changes.
*/
static public function check_install_system_app($app) {
if((! is_array(self::$installed_system_apps)) || (! count(self::$installed_system_apps))) {
return true;
}
$notfound = true;
foreach(self::$installed_system_apps as $iapp) {
if($iapp['app_id'] == hash('whirlpool',$app['name'])) {
$notfound = false;
if($iapp['app_version'] != $app['version']) {
return intval($iapp['app_id']);
}
}
}
return $notfound;
}
static public function app_name_compare($a,$b) {
return strcmp($a['name'],$b['name']);
}
static public function parse_app_description($f,$translate = true) {
$ret = array();
$baseurl = z_root();
$channel = \App::get_channel();
$address = (($channel) ? $channel['channel_address'] : '');
//future expansion
$observer = \App::get_observer();
$lines = @file($f);
if($lines) {
foreach($lines as $x) {
if(preg_match('/^([a-zA-Z].*?):(.*?)$/ism',$x,$matches)) {
$ret[$matches[1]] = trim(str_replace(array('$baseurl','$nick'),array($baseurl,$address),$matches[2]));
}
}
}
if(! $ret['photo'])
$ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
$ret['type'] = 'system';
foreach($ret as $k => $v) {
if(strpos($v,'http') === 0)
$ret[$k] = zid($v);
}
if(array_key_exists('desc',$ret))
$ret['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['desc']);
if(array_key_exists('target',$ret))
$ret['target'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['target']);
if(array_key_exists('version',$ret))
$ret['version'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['version']);
if(array_key_exists('requires',$ret)) {
$requires = explode(',',$ret['requires']);
foreach($requires as $require) {
$require = trim(strtolower($require));
switch($require) {
case 'nologin':
if(local_channel())
unset($ret);
break;
case 'admin':
if(! is_site_admin())
unset($ret);
break;
case 'local_channel':
if(! local_channel())
unset($ret);
break;
case 'public_profile':
if(! is_public_profile())
unset($ret);
break;
case 'observer':
if(! $observer)
unset($ret);
break;
default:
if(! (local_channel() && feature_enabled(local_channel(),$require)))
unset($ret);
break;
}
}
}
if($ret) {
if($translate)
self::translate_system_apps($ret);
return $ret;
}
return false;
}
static public function translate_system_apps(&$arr) {
$apps = array(
'Site Admin' => t('Site Admin'),
'Bug Report' => t('Bug Report'),
'View Bookmarks' => t('View Bookmarks'),
'My Chatrooms' => t('My Chatrooms'),
'Connections' => t('Connections'),
'Firefox Share' => t('Firefox Share'),
'Remote Diagnostics' => t('Remote Diagnostics'),
'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'),
'Grid' => t('Grid'),
'Settings' => t('Settings'),
'Files' => t('Files'),
'Webpages' => t('Webpages'),
'Wiki' => t('Wiki'),
'Channel Home' => t('Channel Home'),
'View Profile' => t('View Profile'),
'Photos' => t('Photos'),
'Events' => t('Events'),
'Directory' => t('Directory'),
'Help' => t('Help'),
'Mail' => t('Mail'),
'Mood' => t('Mood'),
'Poke' => t('Poke'),
'Chat' => t('Chat'),
'Search' => t('Search'),
'Probe' => t('Probe'),
'Suggest' => t('Suggest'),
'Random Channel' => t('Random Channel'),
'Invite' => t('Invite'),
'Features' => t('Features'),
'Language' => t('Language'),
'Post' => t('Post'),
'Profile Photo' => t('Profile Photo')
);
if(array_key_exists($arr['name'],$apps))
$arr['name'] = $apps[$arr['name']];
}
// papp is a portable app
static public function app_render($papp,$mode = 'view') {
/**
* modes:
* view: normal mode for viewing an app via bbcode from a conversation or page
* provides install/update button if you're logged in locally
* list: normal mode for viewing an app on the app page
* no buttons are shown
* edit: viewing the app page in editing mode provides a delete button
*/
$installed = false;
if(! $papp)
return;
if(! $papp['photo'])
$papp['photo'] = z_root() . '/' . get_default_profile_photo(80);
self::translate_system_apps($papp);
$papp['papp'] = self::papp_encode($papp);
if(! strstr($papp['url'],'://'))
$papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url'];
foreach($papp as $k => $v) {
if(strpos($v,'http') === 0 && $k != 'papp')
$papp[$k] = zid($v);
if($k === 'desc')
$papp['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$papp['desc']);
if($k === 'requires') {
$requires = explode(',',$v);
foreach($requires as $require) {
$require = trim(strtolower($require));
switch($require) {
case 'nologin':
if(local_channel())
return '';
break;
case 'admin':
if(! is_site_admin())
return '';
break;
case 'local_channel':
if(! local_channel())
return '';
break;
case 'public_profile':
if(! is_public_profile())
return '';
break;
case 'observer':
$observer = \App::get_observer();
if(! $observer)
return '';
break;
default:
if(! (local_channel() && feature_enabled(local_channel(),$require)))
return '';
break;
}
}
}
}
$hosturl = '';
if(local_channel()) {
$installed = self::app_installed(local_channel(),$papp);
$hosturl = z_root() . '/';
}
elseif(remote_channel()) {
$observer = \App::get_observer();
if($observer && $observer['xchan_network'] === 'zot') {
// some folks might have xchan_url redirected offsite, use the connurl
$x = parse_url($observer['xchan_connurl']);
if($x) {
$hosturl = $x['scheme'] . '://' . $x['host'] . '/';
}
}
}
$install_action = (($installed) ? t('Update') : t('Install'));
return replace_macros(get_markup_template('app.tpl'),array(
'$app' => $papp,
'$hosturl' => $hosturl,
'$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''),
'$install' => (($hosturl && $mode == 'view') ? $install_action : ''),
'$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
'$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : '')
));
}
static public function app_install($uid,$app) {
$app['uid'] = $uid;
if(self::app_installed($uid,$app))
$x = self::app_update($app);
else
$x = self::app_store($app);
if($x['success']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($x['app_id']),
intval($uid)
);
if($r) {
if(! $r[0]['app_system']) {
if($app['categories'] && (! $app['term'])) {
$r[0]['term'] = q("select * from term where otype = %d and oid = d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
);
build_sync_packet($uid,array('app' => $r[0]));
}
}
}
return $x['app_id'];
}
return false;
}
static public function app_destroy($uid,$app) {
if($uid && $app['guid']) {
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($app['guid']),
intval($uid)
);
if($x) {
$x[0]['app_deleted'] = 1;
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
if($x[0]['app_system']) {
$r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
}
else {
$r = q("delete from app where app_id = '%s' and app_channel = %d",
dbesc($app['guid']),
intval($uid)
);
// we don't sync system apps - they may be completely different on the other system
build_sync_packet($uid,array('app' => $x));
}
}
}
}
static public function app_installed($uid,$app) {
$r = q("select id from app where app_id = '%s' and app_version = '%s' and app_channel = %d limit 1",
dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''),
dbesc((array_key_exists('version',$app)) ? $app['version'] : ''),
intval($uid)
);
return(($r) ? true : false);
}
static public function app_list($uid, $deleted = false, $cat = '') {
if($deleted)
$sql_extra = " and app_deleted = 1 ";
else
$sql_extra = " and app_deleted = 0 ";
if($cat) {
$r = q("select oid from term where otype = %d and term = '%s'",
intval(TERM_OBJ_APP),
dbesc($cat)
);
if(! $r)
return $r;
$sql_extra .= " and app.id in ( ";
$s = '';
foreach($r as $rr) {
if($s)
$s .= ',';
$s .= intval($rr['oid']);
}
$sql_extra .= $s . ') ';
}
$r = q("select * from app where app_channel = %d $sql_extra order by app_name asc",
intval($uid)
);
if($r) {
for($x = 0; $x < count($r); $x ++) {
if(! $r[$x]['app_system'])
$r[$x]['type'] = 'personal';
$r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[$x]['id'])
);
}
}
return($r);
}
static public function app_decode($s) {
$x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s));
return json_decode($x,true);
}
static public function app_store($arr) {
// logger('app_store: ' . print_r($arr,true));
$darray = array();
$ret = array('success' => false);
$darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
$darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
if((! $darray['app_url']) || (! $darray['app_channel']))
return $ret;
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
$arr['photo'] = $x[1];
}
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . \App::get_hostname());
$darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
$darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
$darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
$darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
$darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
$darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$created = datetime_convert();
$r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited, app_system, app_deleted ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
dbesc($darray['app_id']),
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
dbesc($darray['app_name']),
dbesc($darray['app_desc']),
dbesc($darray['app_url']),
dbesc($darray['app_photo']),
dbesc($darray['app_version']),
intval($darray['app_channel']),
dbesc($darray['app_addr']),
dbesc($darray['app_price']),
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($created),
dbesc($created),
intval($darray['app_system']),
intval($darray['app_deleted'])
);
if($r) {
$ret['success'] = true;
$ret['app_id'] = $darray['app_id'];
}
if($arr['categories']) {
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
$t = trim($t);
if($t) {
store_item_tag($darray['app_channel'],$x[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,escape_tags($t),escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t)));
}
}
}
}
return $ret;
}
static public function app_update($arr) {
$darray = array();
$ret = array('success' => false);
$darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
$darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
$darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : 0);
if((! $darray['app_url']) || (! $darray['app_channel']) || (! $darray['app_id']))
return $ret;
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
$arr['photo'] = $x[1];
}
$darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
$darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
$darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
$darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
$darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
$darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
$darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
$darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
$darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0);
$darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0);
$edited = datetime_convert();
$r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s', app_system = %d, app_deleted = %d where app_id = '%s' and app_channel = %d",
dbesc($darray['app_sig']),
dbesc($darray['app_author']),
dbesc($darray['app_name']),
dbesc($darray['app_desc']),
dbesc($darray['app_url']),
dbesc($darray['app_photo']),
dbesc($darray['app_version']),
dbesc($darray['app_addr']),
dbesc($darray['app_price']),
dbesc($darray['app_page']),
dbesc($darray['app_requires']),
dbesc($edited),
intval($darray['app_system']),
intval($darray['app_deleted']),
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
if($r) {
$ret['success'] = true;
$ret['app_id'] = $darray['app_id'];
}
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($darray['app_id']),
intval($darray['app_channel'])
);
if($x) {
q("delete from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
if($arr['categories']) {
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
$t = trim($t);
if($t) {
store_item_tag($darray['app_channel'],$x[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,escape_tags($t),escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t)));
}
}
}
}
}
return $ret;
}
static public function app_encode($app,$embed = false) {
$ret = array();
$ret['type'] = 'personal';
if($app['app_id'])
$ret['guid'] = $app['app_id'];
if($app['app_id'])
$ret['guid'] = $app['app_id'];
if($app['app_sig'])
$ret['sig'] = $app['app_sig'];
if($app['app_author'])
$ret['author'] = $app['app_author'];
if($app['app_name'])
$ret['name'] = $app['app_name'];
if($app['app_desc'])
$ret['desc'] = $app['app_desc'];
if($app['app_url'])
$ret['url'] = $app['app_url'];
if($app['app_photo'])
$ret['photo'] = $app['app_photo'];
if($app['app_version'])
$ret['version'] = $app['app_version'];
if($app['app_addr'])
$ret['addr'] = $app['app_addr'];
if($app['app_price'])
$ret['price'] = $app['app_price'];
if($app['app_page'])
$ret['page'] = $app['app_page'];
if($app['app_requires'])
$ret['requires'] = $app['app_requires'];
if($app['app_system'])
$ret['system'] = $app['app_system'];
if($app['app_deleted'])
$ret['deleted'] = $app['app_deleted'];
if($app['term']) {
$s = '';
foreach($app['term'] as $t) {
if($s)
$s .= ',';
$s .= $t['term'];
}
$ret['categories'] = $s;
}
if(! $embed)
return $ret;
if(array_key_exists('categories',$ret))
unset($ret['categories']);
$j = json_encode($ret);
return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
}
static public function papp_encode($papp) {
return chunk_split(base64_encode(json_encode($papp)),72,"\n");
}
}

View file

@ -1,166 +0,0 @@
<?php /** @file */
namespace Zotlabs\Lib;
class Config {
/**
* @brief Loads the hub's configuration from database to a cached storage.
*
* Retrieve a category ($family) of config variables from database to a cached
* storage in the global App::$config[$family].
*
* @param string $family
* The category of the configuration value
*/
static public function Load($family) {
if(! array_key_exists($family, \App::$config))
\App::$config[$family] = array();
if(! array_key_exists('config_loaded', \App::$config[$family])) {
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
if($r !== false) {
if($r) {
foreach($r as $rr) {
$k = $rr['k'];
\App::$config[$family][$k] = $rr['v'];
}
}
\App::$config[$family]['config_loaded'] = true;
}
}
}
/**
* @brief Sets a configuration value for the hub.
*
* Stores a config value ($value) in the category ($family) under the key ($key).
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param mixed $value
* The value to store in the configuration
* @return mixed
* Return the set value, or false if the database update failed
*/
static public function Set($family,$key,$value) {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(get_config($family, $key) === false || (! self::get_from_storage($family, $key))) {
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret) {
\App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
}
$ret = q("UPDATE config SET v = '%s' WHERE cat = '%s' AND k = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
if($ret) {
\App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
}
/**
* @brief Get a particular config variable given the category name ($family)
* and a key.
*
* Get a particular config variable from the given category ($family) and the
* $key from a cached storage in App::$config[$family]. If a key is found in the
* DB but does not exist in local config cache, pull it into the cache so we
* do not have to hit the DB again for this item.
*
* Returns false if not set.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @return mixed Return value or false on error or if not set
*/
static public function Get($family,$key) {
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
self::Load($family);
if(array_key_exists('config_loaded', \App::$config[$family])) {
if(! array_key_exists($key, \App::$config[$family])) {
return false;
}
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
? unserialize(\App::$config[$family][$key])
: \App::$config[$family][$key]
);
}
return false;
}
/**
* @brief Deletes the given key from the hub's configuration database.
*
* Removes the configured value from the stored cache in App::$config[$family]
* and removes it from the database.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
static public function Delete($family,$key) {
$ret = false;
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
unset(\App::$config[$family][$key]);
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
dbesc($family),
dbesc($key)
);
return $ret;
}
/**
* @brief Returns a value directly from the database configuration storage.
*
* This function queries directly the database and bypasses the chached storage
* from get_config($family, $key).
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @return mixed
*/
static private function get_from_storage($family,$key) {
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
return $ret;
}
}

View file

@ -1,58 +0,0 @@
<?php
namespace Zotlabs\Lib;
class System {
static public function get_platform_name() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('platform_name',\App::$config['system']))
return \App::$config['system']['platform_name'];
return PLATFORM_NAME;
}
static public function get_site_name() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['sitename'])
return \App::$config['system']['sitename'];
return '';
}
static public function get_project_version() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
return '';
return self::get_std_version();
}
static public function get_update_version() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
return '';
return DB_UPDATE_VERSION;
}
static public function get_notify_icon() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['email_notify_icon_url'])
return \App::$config['system']['email_notify_icon_url'];
return z_root() . '/images/hz-white-32.png';
}
static public function get_site_icon() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['site_icon_url'])
return \App::$config['system']['site_icon_url'];
return z_root() . '/images/hz-32.png';
}
static public function get_server_role() {
if(UNO)
return 'basic';
return 'pro';
}
static public function get_std_version() {
if(defined('STD_VERSION'))
return STD_VERSION;
return '0.0.0';
}
}

View file

@ -1,93 +0,0 @@
<?php
namespace Zotlabs\Module;
class Achievements extends \Zotlabs\Web\Controller {
function get() {
// This doesn't work, so
if (! is_developer())
return;
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
return;
}
$profile = 0;
$profile = argv(1);
profile_load($a,$which,$profile);
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['view_profile']) {
notice( t('Permission denied.') . EOL);
return;
}
$newmembertext = t('Some blurb about what to do when you\'re new here');
// By default, all badges are false
$contactbadge = false;
$profilebadge = false;
$keywordsbadge = false;
// Check number of contacts. Award a badge if over 10
// We'll figure these out on each page load instead of
// writing them to the DB because that will mean one needs
// to retain their achievements - eg, you can't add
// a bunch of channels just to get your badge, and then
// delete them all again. If these become popular or
// used in profiles or something, we may need to reconsider
// and add a table for this - because this won't scale.
$r = q("select * from abook where abook_channel = %d",
intval($owner)
);
if (count($r))
$contacts = count($r);
// We're checking for 11 to adjust for the abook record for self
if ($contacts >= 11)
$contactbadge = true;
// Check if an about field in the profile has been created.
$r = q("select * from profile where uid = %d and about <> ''",
intval($owner)
);
if ($r)
$profilebadge = 1;
// Check if keywords have been set
$r = q("select * from profile where uid = %d and keywords <> ''",
intval($owner)
);
if($r)
$keywordsbadge = 1;
return replace_macros(get_markup_template("achievements.tpl"), array(
'$newmembertext' => $newmembertext,
'$profilebadge' => $profilebadge,
'$contactbadge' => $contactbadge,
'$keywordsbadge' => $keywordsbadge,
'$channelsbadge' => $channelsbadge
));
}
}

View file

@ -1,316 +0,0 @@
<?php
namespace Zotlabs\Module;
/* ACL selector json backend */
require_once("include/acl_selectors.php");
require_once("include/group.php");
class Acl extends \Zotlabs\Web\Controller {
function init(){
// logger('mod_acl: ' . print_r($_REQUEST,true));
$start = (x($_REQUEST,'start')?$_REQUEST['start']:0);
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
$search = (x($_REQUEST,'search')?$_REQUEST['search']:"");
$type = (x($_REQUEST,'type')?$_REQUEST['type']:"");
$noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false);
// List of channels whose connections to also suggest, e.g. currently viewed channel or channels mentioned in a post
$extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array());
// For use with jquery.autocomplete for private mail completion
if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
if(! $type)
$type = 'm';
$search = $_REQUEST['query'];
}
if(!(local_channel()))
if(!($type == 'x' || $type == 'c'))
killme();
if ($search != "") {
$sql_extra = " AND `name` LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc($search) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
// This horrible mess is needed because position also returns 0 if nothing is found. W/ould be MUCH easier if it instead returned a very large value
// Otherwise we could just order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
$order_extra2 = "CASE WHEN xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) ." then POSITION('".dbesc($search)."' IN xchan_name) else position('".dbesc($search)."' IN xchan_addr) end, ";
$col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' );
$sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
} else {
$sql_extra = $sql_extra2 = $sql_extra3 = "";
}
$groups = array();
$contacts = array();
if ($type=='' || $type=='g'){
$r = q("SELECT `groups`.`id`, `groups`.`hash`, `groups`.`gname`
FROM `groups`,`group_member`
WHERE `groups`.`deleted` = 0 AND `groups`.`uid` = %d
AND `group_member`.`gid`=`groups`.`id`
$sql_extra
GROUP BY `groups`.`id`
ORDER BY `groups`.`gname`
LIMIT %d OFFSET %d",
intval(local_channel()),
intval($count),
intval($start)
);
if($r) {
foreach($r as $g){
// logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['gname'],
"id" => $g['id'],
"xid" => $g['hash'],
"uids" => group_get_members_xchan($g['id']),
"link" => ''
);
}
}
}
if ($type=='' || $type=='c') {
$extra_channels_sql = '';
// Only include channels who allow the observer to view their permissions
foreach($extra_channels as $channel) {
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts'))
$extra_channels_sql .= "," . intval($channel);
}
$extra_channels_sql = substr($extra_channels_sql,1); // Remove initial comma
// Getting info from the abook is better for local users because it contains info about permissions
if(local_channel()) {
if($extra_channels_sql != '')
$extra_channels_sql = " OR (abook_channel IN ($extra_channels_sql)) and abook_hidden = 0 ";
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
intval(local_channel())
);
}
else { // Visitors
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
FROM xchan left join xlink on xlink_link = xchan_hash
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
dbesc(get_observer_hash())
);
// Find contacts of extra channels
// This is probably more complicated than it needs to be
if($extra_channels_sql) {
// Build a list of hashes that we got previously so we don't get them again
$known_hashes = array("'".get_observer_hash()."'");
if($r)
foreach($r as $rr)
$known_hashes[] = "'".$rr['hash']."'";
$known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')';
$r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND abook_blocked = 0 and abook_pending = 0 and abook_hidden = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc");
if($r2)
$r = array_merge($r,$r2);
// Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user)
$matchpos = function($x) use($search) {
$namepos = strpos($x['name'],$search);
$nickpos = strpos($x['nick'],$search);
// Use a large position if not found
return min($namepos === false ? 9999 : $namepos, $nickpos === false ? 9999 : $nickpos);
};
// This could be made simpler if PHP supported stable sorting
usort($r,function($a,$b) use($matchpos) {
$pos1 = $matchpos($a);
$pos2 = $matchpos($b);
if($pos1 == $pos2) { // Order alphabetically if match position is the same
if($a['name'] == $b['name'])
return 0;
else
return ($a['name'] < $b['name']) ? -1 : 1;
}
return ($pos1 < $pos2) ? -1 : 1;
});
}
}
if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_channel(),'system','taganyone'))) {
if((count($r) < 100) && $type == 'c') {
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
FROM xchan
WHERE xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc"
);
if($r2)
$r = array_merge($r,$r2);
}
}
}
elseif($type == 'm') {
$r = q("SELECT xchan_hash as id, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and ( (abook_their_perms = null) or (abook_their_perms & %d )>0)
and xchan_deleted = 0
$sql_extra3
ORDER BY `xchan_name` ASC ",
intval(local_channel()),
intval(PERMS_W_MAIL)
);
}
elseif(($type == 'a') || ($type == 'p')) {
$r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
and xchan_deleted = 0
$sql_extra3
ORDER BY xchan_name ASC ",
intval(local_channel())
);
}
elseif($type == 'x') {
$r = $this->navbar_complete($a);
$contacts = array();
if($r) {
foreach($r as $g) {
$contacts[] = array(
"photo" => $g['photo'],
"name" => $g['name'],
"nick" => $g['address'],
);
}
}
$o = array(
'start' => $start,
'count' => $count,
'items' => $contacts,
);
echo json_encode($o);
killme();
}
else
$r = array();
if($r) {
foreach($r as $g){
// remove RSS feeds from ACLs - they are inaccessible
if(strpos($g['hash'],'/') && $type != 'a')
continue;
if(($g['abook_their_perms'] & PERMS_W_TAGWALL) && $type == 'c' && (! $noforums)) {
$contacts[] = array(
"type" => "c",
"photo" => "images/twopeople.png",
"name" => $g['name'] . '+',
"id" => $g['id'] . '+',
"xid" => $g['hash'],
"link" => $g['nick'],
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => 'taggable',
"label" => t('network')
);
}
$contacts[] = array(
"type" => "c",
"photo" => $g['micro'],
"name" => $g['name'],
"id" => $g['id'],
"xid" => $g['hash'],
"link" => $g['nick'],
"nick" => (($g['nick']) ? substr($g['nick'],0,strpos($g['nick'],'@')) : t('RSS')),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => '',
"label" => '',
);
}
}
$items = array_merge($groups, $contacts);
$o = array(
'start' => $start,
'count' => $count,
'items' => $items,
);
echo json_encode($o);
killme();
}
function navbar_complete(&$a) {
// logger('navbar_complete');
if(observer_prohibited()) {
return;
}
$dirmode = intval(get_config('system','directory_mode'));
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
if(! $search || mb_strlen($search) < 2)
return array();
$star = false;
$address = false;
if(substr($search,0,1) === '@')
$search = substr($search,1);
if(substr($search,0,1) === '*') {
$star = true;
$search = substr($search,1);
}
if(strpos($search,'@') !== false) {
$address = true;
}
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if(! $url) {
require_once("include/dir_fns.php");
$directory = find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
if($url) {
$query = $url . '?f=' ;
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode($search) : '');
$x = z_fetch_url($query);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j && $j['results']) {
return $j['results'];
}
}
}
return array();
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,122 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/api.php');
class Api extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(count(\App::$user) && x(\App::$user,'uid') && \App::$user['uid'] != local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
}
function get() {
if(\App::$cmd=='api/oauth/authorize'){
/*
* api/oauth/authorize interact with the user. return a standard page
*/
\App::$page['template'] = "minimal";
// get consumer/client from request token
try {
$request = OAuth1Request::from_request();
} catch(Exception $e) {
echo "<pre>"; var_dump($e); killme();
}
if(x($_POST,'oauth_yes')){
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
$consumer = new OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
$verifier = md5($app['secret'].local_channel());
set_config("oauth", $verifier, local_channel());
if($consumer->callback_url!=null) {
$params = $request->get_parameters();
$glue="?";
if (strstr($consumer->callback_url,$glue)) $glue="?";
goaway($consumer->callback_url . $glue . "oauth_token=" . OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . OAuth1Util::urlencode_rfc3986($verifier));
killme();
}
$tpl = get_markup_template("oauth_authorize_done.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$info' => t('Return to your app and insert this Securty Code:'),
'$code' => $verifier,
));
return $o;
}
if(! local_channel()) {
//TODO: we need login form to redirect to this page
notice( t('Please login to continue.') . EOL );
return login(false,'api-login',$request->get_parameters());
}
//FKOAuth1::loginUser(4);
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
$tpl = get_markup_template('oauth_authorize.tpl');
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$app' => $app,
'$authorize' => t('Do you want to authorize this application to access your posts and contacts, and/or create new posts for you?'),
'$yes' => t('Yes'),
'$no' => t('No'),
));
//echo "<pre>"; var_dump($app); killme();
return $o;
}
echo api_call($a);
killme();
}
function oauth_get_client($request){
$params = $request->get_parameters();
$token = $params['oauth_token'];
$r = q("SELECT `clients`.*
FROM `clients`, `tokens`
WHERE `clients`.`client_id`=`tokens`.`client_id`
AND `tokens`.`id`='%s' AND `tokens`.`auth_scope`='request'",
dbesc($token));
if (!count($r))
return null;
return $r[0];
}
}

View file

@ -1,131 +0,0 @@
<?php /** @file */
namespace Zotlabs\Module;
//require_once('include/apps.php');
use \Zotlabs\Lib as Zlib;
class Appman extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
if($_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
'url' => escape_tags($_REQUEST['url']),
'guid' => escape_tags($_REQUEST['guid']),
'author' => escape_tags($_REQUEST['author']),
'addr' => escape_tags($_REQUEST['addr']),
'name' => escape_tags($_REQUEST['name']),
'desc' => escape_tags($_REQUEST['desc']),
'photo' => escape_tags($_REQUEST['photo']),
'version' => escape_tags($_REQUEST['version']),
'price' => escape_tags($_REQUEST['price']),
'requires' => escape_tags($_REQUEST['requires']),
'system' => intval($_REQUEST['system']),
'sig' => escape_tags($_REQUEST['sig']),
'categories' => escape_tags($_REQUEST['categories'])
);
$_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr);
if(Zlib\Apps::app_installed(local_channel(),$arr))
info( t('App installed.') . EOL);
return;
}
$papp = Zlib\Apps::app_decode($_POST['papp']);
if(! is_array($papp)) {
notice( t('Malformed app.') . EOL);
return;
}
if($_POST['install']) {
Zlib\Apps::app_install(local_channel(),$papp);
if(Zlib\Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
}
if($_POST['delete']) {
Zlib\Apps::app_destroy(local_channel(),$papp);
}
if($_POST['edit']) {
return;
}
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/apps');
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = \App::get_channel();
$app = null;
$embed = null;
if($_REQUEST['appid']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($_REQUEST['appid']),
dbesc(local_channel())
);
if($r) {
$app = $r[0];
$term = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
);
if($term) {
$app['categories'] = '';
foreach($term as $t) {
if($app['categories'])
$app['categories'] .= ',';
$app['categories'] .= $t['term'];
}
}
}
$embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"');
}
return replace_macros(get_markup_template('app_create.tpl'), array(
'$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''),
'$author' => (($app) ? $app['app_author'] : $channel['channel_hash']),
'$addr' => (($app) ? $app['app_addr'] : $channel['xchan_addr']),
'$name' => array('name', t('Name of app'),(($app) ? $app['app_name'] : ''), t('Required')),
'$url' => array('url', t('Location (URL) of app'),(($app) ? $app['app_url'] : ''), t('Required')),
'$desc' => array('desc', t('Description'),(($app) ? $app['app_desc'] : ''), ''),
'$photo' => array('photo', t('Photo icon URL'),(($app) ? $app['app_photo'] : ''), t('80 x 80 pixels - optional')),
'$categories' => array('categories',t('Categories (optional, comma separated list)'),(($app) ? $app['categories'] : ''),''),
'$version' => array('version', t('Version ID'),(($app) ? $app['app_version'] : ''), ''),
'$price' => array('price', t('Price of app'),(($app) ? $app['app_price'] : ''), ''),
'$page' => array('page', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : ''), ''),
'$system' => (($app) ? intval($app['app_system']) : 0),
'$requires' => (($app) ? $app['app_requires'] : ''),
'$embed' => $embed,
'$submit' => t('Submit')
));
}
}

View file

@ -1,53 +0,0 @@
<?php
namespace Zotlabs\Module;
//require_once('include/apps.php');
use \Zotlabs\Lib as Zlib;
class Apps extends \Zotlabs\Web\Controller {
function get() {
if(argc() == 2 && argv(1) == 'edit')
$mode = 'edit';
else
$mode = 'list';
$_SESSION['return_url'] = \App::$cmd;
$apps = array();
if(local_channel()) {
Zlib\Apps::import_system_apps();
$syslist = array();
$list = Zlib\Apps::app_list(local_channel(), false, $_GET['cat']);
if($list) {
foreach($list as $x) {
$syslist[] = Zlib\Apps::app_encode($x);
}
}
Zlib\Apps::translate_system_apps($syslist);
}
else
$syslist = Zlib\Apps::get_system_apps(true);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
// logger('apps: ' . print_r($syslist,true));
foreach($syslist as $app) {
$apps[] = Zlib\Apps::app_render($app,$mode);
}
return replace_macros(get_markup_template('myapps.tpl'), array(
'$sitename' => get_config('system','sitename'),
'$cat' => ((array_key_exists('cat',$_GET) && $_GET['cat']) ? ' - ' . escape_tags($_GET['cat']) : ''),
'$title' => t('Apps'),
'$apps' => $apps,
));
}
}

View file

@ -1,61 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/attach.php');
class Attach extends \Zotlabs\Web\Controller {
function init() {
if(argc() < 2) {
notice( t('Item not available.') . EOL);
return;
}
$r = attach_by_hash(argv(1),((argc() > 2) ? intval(argv(2)) : 0));
if(! $r['success']) {
notice( $r['message'] . EOL);
return;
}
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($r['data']['uid'])
);
if(! $c)
return;
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types)) {
header('Content-type: text/plain');
}
else {
header('Content-type: ' . $r['data']['filetype']);
}
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['content']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
else
$istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb');
$ostream = fopen('php://output','wb');
if($istream && $ostream) {
pipe_streams($istream,$ostream);
fclose($istream);
fclose($ostream);
}
}
else
echo dbunescbin($r['data']['content']);
killme();
}
}

View file

@ -1,61 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/zot.php');
class Authtest extends \Zotlabs\Web\Controller {
function get() {
$auth_success = false;
$o .= '<h3>Magic-Auth Diagnostic</h3>';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return $o;
}
$o .= '<form action="authtest" method="get">';
$o .= 'Target URL: <input type="text" style="width: 250px;" name="dest" value="' . $_GET['dest'] .'" />';
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$o .= '<br /><br />';
if(x($_GET,'dest')) {
if(strpos($_GET['dest'],'@')) {
$_GET['dest'] = $_REQUEST['dest'] = 'https://' . substr($_GET['dest'],strpos($_GET['dest'],'@')+1) . '/channel/' . substr($_GET['dest'],0,strpos($_GET['dest'],'@'));
}
$_REQUEST['test'] = 1;
$mod = new Magic();
$x = $mod->init($a);
$o .= 'Local Setup returns: ' . print_r($x,true);
if($x['url']) {
$z = z_fetch_url($x['url'] . '&test=1');
if($z['success']) {
$j = json_decode($z['body'],true);
if(! $j)
$o .= 'json_decode failure from remote site. ' . print_r($z['body'],true);
$o .= 'Remote site responded: ' . print_r($j,true);
if($j['success'] && strpos($j['message'],'Authentication Success'))
$auth_success = true;
}
else {
$o .= 'fetch url failure.' . print_r($z,true);
}
}
if(! $auth_success)
$o .= 'Authentication Failed!' . EOL;
}
return str_replace("\n",'<br />',$o);
}
}

View file

@ -1,92 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/conversation.php');
require_once('include/page_widgets.php');
class Block extends \Zotlabs\Web\Controller {
function init() {
$which = argv(1);
$profile = 0;
profile_load($a,$which,$profile);
if(\App::$profile['profile_uid'])
head_set_icon(\App::$profile['thumb']);
}
function get() {
if(! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
if(argc() < 3) {
notice( t('Invalid item.') . EOL);
return;
}
$channel_address = argv(1);
$page_id = argv(2);
$u = q("select channel_id from channel where channel_address = '%s' limit 1",
dbesc($channel_address)
);
if(! $u) {
notice( t('Channel not found.') . EOL);
return;
}
if($_REQUEST['rev'])
$revision = " and revision = " . intval($_REQUEST['rev']) . " ";
else
$revision = " order by revision desc ";
require_once('include/security.php');
$sql_options = item_permissions_sql($u[0]['channel_id']);
$r = q("select item.* from item left join item_id on item.id = item_id.iid
where item.uid = %d and sid = '%s' and service = 'BUILDBLOCK' and
item_type = %d $sql_options $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_BLOCK)
);
if(! $r) {
// Check again with no permissions clause to see if it is a permissions issue
$x = q("select item.* from item left join item_id on item.id = item_id.iid
where item.uid = %d and sid = '%s' and service = 'BUILDBLOCK' and
item_type = %d $revision limit 1",
intval($u[0]['channel_id']),
dbesc($page_id),
intval(ITEM_TYPE_BLOCK)
);
if($x) {
// Yes, it's there. You just aren't allowed to see it.
notice( t('Permission denied.') . EOL);
}
else {
notice( t('Page not found.') . EOL);
}
return;
}
xchan_query($r);
$r = fetch_post_tags($r,true);
$o .= prepare_page($r[0]);
return $o;
}
}

View file

@ -1,170 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
class Blocks extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$_SESSION['return_url'] = \App::$query_string;
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// Block design features from visitors
if((! $uid) || ($uid != $owner)) {
notice( t('Permission denied.') . EOL);
return;
}
$mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
$x = array(
'webpage' => ITEM_TYPE_BLOCK,
'is_owner' => true,
'nickname' => \App::$profile['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'bang' => '',
'showacl' => false,
'visitor' => true,
'mimetype' => $mimetype,
'mimeselect' => true,
'hide_location' => true,
'ptlabel' => t('Block Name'),
'profile_uid' => intval($owner),
'expanded' => true,
'novoting' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
$editor = status_editor($a,$x);
$r = q("select iid, sid, mid, title, body, mimetype, created, edited from item_id left join item on item_id.iid = item.id
where item_id.uid = %d and service = 'BUILDBLOCK' and item_type = %d order by item.created desc",
intval($owner),
intval(ITEM_TYPE_BLOCK)
);
$pages = null;
if($r) {
$pages = array();
foreach($r as $rr) {
$element_arr = array(
'type' => 'block',
'title' => $rr['title'],
'body' => $rr['body'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'mimetype' => $rr['mimetype'],
'pagetitle' => $rr['sid'],
'mid' => $rr['mid']
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'name' => $rr['sid'],
'title' => $rr['title'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'
);
}
}
//Build the base URL for edit links
$url = z_root() . '/editblock/' . $which;
$o .= replace_macros(get_markup_template('blocklist.tpl'), array(
'$baseurl' => $url,
'$title' => t('Blocks'),
'$name' => t('Block Name'),
'$blocktitle' => t('Block Title'),
'$created' => t('Created'),
'$edited' => t('Edited'),
'$create' => t('Create'),
'$edit' => t('Edit'),
'$share' => t('Share'),
'$delete' => t('Delete'),
'$editor' => $editor,
'$pages' => $pages,
'$channel' => $which,
'$view' => t('View'),
'$preview' => '1',
));
return $o;
}
}

View file

@ -1,105 +0,0 @@
<?php
namespace Zotlabs\Module;
class Bookmarks extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$item_id = intval($_REQUEST['item']);
$burl = trim($_REQUEST['burl']);
if(! $item_id)
return;
$u = \App::get_channel();
$item_normal = item_normal();
$i = q("select * from item where id = %d and uid = %d $item_normal limit 1",
intval($item_id),
intval(local_channel())
);
if(! $i)
return;
$i = fetch_post_tags($i);
$item = $i[0];
$terms = get_terms_oftype($item['term'],TERM_BOOKMARK);
if($terms) {
require_once('include/bookmarks.php');
$s = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
if(! $s) {
logger('mod_bookmarks: author lookup failed.');
killme();
}
foreach($terms as $t) {
if($burl) {
if($burl == $t['url']) {
bookmark_add($u,$s[0],$t,$item['item_private']);
}
}
else
bookmark_add($u,$s[0],$t,$item['item_private']);
info( t('Bookmark added') . EOL);
}
}
killme();
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
require_once('include/menu.php');
require_once('include/conversation.php');
$channel = \App::get_channel();
$o = profile_tabs($a,true,$channel['channel_address']);
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h3>' . t('My Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '<h3>' . t('My Connections Bookmarks') . '</h3>';
$x = menu_list(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
$o .= '</div>';
return $o;
}
}

View file

@ -1,47 +0,0 @@
<?php
namespace Zotlabs\Module;
class Branchtopic extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$item_id = 0;
if(argc() > 1)
$item_id = intval(argv(1));
if(! $item_id)
return;
$channel = \App::get_channel();
if(! $channel)
return;
$r = q("select * from item where id = %d and uid = %d and owner_xchan = '%s' and id != parent limit 1",
intval($item_id),
intval(local_channel()),
dbesc($channel['channel_hash'])
);
if(! $r)
return;
$p = q("select * from item where id = %d and uid = %d limit 1",
intval($r[0]['parent']),
intval(local_channel())
);
$x = q("update item set parent = id, route = '', item_thread_top = 1 where id = %d",
intval($item_id)
);
return;
}
}

View file

@ -1,354 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/conversation.php');
require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
class Cal extends \Zotlabs\Web\Controller {
function init() {
if(observer_prohibited()) {
return;
}
$o = '';
if(argc() > 1) {
$nick = argv(1);
profile_load($a,$nick);
$channelx = channelx_by_nick($nick);
if(! $channelx)
return;
\App::$data['channel'] = $channelx;
$observer = \App::get_observer();
\App::$data['observer'] = $observer;
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
head_set_icon(\App::$data['channel']['xchan_photo_s']);
\App::$page['htmlhead'] .= "<script> var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ;
}
return;
}
function get() {
if(observer_prohibited()) {
return;
}
$channel = null;
if(argc() > 1) {
$channel = channelx_by_nick(argv(1));
}
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
// since we don't currently have an event permission - use the stream permission
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
notice( t('Permissions denied.') . EOL);
return;
}
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl');
\App::$page['htmlhead'] .= replace_macros($htpl,array(
'$baseurl' => z_root(),
'$module_url' => '/cal/' . $channel['channel_address'],
'$modparams' => 2,
'$lang' => \App::$language,
'$first_day' => $first_day
));
$o = '';
$tabs = profile_tabs($a, True, $channel['channel_address']);
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
if(argc() > 3 && intval(argv(2)) && intval(argv(3))) {
$mode = 'view';
$y = intval(argv(2));
$m = intval(argv(3));
}
if(argc() <= 3) {
$mode = 'view';
$event_id = argv(2);
}
if($mode == 'view') {
/* edit/create form */
if($event_id) {
$r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1",
dbesc($event_id),
intval($channel['channel_id'])
);
if(count($r))
$orig_event = $r[0];
}
// Passed parameters overrides anything found in the DB
if(!x($orig_event))
$orig_event = array();
$tz = date_default_timezone_get();
if(x($orig_event))
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
$stext = datetime_convert('UTC',$tz,$sdt);
$stext = substr($stext,0,14) . "00:00";
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
$f = 'ymd';
$catsenabled = feature_enabled($channel['channel_id'],'categories');
$show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts');
if(! $show_bd) {
$sql_extra .= " and event.etype != 'birthday' ";
}
$category = '';
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
if(! $y)
$y = intval($thisyear);
if(! $m)
$m = intval($thismonth);
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
if($y < 1901)
$y = 1900;
if($y > 2099)
$y = 2100;
$nextyear = $y;
$nextmonth = $m + 1;
if($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if($m > 1)
$prevmonth = $m - 1;
else {
$prevmonth = 12;
$prevyear --;
}
$dim = get_dim($y,$m);
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
if (argv(2) === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
if (x($_GET,'id')){
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
intval($channel['channel_id']),
intval($_GET['id'])
);
}
else {
// fixed an issue with "nofinish" events not showing up in the calendar.
// There's still an issue if the finish date crosses the end of month.
// Noting this for now - it will need to be fixed here and in Friendica.
// Ultimately the finish date shouldn't be involved in the query.
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on event_hash = resource_id
where resource_type = 'event' and event.uid = %d $ignored
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) $sql_extra ",
intval($channel['channel_id']),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
$links = array();
if($r) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = sort_by_date($r);
}
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
if(! x($links,$j))
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
}
}
$events=array();
$last_date = '';
$fmt = t('l, F j');
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
$d = day_translate($d);
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
if ($rr['nofinish']){
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
}
$is_first = ($d !== $last_date);
$last_date = $d;
$edit = false;
$drop = false;
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
if(! $title) {
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
}
$html = format_event_html($rr);
$rr['desc'] = bbcode($rr['desc']);
$rr['location'] = bbcode($rr['location']);
$events[] = array(
'id'=>$rr['id'],
'hash' => $rr['event_hash'],
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => false,
'title' => $title,
'j' => $j,
'd' => $d,
'edit' => $edit,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('Link to Source'),'',''),
);
}
}
if (argv(2) === 'json'){
echo json_encode($events); killme();
}
// links: array('href', 'text', 'extra css classes', 'title')
if (x($_GET,'id')){
$tpl = get_markup_template("event_cal.tpl");
}
else {
$tpl = get_markup_template("events_cal-js.tpl");
}
$nick = $channel['channel_address'];
$o = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$new_event' => array(z_root().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
'$previus' => array(z_root()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''),
'$next' => array(z_root()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''),
'$export' => array(z_root()."/cal/$nick/$y/$m/export",t('Export'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$events' => $events,
'$upload' => t('Import'),
'$submit' => t('Submit'),
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),
'$form' => $form,
'$expandform' => ((x($_GET,'expandform')) ? true : false),
'$tabs' => $tabs
));
if (x($_GET,'id')){ echo $o; killme(); }
return $o;
}
}
}

View file

@ -1,367 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/contact_widgets.php');
require_once('include/items.php');
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/permissions.php');
require_once('include/PermissionDescription.php');
class Channel extends \Zotlabs\Web\Controller {
function init() {
$which = null;
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = \App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
}
if(! $which) {
notice( t('You must be logged in to see this page.') . EOL );
return;
}
$profile = 0;
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Posts and comments') . '" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n" ;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" title="' . t('Only posts') . '" href="' . z_root() . '/feed/' . $which . '?top=1" />' . "\r\n" ;
// Not yet ready for prime time
// \App::$page['htmlhead'] .= '<link rel="openid.server" href="' . z_root() . '/id/' . $which .'?f=" />' . "\r\n" ;
// \App::$page['htmlhead'] .= '<link rel="openid.delegate" href="' . z_root() . '/channel/' . $which .'" />' . "\r\n" ;
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($a,$which,$profile);
}
function get($update = 0, $load = false) {
if($load)
$_SESSION['loadtime'] = datetime_convert();
$checkjs = new \Zotlabs\Web\CheckJS(1);
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
if(observer_prohibited(true)) {
return login();
}
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$groups = array();
$o = '';
if($update) {
// Ensure we've got a profile owner if updating.
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
}
else {
if(\App::$profile['profile_uid'] == local_channel()) {
nav_set_selected('home');
}
}
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
$channel = \App::get_channel();
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash);
if(! $perms['view_stream']) {
// We may want to make the target of this redirect configurable
if($perms['view_profile']) {
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
goaway (z_root() . "/profile/" . \App::$profile['channel_address']);
}
notice( t('Permission denied.') . EOL);
return;
}
if(! $update) {
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
if($channel && $is_owner) {
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
}
else
$channel_acl = array();
if($perms['post_wall']) {
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
'nickname' => \App::$profile['channel_address'],
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl,true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => \App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
$o .= status_editor($a,$x);
}
}
/**
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
$item_normal = item_normal();
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
$page_mode = 'list';
else
$page_mode = 'client';
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n";
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if(($update) && (! $load)) {
if($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 AND item_unseen = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(\App::$profile['profile_uid'])
);
}
else {
$r = q("SELECT distinct parent AS `item_id`, created from item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
WHERE uid = %d $item_normal
AND item_wall = 1 $simple_update
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra
ORDER BY created DESC",
intval(\App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
}
else {
if(x($category)) {
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
if($load || ($checkjs->disabled())) {
if($mid) {
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid),
intval(\App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
}
}
else {
$r = q("SELECT distinct id AS item_id, created FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE uid = %d $item_normal
AND item_wall = 1 and item_thread_top = 1
AND (abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $sql_extra2
ORDER BY created DESC $pager_sql ",
intval(\App::$profile['profile_uid'])
);
}
}
else {
$r = array();
}
}
if($r) {
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`
FROM `item`
WHERE `item`.`uid` = %d $item_normal
AND `item`.`parent` IN ( %s )
$sql_extra ",
intval(\App::$profile['profile_uid']),
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items, true);
$items = conv_sort($items,'created');
if($load && $mid && (! count($items))) {
// This will happen if we don't have sufficient permissions
// to view the parent item (or the item itself if it is toplevel)
notice( t('Permission denied.') . EOL);
}
}
else {
$items = array();
}
if((! $update) && (! $load)) {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
$maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
'$cmax' => '0',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$nouveau' => '0',
'$wall' => '1',
'$fh' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$order' => '',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? $category : ''),
'$tags' => (($hashtags) ? $hashtags : ''),
'$mid' => $mid,
'$verb' => '',
'$dend' => $datequery,
'$dbegin' => $datequery2
));
}
$update_unseen = '';
if($page_mode === 'list') {
/**
* in "list mode", only mark the parent item and any like activities as "seen".
* We won't distinguish between comment likes and post likes. The important thing
* is that the number of unseen comments will be accurate. The SQL to separate the
* comment likes could also get somewhat hairy.
*/
if($parents_str) {
$update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )";
$update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) ";
}
}
else {
if($parents_str) {
$update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )";
}
}
if($is_owner && $update_unseen) {
$r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen",
intval(local_channel())
);
}
if($checkjs->disabled()) {
$o .= conversation($a,$items,'channel',$update,'traditional');
}
else {
$o .= conversation($a,$items,'channel',$update,$page_mode);
}
if((! $update) || ($checkjs->disabled())) {
$o .= alt_pager($a,count($items));
if ($mid && $items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
if($mid)
$o .= '<div id="content-complete"></div>';
return $o;
}
}

View file

@ -1,105 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/zot.php');
class Chanview extends \Zotlabs\Web\Controller {
function get() {
$observer = \App::get_observer();
$xchan = null;
$r = null;
if($_REQUEST['hash']) {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($_REQUEST['hash'])
);
}
if($_REQUEST['address']) {
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($_REQUEST['address'])
);
}
elseif(local_channel() && intval($_REQUEST['cid'])) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval($_REQUEST['cid'])
);
}
elseif($_REQUEST['url']) {
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
// the most useful consistently ascending table item we have.
$r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc limit 1",
dbesc($_REQUEST['url'])
);
}
if($r) {
\App::$poi = $r[0];
}
// Here, let's see if we have an xchan. If we don't, how we proceed is determined by what
// info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
// address, we can and should try to import it. If it's just a hash, we can't continue, but we
// probably wouldn't have a hash if we don't already have an xchan for this channel.
if(! \App::$poi) {
logger('mod_chanview: fallback');
// This is hackish - construct a zot address from the url
if($_REQUEST['url']) {
if(preg_match('/https?\:\/\/(.*?)(\/channel\/|\/profile\/)(.*?)$/ism',$_REQUEST['url'],$matches)) {
$_REQUEST['address'] = $matches[3] . '@' . $matches[1];
}
logger('mod_chanview: constructed address ' . print_r($matches,true));
}
if($_REQUEST['address']) {
$j = \Zotlabs\Zot\Finger::run($_REQUEST['address'],null);
if($j['success']) {
import_xchan($j);
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
dbesc($_REQUEST['address'])
);
if($r)
\App::$poi = $r[0];
}
}
}
if(! \App::$poi) {
// We don't know who this is, and we can't figure it out from the URL
// On the plus side, there's a good chance we know somebody else at that
// hub so sending them there with a Zid will probably work anyway.
$url = ($_REQUEST['url']);
if($observer)
$url = zid($url);
}
if (\App::$poi) {
$url = \App::$poi['xchan_url'];
if($observer)
$url = zid($url);
}
// let somebody over-ride the iframed viewport presentation
// or let's just declare this a failed experiment.
// if((! local_channel()) || (get_pconfig(local_channel(),'system','chanview_full')))
goaway($url);
// $o = replace_macros(get_markup_template('chanview.tpl'),array(
// '$url' => $url,
// '$full' => t('toggle full screen mode')
// ));
// return $o;
}
}

View file

@ -1,263 +0,0 @@
<?php /** @file */
namespace Zotlabs\Module;
require_once('include/bookmarks.php');
use \Zotlabs\Lib as Zlib;
class Chat extends \Zotlabs\Web\Controller {
function init() {
$which = null;
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = \App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
}
if(! $which) {
notice( t('You must be logged in to see this page.') . EOL );
return;
}
$profile = 0;
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which .'" />' . "\r\n" ;
// Run profile_load() here to make sure the theme is set before
// we start loading content
profile_load($a,$which,$profile);
}
function post() {
if($_POST['room_name'])
$room = strip_tags(trim($_POST['room_name']));
if((! $room) || (! local_channel()))
return;
$channel = \App::get_channel();
if($_POST['action'] === 'drop') {
logger('delete chatroom');
Zlib\Chatroom::destroy($channel,array('cr_name' => $room));
goaway(z_root() . '/chat/' . $channel['channel_address']);
}
$acl = new \Zotlabs\Access\AccessList($channel);
$acl->set_from_array($_REQUEST);
$arr = $acl->get();
$arr['name'] = $room;
$arr['expire'] = intval($_POST['chat_expire']);
if(intval($arr['expire']) < 0)
$arr['expire'] = 0;
Zlib\Chatroom::create($channel,$arr);
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
dbesc($room),
intval(local_channel())
);
build_sync_packet(0, array('chatroom' => $x));
if($x)
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']);
// that failed. Try again perhaps?
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new');
}
function get() {
if(local_channel())
$channel = \App::get_channel();
$ob = \App::get_observer();
$observer = get_observer_hash();
if(! $observer) {
notice( t('Permission denied.') . EOL);
return;
}
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer,'chat')) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
Zlib\Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
goaway(z_root() . '/channel/' . argv(1));
}
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'status')) {
$ret = array('success' => false);
$room_id = intval(argv(2));
if(! $room_id || ! $observer)
return;
$r = q("select * from chatroom where cr_id = %d limit 1",
intval($room_id)
);
if(! $r) {
json_return_and_die($ret);
}
require_once('include/security.php');
$sql_extra = permissions_sql($r[0]['cr_uid']);
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
intval($room_id),
intval($r[0]['cr_uid'])
);
if(! $x) {
json_return_and_die($ret);
}
$y = q("select count(*) as total from chatpresence where cp_room = %d",
intval($room_id)
);
if($y) {
$ret['success'] = true;
$ret['chatroom'] = $r[0]['cr_name'];
$ret['inroom'] = $y[0]['total'];
}
// figure out how to present a timestamp of the last activity, since we don't know the observer's timezone.
$z = q("select created from chat where chat_room = %d order by created desc limit 1",
intval($room_id)
);
if($z) {
$ret['last'] = $z[0]['created'];
}
json_return_and_die($ret);
}
if(argc() > 2 && intval(argv(2))) {
$room_id = intval(argv(2));
$bookmark_link = get_bookmark_link($ob);
$x = Zlib\Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
intval($room_id),
intval(\App::$profile['profile_uid'])
);
if($x) {
$acl = new \Zotlabs\Access\AccessList(false);
$acl->set($x[0]);
$private = $acl->is_private();
$room_name = $x[0]['cr_name'];
if($bookmark_link)
$bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
}
else {
notice( t('Room not found') . EOL);
return;
}
$cipher = get_pconfig(local_channel(),'system','default_cipher');
if(! $cipher)
$cipher = 'aes256';
$o = replace_macros(get_markup_template('chat.tpl'),array(
'$is_owner' => ((local_channel() && local_channel() == $x[0]['cr_uid']) ? true : false),
'$room_name' => $room_name,
'$room_id' => $room_id,
'$baseurl' => z_root(),
'$nickname' => argv(1),
'$submit' => t('Submit'),
'$leave' => t('Leave Room'),
'$drop' => t('Delete Room'),
'$away' => t('I am away right now'),
'$online' => t('I am online'),
'$bookmark_link' => $bookmark_link,
'$bookmark' => t('Bookmark this room'),
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
'$cipher' => $cipher,
'$linkurl' => t('Please enter a link URL:'),
'$encrypt' => t('Encrypt text'),
'$insert' => t('Insert web link')
));
return $o;
}
require_once('include/conversation.php');
$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) {
notice( t('Feature disabled.') . EOL);
return $o;
}
$acl = new \Zotlabs\Access\AccessList($channel);
$channel_acl = $acl->get();
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');
require_once('include/acl_selectors.php');
$chatroom_new = '';
if(local_channel()) {
$chatroom_new = replace_macros(get_markup_template('chatroom_new.tpl'),array(
'$header' => t('New Chatroom'),
'$name' => array('room_name',t('Chatroom name'),'', ''),
'$chat_expire' => array('chat_expire',t('Expiration of chats (minutes)'),120,''),
'$permissions' => t('Permissions'),
'$acl' => populate_acl($channel_acl,false),
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
}
$rooms = Zlib\Chatroom::roomlist(\App::$profile['profile_uid']);
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
'$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['fullname']),
'$name' => t('Name'),
'$baseurl' => z_root(),
'$nickname' => \App::$profile['channel_address'],
'$rooms' => $rooms,
'$norooms' => t('No chatrooms available'),
'$newroom' => t('Create New'),
'$is_owner' => ((local_channel() && local_channel() == \App::$profile['profile_uid']) ? 1 : 0),
'$chatroom_new' => $chatroom_new,
'$expire' => t('Expiration'),
'$expire_unit' => t('min') //minutes
));
return $o;
}
}

View file

@ -1,170 +0,0 @@
<?php /** @file */
namespace Zotlabs\Module;
require_once('include/security.php');
use \Zotlabs\Lib as Zlib;
class Chatsvc extends \Zotlabs\Web\Controller {
function init() {
//logger('chatsvc');
$ret = array('success' => false);
\App::$data['chat']['room_id'] = intval($_REQUEST['room_id']);
$x = q("select cr_uid from chatroom where cr_id = %d and cr_id != 0 limit 1",
intval(\App::$data['chat']['room_id'])
);
if(! $x)
json_return_and_die($ret);
\App::$data['chat']['uid'] = $x[0]['cr_uid'];
if(! perm_is_allowed(\App::$data['chat']['uid'],get_observer_hash(),'chat')) {
json_return_and_die($ret);
}
}
function post() {
$ret = array('success' => false);
$room_id = \App::$data['chat']['room_id'];
$text = escape_tags($_REQUEST['chat_text']);
if(! $text)
return;
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$arr = array(
'chat_room' => \App::$data['chat']['room_id'],
'chat_xchan' => get_observer_hash(),
'chat_text' => $text
);
call_hooks('chat_post',$arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
values( %d, '%s', '%s', '%s' )",
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc(datetime_convert()),
dbesc($arr['chat_text'])
);
$ret['success'] = true;
json_return_and_die($ret);
}
function get() {
$status = strip_tags($_REQUEST['status']);
$room_id = intval(\App::$data['chat']['room_id']);
$stopped = ((x($_REQUEST,'stopped') && intval($_REQUEST['stopped'])) ? true : false);
if($status && $room_id) {
$x = q("select channel_address from channel where channel_id = %d limit 1",
intval(\App::$data['chat']['uid'])
);
$r = q("update chatpresence set cp_status = '%s', cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc($status),
dbesc(datetime_convert()),
intval($room_id),
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
goaway(z_root() . '/chat/' . $x[0]['channel_address'] . '/' . $room_id);
}
if(! $stopped) {
$lastseen = intval($_REQUEST['last']);
$ret = array('success' => false);
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$inroom = array();
$r = q("select * from chatpresence left join xchan on xchan_hash = cp_xchan where cp_room = %d order by xchan_name",
intval(\App::$data['chat']['room_id'])
);
if($r) {
foreach($r as $rr) {
switch($rr['cp_status']) {
case 'away':
$status = t('Away');
$status_class = 'away';
break;
case 'online':
default:
$status = t('Online');
$status_class = 'online';
break;
}
$inroom[] = array('img' => zid($rr['xchan_photo_m']), 'img_type' => $rr['xchan_photo_mimetype'],'name' => $rr['xchan_name'], 'status' => $status, 'status_class' => $status_class);
}
}
$chats = array();
$r = q("select * from chat left join xchan on chat_xchan = xchan_hash where chat_room = %d and chat_id > %d order by created",
intval(\App::$data['chat']['room_id']),
intval($lastseen)
);
if($r) {
foreach($r as $rr) {
$chats[] = array(
'id' => $rr['chat_id'],
'img' => zid($rr['xchan_photo_m']),
'img_type' => $rr['xchan_photo_mimetype'],
'name' => $rr['xchan_name'],
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'r'),
'text' => smilies(bbcode($rr['chat_text'])),
'self' => ((get_observer_hash() == $rr['chat_xchan']) ? 'self' : '')
);
}
}
}
$r = q("update chatpresence set cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc(datetime_convert()),
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
$ret['success'] = true;
if(! $stopped) {
$ret['inroom'] = $inroom;
$ret['chats'] = $chats;
}
json_return_and_die($ret);
}
}

View file

@ -1,112 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/cloud.php
* @brief Initialize Hubzilla's cloud (SabreDAV).
*
* Module for accessing the DAV storage area.
*/
use Sabre\DAV as SDAV;
use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
/**
* @brief Fires up the SabreDAV server.
*
* @param App &$a
*/
class Cloud extends \Zotlabs\Web\Controller {
function init() {
require_once('include/reddav.php');
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
$which = null;
if (argc() > 1)
$which = argv(1);
$profile = 0;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n";
if ($which)
profile_load($a, $which, $profile);
$auth = new \Zotlabs\Storage\BasicAuth();
$ob_hash = get_observer_hash();
if ($ob_hash) {
if (local_channel()) {
$channel = \App::get_channel();
$auth->setCurrentUser($channel['channel_address']);
$auth->channel_id = $channel['channel_id'];
$auth->channel_hash = $channel['channel_hash'];
$auth->channel_account_id = $channel['channel_account_id'];
if($channel['channel_timezone'])
$auth->setTimezone($channel['channel_timezone']);
}
$auth->observer = $ob_hash;
}
if ($_GET['davguest'])
$_SESSION['davguest'] = true;
$_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']);
$_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']);
$_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']);
$_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']);
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
// A SabreDAV server-object
$server = new SDAV\Server($rootDirectory);
// prevent overwriting changes each other with a lock backend
$lockBackend = new SDAV\Locks\Backend\File('store/[data]/locks');
$lockPlugin = new SDAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
$is_readable = false;
if($_SERVER['REQUEST_METHOD'] === 'GET') {
try {
$x = RedFileData('/' . \App::$cmd, $auth);
}
catch(\Exception $e) {
if($e instanceof Sabre\DAV\Exception\Forbidden) {
http_status_exit(401, 'Permission denied.');
}
}
}
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$auth->setBrowserPlugin($browser);
$server->addPlugin($browser);
// Experimental QuotaPlugin
// require_once('\Zotlabs\Storage/QuotaPlugin.php');
// $server->addPlugin(new \Zotlabs\Storage\\QuotaPlugin($auth));
ob_start();
// All we need to do now, is to fire up the server
$server->exec();
ob_end_flush();
killme();
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/socgraph.php');
class Common extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && intval(argv(1)))
$channel_id = intval(argv(1));
else {
notice( t('No channel.') . EOL );
\App::$error = 404;
return;
}
$x = q("select channel_address from channel where channel_id = %d limit 1",
intval($channel_id)
);
if($x)
profile_load($a,$x[0]['channel_address'],0);
}
function get() {
$o = '';
if(! \App::$profile['profile_uid'])
return;
$observer_hash = get_observer_hash();
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer_hash,'view_contacts')) {
notice( t('Permission denied.') . EOL);
return;
}
$o .= '<h2>' . t('Common connections') . '</h2>';
$t = count_common_friends(\App::$profile['profile_uid'],$observer_hash);
if(! $t) {
notice( t('No connections in common.') . EOL);
return $o;
}
$r = common_friends(\App::$profile['profile_uid'],$observer_hash);
if($r) {
$tpl = get_markup_template('common_friends.tpl');
foreach($r as $rr) {
$o .= replace_macros($tpl,array(
'$url' => $rr['xchan_url'],
'$name' => $rr['xchan_name'],
'$photo' => $rr['xchan_photo_m'],
'$tags' => ''
));
}
$o .= cleardiv();
}
return $o;
}
}

View file

@ -1,131 +0,0 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/contact_widgets.php');
require_once('include/items.php');
class Connect extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$r = q("select * from channel where channel_address = '%s' limit 1",
dbesc($which)
);
if($r)
\App::$data['channel'] = $r[0];
profile_load($a,$which,'');
}
function post() {
if(! array_key_exists('channel', \App::$data))
return;
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
if($edit) {
$has_premium = ((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0);
$premium = (($_POST['premium']) ? intval($_POST['premium']) : 0);
$text = escape_tags($_POST['text']);
if($has_premium != $premium) {
$r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d",
db_getfunc('^'),
intval(PAGE_PREMIUM),
intval(local_channel())
);
\Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',\App::$data['channel']['channel_id']));
}
set_pconfig(\App::$data['channel']['channel_id'],'system','selltext',$text);
// reload the page completely to get fresh data
goaway(z_root() . '/' . \App::$query_string);
}
$url = '';
$observer = \App::get_observer();
if(($observer) && ($_POST['submit'] === t('Continue'))) {
if($observer['xchan_follow'])
$url = sprintf($observer['xchan_follow'],urlencode(\App::$data['channel']['channel_address'] . '@' . \App::get_hostname()));
if(! $url) {
$r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1",
dbesc($observer['xchan_hash'])
);
if($r)
$url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(\App::$data['channel']['channel_address'] . '@' . \App::get_hostname());
}
}
if($url)
goaway($url . '&confirm=1');
else
notice('Unable to connect to your home hub location.');
}
function get() {
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
$text = get_pconfig(\App::$data['channel']['channel_id'],'system','selltext');
if($edit) {
$o = replace_macros(get_markup_template('sellpage_edit.tpl'),array(
'$header' => t('Premium Channel Setup'),
'$address' => \App::$data['channel']['channel_address'],
'$premium' => array('premium', t('Enable premium channel connection restrictions'),((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''),
'$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'),
'$text' => $text,
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
'$lbl2' => t('Potential connections will then see the following text before proceeding:'),
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
'$submit' => t('Submit'),
));
return $o;
}
else {
if(! $text)
$text = t('(No specific instructions have been provided by the channel owner.)');
$submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array(
'$continue' => t('Continue'),
'$address' => \App::$data['channel']['channel_address']
));
$o = replace_macros(get_markup_template('sellpage_view.tpl'),array(
'$header' => t('Restricted or Premium Channel'),
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
'$text' => prepare_text($text),
'$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'),
'$submit' => $submit,
));
$arr = array('channel' => \App::$data['channel'],'observer' => \App::get_observer(), 'sellpage' => $o, 'submit' => $submit);
call_hooks('connect_premium', $arr);
$o = $arr['sellpage'];
}
return $o;
}
}

View file

@ -1,324 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/socgraph.php');
require_once('include/selectors.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/zot.php');
require_once('include/widgets.php');
class Connections extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
$channel = \App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
}
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$blocked = false;
$hidden = false;
$ignored = false;
$archived = false;
$unblocked = false;
$pending = false;
$unconnected = false;
$all = false;
if(! $_REQUEST['aj'])
$_SESSION['return_url'] = \App::$query_string;
$search_flags = '';
$head = '';
if(argc() == 2) {
switch(argv(1)) {
case 'blocked':
$search_flags = " and abook_blocked = 1 ";
$head = t('Blocked');
$blocked = true;
break;
case 'ignored':
$search_flags = " and abook_ignored = 1 ";
$head = t('Ignored');
$ignored = true;
break;
case 'hidden':
$search_flags = " and abook_hidden = 1 ";
$head = t('Hidden');
$hidden = true;
break;
case 'archived':
$search_flags = " and abook_archived = 1 ";
$head = t('Archived');
$archived = true;
break;
case 'pending':
$search_flags = " and abook_pending = 1 ";
$head = t('New');
$pending = true;
nav_set_selected('intros');
break;
case 'ifpending':
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval(local_channel())
);
if($r && $r[0]['total']) {
$search_flags = " and abook_pending = 1 ";
$head = t('New');
$pending = true;
nav_set_selected('intros');
\App::$argv[1] = 'pending';
}
else {
$head = t('All');
$search_flags = '';
$all = true;
\App::$argc = 1;
unset(\App::$argv[1]);
}
nav_set_selected('intros');
break;
// case 'unconnected':
// $search_flags = " and abook_unconnected = 1 ";
// $head = t('Unconnected');
// $unconnected = true;
// break;
case 'all':
$head = t('All');
default:
$search_flags = '';
$all = true;
break;
}
$sql_extra = $search_flags;
if(argv(1) === 'pending')
$sql_extra .= " and abook_ignored = 0 ";
}
else {
$sql_extra = " and abook_blocked = 0 ";
$unblocked = true;
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$tabs = array(
/*
array(
'label' => t('Suggestions'),
'url' => z_root() . '/suggest',
'sel' => '',
'title' => t('Suggest new connections'),
),
*/
'pending' => array(
'label' => t('New Connections'),
'url' => z_root() . '/connections/pending',
'sel' => ($pending) ? 'active' : '',
'title' => t('Show pending (new) connections'),
),
'all' => array(
'label' => t('All Connections'),
'url' => z_root() . '/connections/all',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all connections'),
),
/*
array(
'label' => t('Unblocked'),
'url' => z_root() . '/connections',
'sel' => (($unblocked) && (! $search) && (! $nets)) ? 'active' : '',
'title' => t('Only show unblocked connections'),
),
*/
'blocked' => array(
'label' => t('Blocked'),
'url' => z_root() . '/connections/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked connections'),
),
'ignored' => array(
'label' => t('Ignored'),
'url' => z_root() . '/connections/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored connections'),
),
'archived' => array(
'label' => t('Archived'),
'url' => z_root() . '/connections/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived connections'),
),
'hidden' => array(
'label' => t('Hidden'),
'url' => z_root() . '/connections/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden connections'),
),
// array(
// 'label' => t('Unconnected'),
// 'url' => z_root() . '/connections/unconnected',
// 'sel' => ($unconnected) ? 'active' : '',
// 'title' => t('Only show one-way connections'),
// ),
);
//$tab_tpl = get_markup_template('common_tabs.tpl');
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
$searching = false;
if($search) {
$search_hdr = $search;
$search_txt = dbesc(protect_sprintf(preg_quote($search)));
$searching = true;
}
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
if($_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
}
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ",
intval(local_channel())
);
if($r) {
\App::set_pager_total($r[0]['total']);
$total = $r[0]['total'];
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(\App::$pager['itemspage']),
intval(\App::$pager['start'])
);
$contacts = array();
if(count($r)) {
foreach($r as $rr) {
if($rr['xchan_url']) {
$status_str = '';
$status = array(
((intval($rr['abook_pending'])) ? t('Pending approval') : ''),
((intval($rr['abook_archived'])) ? t('Archived') : ''),
((intval($rr['abook_hidden'])) ? t('Hidden') : ''),
((intval($rr['abook_ignored'])) ? t('Ignored') : ''),
((intval($rr['abook_blocked'])) ? t('Blocked') : '')
);
foreach($status as $str) {
if(!$str)
continue;
$status_str .= $str;
$status_str .= ', ';
}
$status_str = rtrim($status_str, ', ');
$contacts[] = array(
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
'edit_hover' => t('Edit connection'),
'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'],
'thumb' => $rr['xchan_photo_m'],
'name' => $rr['xchan_name'],
'classes' => (intval($rr['abook_archived']) ? 'archived' : ''),
'link' => z_root() . '/connedit/' . $rr['abook_id'],
'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
'delete' => t('Delete'),
'url' => chanlink_url($rr['xchan_url']),
'webbie_label' => t('Channel address'),
'webbie' => $rr['xchan_addr'],
'network_label' => t('Network'),
'network' => network_to_name($rr['xchan_network']),
'public_forum' => ((intval($rr['xchan_pubforum'])) ? true : false),
'status_label' => t('Status'),
'status' => $status_str,
'connected_label' => t('Connected'),
'connected' => datetime_convert('UTC',date_default_timezone_get(),$rr['abook_created'], 'c'),
'approve_hover' => t('Approve connection'),
'approve' => (($rr['abook_pending']) ? t('Approve') : false),
'ignore_hover' => t('Ignore connection'),
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
'recent_label' => t('Recent activity'),
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id'])
);
}
}
}
if($_REQUEST['aj']) {
if($contacts) {
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
'$contacts' => $contacts,
'$edit' => t('Edit'),
));
}
else {
$o = '<div id="content-complete"></div>';
}
echo $o;
killme();
}
else {
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$o .= replace_macros(get_markup_template('connections.tpl'),array(
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
'$total' => $total,
'$search' => $search_hdr,
'$label' => t('Search'),
'$desc' => t('Search your connections'),
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
'$cmd' => \App::$cmd,
'$contacts' => $contacts,
'$paginate' => paginate($a),
));
}
if(! $contacts)
$o .= '<div id="content-complete"></div>';
return $o;
}
}

View file

@ -1,760 +0,0 @@
<?php
namespace Zotlabs\Module;
/* @file connedit.php
* @brief In this file the connection-editor form is generated and evaluated.
*
*
*/
require_once('include/socgraph.php');
require_once('include/selectors.php');
require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/zot.php');
require_once('include/widgets.php');
require_once('include/photos.php');
/* @brief Initialize the connection-editor
*
*
*/
class Connedit extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
if((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval(argv(1))
);
if($r) {
\App::$poi = $r[0];
}
}
$channel = \App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
}
/* @brief Evaluate posted values and set changes
*
*/
function post() {
if(! local_channel())
return;
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$channel = \App::get_channel();
// TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
// connection enable is toggled to a special autopost url and set permissions immediately, leaving
// the other form elements alone pending a manual submit of the form. The downside is that there
// will be a window of opportunity when the permissions have been set but before you've had a chance
// to review and possibly restrict them. The upside is we won't have to warn you that your connection
// can't do anything until you save the bloody form.
$autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! $orig_record) {
notice( t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
call_hooks('contact_edit_post', $_POST);
if(intval($orig_record[0]['abook_self'])) {
$autoperms = intval($_POST['autoperms']);
$is_self = true;
}
else {
$autoperms = null;
$is_self = false;
}
$profile_id = $_POST['profile_assign'];
if($profile_id) {
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND `uid` = %d LIMIT 1",
dbesc($profile_id),
intval(local_channel())
);
if(! count($r)) {
notice( t('Could not locate selected profile.') . EOL);
return;
}
}
$abook_incl = escape_tags($_POST['abook_incl']);
$abook_excl = escape_tags($_POST['abook_excl']);
$hidden = intval($_POST['hidden']);
$priority = intval($_POST['poll']);
if($priority > 5 || $priority < 0)
$priority = 0;
$closeness = intval($_POST['closeness']);
if($closeness < 0)
$closeness = 99;
$rating = intval($_POST['rating']);
if($rating < (-10))
$rating = (-10);
if($rating > 10)
$rating = 10;
$rating_text = trim(escape_tags($_REQUEST['rating_text']));
$abook_my_perms = 0;
foreach($_POST as $k => $v) {
if(strpos($k,'perms_') === 0) {
$abook_my_perms += $v;
}
}
$new_friend = false;
if(! $is_self) {
$signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
$sig = base64url_encode(rsa_sign($signed,$channel['channel_prvkey']));
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan'])
);
if($z) {
$record = $z[0]['xlink_id'];
$w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
where xlink_id = %d",
intval($rating),
dbesc($rating_text),
dbesc($sig),
dbesc(datetime_convert()),
intval($record)
);
}
else {
$w = 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', 1 ) ",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan']),
intval($rating),
dbesc($rating_text),
dbesc($sig),
dbesc(datetime_convert())
);
$z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
dbesc($channel['channel_hash']),
dbesc($orig_record[0]['abook_xchan'])
);
if($z)
$record = $z[0]['xlink_id'];
}
if($record) {
\Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record));
}
}
if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
$new_friend = true;
// @fixme it won't be common, but when you accept a new connection request
// the permissions will now be that of your permissions role and ignore
// any you may have set manually on the form. We'll probably see a bug if somebody
// tries to set the permissions *and* approve the connection in the same
// request. The workaround is to approve the connection, then go back and
// adjust permissions as desired.
$abook_my_perms = get_channel_default_perms(local_channel());
$role = get_pconfig(local_channel(),'system','permissions_role');
if($role) {
$x = get_role_perms($role);
if($x['perms_accept'])
$abook_my_perms = $x['perms_accept'];
}
}
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_my_perms = %d , abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
where abook_id = %d AND abook_channel = %d",
dbesc($profile_id),
intval($abook_my_perms),
intval($closeness),
intval($abook_pending),
dbesc($abook_incl),
dbesc($abook_excl),
intval($contact_id),
intval(local_channel())
);
if($orig_record[0]['abook_profile'] != $profile_id) {
//Update profile photo permissions
logger('A new profile was assigned - updating profile photos');
profile_photo_set_profile_perms($profile_id);
}
if($r)
info( t('Connection updated.') . EOL);
else
notice( t('Failed to update connection record.') . EOL);
if(\App::$poi && \App::$poi['abook_my_perms'] != $abook_my_perms
&& (! intval(\App::$poi['abook_self']))) {
\Zotlabs\Daemon\Master::Summon(array('Notifier', (($new_friend) ? 'permission_create' : 'permission_update'), $contact_id));
}
if($new_friend) {
$default_group = $channel['channel_default_group'];
if($default_group) {
require_once('include/group.php');
$g = group_rec_byhash(local_channel(),$default_group);
if($g)
group_add_member(local_channel(),'',\App::$poi['abook_xchan'],$g['id']);
}
// Check if settings permit ("post new friend activity" is allowed, and
// friends in general or this friend in particular aren't hidden)
// and send out a new friend activity
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
intval($channel['channel_id'])
);
if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
$xarr = array();
$xarr['verb'] = ACTIVITY_FRIEND;
$xarr['item_wall'] = 1;
$xarr['item_origin'] = 1;
$xarr['item_thread_top'] = 1;
$xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
$xarr['allow_cid'] = $channel['channel_allow_cid'];
$xarr['allow_gid'] = $channel['channel_allow_gid'];
$xarr['deny_cid'] = $channel['channel_deny_cid'];
$xarr['deny_gid'] = $channel['channel_deny_gid'];
$xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
$obj = array(
'type' => ACTIVITY_OBJ_PERSON,
'title' => \App::$poi['xchan_name'],
'id' => \App::$poi['xchan_hash'],
'link' => array(
array('rel' => 'alternate', 'type' => 'text/html', 'href' => \App::$poi['xchan_url']),
array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l'])
),
);
$xarr['obj'] = json_encode($obj);
$xarr['obj_type'] = ACTIVITY_OBJ_PERSON;
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . \App::$poi['xchan_url'] . ']' . \App::$poi['xchan_name'] . '[/zrl]';
$xarr['body'] .= "\n\n\n" . '[zrl=' . \App::$poi['xchan_url'] . '][zmg=80x80]' . \App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
post_activity_item($xarr);
}
// pull in a bit of content if there is any to pull in
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$contact_id));
}
// Refresh the structure in memory with the new data
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval($contact_id)
);
if($r) {
\App::$poi = $r[0];
}
if($new_friend) {
$arr = array('channel_id' => local_channel(), 'abook' => \App::$poi);
call_hooks('accept_follow', $arr);
}
if(! is_null($autoperms))
set_pconfig(local_channel(),'system','autoperms',(($autoperms) ? $abook_my_perms : 0));
$this->connedit_clone($a);
if(($_REQUEST['pending']) && (!$_REQUEST['done']))
goaway(z_root() . '/connections/ifpending');
return;
}
/* @brief Clone connection
*
*
*/
function connedit_clone(&$a) {
if(! \App::$poi)
return;
$channel = \App::get_channel();
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
intval(local_channel()),
intval(\App::$poi['abook_id'])
);
if($r) {
\App::$poi = $r[0];
}
$clone = \App::$poi;
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
}
/* @brief Generate content of connection edit page
*
*
*/
function get() {
$sort_type = 0;
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
$channel = \App::get_channel();
$my_perms = get_channel_default_perms(local_channel());
$role = get_pconfig(local_channel(),'system','permissions_role');
if($role) {
$x = get_role_perms($role);
if($x['perms_accept'])
$my_perms = $x['perms_accept'];
}
$yes_no = array(t('No'),t('Yes'));
if($my_perms) {
$o .= "<script>function connectDefaultShare() {
\$('.abook-edit-me').each(function() {
if(! $(this).is(':disabled'))
$(this).prop('checked', false);
});\n\n";
$perms = get_perms();
foreach($perms as $p => $v) {
if($my_perms & $v[1]) {
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
}
}
$o .= " }\n</script>\n";
}
if(argc() == 3) {
$contact_id = intval(argv(1));
if(! $contact_id)
return;
$cmd = argv(2);
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
if(! count($orig_record)) {
notice( t('Could not access address book record.') . EOL);
goaway(z_root() . '/connections');
}
if($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
\Zotlabs\Daemon\Master::Summon(array('Poller',$contact_id));
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'refresh') {
if($orig_record[0]['xchan_network'] === 'zot') {
if(! zot_refresh($orig_record[0],\App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
else {
// if you are on a different network we'll force a refresh of the connection basic info
Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id));
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'block') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'ignore') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'archive') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'hide') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
// We'll prevent somebody from unapproving an already approved contact.
// Though maybe somebody will want this eventually (??)
if($cmd === 'approve') {
if(intval($orig_record[0]['abook_pending'])) {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'drop') {
// FIXME
// We need to send either a purge or a refresh packet to the other side (the channel being unfriended).
// The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier runs
// in the background there could be a race condition preventing this packet from being sent in all cases.
// PLACEHOLDER
contact_remove(local_channel(), $orig_record[0]['abook_id']);
build_sync_packet(0 /* use the current local_channel */,
array('abook' => array(array(
'abook_xchan' => $orig_record[0]['abook_xchan'],
'entry_deleted' => true))
)
);
info( t('Connection has been removed.') . EOL );
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/contacts');
}
}
if(\App::$poi) {
$contact_id = \App::$poi['abook_id'];
$contact = \App::$poi;
$tools = array(
'view' => array(
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']),
),
'refresh' => array(
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
'sel' => '',
'title' => t('Fetch updated permissions'),
),
'recent' => array(
'label' => t('Recent Activity'),
'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
),
'block' => array(
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
),
'ignore' => array(
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
),
'archive' => array(
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
),
'hide' => array(
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
),
'delete' => array(
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
),
);
$self = false;
if(intval($contact['abook_self']))
$self = true;
$tpl = get_markup_template("abook_edit.tpl");
if(feature_enabled(local_channel(),'affinity')) {
$labels = array(
t('Me'),
t('Family'),
t('Friends'),
t('Acquaintances'),
t('All')
);
call_hooks('affinity_labels',$labels);
$label_str = '';
if($labels) {
foreach($labels as $l) {
if($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
else
$label_str .= "'" . $l . "'";
}
}
$slider_tpl = get_markup_template('contact_slider.tpl');
$slide = replace_macros($slider_tpl,array(
'$min' => 1,
'$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99),
'$labels' => $label_str,
));
}
$rating_val = 0;
$rating_text = '';
$xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
dbesc($channel['channel_hash']),
dbesc($contact['xchan_hash'])
);
if($xl) {
$rating_val = intval($xl[0]['xlink_rating']);
$rating_text = $xl[0]['xlink_rating_text'];
}
$poco_rating = get_config('system','poco_rating_enable');
// if unset default to enabled
if($poco_rating === false)
$poco_rating = true;
if($poco_rating) {
$rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
'$min' => -10,
'$val' => $rating_val
));
}
else {
$rating = false;
}
$perms = array();
$channel = \App::get_channel();
$global_perms = get_perms();
$existing = get_all_perms(local_channel(),$contact['abook_xchan']);
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
$multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
if($slide && !$multiprofs)
$affinity = t('Set Affinity');
if(!$slide && $multiprofs)
$affinity = t('Set Profile');
if($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
foreach($global_perms as $k => $v) {
$thisperm = (($contact['abook_my_perms'] & $v[1]) ? "1" : '');
$checkinherited = ((($channel[$v[0]]) && ($channel[$v[0]] != PERMS_SPECIFIC)) ? "1" : '');
// For auto permissions (when $self is true) we don't want to look at existing
// permissions because they are enabled for the channel owner
if((! $self) && ($existing[$k]))
$thisperm = "1";
$perms[] = array('perms_' . $k, $v[3], (($contact['abook_their_perms'] & $v[1]) ? "1" : ""),$thisperm, $v[1], (($channel[$v[0]] == PERMS_SPECIFIC) ? '' : '1'), $v[4], $checkinherited);
}
$locstr = '';
$locs = q("select hubloc_addr as location from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s'
and hubloc_deleted = 0 and site_dead = 0",
dbesc($contact['xchan_hash'])
);
if($locs) {
foreach($locs as $l) {
if(!($l['location']))
continue;
if(strpos($locstr,$l['location']) !== false)
continue;
if(strlen($locstr))
$locstr .= ', ';
$locstr .= $l['location'];
}
}
else
$locstr = t('none');
$o .= replace_macros($tpl,array(
'$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
'$addr' => $contact['xchan_addr'],
'$addr_text' => t('This connection\'s primary address is'),
'$loc_text' => t('Available locations:'),
'$locstr' => $locstr,
'$notself' => (($self) ? '' : '1'),
'$self' => (($self) ? '1' : ''),
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
'$tools_label' => t('Connection Tools'),
'$tools' => (($self) ? '' : $tools),
'$lbl_slider' => t('Slide to adjust your degree of friendship'),
'$lbl_rating' => t('Rating'),
'$lbl_rating_label' => t('Slide to adjust your rating'),
'$lbl_rating_txt' => t('Optionally explain your rating'),
'$connfilter' => feature_enabled(local_channel(),'connfilter'),
'$connfilter_label' => t('Custom Filter'),
'$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''),
'$rating_info' => t('This information is public!'),
'$rating' => $rating,
'$rating_val' => $rating_val,
'$slide' => $slide,
'$affinity' => $affinity,
'$pending_label' => t('Connection Pending Approval'),
'$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
'$unapproved' => $unapproved,
'$inherited' => t('inherited'),
'$submit' => t('Submit'),
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
'$close' => $contact['abook_closeness'],
'$them' => t('Their Settings'),
'$me' => t('My Settings'),
'$perms' => $perms,
'$permlbl' => t('Individual Permissions'),
'$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
'$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
'$lastupdtext' => t('Last update:'),
'$last_update' => relative_date($contact['abook_connected']),
'$profile_select' => contact_profile_assign($contact['abook_profile']),
'$multiprofs' => $multiprofs,
'$contact_id' => $contact['abook_id'],
'$name' => $contact['xchan_name'],
));
$arr = array('contact' => $contact,'output' => $o);
call_hooks('contact_edit', $arr);
return $arr['output'];
}
}
}

View file

@ -1,54 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/group.php');
class Contactgroup extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
if((argc() > 2) && (intval(argv(1))) && (argv(2))) {
$r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if($r)
$change = $r[0]['abook_xchan'];
}
if((argc() > 1) && (intval(argv(1)))) {
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
killme();
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['gname'],$change);
}
else {
group_add_member(local_channel(),$group['gname'],$change);
}
}
}
killme();
}
}

View file

@ -1,423 +0,0 @@
<?php
namespace Zotlabs\Module;
/*
@file cover_photo.php
@brief Module-file with functions for handling of cover-photos
*/
require_once('include/photo/photo_driver.php');
require_once('include/channel.php');
/* @brief Initalize the cover-photo edit view
*
* @param $a Current application
* @return void
*
*/
class Cover_photo extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
profile_load($a,$channel['channel_address']);
}
/* @brief Evaluate posted values
*
* @param $a Current application
* @return void
*
*/
function post() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
// phase 2 - we have finished cropping
if(argc() != 2) {
notice( t('Image uploaded but image cropping failed.') . EOL );
return;
}
$image_id = argv(1);
if(substr($image_id,-2,1) == '-') {
$scale = substr($image_id,-1,1);
$image_id = substr($image_id,0,-2);
}
$srcX = $_POST['xstart'];
$srcY = $_POST['ystart'];
$srcW = $_POST['xfinal'] - $srcX;
$srcH = $_POST['yfinal'] - $srcY;
$r = q("select gender from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel())
);
if($r) {
$profile = $r[0];
}
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = 0 LIMIT 1",
dbesc($image_id),
intval(local_channel())
);
if($r) {
$base_image = $r[0];
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents($base_image['content']) : dbunescbin($base_image['content']));
$im = photo_factory($base_image['content'], $base_image['mimetype']);
if($im->is_valid()) {
// We are scaling and cropping the relative pixel locations to the original photo instead of the
// scaled photo we operated on.
// First load the scaled photo to check its size. (Should probably pass this in the post form and save
// a query.)
$g = q("select width, height from photo where resource_id = '%s' and uid = %d and imgscale = 3",
dbesc($image_id),
intval(local_channel())
);
$scaled_width = $g[0]['width'];
$scaled_height = $g[0]['height'];
if((! $scaled_width) || (! $scaled_height)) {
logger('potential divide by zero scaling cover photo');
return;
}
// unset all other cover photos
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_COVER),
intval(local_channel())
);
$orig_srcx = ( $r[0]['width'] / $scaled_width ) * $srcX;
$orig_srcy = ( $r[0]['height'] / $scaled_height ) * $srcY;
$orig_srcw = ( $srcW / $scaled_width ) * $r[0]['width'];
$orig_srch = ( $srcH / $scaled_height ) * $r[0]['height'];
$im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
$aid = get_account_id();
$p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'], 'album' => t('Cover Photos'));
$p['imgscale'] = 7;
$p['photo_usage'] = PHOTO_COVER;
$r1 = $im->save($p);
$im->doScaleImage(850,310);
$p['imgscale'] = 8;
$r2 = $im->save($p);
$im->doScaleImage(425,160);
$p['imgscale'] = 9;
$r3 = $im->save($p);
if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL );
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ",
dbesc($base_image['resource_id']),
local_channel()
);
return;
}
$channel = \App::get_channel();
$this->send_cover_photo_activity($channel,$base_image,$profile);
}
else
notice( t('Unable to process image') . EOL);
}
goaway(z_root() . '/channel/' . $channel['channel_address']);
}
$hash = photo_new_resource();
$smallest = 0;
require_once('include/attach.php');
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
logger('attach_store: ' . print_r($res,true));
if($res && intval($res['data']['is_photo'])) {
$i = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($hash),
intval(local_channel())
);
if(! $i) {
notice( t('Image upload failed.') . EOL );
return;
}
$os_storage = false;
foreach($i as $ii) {
$smallest = intval($ii['imgscale']);
$os_storage = intval($ii['os_storage']);
$imagedata = $ii['content'];
$filetype = $ii['mimetype'];
}
}
$imagedata = (($os_storage) ? @file_get_contents($imagedata) : $imagedata);
$ph = photo_factory($imagedata, $filetype);
if(! $ph->is_valid()) {
notice( t('Unable to process image.') . EOL );
return;
}
return $this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
function send_cover_photo_activity($channel,$photo,$profile) {
$arr = array();
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
$arr['verb'] = ACTIVITY_UPDATE;
$arr['obj'] = json_encode(array(
'type' => $arr['obj_type'],
'id' => z_root() . '/photo/' . $photo['resource_id'] . '-7',
'link' => array('rel' => 'photo', 'type' => $photo['mimetype'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7')
));
if($profile && stripos($profile['gender'],t('female')) !== false)
$t = t('%1$s updated her %2$s');
elseif($profile && stripos($profile['gender'],t('male')) !== false)
$t = t('%1$s updated his %2$s');
else
$t = t('%1$s updated their %2$s');
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
$acl = new \Zotlabs\Access\AccessList($channel);
$x = $acl->get();
$arr['allow_cid'] = $x['allow_cid'];
$arr['allow_gid'] = $x['allow_gid'];
$arr['deny_cid'] = $x['deny_cid'];
$arr['deny_gid'] = $x['deny_gid'];
$arr['uid'] = $channel['channel_id'];
$arr['aid'] = $channel['channel_account_id'];
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $channel['channel_hash'];
post_activity_item($arr);
}
/* @brief Generate content of profile-photo view
*
* @param $a Current application
* @return void
*
*/
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL );
return;
}
$channel = \App::get_channel();
$newuser = false;
if(argc() == 2 && argv(1) === 'new')
$newuser = true;
if(argv(1) === 'use') {
if (argc() < 3) {
notice( t('Permission denied.') . EOL );
return;
};
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
$resource_id = argv(2);
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
intval(local_channel()),
dbesc($resource_id)
);
if(! $r) {
notice( t('Photo not available.') . EOL );
return;
}
$havescale = false;
foreach($r as $rr) {
if($rr['imgscale'] == 7)
$havescale = true;
}
$r = q("SELECT `content`, `mimetype`, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']),
intval(local_channel())
);
if(! $r) {
notice( t('Photo not available.') . EOL );
return;
}
if(intval($r[0]['os_storage']))
$data = @file_get_contents($r[0]['content']);
else
$data = dbunescbin($r[0]['content']);
$ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0;
if($ph->is_valid()) {
// go ahead as if we have just uploaded a new photo to crop
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($r[0]['resource_id']),
intval(local_channel())
);
if($i) {
$hash = $i[0]['resource_id'];
foreach($i as $ii) {
$smallest = intval($ii['imgscale']);
}
}
}
$this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
if(! x(\App::$data,'imagecrop')) {
$tpl = get_markup_template('cover_photo.tpl');
$o .= replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$lbl_upfile' => t('Upload File:'),
'$lbl_profiles' => t('Select a profile:'),
'$title' => t('Upload Cover Photo'),
'$submit' => t('Upload'),
'$profiles' => $profiles,
'$form_security_token' => get_form_security_token("cover_photo"),
// FIXME - yuk
'$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>')
));
call_hooks('cover_photo_content_end', $o);
return $o;
}
else {
$filename = \App::$data['imagecrop'] . '-3';
$resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
$o .= replace_macros($tpl,array(
'$filename' => $filename,
'$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3',
'$image_url' => z_root() . '/photo/' . $filename,
'$title' => t('Crop Image'),
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing')
));
return $o;
}
return; // NOTREACHED
}
/* @brief Generate the UI for photo-cropping
*
* @param $a Current application
* @param $ph Photo-Factory
* @return void
*
*/
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$max_length = get_config('system','max_image_length');
if(! $max_length)
$max_length = MAX_IMAGE_LENGTH;
if($max_length > 0)
$ph->scaleImage($max_length);
$width = $ph->getWidth();
$height = $ph->getHeight();
if($width < 300 || $height < 300) {
$ph->scaleImageUp(240);
$width = $ph->getWidth();
$height = $ph->getHeight();
}
\App::$data['imagecrop'] = $hash;
\App::$data['imagecrop_resolution'] = $smallest;
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
return;
}
}

View file

@ -1,166 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/dav.php
* @brief Initialize Hubzilla's cloud (SabreDAV).
*
* Module for accessing the DAV storage area from a DAV client.
*/
use \Sabre\DAV as SDAV;
use \Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
/**
* @brief Fires up the SabreDAV server.
*
* @param App &$a
*/
class Dav extends \Zotlabs\Web\Controller {
function init() {
// workaround for HTTP-auth in CGI mode
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
if(strlen($userpass)) {
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
}
if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
$userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ;
if(strlen($userpass)) {
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
}
require_once('include/reddav.php');
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
$which = null;
if (argc() > 1)
$which = argv(1);
$profile = 0;
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which . '" />' . "\r\n";
if ($which)
profile_load($a, $which, $profile);
$auth = new \Zotlabs\Storage\BasicAuth();
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'WebDAV');
// $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function($userName,$password) {
// if(account_verify_password($userName,$password))
// return true;
// return false;
// });
// $ob_hash = get_observer_hash();
// if ($ob_hash) {
// if (local_channel()) {
// $channel = \App::get_channel();
// $auth->setCurrentUser($channel['channel_address']);
// $auth->channel_id = $channel['channel_id'];
// $auth->channel_hash = $channel['channel_hash'];
// $auth->channel_account_id = $channel['channel_account_id'];
// if($channel['channel_timezone'])
// $auth->setTimezone($channel['channel_timezone']);
// }
// $auth->observer = $ob_hash;
// }
// if ($_GET['davguest'])
// $_SESSION['davguest'] = true;
// $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']);
// $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']);
// $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']);
//
// $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']);
// $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']);
// $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']);
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
// A SabreDAV server-object
$server = new SDAV\Server($rootDirectory);
$authPlugin = new \Sabre\DAV\Auth\Plugin($auth);
$server->addPlugin($authPlugin);
// prevent overwriting changes each other with a lock backend
$lockBackend = new SDAV\Locks\Backend\File('store/[data]/locks');
$lockPlugin = new SDAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
// The next section of code allows us to bypass prompting for http-auth if a
// FILE is being accessed anonymously and permissions allow this. This way
// one can create hotlinks to public media files in their cloud and anonymous
// viewers won't get asked to login.
// If a DIRECTORY is accessed or there are permission issues accessing the
// file and we aren't previously authenticated via zot, prompt for HTTP-auth.
// This will be the default case for mounting a DAV directory.
// In order to avoid prompting for passwords for viewing a DIRECTORY, add
// the URL query parameter 'davguest=1'.
// $isapublic_file = false;
// $davguest = ((x($_SESSION, 'davguest')) ? true : false);
// if ((! $auth->observer) && ($_SERVER['REQUEST_METHOD'] === 'GET')) {
// try {
// $x = RedFileData('/' . \App::$cmd, $auth);
// if($x instanceof \Zotlabs\Storage\File)
// $isapublic_file = true;
// }
// catch (Exception $e) {
// $isapublic_file = false;
// }
// }
// if ((! $auth->observer) && (! $isapublic_file) && (! $davguest)) {
// try {
// $auth->Authenticate($server, t('$Projectname channel'));
// }
// catch (Exception $e) {
// logger('mod_cloud: auth exception' . $e->getMessage());
// http_status_exit($e->getHTTPCode(), $e->getMessage());
// }
// }
// require_once('Zotlabs/Storage/Browser.php');
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$auth->setBrowserPlugin($browser);
// Experimental QuotaPlugin
// require_once('Zotlabs/Storage/QuotaPlugin.php');
// $server->addPlugin(new \Zotlabs\Storage\QuotaPlugin($auth));
// All we need to do now, is to fire up the server
$server->exec();
killme();
}
}

View file

@ -1,425 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/socgraph.php');
require_once('include/dir_fns.php');
require_once('include/widgets.php');
require_once('include/bbcode.php');
class Directory extends \Zotlabs\Web\Controller {
function init() {
\App::set_pager_itemspage(60);
if(x($_GET,'ignore')) {
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
intval(local_channel()),
dbesc($_GET['ignore'])
);
goaway(z_root() . '/directory?suggest=1');
}
$observer = get_observer_hash();
$global_changed = false;
$safe_changed = false;
$pubforums_changed = false;
if(array_key_exists('global',$_REQUEST)) {
$globaldir = intval($_REQUEST['global']);
$global_changed = true;
}
if($global_changed) {
$_SESSION['globaldir'] = $globaldir;
if($observer)
set_xconfig($observer,'directory','globaldir',$globaldir);
}
if(array_key_exists('safe',$_REQUEST)) {
$safemode = intval($_REQUEST['safe']);
$safe_changed = true;
}
if($safe_changed) {
$_SESSION['safemode'] = $safemode;
if($observer)
set_xconfig($observer,'directory','safemode',$safemode);
}
if(array_key_exists('pubforums',$_REQUEST)) {
$pubforums = intval($_REQUEST['pubforums']);
$pubforums_changed = true;
}
if($pubforums_changed) {
$_SESSION['pubforums'] = $pubforums;
if($observer)
set_xconfig($observer,'directory','pubforums',$pubforums);
}
}
function get() {
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
$observer = get_observer_hash();
$globaldir = get_directory_setting($observer, 'globaldir');
// override your personal global search pref if we're doing a navbar search of the directory
if(intval($_REQUEST['navsearch']))
$globaldir = 1;
$safe_mode = get_directory_setting($observer, 'safemode');
$pubforums = get_directory_setting($observer, 'pubforums');
$o = '';
nav_set_selected('directory');
if(x($_POST,'search'))
$search = notags(trim($_POST['search']));
else
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
if(strpos($search,'=') && local_channel() && get_pconfig(local_channel(),'feature','expert'))
$advanced = $search;
$keywords = (($_GET['keywords']) ? $_GET['keywords'] : '');
// Suggest channels if no search terms or keywords are given
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
if($suggest) {
$r = suggestion_query(local_channel(),get_observer_hash());
// Remember in which order the suggestions were
$addresses = array();
$common = array();
$index = 0;
foreach($r as $rr) {
$common[$rr['xchan_addr']] = $rr['total'];
$addresses[$rr['xchan_addr']] = $index++;
}
// Build query to get info about suggested people
$advanced = '';
foreach(array_keys($addresses) as $address) {
$advanced .= "address=\"$address\" ";
}
// Remove last space in the advanced query
$advanced = rtrim($advanced);
}
$tpl = get_markup_template('directory_header.tpl');
$dirmode = intval(get_config('system','directory_mode'));
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch';
}
if(! $url) {
$directory = 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();
if(local_channel()) {
$x = q("select abook_xchan from abook where abook_channel = %d",
intval(local_channel())
);
if($x) {
foreach($x as $xx)
$contacts[] = $xx['abook_xchan'];
}
}
if($url) {
$numtags = get_config('system','directorytags');
$kw = ((intval($numtags) > 0) ? intval($numtags) : 50);
if(get_config('system','disable_directory_keywords'))
$kw = 0;
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
if($token)
$query .= '&t=' . $token;
if(! $globaldir)
$query .= '&hub=' . \App::get_hostname();
if($search)
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
if(strpos($search,'@'))
$query .= '&address=' . urlencode($search);
if($keywords)
$query .= '&keywords=' . urlencode($keywords);
if($advanced)
$query .= '&query=' . urlencode($advanced);
if(! is_null($pubforums))
$query .= '&pubforums=' . intval($pubforums);
$directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order)
$directory_sort_order = 'date';
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order);
if($sort_order)
$query .= '&order=' . urlencode($sort_order);
if(\App::$pager['page'] != 1)
$query .= '&p=' . \App::$pager['page'];
logger('mod_directory: query: ' . $query);
$x = z_fetch_url($query);
logger('directory: return from upstream: ' . print_r($x,true), LOGGER_DATA);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j) {
if($j['results']) {
$entries = array();
$photo = 'thumb';
foreach($j['results'] as $rr) {
$profile_link = chanlink_url($rr['url']);
$pdesc = (($rr['description']) ? $rr['description'] . '<br />' : '');
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
// Checking status is disabled ATM until someone checks the performance impact more carefully
//$online = remote_online_status($rr['address']);
$online = '';
if(in_array($rr['hash'],$contacts))
$connect_link = '';
$location = '';
if(strlen($rr['locale']))
$location .= $rr['locale'];
if(strlen($rr['region'])) {
if(strlen($rr['locale']))
$location .= ', ';
$location .= $rr['region'];
}
if(strlen($rr['country'])) {
if(strlen($location))
$location .= ', ';
$location .= $rr['country'];
}
$age = '';
if(strlen($rr['birthday'])) {
if(($years = age($rr['birthday'],'UTC','')) != 0)
$age = $years;
}
$page_type = '';
if($rr['total_ratings'])
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
else
$total_ratings = '';
$profile = $rr;
if ((x($profile,'locale') == 1)
|| (x($profile,'region') == 1)
|| (x($profile,'postcode') == 1)
|| (x($profile,'country') == 1))
$gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False);
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
$homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : '');
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
$about = ((x($profile,'about') == 1) ? bbcode($profile['about']) : False);
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
$out = '';
if($keywords) {
$keywords = str_replace(',',' ', $keywords);
$keywords = str_replace(' ',' ', $keywords);
$karr = explode(' ', $keywords);
if($karr) {
if(local_channel()) {
$r = q("select keywords from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel())
);
if($r) {
$keywords = str_replace(',',' ', $r[0]['keywords']);
$keywords = str_replace(' ',' ', $keywords);
$marr = explode(' ', $keywords);
}
}
foreach($karr as $k) {
if(strlen($out))
$out .= ', ';
if($marr && in_arrayi($k,$marr))
$out .= '<strong>' . $k . '</strong>';
else
$out .= $k;
}
}
}
$entry = array(
'id' => ++$t,
'profile_link' => $profile_link,
'public_forum' => $rr['public_forum'],
'photo' => $rr['photo'],
'hash' => $rr['hash'],
'alttext' => $rr['name'] . ((local_channel() || remote_channel()) ? ' ' . $rr['address'] : ''),
'name' => $rr['name'],
'age' => $age,
'age_label' => t('Age:'),
'profile' => $profile,
'address' => $rr['address'],
'nickname' => substr($rr['address'],0,strpos($rr['address'],'@')),
'location' => $location,
'location_label' => t('Location:'),
'gender' => $gender,
'total_ratings' => $total_ratings,
'viewrate' => true,
'canrate' => ((local_channel()) ? true : false),
'pdesc' => $pdesc,
'pdesc_label' => t('Description:'),
'marital' => $marital,
'homepage' => $homepage,
'homepageurl' => linkify($homepageurl),
'hometown' => $hometown,
'hometown_label' => t('Hometown:'),
'about' => $about,
'about_label' => t('About:'),
'conn_label' => t('Connect'),
'forum_label' => t('Public Forum:'),
'connect' => $connect_link,
'online' => $online,
'kw' => (($out) ? t('Keywords: ') : ''),
'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:'),
'common_count' => intval($common[$rr['address']]),
'safe' => $safe_mode
);
$arr = array('contact' => $rr, 'entry' => $entry);
call_hooks('directory_item', $arr);
unset($profile);
unset($location);
if(! $arr['entry']) {
continue;
}
if($sort_order == '' && $suggest) {
$entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first
}
else {
$entries[] = $arr['entry'];
}
}
ksort($entries); // Sort array by key so that foreach-constructs work as expected
if($j['keywords']) {
\App::$data['directory_keywords'] = $j['keywords'];
}
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
if($_REQUEST['aj']) {
if($entries) {
$o = replace_macros(get_markup_template('directajax.tpl'),array(
'$entries' => $entries
));
}
else {
$o = '<div id="content-complete"></div>';
}
echo $o;
killme();
}
else {
$maxheight = 94;
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array(
'$search' => $search,
'$desc' => t('Find'),
'$finddsc' => t('Finding:'),
'$safetxt' => htmlspecialchars($search,ENT_QUOTES,'UTF-8'),
'$entries' => $entries,
'$dirlbl' => $suggest ? t('Channel Suggestions') : $dirtitle,
'$submit' => t('Find'),
'$next' => alt_pager($a,$j['records'], t('next page'), t('previous page')),
'$sort' => t('Sort options'),
'$normal' => t('Alphabetic'),
'$reverse' => t('Reverse Alphabetic'),
'$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'),
'$suggest' => $suggest ? '&suggest=1' : ''
));
}
}
else {
if($_REQUEST['aj']) {
$o = '<div id="content-complete"></div>';
echo $o;
killme();
}
if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) {
goaway(z_root() . '/chanview/?f=&address=' . $search);
}
info( t("No entries (some entries may be hidden).") . EOL);
}
}
}
}
return $o;
}
}

View file

@ -1,462 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/dir_fns.php');
class Dirsearch extends \Zotlabs\Web\Controller {
function init() {
\App::set_pager_itemspage(60);
}
function get() {
$ret = array('success' => false);
// logger('request: ' . print_r($_REQUEST,true));
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode == DIRECTORY_MODE_NORMAL) {
$ret['message'] = t('This site is not a directory server');
json_return_and_die($ret);
}
$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);
}
$sql_extra = '';
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
if($_REQUEST['query']) {
$advanced = $this->dir_parse_query($_REQUEST['query']);
if($advanced) {
foreach($advanced as $adv) {
if(in_array($adv['field'],$tables)) {
if($adv['field'] === 'name')
$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']);
else
$sql_extra .= $this->dir_query_build($adv['logic'],'xprof_' . $adv['field'],$adv['value']);
}
}
}
}
$hash = ((x($_REQUEST['hash'])) ? $_REQUEST['hash'] : '');
$name = ((x($_REQUEST,'name')) ? $_REQUEST['name'] : '');
$hub = ((x($_REQUEST,'hub')) ? $_REQUEST['hub'] : '');
$address = ((x($_REQUEST,'address')) ? $_REQUEST['address'] : '');
$locale = ((x($_REQUEST,'locale')) ? $_REQUEST['locale'] : '');
$region = ((x($_REQUEST,'region')) ? $_REQUEST['region'] : '');
$postcode = ((x($_REQUEST,'postcode')) ? $_REQUEST['postcode'] : '');
$country = ((x($_REQUEST,'country')) ? $_REQUEST['country'] : '');
$gender = ((x($_REQUEST,'gender')) ? $_REQUEST['gender'] : '');
$marital = ((x($_REQUEST,'marital')) ? $_REQUEST['marital'] : '');
$sexual = ((x($_REQUEST,'sexual')) ? $_REQUEST['sexual'] : '');
$keywords = ((x($_REQUEST,'keywords')) ? $_REQUEST['keywords'] : '');
$agege = ((x($_REQUEST,'agege')) ? intval($_REQUEST['agege']) : 0 );
$agele = ((x($_REQUEST,'agele')) ? intval($_REQUEST['agele']) : 0 );
$kw = ((x($_REQUEST,'kw')) ? intval($_REQUEST['kw']) : 0 );
$forums = ((array_key_exists('pubforums',$_REQUEST)) ? intval($_REQUEST['pubforums']) : 0);
if(get_config('system','disable_directory_keywords'))
$kw = 0;
// by default use a safe search
$safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
if ($safe === false)
$safe = 1;
if(array_key_exists('sync',$_REQUEST)) {
if($_REQUEST['sync'])
$sync = datetime_convert('UTC','UTC',$_REQUEST['sync']);
else
$sync = datetime_convert('UTC','UTC','2010-01-01 01:01:00');
}
else
$sync = false;
if($hub)
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
else
$hub_query = '';
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
$joiner = ' OR ';
if($_REQUEST['and'])
$joiner = ' AND ';
if($name)
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
if($address)
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
if($city)
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$city);
if($region)
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
if($post)
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$post);
if($country)
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
if($gender)
$sql_extra .= $this->dir_query_build($joiner,'xprof_gender',$gender);
if($marital)
$sql_extra .= $this->dir_query_build($joiner,'xprof_marital',$marital);
if($sexual)
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
if($keywords)
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
// we only support an age range currently. You must set both agege
// (greater than or equal) and agele (less than or equal)
if($agele && $agege) {
$sql_extra .= " $joiner ( xprof_age <= " . intval($agele) . " ";
$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;
$limit = (($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 0);
$return_total = ((x($_REQUEST,'return_total')) ? intval($_REQUEST['return_total']) : 0);
// mtime is not currently working
$mtime = ((x($_REQUEST,'mtime')) ? datetime_convert('UTC','UTC',$_REQUEST['mtime']) : '');
// ok a separate tag table won't work.
// merge them into xprof
$ret['success'] = true;
// 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
$logic = ((strlen($sql_extra)) ? 'false' : 'true');
if($hash)
$logic = 'true';
if($dirmode == DIRECTORY_MODE_STANDALONE) {
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
}
$safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
if($safe < 0)
$safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
if($forums)
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
if($limit)
$qlimit = " LIMIT $limit ";
else {
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
if($return_total) {
$r = q("SELECT COUNT(xchan_hash) AS `total` FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
if($r) {
$ret['total_items'] = $r[0]['total'];
}
}
}
if($sort_order == 'normal') {
$order = " order by xchan_name asc ";
// Start the alphabetic search at 'A'
// This will make a handful of channels whose names begin with
// punctuation un-searchable in this mode
$safesql .= " and ascii(substring(xchan_name FROM 1 FOR 1)) > 64 ";
}
elseif($sort_order == 'reverse')
$order = " order by xchan_name desc ";
elseif($sort_order == 'reversedate')
$order = " order by xchan_name_date asc ";
else
$order = " order by xchan_name_date desc ";
if($sync) {
$spkt = array('transactions' => array());
$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 = array();
if($rr['ud_flags'] & UPDATE_FLAGS_DELETED)
$flags[] = 'deleted';
if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
$flags[] = 'forced';
$spkt['transactions'][] = array(
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
'transaction_id' => $rr['ud_guid'],
'timestamp' => $rr['ud_date'],
'flags' => $flags
);
}
}
$r = q("select * from xlink where xlink_static = 1 and xlink_updated >= '%s' ",
dbesc($sync)
);
if($r) {
$spkt['ratings'] = array();
foreach($r as $rr) {
$spkt['ratings'][] = array(
'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);
}
else {
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit "
);
$ret['page'] = $page + 1;
$ret['records'] = count($r);
}
if($r) {
$entries = array();
foreach($r as $rr) {
$entry = array();
$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['public_forum'] = (intval($rr['xchan_pubforum']) ? true : false);
$entry['url'] = $rr['xchan_url'];
$entry['photo_l'] = $rr['xchan_photo_l'];
$entry['photo'] = $rr['xchan_photo_m'];
$entry['address'] = $rr['xchan_addr'];
$entry['description'] = $rr['xprof_desc'];
$entry['locale'] = $rr['xprof_locale'];
$entry['region'] = $rr['xprof_region'];
$entry['postcode'] = $rr['xprof_postcode'];
$entry['country'] = $rr['xprof_country'];
$entry['birthday'] = $rr['xprof_dob'];
$entry['age'] = $rr['xprof_age'];
$entry['gender'] = $rr['xprof_gender'];
$entry['marital'] = $rr['xprof_marital'];
$entry['sexual'] = $rr['xprof_sexual'];
$entry['about'] = $rr['xprof_about'];
$entry['homepage'] = $rr['xprof_homepage'];
$entry['hometown'] = $rr['xprof_hometown'];
$entry['keywords'] = $rr['xprof_keywords'];
$entries[] = $entry;
}
$ret['results'] = $entries;
if($kw) {
$k = dir_tagadelic($kw);
if($k) {
$ret['keywords'] = array();
foreach($k as $kv) {
$ret['keywords'][] = array('term' => $kv[0],'weight' => $kv[1], 'normalise' => $kv[2]);
}
}
}
}
json_return_and_die($ret);
}
function dir_query_build($joiner,$field,$s) {
$ret = '';
if(trim($s))
$ret .= dbesc($joiner) . " " . dbesc($field) . " like '" . protect_sprintf( '%' . dbesc($s) . '%' ) . "' ";
return $ret;
}
function dir_flag_build($joiner,$field,$bit,$s) {
return dbesc($joiner) . " ( " . dbesc($field) . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 ";
}
function dir_parse_query($s) {
$ret = array();
$curr = array();
$all = explode(' ',$s);
$quoted_string = false;
if($all) {
foreach($all as $q) {
if($quoted_string === false) {
if($q === 'and') {
$curr['logic'] = 'and';
continue;
}
if($q === 'or') {
$curr['logic'] = 'or';
continue;
}
if($q === 'not') {
$curr['logic'] .= ' not';
continue;
}
if(strpos($q,'=')) {
if(! isset($curr['logic']))
$curr['logic'] = 'or';
$curr['field'] = trim(substr($q,0,strpos($q,'=')));
$curr['value'] = trim(substr($q,strpos($q,'=')+1));
if($curr['value'][0] == '"' && $curr['value'][strlen($curr['value'])-1] != '"') {
$quoted_string = true;
$curr['value'] = substr($curr['value'],1);
continue;
}
elseif($curr['value'][0] == '"' && $curr['value'][strlen($curr['value'])-1] == '"') {
$curr['value'] = substr($curr['value'],1,strlen($curr['value'])-2);
$ret[] = $curr;
$curr = array();
continue;
}
else {
$ret[] = $curr;
$curr = array();
continue;
}
}
}
else {
if($q[strlen($q)-1] == '"') {
$curr['value'] .= ' ' . str_replace('"','',trim($q));
$ret[] = $curr;
$curr = array();
$quoted_string = false;
}
else
$curr['value'] .= ' ' . trim(q);
}
}
}
logger('dir_parse_query:' . print_r($ret,true),LOGGER_DATA);
return $ret;
}
function list_public_sites() {
$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 order by $rand",
dbesc($realm),
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 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) {
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';
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']);
else
$insecure[] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project']);
}
if($insecure) {
$ret['sites'] = array_merge($ret['sites'],$insecure);
}
}
return $ret;
}
}

View file

@ -1,342 +0,0 @@
<?php
namespace Zotlabs\Module;
class Display extends \Zotlabs\Web\Controller {
function get($update = 0, $load = false) {
$checkjs = new \Zotlabs\Web\CheckJS(1);
if($load)
$_SESSION['loadtime'] = datetime_convert();
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/items.php');
\App::$page['htmlhead'] .= replace_macros(get_markup_template('display-head.tpl'), array());
if(argc() > 1 && argv(1) !== 'load')
$item_hash = argv(1);
if($_REQUEST['mid'])
$item_hash = $_REQUEST['mid'];
if(! $item_hash) {
\App::$error = 404;
notice( t('Item not found.') . EOL);
return;
}
$observer_is_owner = false;
if(local_channel() && (! $update)) {
$channel = \App::get_channel();
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
$x = array(
'is_owner' => true,
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl),
'bang' => '',
'visitor' => true,
'profile_uid' => local_channel(),
'return_path' => 'channel/' . $channel['channel_address'],
'expanded' => true,
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
$o = '<div id="jot-popup">';
$o .= status_editor($a,$x);
$o .= '</div>';
}
// This page can be viewed by anybody so the query could be complicated
// First we'll see if there is a copy of the item which is owned by us - if we're logged in locally.
// If that fails (or we aren't logged in locally),
// query an item in which the observer (if logged in remotely) has cid or gid rights
// and if that fails, look for a copy of the post that has no privacy restrictions.
// If we find the post, but we don't find a copy that we're allowed to look at, this fact needs to be reported.
// find a copy of the item somewhere
$target_item = null;
$r = q("select id, uid, mid, parent_mid, item_type, item_deleted from item where mid like '%s' limit 1",
dbesc($item_hash . '%')
);
if($r) {
$target_item = $r[0];
}
$r = null;
if($target_item['item_type'] == ITEM_TYPE_WEBPAGE) {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from item_id where uid = %d and service = 'WEBPAGE' and iid = %d limit 1",
intval($target_item['uid']),
intval($target_item['id'])
);
if($x && $y) {
goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['sid']);
}
else {
notice( t('Page not found.') . EOL);
return '';
}
}
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
if($load)
$simple_update = '';
if((! $update) && (! $load)) {
$o .= '<div id="live-display"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'display',
'$uid' => '0',
'$gid' => '0',
'$cid' => '0',
'$cmin' => '0',
'$cmax' => '99',
'$star' => '0',
'$liked' => '0',
'$conv' => '0',
'$spam' => '0',
'$fh' => '0',
'$nouveau' => '0',
'$wall' => '0',
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$order' => '',
'$file' => '',
'$cats' => '',
'$tags' => '',
'$dend' => '',
'$dbegin' => '',
'$verb' => '',
'$mid' => $item_hash
));
}
$observer_hash = get_observer_hash();
$item_normal = item_normal();
$sql_extra = public_permissions_sql($observer_hash);
if(($update && $load) || ($checkjs->disabled())) {
$updateable = false;
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start']));
if($load || ($checkjs->disabled())) {
$r = null;
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
if(local_channel()) {
$r = q("SELECT * from item
WHERE uid = %d
and mid = '%s'
$item_normal
limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
}
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner_xchan can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT * from item
WHERE mid = '%s'
AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = ''
AND `item`.`deny_gid` = '' AND item_private = 0 )
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
}
}
elseif($update && !$load) {
$r = null;
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
if(local_channel()) {
$r = q("SELECT * from item
WHERE uid = %d
and mid = '%s'
$item_normal
$simple_update
limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
}
if($r === null) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner_xchan can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT * from item
WHERE mid = '%s'
AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = ''
AND `item`.`deny_gid` = '' AND item_private = 0 )
and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
$simple_update
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
$_SESSION['loadtime'] = datetime_convert();
}
else {
$r = array();
}
if($r) {
$parents_str = ids_to_querystr($r,'id');
if($parents_str) {
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`
FROM `item`
WHERE parent in ( %s ) $item_normal ",
dbesc($parents_str)
);
xchan_query($items);
$items = fetch_post_tags($items,true);
$items = conv_sort($items,'created');
}
} else {
$items = array();
}
if ($checkjs->disabled()) {
$o .= conversation($a, $items, 'display', $update, 'traditional');
if ($items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
else {
$o .= conversation($a, $items, 'display', $update, 'client');
}
if($updateable) {
$x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ",
intval(local_channel()),
intval($r[0]['parent'])
);
}
$o .= '<div id="content-complete"></div>';
return $o;
/*
elseif((! $update) && (! {
$r = q("SELECT `id`, item_flags FROM `item` WHERE `id` = '%s' OR `mid` = '%s' LIMIT 1",
dbesc($item_hash),
dbesc($item_hash)
);
if($r) {
if(intval($r[0]['item_deleted'])) {
notice( t('Item has been removed.') . EOL );
}
else {
notice( t('Permission denied.') . EOL );
}
}
else {
notice( t('Item not found.') . EOL );
}
}
*/
}
}

View file

@ -1,145 +0,0 @@
<?php
namespace Zotlabs\Module;
class Dreport extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
$table = 'item';
$channel = \App::get_channel();
$mid = ((argc() > 1) ? argv(1) : '');
if($mid === 'mail') {
$table = 'mail';
$mid = ((argc() > 2) ? argv(2) : '');
}
if(! $mid) {
notice( t('Invalid message') . EOL);
return;
}
switch($table) {
case 'item':
$i = q("select id from item where mid = '%s' and author_xchan = '%s' ",
dbesc($mid),
dbesc($channel['channel_hash'])
);
break;
case 'mail':
$i = q("select id from mail where mid = '%s' and from_xchan = '%s'",
dbesc($mid),
dbesc($channel['channel_hash'])
);
break;
default:
break;
}
if(! $i) {
notice( t('Permission denied') . EOL);
return;
}
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
dbesc($channel['channel_hash']),
dbesc($mid)
);
if(! $r) {
notice( t('no results') . EOL);
return;
}
$o .= '<div class="generic-content-wrapper-styled">';
$o .= '<h2>' . sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...' . '</h2>';
$o .= '<table>';
for($x = 0; $x < count($r); $x++ ) {
$r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' ')));
// This has two purposes: 1. make the delivery report strings translateable, and
// 2. assign an ordering to item delivery results so we can group them and provide
// a readable report with more interesting events listed toward the top and lesser
// interesting items towards the bottom
switch($r[$x]['dreport_result']) {
case 'channel sync processed':
$r[$x]['gravity'] = 0;
$r[$x]['dreport_result'] = t('channel sync processed');
break;
case 'queued':
$r[$x]['gravity'] = 2;
$r[$x]['dreport_result'] = t('queued');
break;
case 'posted':
$r[$x]['gravity'] = 3;
$r[$x]['dreport_result'] = t('posted');
break;
case 'accepted for delivery':
$r[$x]['gravity'] = 4;
$r[$x]['dreport_result'] = t('accepted for delivery');
break;
case 'updated':
$r[$x]['gravity'] = 5;
$r[$x]['dreport_result'] = t('updated');
case 'update ignored':
$r[$x]['gravity'] = 6;
$r[$x]['dreport_result'] = t('update ignored');
break;
case 'permission denied':
$r[$x]['dreport_result'] = t('permission denied');
$r[$x]['gravity'] = 6;
break;
case 'recipient not found':
$r[$x]['dreport_result'] = t('recipient not found');
break;
case 'mail recalled':
$r[$x]['dreport_result'] = t('mail recalled');
break;
case 'duplicate mail received':
$r[$x]['dreport_result'] = t('duplicate mail received');
break;
case 'mail delivered':
$r[$x]['dreport_result'] = t('mail delivered');
break;
default:
$r[$x]['gravity'] = 1;
break;
}
}
usort($r,'self::dreport_gravity_sort');
foreach($r as $rr) {
$o .= '<tr><td width="40%">' . $rr['name'] . '</td><td width="20%">' . escape_tags($rr['dreport_result']) . '</td><td width="20%">' . escape_tags($rr['dreport_time']) . '</td></tr>';
}
$o .= '</table>';
$o .= '</div>';
return $o;
}
private static function dreport_gravity_sort($a,$b) {
if($a['gravity'] == $b['gravity']) {
if($a['name'] === $b['name'])
return strcmp($a['dreport_time'],$b['dreport_time']);
return strcmp($a['name'],$b['name']);
}
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
}
}

View file

@ -1,143 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Editblock extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! ($post_id && $owner)) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1",
intval($post_id),
intval($owner)
);
if($itm) {
$item_id = q("select * from item_id where service = 'BUILDBLOCK' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$block_title = $item_id[0]['sid'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$mimetype = $itm[0]['mimetype'];
$rp = 'blocks/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : 'comanche-block'),
'return_path' => $rp,
'webpage' => ITEM_TYPE_BLOCK,
'ptlabel' => t('Block Name'),
'button' => t('Edit'),
'writefiles' => (($mimetype == 'text/bbcode') ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false),
'weblink' => (($mimetype == 'text/bbcode') ? t('Insert web link') : false),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
'hide_expire' => true,
'showacl' => false,
'ptyp' => $itm[0]['type'],
'mimeselect' => true,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $block_title,
'profile_uid' => (intval($channel['channel_id'])),
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Block'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$editor' => $editor
));
return $o;
}
}

View file

@ -1,145 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Editlayout extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
// Now we've got a post and an owner, let's find out if we're allowed to edit it
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1",
intval($post_id),
intval($owner)
);
$item_id = q("select * from item_id where service = 'PDL' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$layout_title = $item_id[0]['sid'];
$rp = 'layouts/' . $which;
$x = array(
'webpage' => ITEM_TYPE_PDL,
'nickname' => $channel['channel_address'],
'editor_autocomplete'=> true,
'bbco_autocomplete'=> 'comanche',
'return_path' => $rp,
'button' => t('Edit'),
'hide_voting' => true,
'hide_future' => true,
'hide_expire' => true,
'hide_location' => true,
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'ptyp' => $itm[0]['obj_type'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'pagetitle' => $layout_title,
'ptlabel' => t('Layout Name'),
'placeholdertitle' => t('Layout Description (Optional)'),
'showacl' => false,
'profile_uid' => intval($owner),
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Layout'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$editor' => $editor
));
return $o;
}
}

View file

@ -1,114 +0,0 @@
<?php
namespace Zotlabs\Module; /** @file */
require_once('include/acl_selectors.php');
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/taxonomy.php');
require_once('include/conversation.php');
class Editpost extends \Zotlabs\Web\Controller {
function get() {
$o = '';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM `item` WHERE `id` = %d AND ( owner_xchan = '%s' OR author_xchan = '%s' ) LIMIT 1",
intval($post_id),
dbesc(get_observer_hash()),
dbesc(get_observer_hash())
);
if(! count($itm)) {
notice( t('Item is not editable') . EOL);
return;
}
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
}
$owner_uid = $itm[0]['uid'];
$channel = \App::get_channel();
if(intval($itm[0]['item_obscured'])) {
$key = get_config('system','prvkey');
if($itm[0]['title'])
$itm[0]['title'] = crypto_unencapsulate(json_decode_plus($itm[0]['title']),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
}
$category = '';
$catsenabled = ((feature_enabled($owner_uid,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$x = array(
'nickname' => $channel['channel_address'],
'editor_autocomplete'=> true,
'bbco_autocomplete'=> 'bbcode',
'return_path' => $_SESSION['return_url'],
'button' => t('Edit'),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
'mimetype' => $itm[0]['mimetype'],
'ptyp' => $itm[0]['obj_type'],
'body' => htmlspecialchars_decode(undo_post_tagging($itm[0]['body']),ENT_COMPAT),
'post_id' => $post_id,
'defloc' => $channel['channel_location'],
'visitor' => true,
'title' => htmlspecialchars_decode($itm[0]['title'],ENT_COMPAT),
'category' => $category,
'showacl' => false,
'profile_uid' => $owner_uid,
'catsenabled' => $catsenabled,
'hide_expire' => true,
'bbcode' => true
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit post'),
'$editor' => $editor
));
return $o;
}
}

View file

@ -1,179 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
require_once('include/PermissionDescription.php');
class Editwebpage extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// We've already figured out which item we want and whose copy we need,
// so we don't need anything fancy here
$sql_extra = item_permissions_sql($owner);
$itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s $sql_extra LIMIT 1",
intval($post_id),
intval($owner)
);
if(! $itm) {
notice( t('Permission denied.') . EOL);
return;
}
if(intval($itm[0]['item_obscured'])) {
$key = get_config('system','prvkey');
if($itm[0]['title'])
$itm[0]['title'] = crypto_unencapsulate(json_decode_plus($itm[0]['title']),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']),$key);
}
$item_id = q("select * from item_id where service = 'WEBPAGE' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$page_title = $item_id[0]['sid'];
$mimetype = $itm[0]['mimetype'];
if($mimetype === 'application/x-php') {
if((! $uid) || ($uid != $itm[0]['uid'])) {
notice( t('Permission denied.') . EOL);
return;
}
}
$layout = $itm[0]['layout_mid'];
$tpl = get_markup_template("jot.tpl");
$rp = 'webpages/' . $which;
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> (($mimetype == 'text/bbcode') ? 'bbcode' : ''),
'return_path' => $rp,
'webpage' => ITEM_TYPE_WEBPAGE,
'ptlabel' => t('Page link'),
'pagetitle' => $page_title,
'writefiles' => (($mimetype == 'text/bbcode') ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false),
'button' => t('Edit'),
'weblink' => (($mimetype == 'text/bbcode') ? t('Insert web link') : false),
'hide_location' => true,
'hide_voting' => true,
'ptyp' => $itm[0]['type'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,
'visitor' => ($is_owner) ? true : false,
'acl' => populate_acl($itm[0],false,\PermissionDescription::fromGlobalPermission('view_pages')),
'showacl' => ($is_owner) ? true : false,
'mimetype' => $mimetype,
'mimeselect' => true,
'layout' => $layout,
'layoutselect' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'),
'profile_uid' => (intval($owner)),
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x);
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Webpage'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$editor' => $editor,
'$id' => $itm[0]['id']
));
return $o;
}
}

View file

@ -1,717 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/conversation.php');
require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once('include/PermissionDescription.php');
class Events extends \Zotlabs\Web\Controller {
function post() {
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
if(! local_channel())
return;
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) {
$src = $_FILES['userfile']['tmp_name'];
if($src) {
$result = parse_ical_file($src,local_channel());
if($result)
info( t('Calendar entries imported.') . EOL);
else
notice( t('No calendar entries found.') . EOL);
@unlink($src);
}
goaway(z_root() . '/events');
}
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
$xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
$uid = local_channel();
$start_text = escape_tags($_REQUEST['start_text']);
$finish_text = escape_tags($_REQUEST['finish_text']);
$adjust = intval($_POST['adjust']);
$nofinish = intval($_POST['nofinish']);
$categories = escape_tags(trim($_POST['category']));
// only allow editing your own events.
if(($xchan) && ($xchan !== get_observer_hash()))
return;
if($start_text) {
$start = $start_text;
}
else {
$start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute);
}
if($nofinish) {
$finish = NULL_DATE;
}
if($finish_text) {
$finish = $finish_text;
}
else {
$finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute);
}
if($adjust) {
$start = datetime_convert(date_default_timezone_get(),'UTC',$start);
if(! $nofinish)
$finish = datetime_convert(date_default_timezone_get(),'UTC',$finish);
}
else {
$start = datetime_convert('UTC','UTC',$start);
if(! $nofinish)
$finish = datetime_convert('UTC','UTC',$finish);
}
// Don't allow the event to finish before it begins.
// It won't hurt anything, but somebody will file a bug report
// and we'll waste a bunch of time responding to it. Time that
// could've been spent doing something else.
$summary = escape_tags(trim($_POST['summary']));
$desc = escape_tags(trim($_POST['desc']));
$location = escape_tags(trim($_POST['location']));
$type = escape_tags(trim($_POST['type']));
require_once('include/text.php');
linkify_tags($a, $desc, local_channel());
linkify_tags($a, $location, local_channel());
//$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
//fixme: this url gives a wsod if there is a linebreak detected in one of the variables ($desc or $location)
//$onerror_url = z_root() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish&type=$type";
$onerror_url = z_root() . "/events";
if(strcmp($finish,$start) < 0 && !$nofinish) {
notice( t('Event can not end before it has started.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
goaway($onerror_url);
}
if((! $summary) || (! $start)) {
notice( t('Event title and start time are required.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
goaway($onerror_url);
}
$share = ((intval($_POST['share'])) ? intval($_POST['share']) : 0);
$channel = \App::get_channel();
$acl = new \Zotlabs\Access\AccessList(false);
if($event_id) {
$x = q("select * from event where id = %d and uid = %d limit 1",
intval($event_id),
intval(local_channel())
);
if(! $x) {
notice( t('Event not found.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Unable to generate preview.'));
killme();
}
return;
}
$acl->set($x[0]);
$created = $x[0]['created'];
$edited = datetime_convert();
if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>'
&& $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') {
$share = false;
}
else {
$share = true;
}
}
else {
$created = $edited = datetime_convert();
if($share) {
$acl->set_from_array($_POST);
}
else {
$acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
}
}
$post_tags = array();
$channel = \App::get_channel();
$ac = $acl->get();
if(strlen($categories)) {
$cats = explode(',',$categories);
foreach($cats as $cat) {
$post_tags[] = array(
'uid' => $profile_uid,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
);
}
}
$datarray = array();
$datarray['dtstart'] = $start;
$datarray['dtend'] = $finish;
$datarray['summary'] = $summary;
$datarray['description'] = $desc;
$datarray['location'] = $location;
$datarray['etype'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = $nofinish;
$datarray['uid'] = local_channel();
$datarray['account'] = get_account_id();
$datarray['event_xchan'] = $channel['channel_hash'];
$datarray['allow_cid'] = $ac['allow_cid'];
$datarray['allow_gid'] = $ac['allow_gid'];
$datarray['deny_cid'] = $ac['deny_cid'];
$datarray['deny_gid'] = $ac['deny_gid'];
$datarray['private'] = (($acl->is_private()) ? 1 : 0);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
if(intval($_REQUEST['preview'])) {
$html = format_event_html($datarray);
echo $html;
killme();
}
$event = event_store_event($datarray);
if($post_tags)
$datarray['term'] = $post_tags;
$item_id = event_store_item($datarray,$event);
if($item_id) {
$r = q("select * from item where id = %d",
intval($item_id)
);
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
dbesc($r[0]['resource_id']),
intval($channel['channel_id'])
);
if($z) {
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
}
}
}
if($share)
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
}
function get() {
if(argc() > 2 && argv(1) == 'ical') {
$event_id = argv(2);
require_once('include/security.php');
$sql_extra = permissions_sql(local_channel());
$r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
dbesc($event_id)
);
if($r) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
echo ical_wrapper($r);
killme();
}
else {
notice( t('Event not found.') . EOL );
return;
}
}
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
nav_set_selected('all_events');
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
intval(argv(2)),
intval(local_channel())
);
}
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl');
\App::$page['htmlhead'] .= replace_macros($htpl,array(
'$baseurl' => z_root(),
'$module_url' => '/events',
'$modparams' => 1,
'$lang' => \App::$language,
'$first_day' => $first_day
));
$o = '';
$channel = \App::get_channel();
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
// logger('args: ' . print_r(\App::$argv,true));
if(argc() > 1) {
if(argc() > 2 && argv(1) === 'add') {
$mode = 'add';
$item_id = intval(argv(2));
}
if(argc() > 2 && argv(1) === 'drop') {
$mode = 'drop';
$event_id = argv(2);
}
if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
$mode = 'view';
$y = intval(argv(1));
$m = intval(argv(2));
}
if(argc() <= 2) {
$mode = 'view';
$event_id = argv(1);
}
}
if($mode === 'add') {
event_addtocal($item_id,local_channel());
killme();
}
if($mode == 'view') {
/* edit/create form */
if($event_id) {
$r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
if(count($r))
$orig_event = $r[0];
}
$channel = \App::get_channel();
// Passed parameters overrides anything found in the DB
if(!x($orig_event))
$orig_event = array();
// In case of an error the browser is redirected back here, with these parameters filled in with the previous values
/*
if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish'];
if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust'];
if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary'];
if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description'];
if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location'];
if(x($_REQUEST,'start')) $orig_event['dtstart'] = $_REQUEST['start'];
if(x($_REQUEST,'finish')) $orig_event['dtend'] = $_REQUEST['finish'];
if(x($_REQUEST,'type')) $orig_event['etype'] = $_REQUEST['type'];
*/
$n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
$a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
$t_orig = ((x($orig_event)) ? $orig_event['summary'] : '');
$d_orig = ((x($orig_event)) ? $orig_event['description'] : '');
$l_orig = ((x($orig_event)) ? $orig_event['location'] : '');
$eid = ((x($orig_event)) ? $orig_event['id'] : 0);
$event_xchan = ((x($orig_event)) ? $orig_event['event_xchan'] : $channel['channel_hash']);
$mid = ((x($orig_event)) ? $orig_event['mid'] : '');
if(! x($orig_event))
$sh_checked = '';
else
$sh_checked = ((($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' || (! $orig_event['allow_cid'])) && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' );
if($orig_event['event_xchan'])
$sh_checked .= ' disabled="disabled" ';
$sdt = ((x($orig_event)) ? $orig_event['dtstart'] : 'now');
$fdt = ((x($orig_event)) ? $orig_event['dtend'] : '+1 hour');
$tz = date_default_timezone_get();
if(x($orig_event))
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
$stext = datetime_convert('UTC',$tz,$sdt);
$stext = substr($stext,0,14) . "00:00";
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
$ftext = datetime_convert('UTC',$tz,$fdt);
$ftext = substr($ftext,0,14) . "00:00";
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
$f = get_config('system','event_input_format');
if(! $f)
$f = 'ymd';
$catsenabled = feature_enabled(local_channel(),'categories');
$category = '';
if($catsenabled && x($orig_event)){
$itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1",
dbesc($orig_event['event_hash']),
intval(local_channel())
);
$itm = fetch_post_tags($itm);
if($itm) {
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if(strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
}
require_once('include/acl_selectors.php');
$acl = new \Zotlabs\Access\AccessList($channel);
$perm_defaults = $acl->get();
$tpl = get_markup_template('event_form.tpl');
$form = replace_macros($tpl,array(
'$post' => z_root() . '/events',
'$eid' => $eid,
'$type' => $type,
'$xchan' => $event_xchan,
'$mid' => $mid,
'$event_hash' => $event_id,
'$summary' => array('summary', (($event_id) ? t('Edit event title') : t('Event title')), $t_orig, t('Required'), '*'),
'$catsenabled' => $catsenabled,
'$placeholdercategory' => t('Categories (comma-separated list)'),
'$c_text' => (($event_id) ? t('Edit Category') : t('Category')),
'$category' => $category,
'$required' => '<span class="required" title="' . t('Required') . '">*</span>',
'$s_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$syear+5),\DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"), (($event_id) ? t('Edit start date and time') : t('Start date and time')), 'start_text',true,true,'','',true,$first_day),
'$n_text' => t('Finish date and time are not known or not relevant'),
'$n_checked' => $n_checked,
'$f_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$fyear+5),\DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"), (($event_id) ? t('Edit finish date and time') : t('Finish date and time')),'finish_text',true,true,'start_text','',false,$first_day),
'$nofinish' => array('nofinish', t('Finish date and time are not known or not relevant'), $n_checked, '', array(t('No'),t('Yes')), 'onclick="enableDisableFinishDate();"'),
'$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked, t('Important for events that happen in a particular place. Not practical for global holidays.'), array(t('No'),t('Yes'))),
'$a_text' => t('Adjust for viewer timezone'),
'$d_text' => (($event_id) ? t('Edit Description') : t('Description')),
'$d_orig' => $d_orig,
'$l_text' => (($event_id) ? t('Edit Location') : t('Location')),
'$l_orig' => $l_orig,
'$t_orig' => $t_orig,
'$sh_text' => t('Share this event'),
'$sh_checked' => $sh_checked,
'$share' => array('share', t('Share this event'), $sh_checked, '', array(t('No'),t('Yes'))),
'$preview' => t('Preview'),
'$permissions' => t('Permission settings'),
// populating the acl dialog was a permission description from view_stream because Cal.php, which
// displays events, says "since we don't currently have an event permission - use the stream permission"
'$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \PermissionDescription::fromGlobalPermission('view_stream'))),
'$submit' => t('Submit'),
'$advanced' => t('Advanced Options')
));
/* end edit/create form */
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
if(! $y)
$y = intval($thisyear);
if(! $m)
$m = intval($thismonth);
$export = false;
if(argc() === 4 && argv(3) === 'export')
$export = true;
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
if($y < 1901)
$y = 1900;
if($y > 2099)
$y = 2100;
$nextyear = $y;
$nextmonth = $m + 1;
if($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if($m > 1)
$prevmonth = $m - 1;
else {
$prevmonth = 12;
$prevyear --;
}
$dim = get_dim($y,$m);
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
if (argv(1) === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
if (x($_GET,'id')){
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
intval(local_channel()),
intval($_GET['id'])
);
} elseif($export) {
$r = q("SELECT * from event where uid = %d
AND (( `adjust` = 0 AND ( `dtend` >= '%s' or nofinish = 1 ) AND `dtstart` <= '%s' )
OR ( `adjust` = 1 AND ( `dtend` >= '%s' or nofinish = 1 ) AND `dtstart` <= '%s' )) ",
intval(local_channel()),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
else {
// fixed an issue with "nofinish" events not showing up in the calendar.
// There's still an issue if the finish date crosses the end of month.
// Noting this for now - it will need to be fixed here and in Friendica.
// Ultimately the finish date shouldn't be involved in the query.
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
from event left join item on event_hash = resource_id
where resource_type = 'event' and event.uid = %d $ignored
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ",
intval(local_channel()),
dbesc($start),
dbesc($finish),
dbesc($adjust_start),
dbesc($adjust_finish)
);
}
$links = array();
if($r && ! $export) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = sort_by_date($r);
}
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
if(! x($links,$j))
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
}
}
$events=array();
$last_date = '';
$fmt = t('l, F j');
if($r) {
foreach($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
$d = day_translate($d);
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
if ($rr['nofinish']){
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
}
$is_first = ($d !== $last_date);
$last_date = $d;
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
if(! $title) {
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
}
$html = format_event_html($rr);
$rr['desc'] = bbcode($rr['desc']);
$rr['location'] = bbcode($rr['location']);
$events[] = array(
'id'=>$rr['id'],
'hash' => $rr['event_hash'],
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => false,
'title' => $title,
'j' => $j,
'd' => $d,
'edit' => $edit,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('Link to Source'),'',''),
);
}
}
if($export) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
echo ical_wrapper($r);
killme();
}
if (\App::$argv[1] === 'json'){
echo json_encode($events); killme();
}
// links: array('href', 'text', 'extra css classes', 'title')
if (x($_GET,'id')){
$tpl = get_markup_template("event.tpl");
}
else {
$tpl = get_markup_template("events-js.tpl");
}
$o = replace_macros($tpl, array(
'$baseurl' => z_root(),
'$new_event' => array(z_root().'/events',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
'$previus' => array(z_root()."/events/$prevyear/$prevmonth",t('Previous'),'',''),
'$next' => array(z_root()."/events/$nextyear/$nextmonth",t('Next'),'',''),
'$export' => array(z_root()."/events/$y/$m/export",t('Export'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$events' => $events,
'$upload' => t('Import'),
'$submit' => t('Submit'),
'$prev' => t('Previous'),
'$next' => t('Next'),
'$today' => t('Today'),
'$form' => $form,
'$expandform' => ((x($_GET,'expandform')) ? true : false),
));
if (x($_GET,'id')){ echo $o; killme(); }
return $o;
}
if($mode === 'drop' && $event_id) {
$r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1",
dbesc($event_id),
intval(local_channel())
);
$sync_event = $r[0];
if($r) {
$r = q("delete from event where event_hash = '%s' and uid = %d limit 1",
dbesc($event_id),
intval(local_channel())
);
if($r) {
$r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d",
dbesc($event_id),
intval(local_channel())
);
$sync_event['event_deleted'] = 1;
build_sync_packet(0,array('event' => array($sync_event)));
info( t('Event removed') . EOL);
}
else {
notice( t('Failed to remove event' ) . EOL);
}
goaway(z_root() . '/events');
}
}
}
}

View file

@ -1,136 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @package Friendica\modules
* @subpackage FileBrowser
* @author Fabio Comuni <fabrixxm@kirgroup.com>
*/
require_once('include/photo/photo_driver.php');
/**
* @param App $a
*/
class Fbrowser extends \Zotlabs\Web\Controller {
function get(){
if (!local_channel())
killme();
if (\App::$argc==1)
killme();
//echo "<pre>"; var_dump(\App::$argv); killme();
switch(\App::$argv[1]){
case "image":
$path = array( array(z_root()."/fbrowser/image/", t("Photos")));
$albums = false;
$sql_extra = "";
$sql_extra2 = " ORDER BY created DESC LIMIT 0, 10";
if (\App::$argc==2){
$albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d ",
intval(local_channel())
);
// anon functions only from 5.3.0... meglio tardi che mai..
$albums = array_map( "self::folder1" , $albums);
}
$album = "";
if (\App::$argc==3){
$album = hex2bin(\App::$argv[2]);
$sql_extra = sprintf("AND `album` = '%s' ",dbesc($album));
$sql_extra2 = "";
$path[]=array(z_root() . "/fbrowser/image/" . \App::$argv[2] . "/", $album);
}
$r = q("SELECT `resource_id`, `id`, `filename`, type, min(`imgscale`) AS `hiq`,max(`imgscale`) AS `loq`, `description`
FROM `photo` WHERE `uid` = %d $sql_extra
GROUP BY `resource_id` $sql_extra2",
intval(local_channel())
);
$files = array_map("self::files1", $r);
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
'$type' => 'image',
'$baseurl' => z_root(),
'$path' => $path,
'$folders' => $albums,
'$files' =>$files,
'$cancel' => t('Cancel'),
));
break;
case "file":
if (\App::$argc==2){
$files = q("SELECT id, filename, filetype FROM `attach` WHERE `uid` = %d ",
intval(local_channel())
);
$files = array_map("self::files2", $files);
//echo "<pre>"; var_dump($files); killme();
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
'$type' => 'file',
'$baseurl' => z_root(),
'$path' => array( array(z_root()."/fbrowser/image/", t("Files")) ),
'$folders' => false,
'$files' =>$files,
'$cancel' => t('Cancel'),
));
}
break;
}
killme();
}
private static function folder1($el){
return array(bin2hex($el['album']),$el['album']);
}
private static function files1($rr){
$ph = photo_factory('');
$types = $ph->supportedTypes();
$ext = $types[$rr['type']];
$filename_e = $rr['filename'];
return array(
z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['hiq'] . '.' .$ext,
$filename_e,
z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['loq'] . '.'. $ext
);
}
private static function files2($rr){
list($m1,$m2) = explode("/",$rr['filetype']);
$filetype = ( (file_exists("images/icons/$m1.png"))?$m1:"zip");
if(\App::get_template_engine() === 'internal') {
$filename_e = template_escape($rr['filename']);
}
else {
$filename_e = $rr['filename'];
}
return array( z_root() . '/attach/' . $rr['id'], $filename_e, z_root() . '/images/icons/16/' . $filetype . '.png');
}
}

View file

@ -1,48 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
class Feed extends \Zotlabs\Web\Controller {
function init() {
$params = array();
$params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
$params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : '');
$params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml');
$params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0);
$params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0);
$params['start'] = ((x($params,'start')) ? intval($params['start']) : 0);
$params['records'] = ((x($params,'records')) ? intval($params['records']) : 40);
$params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc');
$params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : '');
$channel = '';
if(argc() > 1) {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
dbesc(argv(1))
);
if(!($r && count($r)))
killme();
$channel = $r[0];
if(observer_prohibited(true))
killme();
logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
echo get_public_feed($channel,$params);
killme();
}
}
}

View file

@ -1,71 +0,0 @@
<?php
namespace Zotlabs\Module;
class Ffsapi extends \Zotlabs\Web\Controller {
function get() {
$baseurl = z_root();
$name = get_config('system','sitename');
$description = t('Share content from Firefox to $Projectname');
$author = 'Mike Macgirvin';
$homepage = 'http://hubzilla.org';
$activate = t('Activate the Firefox $Projectname provider');
$s = <<< EOT
<script>
var baseurl = '$baseurl';
var data = {
"origin": baseurl,
// currently required
"name": '$name',
"iconURL": baseurl+"/images/hz-16.png",
"icon32URL": baseurl+"/images/hz-32.png",
"icon64URL": baseurl+"/images/hz-64.png",
// at least one of these must be defined
// "workerURL": baseurl+"/worker.js",
// "sidebarURL": baseurl+"/sidebar.htm",
"shareURL": baseurl+"/rpost?f=&url=%{url}",
// status buttons are scheduled for Firefox 26 or 27
//"statusURL": baseurl+"/statusPanel.html",
// social bookmarks are available in Firefox 26
"markURL": baseurl+"/rbmark?f=&url=%{url}&title=%{title}",
// icons should be 32x32 pixels
// "markedIcon": baseurl+"/images/checkbox-checked-32.png",
// "unmarkedIcon": baseurl+"/images/checkbox-unchecked-32.png",
"unmarkedIcon": baseurl+"/images/hz-bookmark-32.png",
// should be available for display purposes
"description": "$description",
"author": "$author",
"homepageURL": "$homepage",
// optional
"version": "1.0"
}
function activate(node) {
var event = new CustomEvent("ActivateSocialFeature");
var jdata = JSON.stringify(data);
node.setAttribute("data-service", JSON.stringify(data));
node.dispatchEvent(event);
}
</script>
<button onclick="activate(this)" title="$activate" class="btn btn-primary">$activate</button>
EOT;
return $s;
}
}

View file

@ -1,85 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/zot.php');
require_once('include/crypto.php');
/* fix missing or damaged hublocs */
class Fhublocs extends \Zotlabs\Web\Controller {
function get() {
if(! is_site_admin())
return;
$o = '';
$r = q("select * from channel where channel_removed = 0");
$sitekey = get_config('system','pubkey');
if($r) {
foreach($r as $rr) {
$found = false;
$primary_address = '';
$x = zot_get_hublocs($rr['channel_hash']);
if($x) {
foreach($x as $xx) {
if($xx['hubloc_url'] === z_root() && $xx['hubloc_sitekey'] === $sitekey) {
$found = true;
break;
}
}
if($found) {
$o .= 'Hubloc exists for ' . $rr['channel_name'] . EOL;
continue;
}
}
$y = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
dbesc($rr['channel_hash'])
);
if($y)
$primary_address = $y[0]['xchan_addr'];
$hub_address = $rr['channel']['channel_address'] . '@' . \App::get_hostname();
$primary = (($hub_address === $primary_address) ? 1 : 0);
if(! $y)
$primary = 1;
$m = q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
dbesc($rr['channel_hash']),
dbesc(z_root())
);
// Create a verified hub location pointing to this site.
$h = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )
values ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
dbesc($rr['channel_guid']),
dbesc($rr['channel_guid_sig']),
dbesc($rr['channel_hash']),
dbesc($rr['channel_address'] . '@' . \App::get_hostname()),
intval($primary),
dbesc(z_root()),
dbesc(base64url_encode(rsa_sign(z_root(),$rr['channel_prvkey']))),
dbesc(\App::get_hostname()),
dbesc(z_root() . '/post'),
dbesc($sitekey),
dbesc('zot')
);
if($h)
$o . 'local hubloc created for ' . $rr['channel_name'] . EOL;
else
$o .= 'DB update failed for ' . $rr['channel_name'] . EOL;
}
return $o;
}
}
}

View file

@ -1,61 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
class Filer extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
$term = unxmlify(trim($_GET['term']));
$item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
logger('filer: tag ' . $term . ' item ' . $item_id);
if($item_id && strlen($term)){
// file item
store_item_tag(local_channel(),$item_id,TERM_OBJ_POST,TERM_FILE,$term,'');
// protect the entire conversation from periodic expiration
$r = q("select parent from item where id = %d and uid = %d limit 1",
intval($item_id),
intval(local_channel())
);
if($r) {
$x = q("update item set item_retained = 1 where id = %d and uid = %d",
intval($r[0]['parent']),
intval(local_channel())
);
}
}
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
intval(local_channel()),
intval(TERM_FILE)
);
if(count($r)) {
foreach($r as $rr)
$filetags[] = $rr['term'];
}
$tpl = get_markup_template("filer_dialog.tpl");
$o = replace_macros($tpl, array(
'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
'$submit' => t('Save'),
));
echo $o;
}
killme();
}
}

View file

@ -1,39 +0,0 @@
<?php
namespace Zotlabs\Module;
class Filerm extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
killme();
}
$term = trim($_GET['term']);
$cat = trim($_GET['cat']);
$category = (($cat) ? true : false);
if($category)
$term = $cat;
$item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
logger('filerm: tag ' . $term . ' item ' . $item_id);
if($item_id && strlen($term)) {
$r = q("delete from term where uid = %d and ttype = %d and oid = %d and term = '%s'",
intval(local_channel()),
intval(($category) ? TERM_CATEGORY : TERM_FILE),
intval($item_id),
dbesc($term)
);
}
if(x($_SESSION,'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
killme();
}
}

View file

@ -1,175 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/filestorage.php
*
*/
require_once('include/attach.php');
require_once('include/PermissionDescription.php');
/**
*
* @param object &$a
*/
class Filestorage extends \Zotlabs\Web\Controller {
function post() {
$channel_id = ((x($_POST, 'uid')) ? intval($_POST['uid']) : 0);
if((! $channel_id) || (! local_channel()) || ($channel_id != local_channel())) {
notice( t('Permission denied.') . EOL);
return;
}
$recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0);
$resource = ((x($_POST, 'filehash')) ? notags($_POST['filehash']) : '');
$notify = ((x($_POST, 'notify')) ? intval($_POST['notify']) : 0);
if(! $resource) {
notice(t('Item not found.') . EOL);
return;
}
$channel = \App::get_channel();
$acl = new \Zotlabs\Access\AccessList($channel);
$acl->set_from_array($_REQUEST);
$x = $acl->get();
$cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource);
//get the object before permissions change so we can catch eventual former allowed members
$object = get_file_activity_object($channel_id, $resource, $cloudPath);
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse);
file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify);
goaway($cloudPath);
}
function get() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$r = q("select * from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$channel = $r[0];
$owner = intval($r[0]['channel_id']);
}
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner, $ob_hash);
if(! $perms['view_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
// need to return for anyone other than the owner, despite the perms check for now.
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
if(! $is_owner) {
info( t('Permission Denied.') . EOL );
return;
}
if(argc() > 3 && argv(3) === 'delete') {
if(! $perms['write_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
$file = intval(argv(2));
$r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1",
dbesc($file),
intval($owner)
);
if(! $r) {
notice( t('File not found.') . EOL);
goaway(z_root() . '/cloud/' . $which);
}
$f = $r[0];
$channel = \App::get_channel();
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
attach_delete($owner, $f['hash']);
goaway($parentpath);
}
if(argc() > 3 && argv(3) === 'edit') {
require_once('include/acl_selectors.php');
if(! $perms['write_storage']) {
notice( t('Permission denied.') . EOL);
return;
}
$file = intval(argv(2));
$r = q("select id, uid, folder, filename, revision, flags, is_dir, os_storage, hash, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and uid = %d limit 1",
intval($file),
intval($owner)
);
$f = $r[0];
$channel = \App::get_channel();
$cloudpath = get_cloudpath($f) . (intval($f['is_dir']) ? '?f=&davguest=1' : '');
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
$aclselect_e = populate_acl($f, false, \PermissionDescription::fromGlobalPermission('view_storage'));
$is_a_dir = (intval($f['is_dir']) ? true : false);
$lockstate = (($f['allow_cid'] || $f['allow_gid'] || $f['deny_cid'] || $f['deny_gid']) ? 'lock' : 'unlock');
// Encode path that is used for link so it's a valid URL
// Keep slashes as slashes, otherwise mod_rewrite doesn't work correctly
$encoded_path = str_replace('%2F', '/', rawurlencode($cloudpath));
$o = replace_macros(get_markup_template('attach_edit.tpl'), array(
'$header' => t('Edit file permissions'),
'$file' => $f,
'$cloudpath' => z_root() . '/' . $encoded_path,
'$parentpath' => $parentpath,
'$uid' => $channel['channel_id'],
'$channelnick' => $channel['channel_address'],
'$permissions' => t('Permissions'),
'$aclselect' => $aclselect_e,
'$lockstate' => $lockstate,
'$permset' => t('Set/edit permissions'),
'$recurse' => array('recurse', t('Include all files and sub folders'), 0, '', array(t('No'), t('Yes'))),
'$backlink' => t('Return to file list'),
'$isadir' => $is_a_dir,
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
'$submit' => t('Submit'),
'$attach_btn_title' => t('Share this file'),
'$link_btn_title' => t('Show URL to this file'),
'$notify' => array('notify', t('Notify your contacts about this file'), 0, '', array(t('No'), t('Yes')))
));
echo $o;
killme();
}
goaway(z_root() . '/cloud/' . $which);
}
}

View file

@ -1,67 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/follow.php');
class Follow extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
return;
}
$uid = local_channel();
$url = notags(trim($_REQUEST['url']));
$return_url = $_SESSION['return_url'];
$confirm = intval($_REQUEST['confirm']);
$channel = \App::get_channel();
// Warning: Do not edit the following line. The first symbol is UTF-8 &#65312;
$url = str_replace('@','@',$url);
$result = new_contact($uid,$url,$channel,true,$confirm);
if($result['success'] == false) {
if($result['message'])
notice($result['message']);
goaway($return_url);
}
info( t('Channel added.') . EOL);
$clone = array();
foreach($result['abook'] as $k => $v) {
if(strpos($k,'abook_') === 0) {
$clone[$k] = $v;
}
}
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
// If we can view their stream, pull in some posts
if(($result['abook']['abook_their_perms'] & PERMS_R_STREAM) || ($result['abook']['xchan_network'] === 'rss'))
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$result['abook']['abook_id']));
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1');
}
function get() {
if(! local_channel()) {
return login();
}
}
}

View file

@ -1,101 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* module: getfile
*
* used for synchronising files and photos across clones
*
* The site initiating the file operation will send a sync packet to known clones.
* They will respond by building the DB structures they require, then will provide a
* post request to this site to grab the file data. This is sent as a stream direct to
* disk at the other end, avoiding memory issues.
*
* Since magic-auth cannot easily be used by the CURL process at the other end,
* we will require a signed request which includes a timestamp. This should not be
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
* the SSL traffic fast enough. The amount of time slop is configurable but defaults
* to 3 minutes.
*
*/
require_once('include/attach.php');
class Getfile extends \Zotlabs\Web\Controller {
function post() {
$hash = $_POST['hash'];
$time = $_POST['time'];
$sig = $_POST['signature'];
$resource = $_POST['resource'];
$revision = intval($_POST['revision']);
if(! $hash)
killme();
$channel = channelx_by_hash($hash);
if((! $channel) || (! $time) || (! $sig))
killme();
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
if($slop < 1)
$slop = 3;
$d1 = datetime_convert('UTC','UTC',"now + $slop minutes");
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
if(($time > $d1) || ($time < $d2)) {
logger('time outside allowable range');
killme();
}
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
logger('verify failed.');
killme();
}
$r = attach_by_hash($resource,$revision);
if(! $r['success']) {
notice( $r['message'] . EOL);
return;
}
$unsafe_types = array('text/html','text/css','application/javascript');
if(in_array($r['data']['filetype'],$unsafe_types)) {
header('Content-type: text/plain');
}
else {
header('Content-type: ' . $r['data']['filetype']);
}
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
if(intval($r['data']['os_storage'])) {
$fname = dbunescbin($r['data']['data']);
if(strpos($fname,'store') !== false)
$istream = fopen($fname,'rb');
else
$istream = fopen('store/' . $channel['channel_address'] . '/' . $fname,'rb');
$ostream = fopen('php://output','wb');
if($istream && $ostream) {
pipe_streams($istream,$ostream);
fclose($istream);
fclose($ostream);
}
}
else
echo dbunescbin($r['data']['data']);
killme();
}
}

View file

@ -1,244 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/group.php');
class Group extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$r = group_add(local_channel(),$name,$public);
if($r) {
info( t('Privacy group created.') . EOL );
$r = group_byname(local_channel(),$name);
if($r)
goaway(z_root() . '/group/' . $r);
}
else
notice( t('Could not create privacy group.') . EOL );
goaway(z_root() . '/group');
}
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/group', 'group_edit');
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE `groups` SET `gname` = '%s', visible = %d WHERE `uid` = %d AND `id` = %d",
dbesc($groupname),
intval($public),
intval(local_channel()),
intval($group['id'])
);
if($r)
info( t('Privacy group updated.') . EOL );
}
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
}
return;
}
function get() {
$change = false;
logger('mod_group: ' . \App::$cmd,LOGGER_DEBUG);
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = get_config('system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = 400;
$tpl = get_markup_template('group_edit.tpl');
$context = array('$submit' => t('Submit'));
if((argc() == 2) && (argv(1) === 'new')) {
return replace_macros($tpl, $context + array(
'$title' => t('Create a group of channels.'),
'$gname' => array('groupname',t('Privacy group name: '), '', ''),
'$gid' => 'new',
'$public' => array('public',t('Members are visible to other channels'), false, ''),
'$form_security_token' => get_form_security_token("group_edit"),
));
}
if((argc() == 3) && (argv(1) === 'drop')) {
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
if(intval(argv(2))) {
$r = q("SELECT `name` FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
if($r)
$result = group_rmv(local_channel(),$r[0]['gname']);
if($result)
info( t('Privacy group removed.') . EOL);
else
notice( t('Unable to remove privacy group.') . EOL);
}
goaway(z_root() . '/group');
// NOTREACHED
}
if((argc() > 2) && intval(argv(1)) && argv(2)) {
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
}
if((argc() > 1) && (intval(argv(1)))) {
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_channel(),$group['gname'],$change);
}
else {
group_add_member(local_channel(),$group['gname'],$change);
}
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
}
$drop_tpl = get_markup_template('group_drop.tpl');
$drop_txt = replace_macros($drop_tpl, array(
'$id' => $group['id'],
'$delete' => t('Delete'),
'$form_security_token' => get_form_security_token("group_drop"),
));
$context = $context + array(
'$title' => t('Privacy group editor'),
'$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
'$form_security_token' => get_form_security_token('group_edit'),
);
}
if(! isset($group))
return;
$groupeditor = array(
'label_members' => t('Members'),
'members' => array(),
'label_contacts' => t('All Connected Channels'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
foreach($members as $member) {
if($member['xchan_url']) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
foreach($r as $member) {
if(! in_array($member['xchan_hash'],$preselected)) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode);
}
}
}
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Click on a channel to add or remove.');
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}
}

View file

@ -1,60 +0,0 @@
<?php
namespace Zotlabs\Module;
class Hcard extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$profile = '';
$channel = \App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
$r = q("select profile_guid from profile where id = %d and uid = %d limit 1",
intval($profile),
intval(local_channel())
);
if(! $r)
$profile = '';
$profile = $r[0]['profile_guid'];
}
\App::$page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . z_root() . '/feed/' . $which .'" />' . "\r\n" ;
if(! $profile) {
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
dbesc(argv(1))
);
if($x) {
\App::$profile = $x[0];
}
}
profile_load($a,$which,$profile);
}
function get() {
require_once('include/widgets.php');
return widget_profile(array());
}
}

View file

@ -1,146 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/help.php');
/**
* You can create local site resources in doc/Site.md and either link to doc/Home.md for the standard resources
* or use our include mechanism to include it on your local page.
*
* #include doc/Home.md;
*
* The syntax is somewhat strict.
*
*/
class Help extends \Zotlabs\Web\Controller {
function get() {
nav_set_selected('help');
if($_REQUEST['search']) {
$o .= '<div id="help-content" class="generic-content-wrapper">';
$o .= '<div class="section-title-wrapper">';
$o .= '<h2>' . t('Documentation Search') . ' - ' . htmlspecialchars($_REQUEST['search']) . '</h2>';
$o .= '</div>';
$o .= '<div class="section-content-wrapper">';
$r = search_doc_files($_REQUEST['search']);
if($r) {
$o .= '<ul class="help-searchlist">';
foreach($r as $rr) {
$dirname = dirname($rr['sid']);
$fname = basename($rr['sid']);
$fname = substr($fname,0,strrpos($fname,'.'));
$path = trim(substr($dirname,4),'/');
$o .= '<li><a href="help/' . (($path) ? $path . '/' : '') . $fname . '" >' . ucwords(str_replace('_',' ',notags($fname))) . '</a><br />' .
str_replace('$Projectname',\Zotlabs\Lib\System::get_platform_name(),substr($rr['text'],0,200)) . '...<br /><br /></li>';
}
$o .= '</ul>';
$o .= '</div>';
$o .= '</div>';
}
return $o;
}
global $lang;
$doctype = 'markdown';
$text = '';
if(argc() > 1) {
$path = '';
for($x = 1; $x < argc(); $x ++) {
if(strlen($path))
$path .= '/';
$path .= argv($x);
}
$title = basename($path);
$text = load_doc_file('doc/' . $path . '.md');
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
if(! $text) {
$text = load_doc_file('doc/' . $path . '.bb');
if($text)
$doctype = 'bbcode';
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('_',' ',notags($title)));
}
if(! $text) {
$text = load_doc_file('doc/' . $path . '.html');
if($text)
$doctype = 'html';
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
}
}
if(! $text) {
$text = load_doc_file('doc/Site.md');
\App::$page['title'] = t('Help');
}
if(! $text) {
$doctype = 'bbcode';
$text = load_doc_file('doc/main.bb');
\App::$page['title'] = t('Help');
}
if(! strlen($text)) {
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
$tpl = get_markup_template("404.tpl");
return replace_macros($tpl, array(
'$message' => t('Page not found.' )
));
}
if($doctype === 'html')
$content = $text;
if($doctype === 'markdown') {
require_once('library/markdown.php');
# escape #include tags
$text = preg_replace('/#include/ism', '%%include', $text);
$content = Markdown($text);
$content = preg_replace('/%%include/ism', '#include', $content);
}
if($doctype === 'bbcode') {
require_once('include/bbcode.php');
$content = bbcode($text);
// bbcode retargets external content to new windows. This content is internal.
$content = str_replace(' target="_blank"','',$content);
}
$content = preg_replace_callback("/#include (.*?)\;/ism", 'self::preg_callback_help_include', $content);
return replace_macros(get_markup_template("help.tpl"), array(
'$title' => t('$Projectname Documentation'),
'$content' => translate_projectname($content)
));
}
private static function preg_callback_help_include($matches) {
if($matches[1]) {
$include = str_replace($matches[0],load_doc_file($matches[1]),$matches[0]);
if(preg_match('/\.bb$/', $matches[1]) || preg_match('/\.txt$/', $matches[1])) {
require_once('include/bbcode.php');
$include = bbcode($include);
$include = str_replace(' target="_blank"','',$include);
}
elseif(preg_match('/\.md$/', $matches[1])) {
require_once('library/markdown.php');
$include = Markdown($include);
}
return $include;
}
}
}

View file

@ -1,89 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
require_once('include/conversation.php');
class Home extends \Zotlabs\Web\Controller {
function init() {
$ret = array();
call_hooks('home_init',$ret);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
$channel = \App::get_channel();
if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) {
$dest = $channel['channel_startpage'];
if(! $dest)
$dest = get_pconfig(local_channel(),'system','startpage');
if(! $dest)
$dest = get_config('system','startpage');
if(! $dest)
$dest = z_root() . '/network';
goaway($dest);
}
if(get_account_id() && ! $splash) {
goaway(z_root() . '/new_channel');
}
}
function get($update = 0, $load = false) {
$o = '';
if(x($_SESSION,'theme'))
unset($_SESSION['theme']);
if(x($_SESSION,'mobile_theme'))
unset($_SESSION['mobile_theme']);
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
call_hooks('home_content',$o);
if($o)
return $o;
$frontpage = get_config('system','frontpage');
if($frontpage) {
if(strpos($frontpage,'include:') !== false) {
$file = trim(str_replace('include:' , '', $frontpage));
if(file_exists($file)) {
\App::$page['template'] = 'full';
\App::$page['title'] = t('$Projectname');
$o .= file_get_contents($file);
return $o;
}
}
if(strpos($frontpage,'http') !== 0)
$frontpage = z_root() . '/' . $frontpage;
if(intval(get_config('system','mirror_frontpage'))) {
$o = '<html><head><title>' . t('$Projectname') . '</title></head><body style="margin: 0; padding: 0; border: none;" ><iframe src="' . $frontpage . '" width="100%" height="100%" style="margin: 0; padding: 0; border: none;" ></iframe></body></html>';
echo $o;
killme();
}
goaway($frontpage);
}
$sitename = get_config('system','sitename');
if($sitename)
$o .= '<h1 class="home-welcome">' . sprintf( t("Welcome to %s") ,$sitename) . '</h1>';
$loginbox = get_config('system','login_on_homepage');
if(intval($loginbox) || $loginbox === false)
$o .= login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1);
return $o;
}
}

View file

@ -1,24 +0,0 @@
<?php
namespace Zotlabs\Module;
class Hostxrd extends \Zotlabs\Web\Controller {
function init() {
header('Access-Control-Allow-Origin: *');
header("Content-type: application/xrd+xml");
logger('hostxrd',LOGGER_DEBUG);
$tpl = get_markup_template('xrd_host.tpl');
$x = replace_macros(get_markup_template('xrd_host.tpl'), array(
'$zhost' => \App::get_hostname(),
'$zroot' => z_root()
));
$arr = array('xrd' => $x);
call_hooks('hostxrd',$arr);
echo $arr['xrd'];
killme();
}
}

View file

@ -1,319 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* @file mod/id.php
* @brief OpenID implementation
*/
require 'library/openid/provider/provider.php';
$attrMap = array(
'namePerson/first' => t('First Name'),
'namePerson/last' => t('Last Name'),
'namePerson/friendly' => t('Nickname'),
'namePerson' => t('Full Name'),
'contact/internet/email' => t('Email'),
'contact/email' => t('Email'),
'media/image/aspect11' => t('Profile Photo'),
'media/image' => t('Profile Photo'),
'media/image/default' => t('Profile Photo'),
'media/image/16x16' => t('Profile Photo 16px'),
'media/image/32x32' => t('Profile Photo 32px'),
'media/image/48x48' => t('Profile Photo 48px'),
'media/image/64x64' => t('Profile Photo 64px'),
'media/image/80x80' => t('Profile Photo 80px'),
'media/image/128x128' => t('Profile Photo 128px'),
'timezone' => t('Timezone'),
'contact/web/default' => t('Homepage URL'),
'language/pref' => t('Language'),
'birthDate/birthYear' => t('Birth Year'),
'birthDate/birthMonth' => t('Birth Month'),
'birthDate/birthday' => t('Birth Day'),
'birthDate' => t('Birthdate'),
'gender' => t('Gender'),
);
/**
* @brief Entrypoint for the OpenID implementation.
*
* @param App &$a
*/
class Id extends \Zotlabs\Web\Controller {
function init() {
logger('id: ' . print_r($_REQUEST, true));
if(argc() > 1) {
$which = argv(1);
} else {
\App::$error = 404;
return;
}
$profile = '';
$channel = \App::get_channel();
profile_load($a,$which,$profile);
$op = new MysqlProvider;
$op->server();
}
/**
* @brief Returns user data needed for OpenID.
*
* If no $handle is provided we will use local_channel() by default.
*
* @param string $handle (default null)
* @return boolean|array
*/
static public function getUserData($handle = null) {
if (! local_channel()) {
notice( t('Permission denied.') . EOL);
\App::$page['content'] = login();
return false;
}
// logger('handle: ' . $handle);
if ($handle) {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
dbesc($handle)
);
} else {
$r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d",
intval(local_channel())
);
}
if (! r)
return false;
$x = q("select * from account where account_id = %d limit 1",
intval($r[0]['channel_account_id'])
);
if ($x)
$r[0]['email'] = $x[0]['account_email'];
$p = q("select * from profile where is_default = 1 and uid = %d limit 1",
intval($r[0]['channel_account_id'])
);
$gender = '';
if ($p[0]['gender'] == t('Male'))
$gender = 'M';
if ($p[0]['gender'] == t('Female'))
$gender = 'F';
$r[0]['firstName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],0,strpos($r[0]['channel_name'],' ')) : $r[0]['channel_name']);
$r[0]['lastName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],strpos($r[0]['channel_name'],' ')+1) : '');
$r[0]['namePerson'] = $r[0]['channel_name'];
$r[0]['pphoto'] = $r[0]['xchan_photo_l'];
$r[0]['pphoto16'] = z_root() . '/photo/profile/16/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto32'] = z_root() . '/photo/profile/32/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto48'] = z_root() . '/photo/profile/48/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto64'] = z_root() . '/photo/profile/64/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto80'] = z_root() . '/photo/profile/80/' . $r[0]['channel_id'] . '.jpg';
$r[0]['pphoto128'] = z_root() . '/photo/profile/128/' . $r[0]['channel_id'] . '.jpg';
$r[0]['timezone'] = $r[0]['channel_timezone'];
$r[0]['url'] = $r[0]['xchan_url'];
$r[0]['language'] = (($x[0]['account_language']) ? $x[0]['account_language'] : 'en');
$r[0]['birthyear'] = ((intval(substr($p[0]['dob'],0,4))) ? intval(substr($p[0]['dob'],0,4)) : '');
$r[0]['birthmonth'] = ((intval(substr($p[0]['dob'],5,2))) ? intval(substr($p[0]['dob'],5,2)) : '');
$r[0]['birthday'] = ((intval(substr($p[0]['dob'],8,2))) ? intval(substr($p[0]['dob'],8,2)) : '');
$r[0]['birthdate'] = (($r[0]['birthyear'] && $r[0]['birthmonth'] && $r[0]['birthday']) ? $p[0]['dob'] : '');
$r[0]['gender'] = $gender;
return $r[0];
/*
* if(isset($_POST['login'],$_POST['password'])) {
* $login = mysql_real_escape_string($_POST['login']);
* $password = sha1($_POST['password']);
* $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'");
* if($data = mysql_fetch_assoc($q)) {
* return $data;
* }
* if($handle) {
* echo 'Wrong login/password.';
* }
* }
* if($handle) {
* ?>
* <form action="" method="post">
* <input type="hidden" name="openid.assoc_handle" value="<?php
namespace Zotlabs\Module; echo $handle?>">
* Login: <input type="text" name="login"><br>
* Password: <input type="password" name="password"><br>
* <button>Submit</button>
* </form>
* <?php
namespace Zotlabs\Module;
* die();
* }
*/
}
}
/**
* @brief MySQL provider for OpenID implementation.
*
*/
class MysqlProvider extends \LightOpenIDProvider {
// See http://openid.net/specs/openid-attribute-properties-list-1_0-01.html
// This list contains a few variations of these attributes to maintain
// compatibility with legacy clients
private $attrFieldMap = array(
'namePerson/first' => 'firstName',
'namePerson/last' => 'lastName',
'namePerson/friendly' => 'channel_address',
'namePerson' => 'namePerson',
'contact/internet/email' => 'email',
'contact/email' => 'email',
'media/image/aspect11' => 'pphoto',
'media/image' => 'pphoto',
'media/image/default' => 'pphoto',
'media/image/16x16' => 'pphoto16',
'media/image/32x32' => 'pphoto32',
'media/image/48x48' => 'pphoto48',
'media/image/64x64' => 'pphoto64',
'media/image/80x80' => 'pphoto80',
'media/image/128x128' => 'pphoto128',
'timezone' => 'timezone',
'contact/web/default' => 'url',
'language/pref' => 'language',
'birthDate/birthYear' => 'birthyear',
'birthDate/birthMonth' => 'birthmonth',
'birthDate/birthday' => 'birthday',
'birthDate' => 'birthdate',
'gender' => 'gender',
);
function setup($identity, $realm, $assoc_handle, $attributes) {
global $attrMap;
// logger('identity: ' . $identity);
// logger('realm: ' . $realm);
// logger('assoc_handle: ' . $assoc_handle);
// logger('attributes: ' . print_r($attributes,true));
$data = \Zotlabs\Module\Id::getUserData($assoc_handle);
/** @FIXME this needs to be a template with localised strings */
$o .= '<form action="" method="post">'
. '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">'
. '<input type="hidden" name="login" value="' . $_POST['login'] .'">'
. '<input type="hidden" name="password" value="' . $_POST['password'] .'">'
. "<b>$realm</b> wishes to authenticate you.";
if($attributes['required'] || $attributes['optional']) {
$o .= " It also requests following information (required fields marked with *):"
. '<ul>';
foreach($attributes['required'] as $attr) {
if(isset($this->attrMap[$attr])) {
$o .= '<li>'
. '<input type="checkbox" name="attributes[' . $attr . ']"> '
. $this->attrMap[$attr] . ' <span class="required">*</span></li>';
}
}
foreach($attributes['optional'] as $attr) {
if(isset($this->attrMap[$attr])) {
$o .= '<li>'
. '<input type="checkbox" name="attributes[' . $attr . ']"> '
. $this->attrMap[$attr] . '</li>';
}
}
$o .= '</ul>';
}
$o .= '<br>'
. '<button name="once">Allow once</button> '
. '<button name="always">Always allow</button> '
. '<button name="cancel">cancel</button> '
. '</form>';
\App::$page['content'] .= $o;
}
function checkid($realm, &$attributes) {
logger('checkid: ' . $realm);
logger('checkid attrs: ' . print_r($attributes,true));
if(isset($_POST['cancel'])) {
$this->cancel();
}
$data = \Zotlabs\Module\Id::getUserData();
if(! $data) {
return false;
}
$q = get_pconfig(local_channel(), 'openid', $realm);
$attrs = array();
if($q) {
$attrs = $q;
} elseif(isset($_POST['attributes'])) {
$attrs = array_keys($_POST['attributes']);
} elseif(!isset($_POST['once']) && !isset($_POST['always'])) {
return false;
}
$attributes = array();
foreach($attrs as $attr) {
if(isset($this->attrFieldMap[$attr])) {
$attributes[$attr] = $data[$this->attrFieldMap[$attr]];
}
}
if(isset($_POST['always'])) {
set_pconfig(local_channel(),'openid',$realm,array_keys($attributes));
}
return z_root() . '/id/' . $data['channel_address'];
}
function assoc_handle() {
logger('assoc_handle');
$channel = \App::get_channel();
return z_root() . '/channel/' . $channel['channel_address'];
}
function setAssoc($handle, $data) {
logger('setAssoc');
$channel = channelx_by_nick(basename($handle));
if($channel)
set_pconfig($channel['channel_id'],'openid','associate',$data);
}
function getAssoc($handle) {
logger('getAssoc: ' . $handle);
$channel = channelx_by_nick(basename($handle));
if($channel)
return get_pconfig($channel['channel_id'], 'openid', 'associate');
return false;
}
function delAssoc($handle) {
logger('delAssoc');
$channel = channelx_by_nick(basename($handle));
if($channel)
return del_pconfig($channel['channel_id'], 'openid', 'associate');
}
}

View file

@ -1,207 +0,0 @@
<?php
namespace Zotlabs\Module; /** @file */
// import page design element
require_once('include/menu.php');
class Impel extends \Zotlabs\Web\Controller {
function init() {
$ret = array('success' => false);
if(! local_channel())
json_return_and_die($ret);
logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA);
$elm = $_REQUEST['element'];
$x = base64url_decode($elm);
if(! $x)
json_return_and_die($ret);
$j = json_decode($x,true);
if(! $j)
json_return_and_die($ret);
$channel = \App::get_channel();
$arr = array();
$is_menu = false;
// a portable menu has its links rewritten with the local baseurl
$portable_menu = false;
switch($j['type']) {
case 'webpage':
$arr['item_type'] = ITEM_TYPE_WEBPAGE;
$namespace = 'WEBPAGE';
$installed_type = t('webpage');
break;
case 'block':
$arr['item_type'] = ITEM_TYPE_BLOCK;
$namespace = 'BUILDBLOCK';
$installed_type = t('block');
break;
case 'layout':
$arr['item_type'] = ITEM_TYPE_PDL;
$namespace = 'PDL';
$installed_type = t('layout');
break;
case 'portable-menu':
$portable_menu = true;
// fall through
case 'menu':
$is_menu = true;
$installed_type = t('menu');
break;
default:
logger('mod_impel: unrecognised element type' . print_r($j,true));
break;
}
if($is_menu) {
$m = array();
$m['menu_channel_id'] = local_channel();
$m['menu_name'] = $j['pagetitle'];
$m['menu_desc'] = $j['desc'];
if($j['created'])
$m['menu_created'] = datetime_convert($j['created']);
if($j['edited'])
$m['menu_edited'] = datetime_convert($j['edited']);
$m['menu_flags'] = 0;
if($j['flags']) {
if(in_array('bookmark',$j['flags']))
$m['menu_flags'] |= MENU_BOOKMARK;
if(in_array('system',$j['flags']))
$m['menu_flags'] |= MENU_SYSTEM;
}
$menu_id = menu_create($m);
if($menu_id) {
if(is_array($j['items'])) {
foreach($j['items'] as $it) {
$mitem = array();
$mitem['mitem_link'] = str_replace('[baseurl]',z_root(),$it['link']);
$mitem['mitem_desc'] = escape_tags($it['desc']);
$mitem['mitem_order'] = intval($it['order']);
if(is_array($it['flags'])) {
$mitem['mitem_flags'] = 0;
if(in_array('zid',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_ZID;
if(in_array('new-window',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_NEWWIN;
if(in_array('chatroom',$it['flags']))
$mitem['mitem_flags'] |= MENU_ITEM_CHATROOM;
}
menu_add_item($menu_id,local_channel(),$mitem);
}
if($j['edited']) {
$x = q("update menu set menu_edited = '%s' where menu_id = %d and menu_channel_id = %d",
dbesc(datetime_convert('UTC','UTC',$j['edited'])),
intval($menu_id),
intval(local_channel())
);
}
}
$ret['success'] = true;
}
$x = $ret;
}
else {
$arr['uid'] = local_channel();
$arr['aid'] = $channel['channel_account_id'];
$arr['title'] = $j['title'];
$arr['body'] = $j['body'];
$arr['term'] = $j['term'];
$arr['layout_mid'] = $j['layout_mid'];
$arr['created'] = datetime_convert('UTC','UTC', $j['created']);
$arr['edited'] = datetime_convert('UTC','UTC',$j['edited']);
$arr['owner_xchan'] = get_observer_hash();
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
if(! $j['mid'])
$j['mid'] = item_message_id();
$arr['mid'] = $arr['parent_mid'] = $j['mid'];
if($j['pagetitle']) {
require_once('library/urlify/URLify.php');
$pagetitle = strtolower(\URLify::transliterate($j['pagetitle']));
}
// Verify ability to use html or php!!!
$execflag = false;
if($arr['mimetype'] === 'application/x-php') {
$z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
intval(local_channel())
);
if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
$execflag = true;
}
}
$remote_id = 0;
$z = q("select * from item_id where sid = '%s' and service = '%s' and uid = %d limit 1",
dbesc($pagetitle),
dbesc($namespace),
intval(local_channel())
);
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['mid']),
intval(local_channel())
);
if($z && $i) {
$remote_id = $z[0]['id'];
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if($arr['edited'] > $i[0]['edited'])
$x = item_store_update($arr,$execflag);
}
else {
if(($i) && (intval($i[0]['item_deleted']))) {
// was partially deleted already, finish it off
q("delete from item where mid = '%s' and uid = %d",
dbesc($arr['mid']),
intval(local_channel())
);
}
$x = item_store($arr,$execflag);
}
if($x['success']) {
$item_id = $x['item_id'];
update_remote_id($channel,$item_id,$arr['item_type'],$pagetitle,$namespace,$remote_id,$arr['mid']);
}
}
if($x['success']) {
$ret['success'] = true;
info( sprintf( t('%s element installed'), $installed_type));
}
else {
notice( sprintf( t('%s element installation failed'), $installed_type));
}
//??? should perhaps return ret?
json_return_and_die(true);
}
}

View file

@ -1,557 +0,0 @@
<?php
namespace Zotlabs\Module;
// Import a channel, either by direct file upload or via
// connection to original server.
require_once('include/zot.php');
require_once('include/channel.php');
require_once('include/import.php');
class Import extends \Zotlabs\Web\Controller {
function import_account($account_id) {
if(! $account_id){
logger("import_account: No account ID supplied");
return;
}
$max_identities = account_service_class_fetch($account_id,'total_identities');
$max_friends = account_service_class_fetch($account_id,'total_channels');
$max_feeds = account_service_class_fetch($account_id,'total_feeds');
if($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d",
intval($account_id)
);
if($r && count($r) > $max_identities) {
notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL);
return;
}
}
$data = null;
$seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
$import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
$completed = ((array_key_exists('import_step',$_SESSION)) ? intval($_SESSION['import_step']) : 0);
if($completed)
logger('saved import step: ' . $_SESSION['import_step']);
if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('mod_import: nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname;
if($import_posts)
$api_path .= '&posts=1';
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('mod_import: empty file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true));
// print_r($data);
if(array_key_exists('user',$data) && array_key_exists('version',$data)) {
require_once('include/Import/import_diaspora.php');
import_diaspora($data);
return;
}
$moving = false;
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
$v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t);
}
if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic')
$moving = true;
}
if($moving)
$seize = 1;
// import channel
if(array_key_exists('channel',$data)) {
if($completed < 1) {
$channel = import_channel($data['channel'], $account_id, $seize);
}
else {
$r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1",
intval($account_id),
dbesc($channel['channel_guid'])
);
if($r)
$channel = $r[0];
}
if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true));
notice( t('Cloned channel not found. Import failed.') . EOL);
return;
}
}
if(! $channel)
$channel = \App::get_channel();
if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true));
notice( t('No channel. Import failed.') . EOL);
return;
}
if($completed < 2) {
if(is_array($data['config'])) {
import_config($channel,$data['config']);
}
logger('import step 2');
$_SESSION['import_step'] = 2;
}
if($completed < 3) {
if($data['photo']) {
require_once('include/photo/photo_driver.php');
import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
}
if(is_array($data['profile']))
import_profiles($channel,$data['profile']);
logger('import step 3');
$_SESSION['import_step'] = 3;
}
if($completed < 4) {
if(is_array($data['hubloc']) && (! $moving)) {
import_hublocs($channel,$data['hubloc'],$seize);
}
logger('import step 4');
$_SESSION['import_step'] = 4;
}
if($completed < 5) {
// create new hubloc for the new channel at this site
$r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_primary,
hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )
values ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )",
dbesc($channel['channel_guid']),
dbesc($channel['channel_guid_sig']),
dbesc($channel['channel_hash']),
dbesc($channel['channel_address'] . '@' . \App::get_hostname()),
dbesc('zot'),
intval(($seize) ? 1 : 0),
dbesc(z_root()),
dbesc(base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey']))),
dbesc(\App::get_hostname()),
dbesc(z_root() . '/post'),
dbesc(get_config('system','pubkey'))
);
// reset the original primary hubloc if it is being seized
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
);
}
logger('import step 5');
$_SESSION['import_step'] = 5;
}
if($completed < 6) {
// import xchans and contact photos
if($seize) {
// replace any existing xchan we may have on this site if we're seizing control
$r = q("delete from xchan where xchan_hash = '%s'",
dbesc($channel['channel_hash'])
);
$r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, %d )",
dbesc($channel['channel_hash']),
dbesc($channel['channel_guid']),
dbesc($channel['channel_guid_sig']),
dbesc($channel['channel_pubkey']),
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']),
dbesc($channel['channel_address'] . '@' . \App::get_hostname()),
dbesc(z_root() . '/channel/' . $channel['channel_address']),
dbesc(z_root() . '/follow?f=&url=%s'),
dbesc(z_root() . '/poco/' . $channel['channel_address']),
dbesc($channel['channel_name']),
dbesc('zot'),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
0,0,0,0,0,0,0
);
}
logger('import step 6');
$_SESSION['import_step'] = 6;
}
if($completed < 7) {
$xchans = $data['xchan'];
if($xchans) {
foreach($xchans as $xchan) {
$hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
logger('forged xchan: ' . print_r($xchan,true));
continue;
}
if(! array_key_exists('xchan_hidden',$xchan)) {
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
$xchan['xchan_censored'] = (($xchan['xchan_flags'] & 0x0004) ? 1 : 0);
$xchan['xchan_selfcensored'] = (($xchan['xchan_flags'] & 0x0008) ? 1 : 0);
$xchan['xchan_system'] = (($xchan['xchan_flags'] & 0x0010) ? 1 : 0);
$xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0);
$xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0);
}
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan['xchan_hash'])
);
if($r)
continue;
dbesc_array($xchan);
$r = dbq("INSERT INTO xchan (`"
. implode("`, `", array_keys($xchan))
. "`) VALUES ('"
. implode("', '", array_values($xchan))
. "')" );
require_once('include/photo/photo_driver.php');
$photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
if($photos[4])
$photodate = NULL_DATE;
else
$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'",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($photodate),
dbesc($xchan['xchan_hash'])
);
}
}
logger('import step 7');
$_SESSION['import_step'] = 7;
}
// FIXME - ensure we have an xchan if somebody is trying to pull a fast one
if($completed < 8) {
$friends = 0;
$feeds = 0;
// import contacts
$abooks = $data['abook'];
if($abooks) {
foreach($abooks as $abook) {
$abconfig = null;
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
$abconfig = $abook['abconfig'];
unset($abook['abook_id']);
unset($abook['abook_rating']);
unset($abook['abook_rating_text']);
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
if(! array_key_exists('abook_blocked',$abook)) {
$abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001 ) ? 1 : 0);
$abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002 ) ? 1 : 0);
$abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004 ) ? 1 : 0);
$abook['abook_archived'] = (($abook['abook_flags'] & 0x0008 ) ? 1 : 0);
$abook['abook_pending'] = (($abook['abook_flags'] & 0x0010 ) ? 1 : 0);
$abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020 ) ? 1 : 0);
$abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
$abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
}
if($abook['abook_self']) {
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ",
dbesc($abook['abook_xchan'])
);
}
}
else {
if($max_friends !== false && $friends > $max_friends)
continue;
if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
continue;
}
dbesc_array($abook);
$r = dbq("INSERT INTO abook (`"
. implode("`, `", array_keys($abook))
. "`) VALUES ('"
. implode("', '", array_values($abook))
. "')" );
$friends ++;
if(intval($abook['abook_feed']))
$feeds ++;
if($abconfig) {
// @fixme does not handle sync of del_abconfig
foreach($abconfig as $abc) {
if($abc['chan'] === $channel['channel_hash'])
set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
}
}
}
}
logger('import step 8');
$_SESSION['import_step'] = 8;
}
if($completed < 9) {
$groups = $data['group'];
if($groups) {
$saved = array();
foreach($groups as $group) {
$saved[$group['hash']] = array('old' => $group['id']);
if(array_key_exists('name',$group)) {
$group['gname'] = $group['name'];
unset($group['name']);
}
unset($group['id']);
$group['uid'] = $channel['channel_id'];
dbesc_array($group);
$r = dbq("INSERT INTO groups (`"
. implode("`, `", array_keys($group))
. "`) VALUES ('"
. implode("', '", array_values($group))
. "')" );
}
$r = q("select * from `groups` where uid = %d",
intval($channel['channel_id'])
);
if($r) {
foreach($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id'];
}
}
}
$group_members = $data['group_member'];
if($group_members) {
foreach($group_members as $group_member) {
unset($group_member['id']);
$group_member['uid'] = $channel['channel_id'];
foreach($saved as $x) {
if($x['old'] == $group_member['gid'])
$group_member['gid'] = $x['new'];
}
dbesc_array($group_member);
$r = dbq("INSERT INTO group_member (`"
. implode("`, `", array_keys($group_member))
. "`) VALUES ('"
. implode("', '", array_values($group_member))
. "')" );
}
}
logger('import step 9');
$_SESSION['import_step'] = 9;
}
if(is_array($data['obj']))
import_objs($channel,$data['obj']);
if(is_array($data['likes']))
import_likes($channel,$data['likes']);
if(is_array($data['app']))
import_apps($channel,$data['app']);
if(is_array($data['chatroom']))
import_chatrooms($channel,$data['chatroom']);
if(is_array($data['conv']))
import_conv($channel,$data['conv']);
if(is_array($data['mail']))
import_mail($channel,$data['mail']);
if(is_array($data['event']))
import_events($channel,$data['event']);
if(is_array($data['event_item']))
import_items($channel,$data['event_item']);
if(is_array($data['menu']))
import_menus($channel,$data['menu']);
$addon = array('channel' => $channel,'data' => $data);
call_hooks('import_channel',$addon);
$saved_notification_flags = notifications_off($channel['channel_id']);
if($import_posts && array_key_exists('item',$data) && $data['item'])
import_items($channel,$data['item']);
notifications_on($channel['channel_id'],$saved_notification_flags);
if(array_key_exists('item_id',$data) && $data['item_id'])
import_item_ids($channel,$data['item_id']);
// FIXME - ensure we have a self entry if somebody is trying to pull a fast one
// send out refresh requests
// notify old server that it may no longer be primary.
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
// This will indirectly perform a refresh_all *and* update the directory
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
notice( t('Import completed.') . EOL);
change_channel($channel['channel_id']);
unset($_SESSION['import_step']);
goaway(z_root() . '/network' );
}
function post() {
$account_id = get_account_id();
if(! $account_id)
return;
$this->import_account($account_id);
}
function get() {
if(! get_account_id()) {
notice( t('You must be logged in to use this feature.'));
return '';
}
$o = replace_macros(get_markup_template('channel_import.tpl'),array(
'$title' => t('Import Channel'),
'$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
'$label_filename' => t('File to Upload'),
'$choice' => t('Or provide the old server/hub details'),
'$label_old_address' => t('Your old identity address (xyz@example.com)'),
'$label_old_email' => t('Your old login email address'),
'$label_old_pass' => t('Your old login password'),
'$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'),
'$label_import_primary' => t('Make this hub my primary location'),
'$label_import_posts' => t('Import existing posts if possible (experimental - limited by available memory'),
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
'$email' => '',
'$pass' => '',
'$submit' => t('Submit')
));
return $o;
}
}

View file

@ -1,129 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/import.php');
class Import_items extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
$data = null;
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
if($src) {
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
if(strpos($filename,'.gz')){
@rename($src,$src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
if($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('mod_import: nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
}
$email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
$password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
$year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
$channelname = substr($old_address,0,strpos($old_address,'@'));
$servername = substr($old_address,strpos($old_address,'@')+1);
$scheme = 'https://';
$api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
$url = $scheme . $servername . $api_path;
$ret = z_fetch_url($url, $binary, $redirects, $opts);
if(! $ret['success'])
$ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
if($ret['success'])
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('mod_import: empty file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true));
// print_r($data);
if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
$v1 = substr($data['compatibility']['database'],-4);
$v2 = substr(DB_UPDATE_VERSION,-4);
if($v2 > $v1) {
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t);
}
}
$channel = \App::get_channel();
if(array_key_exists('item',$data) && $data['item']) {
import_items($channel,$data['item']);
}
if(array_key_exists('item_id',$data) && $data['item_id']) {
import_item_ids($channel,$data['item_id']);
}
info( t('Import completed') . EOL);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return login();
}
$o = replace_macros(get_markup_template('item_import.tpl'),array(
'$title' => t('Import Items'),
'$desc' => t('Use this form to import existing posts and content from an export file.'),
'$label_filename' => t('File to Upload'),
'$submit' => t('Submit')
));
return $o;
}
}

View file

@ -1,152 +0,0 @@
<?php
namespace Zotlabs\Module;
/**
* module: invite.php
*
* send email invitations to join social network
*
*/
class Invite extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
check_form_security_token_redirectOnErr('/', 'send_invite');
$max_invites = intval(get_config('system','max_invites'));
if(! $max_invites)
$max_invites = 50;
$current_invites = intval(get_pconfig(local_channel(),'system','sent_invites'));
if($current_invites > $max_invites) {
notice( t('Total invitation limit exceeded.') . EOL);
return;
};
$recips = ((x($_POST,'recipients')) ? explode("\n",$_POST['recipients']) : array());
$message = ((x($_POST,'message')) ? notags(trim($_POST['message'])) : '');
$total = 0;
if(get_config('system','invitation_only')) {
$invonly = true;
$x = get_pconfig(local_channel(),'system','invites_remaining');
if((! $x) && (! is_site_admin()))
return;
}
foreach($recips as $recip) {
$recip = trim($recip);
if(! $recip)
continue;
if(! valid_email($recip)) {
notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
continue;
}
else
$nmessage = $message;
$account = \App::get_account();
$res = mail($recip, sprintf( t('Please join us on $Projectname'), \App::$config['sitename']),
$nmessage,
"From: " . $account['account_email'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
if($res) {
$total ++;
$current_invites ++;
set_pconfig(local_channel(),'system','sent_invites',$current_invites);
if($current_invites > $max_invites) {
notice( t('Invitation limit exceeded. Please contact your site administrator.') . EOL);
return;
}
}
else {
notice( sprintf( t('%s : Message delivery failed.'), $recip) . EOL);
}
}
notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL);
return;
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$tpl = get_markup_template('invite.tpl');
$invonly = false;
if(get_config('system','invitation_only')) {
$invonly = true;
$x = get_pconfig(local_channel(),'system','invites_remaining');
if((! $x) && (! is_site_admin())) {
notice( t('You have no more invitations available') . EOL);
return '';
}
}
if($invonly && ($x || is_site_admin())) {
$invite_code = autoname(8) . rand(1000,9999);
$nmessage = str_replace('$invite_code',$invite_code,$message);
$r = q("INSERT INTO `register` (`hash`,`created`) VALUES ('%s', '%s') ",
dbesc($invite_code),
dbesc(datetime_convert())
);
if(! is_site_admin()) {
$x --;
if($x >= 0)
set_pconfig(local_channel(),'system','invites_remaining',$x);
else
return;
}
}
$ob = \App::get_observer();
if(! $ob)
return $o;
$channel = \App::get_channel();
$o = replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("send_invite"),
'$invite' => t('Send invitations'),
'$addr_text' => t('Enter email addresses, one per line:'),
'$msg_text' => t('Your message:'),
'$default_message' => t('Please join my community on $Projectname.') . "\r\n" . "\r\n"
. $linktxt
. (($invonly) ? "\r\n" . "\r\n" . t('You will need to supply this invitation code:') . " " . $invite_code . "\r\n" . "\r\n" : '')
. t('1. Register at any $Projectname location (they are all inter-connected)')
. "\r\n" . "\r\n" . z_root() . '/register'
. "\r\n" . "\r\n" . t('2. Enter my $Projectname network address into the site searchbar.')
. "\r\n" . "\r\n" . $ob['xchan_addr'] . ' (' . t('or visit') . " " . z_root() . '/channel/' . $channel['channel_address'] . ')'
. "\r\n" . "\r\n"
. t('3. Click [Connect]')
. "\r\n" . "\r\n" ,
'$submit' => t('Submit')
));
return $o;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
<?php
namespace Zotlabs\Module;
class Lang extends \Zotlabs\Web\Controller {
function get() {
return lang_selector();
}
}

View file

@ -1,202 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
class Layouts extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($a,$which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$_SESSION['return_url'] = \App::$query_string;
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
$uid = $owner = intval($sys['channel_id']);
$channel = $sys;
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// Block design features from visitors
if((! $uid) || ($uid != $owner)) {
notice( t('Permission denied.') . EOL);
return;
}
// Get the observer, check their permissions
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
//This feature is not exposed in redbasic ui since it is not clear why one would want to
//download a json encoded pdl file - we dont have a possibility to import it.
//Use the buildin share/install feature instead.
if((argc() > 3) && (argv(2) === 'share') && (argv(3))) {
$r = q("select sid, service, mimetype, title, body from item_id
left join item on item.id = item_id.iid
where item_id.uid = %d and item.mid = '%s' and service = 'PDL' order by sid asc",
intval($owner),
dbesc(argv(3))
);
if($r) {
header('Content-type: application/x-hubzilla-layout');
header('Content-disposition: attachment; filename="' . $r[0]['sid'] . '.pdl"');
echo json_encode($r);
killme();
}
}
// Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages
// Nickname is set to the observers xchan, and profile_uid to the owners.
// This lets you post pages at other people's channels.
$x = array(
'webpage' => ITEM_TYPE_PDL,
'is_owner' => true,
'nickname' => \App::$profile['channel_address'],
'showacl' => false,
'hide_voting' => true,
'hide_future' => true,
'hide_expire' => true,
'hide_location' => true,
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'ptlabel' => t('Layout Name'),
'profile_uid' => intval($owner),
'expanded' => true,
'placeholdertitle' => t('Layout Description (Optional)'),
'novoting' => true,
'bbco_autocomplete' => 'comanche'
);
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
$editor = status_editor($a,$x);
$r = q("select iid, sid, mid, title, body, mimetype, created, edited, item_type from item_id left join item on item_id.iid = item.id
where item_id.uid = %d and service = 'PDL' and item_type = %d order by item.created desc",
intval($owner),
intval(ITEM_TYPE_PDL)
);
$pages = null;
if($r) {
$pages = array();
foreach($r as $rr) {
$element_arr = array(
'type' => 'layout',
'title' => $rr['title'],
'body' => $rr['body'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'mimetype' => $rr['mimetype'],
'pagetitle' => $rr['sid'],
'mid' => $rr['mid']
);
$pages[$rr['iid']][] = array(
'url' => $rr['iid'],
'title' => $rr['sid'],
'descr' => $rr['title'],
'mid' => $rr['mid'],
'created' => $rr['created'],
'edited' => $rr['edited'],
'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'
);
}
}
//Build the base URL for edit links
$url = z_root() . '/editlayout/' . $which;
$o .= replace_macros(get_markup_template('layoutlist.tpl'), array(
'$title' => t('Layouts'),
'$create' => t('Create'),
'$help' => array('text' => t('Help'), 'url' => 'help/comanche', 'title' => t('Comanche page description language help')),
'$editor' => $editor,
'$baseurl' => $url,
'$name' => t('Layout Name'),
'$descr' => t('Layout Description'),
'$created' => t('Created'),
'$edited' => t('Edited'),
'$edit' => t('Edit'),
'$share' => t('Share'),
'$download' => t('Download PDL file'),
'$pages' => $pages,
'$channel' => $which,
'$view' => t('View'),
));
return $o;
}
}

View file

@ -1,547 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/bbcode.php');
require_once('include/items.php');
class Like extends \Zotlabs\Web\Controller {
function get() {
$o = '';
$observer = \App::get_observer();
$interactive = $_REQUEST['interactive'];
if($interactive) {
$o .= '<h1>' . t('Like/Dislike') . '</h1>';
$o .= EOL . EOL;
if(! $observer) {
$_SESSION['return_url'] = \App::$query_string;
$o .= t('This action is restricted to members.') . EOL;
$o .= t('Please <a href="rmagic">login with your $Projectname ID</a> or <a href="register">register as a new $Projectname member</a> to continue.') . EOL;
return $o;
}
}
$verb = notags(trim($_GET['verb']));
if(! $verb)
$verb = 'like';
switch($verb) {
case 'like':
case 'unlike':
$activity = ACTIVITY_LIKE;
break;
case 'dislike':
case 'undislike':
$activity = ACTIVITY_DISLIKE;
break;
case 'agree':
case 'unagree':
$activity = ACTIVITY_AGREE;
break;
case 'disagree':
case 'undisagree':
$activity = ACTIVITY_DISAGREE;
break;
case 'abstain':
case 'unabstain':
$activity = ACTIVITY_ABSTAIN;
break;
case 'attendyes':
case 'unattendyes':
$activity = ACTIVITY_ATTEND;
break;
case 'attendno':
case 'unattendno':
$activity = ACTIVITY_ATTENDNO;
break;
case 'attendmaybe':
case 'unattendmaybe':
$activity = ACTIVITY_ATTENDMAYBE;
break;
default:
return;
break;
}
$extended_like = false;
$object = $target = null;
$post_type = '';
$objtype = '';
if(argc() == 3) {
if(! $observer)
killme();
$extended_like = true;
$obj_type = argv(1);
$obj_id = argv(2);
$public = true;
if($obj_type == 'profile') {
$r = q("select * from profile where profile_guid = '%s' limit 1",
dbesc(argv(2))
);
if(! $r)
killme();
$owner_uid = $r[0]['uid'];
if($r[0]['is_default'])
$public = true;
if(! $public) {
$d = q("select abook_xchan from abook where abook_profile = '%s' and abook_channel = %d",
dbesc($r[0]['profile_guid']),
intval($owner_uid)
);
if(! $d) {
// forgery - illegal
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
// $d now contains a list of those who can see this profile - only send the status notification
// to them.
$allow_cid = $allow_gid = $deny_cid = $deny_gid = '';
foreach($d as $dd) {
$allow_cid .= '<' . $dd['abook_xchan'] . '>';
}
}
$post_type = t('channel');
$objtype = ACTIVITY_OBJ_PROFILE;
$profile = $r[0];
}
elseif($obj_type == 'thing') {
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
intval(TERM_OBJ_THING),
dbesc(argv(2))
);
if(! $r) {
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
$owner_uid = $r[0]['obj_channel'];
$allow_cid = $r[0]['allow_cid'];
$allow_gid = $r[0]['allow_gid'];
$deny_cid = $r[0]['deny_cid'];
$deny_gid = $r[0]['deny_gid'];
if($allow_cid || $allow_gid || $deny_cid || $deny_gid)
$public = false;
$post_type = t('thing');
$objtype = ACTIVITY_OBJ_PROFILE;
$tgttype = ACTIVITY_OBJ_THING;
$links = array();
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/thing/' . $r[0]['obj_obj']);
if($r[0]['imgurl'])
$links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']);
$target = json_encode(array(
'type' => $tgttype,
'title' => $r[0]['obj_term'],
'id' => z_root() . '/thing/' . $r[0]['obj_obj'],
'link' => $links
));
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
}
if(! ($owner_uid && $r)) {
if($interactive) {
notice( t('Invalid request.') . EOL);
return $o;
}
killme();
}
// The resultant activity is going to be a wall-to-wall post, so make sure this is allowed
$perms = get_all_perms($owner_uid,$observer['xchan_hash']);
if(! ($perms['post_like'] && $perms['view_profile'])) {
if($interactive) {
notice( t('Permission denied.') . EOL);
return $o;
}
killme();
}
$ch = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($owner_uid)
);
if(! $ch) {
if($interactive) {
notice( t('Channel unavailable.') . EOL);
return $o;
}
killme();
}
if(! $plink)
$plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
$links = array();
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
'href' => z_root() . '/profile/' . $ch[0]['channel_address']);
$links[] = array('rel' => 'photo', 'type' => $ch[0]['xchan_photo_mimetype'],
'href' => $ch[0]['xchan_photo_l']);
$object = json_encode(array(
'type' => ACTIVITY_OBJ_PROFILE,
'title' => $ch[0]['channel_name'],
'id' => $ch[0]['xchan_url'] . '/' . $ch[0]['xchan_hash'],
'link' => $links
));
// second like of the same thing is "undo" for the first like
$z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
dbesc($activity),
dbesc(($tgttype)?$tgttype:$objtype),
dbesc($obj_id)
);
if($z) {
$z[0]['deleted'] = 1;
build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
q("delete from likes where id = %d limit 1",
intval($z[0]['id'])
);
if($z[0]['i_mid']) {
$r = q("select id from item where mid = '%s' and uid = %d limit 1",
dbesc($z[0]['i_mid']),
intval($ch[0]['channel_id'])
);
if($r)
drop_item($r[0]['id'],false);
if($interactive) {
notice( t('Previous action reversed.') . EOL);
return $o;
}
}
killme();
}
}
else {
// this is used to like an item or comment
$item_id = ((argc() == 2) ? notags(trim(argv(1))) : 0);
logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
// get the item. Allow linked photos (which are normally hidden) to be liked
$r = q("SELECT * FROM item WHERE id = %d
and item_type = 0 and item_deleted = 0 and item_unpublished = 0
and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
intval($item_id)
);
if(! $item_id || (! $r)) {
logger('like: no item ' . $item_id);
killme();
}
$item = $r[0];
$owner_uid = $item['uid'];
$owner_aid = $item['aid'];
$sys = get_sys_channel();
// if this is a "discover" item, (item['uid'] is the sys channel),
// fallback to the item comment policy, which should've been
// respected when generating the conversation thread.
// Even if the activity is rejected by the item owner, it should still get attached
// to the local discover conversation on this site.
if(($owner_uid != $sys['channel_id']) && (! perm_is_allowed($owner_uid,$observer['xchan_hash'],'post_comments'))) {
notice( t('Permission denied') . EOL);
killme();
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['owner_xchan'])
);
if($r)
$thread_owner = $r[0];
else
killme();
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
if($r)
$item_author = $r[0];
else
killme();
$verbs = " '".dbesc($activity)."' ";
$multi_undo = false;
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
// we need to eradicate your first choice.
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
$multi_undo = 1;
}
if($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
$multi_undo = true;
}
$item_normal = item_normal();
$r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal
AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ",
dbesc($observer['xchan_hash']),
dbesc($item['mid']),
intval($owner_uid)
);
if($r) {
// already liked it. Drop that item.
require_once('include/items.php');
foreach($r as $rr) {
drop_item($rr['id'],false,DROPITEM_PHASE1);
// set the changed timestamp on the parent so we'll see the update without a page reload
$z = q("update item set changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($rr['parent']),
intval($rr['uid'])
);
// Prior activity was a duplicate of the one we're submitting, just undo it;
// don't fall through and create another
if(activity_match($rr['verb'],$activity))
$multi_undo = false;
// drop_item was not done interactively, so we need to invoke the notifier
// in order to push the changes to connections
\Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$rr['id']));
}
if($interactive)
return;
if(! $multi_undo)
killme();
}
}
$mid = item_message_id();
$arr = array();
if($extended_like) {
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
}
else {
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
$post_type = t('event');
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
$body = $item['body'];
$object = json_encode(array(
'type' => $objtype,
'id' => $item['mid'],
'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
'link' => $links,
'title' => $item['title'],
'content' => $item['body'],
'created' => $item['created'],
'edited' => $item['edited'],
'author' => array(
'name' => $item_author['xchan_name'],
'address' => $item_author['xchan_addr'],
'guid' => $item_author['xchan_guid'],
'guid_sig' => $item_author['xchan_guid_sig'],
'link' => array(
array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
),
));
if(! intval($item['item_thread_top']))
$post_type = 'comment';
$arr['item_origin'] = 1;
$arr['item_notshown'] = 1;
if(intval($item['item_wall']))
$arr['item_wall'] = 1;
// if this was a linked photo and was hidden, unhide it.
if(intval($item['item_hidden'])) {
$r = q("update item set item_hidden = 0 where id = %d",
intval($item['id'])
);
}
}
if($verb === 'like')
$bodyverb = t('%1$s likes %2$s\'s %3$s');
if($verb === 'dislike')
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
if($verb === 'agree')
$bodyverb = t('%1$s agrees with %2$s\'s %3$s');
if($verb === 'disagree')
$bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
if($verb === 'abstain')
$bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
if($verb === 'attendyes')
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
if($verb === 'attendno')
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
if($verb === 'attendmaybe')
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
if(! isset($bodyverb))
killme();
if($extended_like) {
$ulink = '[zrl=' . $ch[0]['xchan_url'] . ']' . $ch[0]['xchan_name'] . '[/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
$private = (($public) ? 0 : 1);
}
else {
$arr['parent'] = $item['id'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
$plink = '[zrl=' . z_root() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]';
$allow_cid = $item['allow_cid'];
$allow_gid = $item['allow_gid'];
$deny_cid = $item['deny_cid'];
$deny_gid = $item['deny_gid'];
$private = $item['private'];
}
$arr['mid'] = $mid;
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
$arr['uid'] = $owner_uid;
$arr['item_flags'] = $item_flags;
$arr['item_wall'] = $item_wall;
$arr['parent_mid'] = (($extended_like) ? $mid : $item['mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
if($obj_type === 'thing' && $r[0]['imgurl']) {
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
}
if($obj_type === 'profile') {
if($public) {
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
}
else
$arr['body'] .= "\n\n[zmg=80x80]" . $profile['thumb'] . '[/zmg]';
}
$arr['verb'] = $activity;
$arr['obj_type'] = $objtype;
$arr['obj'] = $object;
if($target) {
$arr['tgt_type'] = $tgttype;
$arr['target'] = $target;
}
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
$post = item_store($arr);
$post_id = $post['item_id'];
$arr['id'] = $post_id;
call_hooks('post_local_end', $arr);
if($extended_like) {
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
intval($ch[0]['channel_id']),
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
intval($post_id),
dbesc($mid),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id),
dbesc(($target) ? $target : $object)
);
$r = q("select * from likes where liker = '%s' and likee = '%s' and i_mid = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' ",
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
dbesc($mid),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id)
);
if($r)
build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
}
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$post_id));
if($interactive) {
notice( t('Action completed.') . EOL);
$o .= t('Thank you.');
return $o;
}
killme();
}
}

View file

@ -1,381 +0,0 @@
<?php
namespace Zotlabs\Module;
class Linkinfo extends \Zotlabs\Web\Controller {
function get() {
logger('linkinfo: ' . print_r($_REQUEST,true));
$text = null;
$str_tags = '';
$br = "\n";
if(x($_GET,'binurl'))
$url = trim(hex2bin($_GET['binurl']));
else
$url = trim($_GET['url']);
$url = strip_zids($url);
if((substr($url,0,1) != '/') && (substr($url,0,4) != 'http'))
$url = 'http://' . $url;
if($_GET['title'])
$title = strip_tags(trim($_GET['title']));
if($_GET['description'])
$text = strip_tags(trim($_GET['description']));
if($_GET['tags']) {
$arr_tags = str_getcsv($_GET['tags']);
if(count($arr_tags)) {
array_walk($arr_tags,'self::arr_add_hashes');
$str_tags = $br . implode(' ',$arr_tags) . $br;
}
}
logger('linkinfo: ' . $url);
$result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true));
if($result['success']) {
$hdrs=array();
$h = explode("\n",$result['header']);
foreach ($h as $l) {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[$k] = $v;
}
if (array_key_exists('Content-Type', $hdrs))
$type = $hdrs['Content-Type'];
if($type) {
$zrl = is_matrix_url($url);
if(stripos($type,'image/') !== false) {
if($zrl)
echo $br . '[zmg]' . $url . '[/zmg]' . $br;
else
echo $br . '[img]' . $url . '[/img]' . $br;
killme();
}
if(stripos($type,'video/') !== false) {
if($zrl)
echo $br . '[zvideo]' . $url . '[/zvideo]' . $br;
else
echo $br . '[video]' . $url . '[/video]' . $br;
killme();
}
if(stripos($type,'audio/') !== false) {
if($zrl)
echo $br . '[zaudio]' . $url . '[/zaudio]' . $br;
else
echo $br . '[audio]' . $url . '[/audio]' . $br;
killme();
}
}
}
$template = $br . '#^[url=%s]%s[/url]%s' . $br;
$arr = array('url' => $url, 'text' => '');
call_hooks('parse_link', $arr);
if(strlen($arr['text'])) {
echo $arr['text'];
killme();
}
$x = oembed_process($url);
if($x) {
echo $x;
killme();
}
if($url && $title && $text) {
$text = $br . '[quote]' . trim($text) . '[/quote]' . $br;
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo (unparsed): returns: ' . $result);
echo $result;
killme();
}
$siteinfo = self::parseurl_getsiteinfo($url);
// If this is a Red site, use zrl rather than url so they get zids sent to them by default
if( x($siteinfo,'generator') && (strpos($siteinfo['generator'], \Zotlabs\Lib\System::get_platform_name() . ' ') === 0))
$template = str_replace('url','zrl',$template);
if($siteinfo["title"] == "") {
echo sprintf($template,$url,$url,'') . $str_tags;
killme();
} else {
$text = $siteinfo["text"];
$title = $siteinfo["title"];
}
$image = "";
if(sizeof($siteinfo["images"]) > 0){
/* Execute below code only if image is present in siteinfo */
$total_images = 0;
$max_images = get_config('system','max_bookmark_images');
if($max_images === false)
$max_images = 2;
else
$max_images = intval($max_images);
foreach ($siteinfo["images"] as $imagedata) {
if ($url) {
$image .= sprintf('[url=%s]', $url);
}
$image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]';
if ($url) {
$image .= '[/url]';
}
$image .= "\n";
$total_images ++;
if($max_images && $max_images >= $total_images)
break;
}
}
if(strlen($text)) {
$text = $br.'[quote]'.trim($text).'[/quote]'.$br ;
}
if($image) {
$text = $br.$br.$image.$text;
}
$title = str_replace(array("\r","\n"),array('',''),$title);
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
logger('linkinfo: returns: ' . $result, LOGGER_DEBUG);
echo trim($result);
killme();
}
public static function deletexnode(&$doc, $node) {
$xpath = new \DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}
public static function completeurl($url, $scheme) {
$urlarr = parse_url($url);
if (isset($urlarr["scheme"]))
return($url);
$schemearr = parse_url($scheme);
$complete = $schemearr["scheme"]."://".$schemearr["host"];
if ($schemearr["port"] != "")
$complete .= ":".$schemearr["port"];
if(strpos($urlarr['path'],'/') !== 0)
$complete .= '/';
$complete .= $urlarr["path"];
if ($urlarr["query"] != "")
$complete .= "?".$urlarr["query"];
if ($urlarr["fragment"] != "")
$complete .= "#".$urlarr["fragment"];
return($complete);
}
public static function parseurl_getsiteinfo($url) {
$siteinfo = array();
$result = z_fetch_url($url,false,0,array('novalidate' => true));
if(! $result['success'])
return $siteinfo;
$header = $result['header'];
$body = $result['body'];
$body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new \DOMDocument();
@$doc->loadHTML($body);
self::deletexnode($doc, 'style');
self::deletexnode($doc, 'script');
self::deletexnode($doc, 'option');
self::deletexnode($doc, 'h1');
self::deletexnode($doc, 'h2');
self::deletexnode($doc, 'h3');
self::deletexnode($doc, 'h4');
self::deletexnode($doc, 'h5');
self::deletexnode($doc, 'h6');
self::deletexnode($doc, 'ol');
self::deletexnode($doc, 'ul');
$xpath = new \DomXPath($doc);
//$list = $xpath->query("head/title");
$list = $xpath->query("//title");
foreach ($list as $node)
$siteinfo["title"] = html_entity_decode($node->nodeValue, ENT_QUOTES, "UTF-8");
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["name"])) {
case 'generator':
$siteinfo['generator'] = $attr['content'];
break;
case "fulltitle":
$siteinfo["title"] = $attr["content"];
break;
case "description":
$siteinfo["text"] = $attr["content"];
break;
case "dc.title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.description":
$siteinfo["text"] = $attr["content"];
break;
}
}
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
break;
case "og:title":
$siteinfo["title"] = $attr["content"];
break;
case "og:description":
$siteinfo["text"] = $attr["content"];
break;
}
}
if ($siteinfo["image"] == "") {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$src = self::completeurl($attr["src"], $url);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
$photodata[0] = 300;
}
if ($photodata[1] > 300) {
$photodata[0] = round($photodata[0] * (300 / $photodata[1]));
$photodata[1] = 300;
}
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
}
} else {
$src = self::completeurl($siteinfo["image"], $url);
unset($siteinfo["image"]);
$photodata = @getimagesize($src);
if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
if ($siteinfo["text"] == "") {
$text = "";
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
while (strpos($text, " "))
$text = trim(str_replace(" ", " ", $text));
$siteinfo["text"] = html_entity_decode(substr($text,0,350), ENT_QUOTES, "UTF-8").'...';
}
}
return($siteinfo);
}
private static function arr_add_hashes(&$item,$k) {
$item = '#' . $item;
}
}

View file

@ -1,121 +0,0 @@
<?php
namespace Zotlabs\Module;
class Lockview extends \Zotlabs\Web\Controller {
function get() {
$type = ((argc() > 1) ? argv(1) : 0);
if (is_numeric($type)) {
$item_id = intval($type);
$type='item';
} else {
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
}
if(! $item_id)
killme();
if (!in_array($type, array('item','photo','event', 'menu_item', 'chatroom')))
killme();
//we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
$id = 'mitem_id';
break;
case 'chatroom':
$id = 'cr_id';
break;
default:
$id = 'id';
break;
}
$r = q("SELECT * FROM %s WHERE $id = %d LIMIT 1",
dbesc($type),
intval($item_id)
);
if(! $r)
killme();
$item = $r[0];
//we have different naming in in menu_item table and chatroom table
switch($type) {
case 'menu_item':
$uid = $item['mitem_channel_id'];
break;
case 'chatroom':
$uid = $item['cr_uid'];
break;
default:
$uid = $item['uid'];
break;
}
if($uid != local_channel()) {
echo '<li>' . t('Remote privacy information not available.') . '</li>';
killme();
}
if(($item['item_private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
// specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
// next section.
echo '<li>' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</li>';
killme();
}
$allowed_users = expand_acl($item['allow_cid']);
$allowed_groups = expand_acl($item['allow_gid']);
$deny_users = expand_acl($item['deny_cid']);
$deny_groups = expand_acl($item['deny_gid']);
$o = '<li>' . t('Visible to:') . '</li>';
$l = array();
stringify_array_elms($allowed_groups,true);
stringify_array_elms($allowed_users,true);
stringify_array_elms($deny_groups,true);
stringify_array_elms($deny_users,true);
if(count($allowed_groups)) {
$r = q("SELECT gname FROM `groups` WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b>' . $rr['gname'] . '</b></li>';
}
if(count($allowed_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li>' . $rr['xchan_name'] . '</li>';
}
if(count($deny_groups)) {
$r = q("SELECT gname FROM `groups` WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b><strike>' . $rr['gname'] . '</strike></b></li>';
}
if(count($deny_users)) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><strike>' . $rr['xchan_name'] . '</strike></li>';
}
echo $o . implode($l);
killme();
}
}

View file

@ -1,132 +0,0 @@
<?php
namespace Zotlabs\Module; /** @file */
class Locs extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
$channel = \App::get_channel();
if($_REQUEST['primary']) {
$hubloc_id = intval($_REQUEST['primary']);
if($hubloc_id) {
$r = q("select hubloc_id from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' ",
dbesc($channel['channel_hash'])
);
$r = q("update hubloc set hubloc_primary = 1 where hubloc_id = %d and hubloc_hash = '%s'",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
return;
}
}
if($_REQUEST['drop']) {
$hubloc_id = intval($_REQUEST['drop']);
if($hubloc_id) {
$r = q("select * from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1",
intval($hubloc_id),
dbesc(z_root()),
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('Location not found.') . EOL);
return;
}
if(intval($r[0]['hubloc_primary'])) {
$x = q("select hubloc_id from hubloc where hubloc_primary = 1 and hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
if(! $x) {
notice( t('Location lookup failed.'));
return;
}
if(count($x) == 1) {
notice( t('Please select another location to become primary before removing the primary location.') . EOL);
return;
}
}
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_id = %d and hubloc_hash = '%s'",
intval($hubloc_id),
dbesc($channel['channel_hash'])
);
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
return;
}
}
}
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
$channel = \App::get_channel();
if($_REQUEST['sync']) {
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
info( t('Syncing locations') . EOL);
goaway(z_root() . '/locs');
}
$r = q("select * from hubloc where hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
if(! $r) {
notice( t('No locations found.') . EOL);
return;
}
for($x = 0; $x < count($r); $x ++) {
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
}
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
'$header' => t('Manage Channel Locations'),
'$loc' => t('Location'),
'$addr' => t('Address'),
'$mkprm' => t('Primary'),
'$drop' => t('Drop'),
'$submit' => t('Submit'),
'$sync' => t('Sync Now'),
'$sync_text' => t('Please wait several minutes between consecutive operations.'),
'$drop_text' => t('When possible, drop a location by logging into that website/hub and removing your channel.'),
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
'$hubs' => $r
));
return $o;
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Zotlabs\Module;
class Login extends \Zotlabs\Web\Controller {
function get() {
if(local_channel())
goaway(z_root());
return login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? false : true);
}
}

View file

@ -1,138 +0,0 @@
<?php
namespace Zotlabs\Module;
class Lostpass extends \Zotlabs\Web\Controller {
function post() {
$loginame = notags(trim($_POST['login-name']));
if(! $loginame)
goaway(z_root());
$r = q("SELECT * FROM account WHERE account_email = '%s' LIMIT 1",
dbesc($loginame)
);
if(! $r) {
notice( t('No valid account found.') . EOL);
goaway(z_root());
}
$aid = $r[0]['account_id'];
$email = $r[0]['account_email'];
$hash = random_string();
$r = q("UPDATE account SET account_reset = '%s' WHERE account_id = %d",
dbesc($hash),
intval($aid)
);
if($r)
info( t('Password reset request issued. Check your email.') . EOL);
$email_tpl = get_intltext_template("lostpass_eml.tpl");
$message = replace_macros($email_tpl, array(
'$sitename' => get_config('system','sitename'),
'$siteurl' => z_root(),
'$username' => sprintf( t('Site Member (%s)'), $email),
'$email' => $email,
'$reset_link' => z_root() . '/lostpass?verify=' . $hash
));
$subject = email_header_encode(sprintf( t('Password reset requested at %s'),get_config('system','sitename')), 'UTF-8');
$res = mail($email, $subject ,
$message,
'From: Administrator@' . $_SERVER['SERVER_NAME'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
goaway(z_root());
}
function get() {
if(x($_GET,'verify')) {
$verify = $_GET['verify'];
$r = q("SELECT * FROM account WHERE account_reset = '%s' LIMIT 1",
dbesc($verify)
);
if(! $r) {
notice( t("Request could not be verified. (You may have previously submitted it.) Password reset failed.") . EOL);
goaway(z_root());
return;
}
$aid = $r[0]['account_id'];
$email = $r[0]['account_email'];
$new_password = autoname(6) . mt_rand(100,9999);
$salt = random_string(32);
$password_encoded = hash('whirlpool', $salt . $new_password);
$r = q("UPDATE account SET account_salt = '%s', account_password = '%s', account_reset = '', account_flags = (account_flags & ~%d) where account_id = %d",
dbesc($salt),
dbesc($password_encoded),
intval(ACCOUNT_UNVERIFIED),
intval($aid)
);
if($r) {
$tpl = get_markup_template('pwdreset.tpl');
$o .= replace_macros($tpl,array(
'$lbl1' => t('Password Reset'),
'$lbl2' => t('Your password has been reset as requested.'),
'$lbl3' => t('Your new password is'),
'$lbl4' => t('Save or copy your new password - and then'),
'$lbl5' => '<a href="' . z_root() . '/login">' . t('click here to login') . '</a>.',
'$lbl6' => t('Your password may be changed from the <em>Settings</em> page after successful login.'),
'$newpass' => $new_password,
'$baseurl' => z_root()
));
info("Your password has been reset." . EOL);
$email_tpl = get_intltext_template("passchanged_eml.tpl");
$message = replace_macros($email_tpl, array(
'$sitename' => \App::$config['sitename'],
'$siteurl' => z_root(),
'$username' => sprintf( t('Site Member (%s)'), $email),
'$email' => $email,
'$new_password' => $new_password,
'$uid' => $newuid ));
$subject = email_header_encode( sprintf( t('Your password has changed at %s'), get_config('system','sitename')), 'UTF-8');
$res = mail($email,$subject,$message,
'From: ' . 'Administrator@' . $_SERVER['SERVER_NAME'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
return $o;
}
}
else {
$tpl = get_markup_template('lostpass.tpl');
$o .= replace_macros($tpl,array(
'$title' => t('Forgot your Password?'),
'$desc' => t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'),
'$name' => t('Email Address'),
'$submit' => t('Reset')
));
return $o;
}
}
}

View file

@ -1,171 +0,0 @@
<?php
namespace Zotlabs\Module;
@require_once('include/zot.php');
class Magic extends \Zotlabs\Web\Controller {
function init() {
$ret = array('success' => false, 'url' => '', 'message' => '');
logger('mod_magic: invoked', LOGGER_DEBUG);
logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA);
$addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : '');
$dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
$test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0);
$rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
$delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : '');
$parsed = parse_url($dest);
if(! $parsed) {
if($test) {
$ret['message'] .= 'could not parse ' . $dest . EOL;
return($ret);
}
goaway($dest);
}
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
if(! $x) {
/*
* We have no records for, or prior communications with this hub.
* If an address was supplied, let's finger them to create a hub record.
* Otherwise we'll use the special address '[system]' which will return
* either a system channel or the first available normal channel. We don't
* really care about what channel is returned - we need the hub information
* from that response so that we can create signed auth packets destined
* for that hub.
*
*/
$j = \Zotlabs\Zot\Finger::run((($addr) ? $addr : '[system]@' . $parsed['host']),null);
if($j['success']) {
import_xchan($j);
// Now try again
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
}
}
if(! $x) {
if($rev)
goaway($dest);
else {
logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true));
if($test) {
$ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL;
return $ret;
}
notice( t('Hub not found.') . EOL);
return;
}
}
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
// By default, we'll proceed without asking.
$arr = array(
'channel_id' => local_channel(),
'xchan' => $x[0],
'destination' => $dest,
'proceed' => true
);
call_hooks('magic_auth',$arr);
$dest = $arr['destination'];
if(! $arr['proceed']) {
if($test) {
$ret['message'] .= 'cancelled by plugin.' . EOL;
return $ret;
}
goaway($dest);
}
if((get_observer_hash()) && ($x[0]['hubloc_url'] === z_root())) {
// We are already authenticated on this site and a registered observer.
// Just redirect.
if($test) {
$ret['success'] = true;
$ret['message'] .= 'Local site - you are already authenticated.' . EOL;
return $ret;
}
$delegation_success = false;
if($delegate) {
$r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1",
dbesc($delegate)
);
if($r && intval($r[0]['channel_id'])) {
$allowed = perm_is_allowed($r[0]['channel_id'],get_observer_hash(),'delegate');
if($allowed) {
$_SESSION['delegate_channel'] = $r[0]['channel_id'];
$_SESSION['delegate'] = get_observer_hash();
$_SESSION['account_id'] = intval($r[0]['channel_account_id']);
change_channel($r[0]['channel_id']);
$delegation_success = true;
}
}
}
// FIXME: check and honour local delegation
goaway($dest);
}
if(local_channel()) {
$channel = \App::get_channel();
$token = random_string();
$token_sig = base64url_encode(rsa_sign($token,$channel['channel_prvkey']));
$channel['token'] = $token;
$channel['token_sig'] = $token_sig;
\Zotlabs\Zot\Verify::create('auth',$channel['channel_id'],$token,$x[0]['hubloc_url']);
$target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode($channel['channel_address'] . '@' . \App::get_hostname())
. '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION;
if($delegate)
$target_url .= '&delegate=' . urlencode($delegate);
logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG);
if($test) {
$ret['success'] = true;
$ret['url'] = $target_url;
$ret['message'] = 'token ' . $token . ' created for channel ' . $channel['channel_id'] . ' for url ' . $x[0]['hubloc_url'] . EOL;
return $ret;
}
goaway($target_url);
}
if($test) {
$ret['message'] = 'Not authenticated or invalid arguments to mod_magic' . EOL;
return $ret;
}
goaway($dest);
}
}

Some files were not shown because too many files have changed in this diff Show more