Merge branch '2.4RC'

This commit is contained in:
Mario Vavti 2017-05-31 09:56:35 +02:00
commit 47d55694a4
2860 changed files with 126970 additions and 86784 deletions

5
.gitignore vendored
View File

@ -44,7 +44,8 @@ doc/html/
.zotshrc
# external repositories for themes/addons
extend/
# files generated by phpunit
tests/results/
## exclude IDE files
# config files and folders from Eclipse
@ -63,6 +64,8 @@ nbproject/
## composer
# locally installed composer binary
composer.phar
# allow composer.lock, as it is required to have a common state
!composer.lock
# vendor/ is managed by composer, no need to include in our repository
# requires new deployment and needs discussion first
#vendor/

View File

@ -1,44 +1,156 @@
#
# Travis-CI configuration file for Hubzilla
#
## configure things
#
# see http://about.travis-ci.org/docs/user/languages/php/ for more hints
language: php
# list any PHP version you want to test against
# use newer 'trusty' based distro, old one is 'precise'
dist: trusty
# use docker based containers
sudo: false
# Git branches whitelist to build on Travis CI
branches:
only:
- master
- dev
# whitelist our tags for release deployments e.g. 2.2
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
# Install additional software
addons:
# Install dependencies for generating API documentation with doxygen
apt:
packages:
- doxygen
- doxygen-latex
- graphviz
- ttf-liberation
# enable and start databases on a per job basis
#services:
# - mariadb
# - postgresql
# any PHP version we want to test against, current stable phpunit requires PHP >= 7.0
php:
# using major version aliases
- '7.0'
- '7.1'
# HHVM does not fulfil PHPUnit platform requirements as being compatible with PHP7 yet
#- 'hhvm'
# 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
# list of environments to test
env:
global:
# used for doxygen deployment script
- DOXYFILE: $TRAVIS_BUILD_DIR/util/Doxyfile
# Uncomment if a newer/specific version of Doxygen should be used
#- DOXY_VER: 1.8.12
# Code Coverage is slow, no need to have it in every build
- PHPUCOV: "--no-coverage"
# use matrix only for PHP and MySQL, all other combinations added through includes
matrix:
# trusty default MySQL 5.6
- DB=mysql MYSQL_VERSION=5.6
# 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 configuration details
matrix:
fast_finish: true
# Additional check combinations
include:
# PHP7.1, mariadb 10.1
- php: '7.1'
env: DB=mariadb MARIADB_VERSION=10.1 CODECOV=1
# use mariadb instead of MySQL
addons:
mariadb: '10.1'
# PHP7.1, PostgreSQL 9.6
- php: '7.1'
env: DB=pgsql POSTGRESQL_VERSION=9.6
# Use newer postgres than 9.2 default
addons:
postgresql: '9.6'
services:
- postgresql
# PHP7.1, old precise distribution with MySQL 5.5
- php: '7.1'
env: DB=mysql MYSQL_VERSION=5.5
dist: precise
services:
- mysql
# Excludes from default matrix combinations
# exclude:
# - php: hhvm
# env: DB=pgsql # PDO driver for pgsql is unsupported by HHVM (3rd party install for support)
allow_failures:
- php: hhvm
# cache composer downloads between runs
cache:
directories:
- $HOME/.composer/cache
#- $HOME/doxygen/doxygen-$DOXY_VER/bin
#
## execute things
#
before_install:
- travis_retry composer self-update
# Install composer dev libs
install:
- travis_retry composer install --optimize-autoloader --no-progress
# 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
install:
- composer require phpunit/phpunit
before_script:
# Use code coverage config for phpunit
- if [[ ! -z $CODECOV ]]; then export PHPUCOV=""; fi
# Some preparation tasks of environment
- ./tests/travis/prepare.sh
# DB specific prepare scripts
- if [[ "$DB" == "mysql" ]]; then ./tests/travis/prepare_mysql.sh; fi
- if [[ "$DB" == "mariadb" ]]; then ./tests/travis/prepare_mysql.sh; fi
- if [[ "$DB" == "pgsql" ]]; then ./tests/travis/prepare_pgsql.sh; fi
# omitting "script:" will default to phpunit
# use the $DB env variable to determine the phpunit.xml to use
script: vendor/bin/phpunit tests/unit/
script: ./vendor/bin/phpunit $PHPUCOV -c tests/phpunit-$DB.xml
after_success:
# Generate API documentation and deploy it to gh-pages
- ./tests/travis/gen_apidocs.sh
#after_failure:
# Deploying release and API documentation to GitHub
#before_deploy:
deploy:
- provider: pages
skip_cleanup: true
local_dir: $TRAVIS_BUILD_DIR/doc/html
github_token: $GH_TOKEN
on:
repo: redmatrix/hubzilla
branch: master
condition: '(-n "$GH_TOKEN") && ("$TRAVIS_JOB_NUMBER" == "${TRAVIS_BUILD_NUMBER}.1")'
# add API documentation to release, could also be used to provide full packages if we want to drop vendor from our repo
- provider: releases
skip_cleanup: true
api_key: $GH_TOKEN
file: 'doc/hubzilla-api-documentation.zip'
on:
repo: redmatrix/hubzilla
tags: true
condition: '(-n "$GH_TOKEN") && ("$TRAVIS_JOB_NUMBER" == "${TRAVIS_BUILD_NUMBER}.1")'
#after_deploy:
#after_script:
# configure notifications (email, IRC, campfire etc)
notifications:
#notifications:
# irc: "irc.freenode.org#yourfavouriteroomfortravis"
# a plugin/script to post to a hubzilla channel would be neat here

View File

@ -1,5 +1,82 @@
Hubzilla 2.4 (2017-05-31)
- Silence php warning during install
- Implemented switch statement logic in Comanche layout parser
- Don't allow html in plugin comment blocks
- Handle Mastodon urls in markdown/bbcode conversion
- Get rid of edit activities
- Collapse sysapps if viewing a remote channel
- Various Doxygen fixes
- Update SimplePie library to version 1.5
- Add check for PHP zip extension during install
- Add unit tests for AccessList class
- Authenticate onepoll so we can receive private posts/comments in zotfeed
- Various postgres fixes
- Some work on preparing clientside e2ee
- Allow to set a default channel for the rare case where a default channel is not selected but channels actually exist
- Support reverse magic-auth in oembed requests
- Improved handling of Mastodon feeds
- When template "none" is used in a webpage layout, then the contents of the page should be the sole output, with no other code before or after the page element content
- If there is no site record, site_dead won't be 0, in a left join it will in fact be null. As long as it isn't 1, we should attempt delivery
- Order wiki pages by creation date
- Backend infrastructure for channel protection password; which will be used to optionally encrypt export files and resolve channel/identity ownership/hijacking disputes
- Don't allow any null fields in notify creation
- Webfinger cleanup
- Envelope privacy
- We do not parse the body in discover_by_url(), so no need to preserve iframes in SimplePie
- Correct the mastodon "boost" (aka 'share') author attribution by checking for share activities and pulling the original author info from the activity:object
- Only log zot_refresh content if json decode was successful
- Revisit the import_author_zot algorithm yet again. There was one bug that we weren't returning necessary information in the first SQL query - and performance/loading problem if one tries to refresh a dead site
- Import_author_xchan - since we rarely refresh zot-info for non-connections, force a cache reload once a week to catch things like profile photo updates and location changes
- Create site_store_lowlevel() to initialise data structures for the site table
- Change hook for perm_is_allowed while retaining backwards compatibility
- import_author_zot() - check for both hubloc and xchan entries. This should catch and repair entries which were subject to transient storage failures
- Import authors from any unrecognised network as network 'unknown'
- Crypto update - default is now aes-256-ctr
- Get rid of get_app()
- Add 'author_is_pmable()' function with plugin hooks to control whether or not to display a 'send mail' link in the thread author menu
- Provide platform specific install script
- Allow for project specific DB updates
- Get rid of davguest
- Move db_upgrade to zlib
- Add CSRF protection for import and import_items
- Add some documentation for import functions
- Do not allow creating two wikis with the same name
- Update textcomplete library to version 1.8.0
- Create channel_store_lowlevel()
- Allow setting the system email name/address/reply
- Use the same host macro for sender address as for reply_to address
- Use the relevant attach directory/path for photo albums instead of an album basename which may not be unique. Created an 'ellipsify()' function to shorten long names and keep the beginning and end intact
- Simplify the message signing spaghetti
- Class MarkdownSoap to safely store markdown by purifying and preserving (escaped) what may be unsafe code in codeblocks. The stored item needs to be unescaped just prior to calling the markdown-to-html processor
- Remove the unimplemented upload limit site settings from UI
- Cleanup code_allowed
- Move widgets to standalone classes
- Upgrade redbasic to bootstrap 4
- Updated HTML Purifier from 4.6.0 to 4.9.2 with better PHP7 compatibility
- Remove redundant and non-functional/broken check for successfully cloned channel record which was left over from an earlier method of creating the table; which was deprecated a few months back
- Update bshaffer/oauth2-server-php library
- Add unit test for purify_html()
Bugfixes
- Fix website export tool creating invalid zip file - issue #790
- Fix files not synced correctly - issue #769
- Fix empty ACL should not result in no ACL when uploading a file
- Fix cover photo was unintentionally disabled when block_public in effect
- Fix markdown autolinks - issue 752
- Fix connectDefaultShare generated js function, though it isn't obvious if we still use it
- Fix a couple more instances where we were still calling mail() directly for site critical messages
- Fix when clicking a notification to view a private mail message, actually view that message instead of the most recent
- Fix group by item query
Plugins/Addon
- smileybutton: do not load emojis
- pubsubhubbub: fixes associated with recent compatibility feed mods
- gnusoc: mastodon follow_activity compatibility issues
- gnusoc: add profile photo to feed meta
- gnusoc: add salmon link information to the public feed when GNU-Social is enabled
- chess: fix bugs when deleting games
Hubzilla 2.2 (2017-03-08)
- Don't collapse long nsfw content if nsfw plugin is already collapsing it
- Provide version compatibility check for themes (minversion, maxversion)
- Use chanlink_hash() instead of chanlink_url() where appropriate
- Use head_add_link() for feed discovery

View File

@ -2,21 +2,55 @@
namespace Zotlabs\Access;
/**
* @brief AccessList class.
*
* A class to hold an AccessList object with allowed and denied contacts and
* groups.
*/
class AccessList {
/**
* @brief Allow contacts
* @var string
*/
private $allow_cid;
/**
* @brief Allow groups
* @var string
*/
private $allow_gid;
/**
* @brief Deny contacts
* @var string
*/
private $deny_cid;
/**
* @brief Deny groups
* @var string
*/
private $deny_gid;
/**
* @brief Indicates if we are using the default constructor values or
* values that have been set explicitly.
* @var boolean
*/
private $explicit;
/* indicates if we are using the default constructor values or values that have been set explicitly. */
private $explicit;
/**
* @brief Constructor for AccessList class.
*
* @note The array to pass to the constructor is different from the array
* that you provide to the set() or set_from_array() functions.
*
* @param array $channel A channel array, where these entries are evaluated:
* * \e string \b channel_allow_cid => string of allowed cids
* * \e string \b channel_allow_gid => string of allowed gids
* * \e string \b channel_deny_cid => string of denied cids
* * \e string \b channel_deny_gid => string of denied gids
*/
function __construct($channel) {
if($channel) {
if($channel) {
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
@ -32,61 +66,95 @@ class AccessList {
$this->explicit = false;
}
/**
* @brief Get if we are using the default constructor values
* or values that have been set explicitly.
*
* @return boolean
*/
function get_explicit() {
return $this->explicit;
}
/**
* Set AccessList from strings such as those in already
* existing stored data items
* @brief Set access list from strings such as those in already
* existing stored data items.
*
* @note The array to pass to this set function is different from the array
* that you provide to the constructor or set_from_array().
*
* @param array $arr
* * \e string \b allow_cid => string of allowed cids
* * \e string \b allow_gid => string of allowed gids
* * \e string \b deny_cid => string of denied cids
* * \e string \b deny_gid => string of denied gids
* @param boolean $explicit (optional) default true
*/
function set($arr,$explicit = true) {
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;
$this->explicit = $explicit;
}
/**
* return an array consisting of the current
* access list components where the elements
* are directly storable.
* @brief Return an array consisting of the current access list components
* where the elements are directly storable.
*
* @return Associative array with:
* * \e string \b allow_cid => string of allowed cids
* * \e string \b allow_gid => string of allowed gids
* * \e string \b deny_cid => string of denied cids
* * \e string \b deny_gid => string of denied gids
*/
function get() {
return array(
return [
'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']));
* @brief Set access list components 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.
*
* @note The array to pass to this set function is different from the array
* that you provide to the constructor or set().
*
* @param array $arr An associative array with:
* * \e array|string \b contact_allow => array with cids or comma-seperated string
* * \e array|string \b group_allow => array with gids or comma-seperated string
* * \e array|string \b contact_deny => array with cids or comma-seperated string
* * \e array|string \b group_deny => array with gids or comma-seperated string
* @param boolean $explicit (optional) default true
*/
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']));
? $arr['group_allow'] : explode(',', $arr['group_allow']));
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
? $arr['contact_deny'] : explode(',',$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']));
? $arr['group_deny'] : explode(',', $arr['group_deny']));
$this->explicit = $explicit;
}
/**
* @brief Returns true if any access lists component is set.
*
* @return boolean Return true if any of allow_* deny_* values is set.
*/
function is_private() {
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
}
}

View File

@ -121,6 +121,9 @@ class Cron {
}
}
require_once('include/attach.php');
attach_upgrade();
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;

View File

@ -38,6 +38,13 @@ class Cron_daily {
db_utcnow(), db_quoteinterval('30 DAY')
);
// expire any unread notifications over a year old
q("delete from notify where seen = 0 and created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('1 YEAR')
);
//update statistics in config
require_once('include/statistics_fns.php');
update_channels_total_stat();

View File

@ -5,6 +5,11 @@ namespace Zotlabs\Daemon;
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once('include/conversation.php');
require_once('include/zot.php');
require_once('include/items.php');
require_once('include/bbcode.php');
/*
* This file was at one time responsible for doing all deliveries, but this caused
@ -68,13 +73,6 @@ require_once('include/conversation.php');
*/
require_once('include/zot.php');
require_once('include/queue_fn.php');
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/channel.php');
class Notifier {
@ -98,16 +96,6 @@ class Notifier {
$deliveries = array();
$dead_hubs = array();
$dh = q("select site_url from site where site_dead = 1");
if($dh) {
foreach($dh as $dead) {
$dead_hubs[] = $dead['site_url'];
}
}
$request = false;
$mail = false;
$top_level = false;
@ -489,10 +477,10 @@ class Notifier {
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs.
// Let's reduce this to a set of hubs; checking that the site is not dead.
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . implode(',',$recipients) . ")
and hubloc_error = 0 and hubloc_deleted = 0"
and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) "
);
@ -506,23 +494,31 @@ class Notifier {
/**
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, since it may have been
* a re-install which has not yet been detected and pruned.
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
* since it may have been a re-install which has not yet been detected and pruned.
* For other networks which don't have or require sitekeys, we'll have to use the URL
*/
$hublist = array(); // this provides an easily printable list for the logs
$dhubs = array(); // delivery hubs where we store our resulting unique array
$keys = array(); // array of keys to check uniquness for zot hubs
$urls = array(); // array of urls to check uniqueness of hubs from other networks
$hublist = []; // this provides an easily printable list for the logs
$dhubs = []; // delivery hubs where we store our resulting unique array
$keys = []; // array of keys to check uniquness for zot hubs
$urls = []; // array of urls to check uniqueness of hubs from other networks
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
foreach($hubs as $hub) {
if(in_array($hub['hubloc_url'],$dead_hubs)) {
logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO);
continue;
if($env_recips) {
foreach($env_recips as $er) {
if($hub['hubloc_hash'] === $er['hash']) {
if(! array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = [];
}
$hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er;
}
}
}
if($hub['hubloc_network'] == 'zot') {
if(! in_array($hub['hubloc_sitekey'],$keys)) {
@ -603,7 +599,8 @@ class Notifier {
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
}
elseif($packet_type === 'request') {
$packet = zot_build_packet($channel,$packet_type,$env_recips,$hub['hubloc_sitekey'],$hub['site_crypto'],
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
$hash, array('message_id' => $request_message_id)
);
}
@ -618,7 +615,8 @@ class Notifier {
));
}
else {
$packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel,'notify',$env,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
queue_insert(array(
'hash' => $hash,
'account_id' => $target_item['aid'],

View File

@ -118,13 +118,29 @@ class Onepoll {
if($fetch_feed) {
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
$feedurl .= '?f=&mindate=' . urlencode($last_update);
if(strpos($contact['xchan_connurl'],z_root()) === 0) {
// local channel - save a network fetch
$c = channelx_by_hash($contact['xchan_hash']);
if($c) {
$x = [
'success' => true,
'body' => json_encode( [
'success' => true,
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ])
])
];
}
}
else {
// remote fetch
$x = z_fetch_url($feedurl);
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname();
$recurse = 0;
$x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]);
}
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
}
if(($x) && ($x['success'])) {

View File

@ -34,7 +34,7 @@ class Apps {
if($files) {
foreach($files as $f) {
$path = explode('/',$f);
$plugin = $path[1];
$plugin = trim($path[1]);
if(plugin_is_installed($plugin)) {
$x = self::parse_app_description($f,$translate);
if($x) {
@ -219,7 +219,7 @@ class Apps {
'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'),
'Grid' => t('Grid'),
'Grid' => t('Activity'),
'Settings' => t('Settings'),
'Files' => t('Files'),
'Webpages' => t('Webpages'),
@ -245,9 +245,19 @@ class Apps {
'Profile Photo' => t('Profile Photo')
);
if(array_key_exists($arr['name'],$apps)) {
$arr['name'] = $apps[$arr['name']];
if(array_key_exists('name',$arr)) {
if(array_key_exists($arr['name'],$apps)) {
$arr['name'] = $apps[$arr['name']];
}
}
else {
for($x = 0; $x < count($arr); $x++) {
if(array_key_exists($arr[$x]['name'],$apps)) {
$arr[$x]['name'] = $apps[$arr[$x]['name']];
}
}
}
}
@ -275,7 +285,7 @@ class Apps {
self::translate_system_apps($papp);
if(($papp['plugin']) && (! plugin_is_installed($papp['plugin'])))
if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
return '';
$papp['papp'] = self::papp_encode($papp);
@ -565,7 +575,7 @@ class Apps {
$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_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : '');
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : '');
$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);
@ -643,7 +653,7 @@ class Apps {
$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_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : '');
$darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : '');
$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);
@ -753,7 +763,7 @@ class Apps {
$ret['system'] = $app['app_system'];
if($app['app_plugin'])
$ret['plugin'] = $app['app_plugin'];
$ret['plugin'] = trim($app['app_plugin']);
if($app['app_deleted'])
$ret['deleted'] = $app['app_deleted'];

119
Zotlabs/Lib/DB_Upgrade.php Normal file
View File

@ -0,0 +1,119 @@
<?php
namespace Zotlabs\Lib;
class DB_Upgrade {
public $config_name = '';
public $func_prefix = '';
function __construct($db_revision) {
$update_file = 'install/' . PLATFORM_NAME . '/update.php';
if(! file_exists($update_file)) {
$update_file = 'install/update.php';
$this->config_name = 'db_version';
$this->func_prefix = 'update_r';
}
else {
$this->config_name = PLATFORM_NAME . '_db_version';
$this->func_prefix = PLATFORM_NAME . '_update_';
}
$build = get_config('system', $this->config_name, 0);
if(! intval($build))
$build = set_config('system', $this->config_name, $db_revision);
if($build == $db_revision) {
// Nothing to be done.
return;
}
else {
$stored = intval($build);
if(! $stored) {
logger('Critical: check_config unable to determine database schema version');
return;
}
$current = intval($db_revision);
if(($stored < $current) && file_exists($update_file)) {
Config::Load('database');
// We're reporting a different version than what is currently installed.
// Run any existing update scripts to bring the database up to current.
require_once($update_file);
// make sure that boot.php and update.php are the same release, we might be
// updating from git right this very second and the correct version of the update.php
// file may not be here yet. This can happen on a very busy site.
if($db_revision == UPDATE_VERSION) {
for($x = $stored; $x < $current; $x ++) {
$func = $this->func_prefix . $x;
if(function_exists($func)) {
// There could be a lot of processes running or about to run.
// We want exactly one process to run the update command.
// So store the fact that we're taking responsibility
// after first checking to see if somebody else already has.
// If the update fails or times-out completely you may need to
// delete the config entry to try again.
if(get_config('database', $func))
break;
set_config('database',$func, '1');
// call the specific update
$retval = $func();
if($retval) {
// Prevent sending hundreds of thousands of emails by creating
// a lockfile.
$lockfile = 'store/[data]/mailsent';
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
return;
@unlink($lockfile);
//send the administrator an e-mail
file_put_contents($lockfile, $x);
$r = q("select account_language from account where account_email = '%s' limit 1",
dbesc(\App::$config['system']['admin_email'])
);
push_lang(($r) ? $r[0]['account_language'] : 'en');
z_mail(
[
'toEmail' => \App::$config['system']['admin_email'],
'messageSubject' => sprintf( t('Update Error at %s'), z_root()),
'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
[
'$sitename' => \App::$config['system']['sitename'],
'$siteurl' => z_root(),
'$update' => $x,
'$error' => sprintf( t('Update %s failed. See error logs.'), $x)
]
)
]
);
//try the logger
logger('CRITICAL: Update Failed: ' . $x);
pop_lang();
}
else {
set_config('database',$func, 'success');
}
}
}
set_config('system', $this->config_name, $db_revision);
}
}
}
}
}

View File

@ -67,7 +67,7 @@ class Enotify {
$sender_name = $product;
$hostname = \App::get_hostname();
if(strpos($hostname,':'))
$hostname = substr($hostname,0,strpos($hostname,':'));
$hostname = substr($hostname,0,strpos($hostname,':'));
// Do not translate 'noreply' as it must be a legal 7-bit email address
@ -77,7 +77,7 @@ class Enotify {
$sender_email = get_config('system','from_email');
if(! $sender_email)
$sender_email = 'Administrator' . '@' . \App::get_hostname();
$sender_email = 'Administrator' . '@' . $hostname;
$sender_name = get_config('system','from_email_name');
if(! $sender_name)
@ -495,13 +495,14 @@ class Enotify {
}
}
$r = q("insert into notify (hash,xname,url,photo,created,aid,uid,link,parent,seen,ntype,verb,otype)
values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
$r = q("insert into notify (hash,xname,url,photo,created,msg,aid,uid,link,parent,seen,ntype,verb,otype)
values('%s','%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
dbesc($datarray['hash']),
dbesc($datarray['xname']),
dbesc($datarray['url']),
dbesc($datarray['photo']),
dbesc($datarray['created']),
dbesc(''), // will fill this in below after the record is created
intval($datarray['aid']),
intval($datarray['uid']),
dbesc($datarray['link']),

View File

@ -0,0 +1,103 @@
<?php
namespace Zotlabs\Lib;
/**
* MarkdownSoap
* Purify Markdown for storage
* $x = new MarkdownSoap($string_to_be_cleansed);
* $text = $x->clean();
*
* What this does:
* 1. extracts code blocks and privately escapes them from processing
* 2. Run html purifier on the content
* 3. put back the code blocks
* 4. run htmlspecialchars on the entire content for safe storage
*
* At render time:
* $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text);
* $html = \Michelf\MarkdownExtra::DefaultTransform($markdown);
*/
class MarkdownSoap {
private $token;
private $str;
function __construct($s) {
$this->str = $s;
$this->token = random_string(20);
}
function clean() {
$x = $this->extract_code($this->str);
$x = $this->purify($x);
$x = $this->putback_code($x);
$x = $this->escape($x);
return $x;
}
function extract_code($s) {
$text = preg_replace_callback('{
(?:\n\n|\A\n?)
( # $1 = the code block -- one or more lines, starting with a space/tab
(?>
[ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
.*\n+
)+
)
((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
}xm',
[ $this , 'encode_code' ], $s);
return $text;
}
function encode_code($matches) {
return $this->token . ';' . base64_encode($matches[0]) . ';' ;
}
function decode_code($matches) {
return base64_decode($matches[1]);
}
function putback_code($s) {
$text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s);
return $text;
}
function purify($s) {
$s = $this->protect_autolinks($s);
$s = purify_html($s);
$s = $this->unprotect_autolinks($s);
return $s;
}
function protect_autolinks($s) {
$s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s);
return $s;
}
function unprotect_autolinks($s) {
return $s;
}
function escape($s) {
return htmlspecialchars($s,ENT_QUOTES);
}
static public function unescape($s) {
return htmlspecialchars_decode($s,ENT_QUOTES);
}
}

View File

@ -101,11 +101,11 @@ class NativeWiki {
static public function sync_a_wiki_item($uid,$id,$resource_id) {
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = %d )) ",
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
intval($uid),
intval($id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($resource_id)
dbesc($resource_id)
);
if($r) {
xchan_query($r);

View File

@ -21,12 +21,23 @@ class NativeWikiPage {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$sql_extra group by mid",
$sql_extra order by created asc",
dbesc($resource_id),
intval($channel_id)
);
if($r) {
$items = fetch_post_tags($r,true);
$x = [];
$y = [];
foreach($r as $rv) {
if(! in_array($rv['mid'],$x)) {
$y[] = $rv;
$x[] = $rv['mid'];
}
}
$items = fetch_post_tags($y,true);
foreach($items as $page_item) {
$title = get_iconfig($page_item['id'],'nwikipage','pagetitle',t('(No Title)'));
if(urldecode($title) !== 'Home') {
@ -156,7 +167,7 @@ class NativeWikiPage {
$content = $item['body'];
return [
'content' => json_encode($content),
'content' => $content,
'mimeType' => $w['mimeType'],
'message' => '',
'success' => true
@ -307,48 +318,22 @@ class NativeWikiPage {
return null;
}
static public function prepare_content($s) {
$text = preg_replace_callback('{
(?:\n\n|\A\n?)
( # $1 = the code block -- one or more lines, starting with a space/tab
(?>
[ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
.*\n+
)+
)
((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
}xm',
'self::nwiki_prepare_content_callback', $s);
return $text;
}
static public function nwiki_prepare_content_callback($matches) {
$codeblock = $matches[1];
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES, UTF8, false);
return "\n\n" . $codeblock ;
}
static public function save_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content',$arr)) ? purify_html(Zlib\NativeWikiPage::prepare_content($arr['content'])) : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0);
$revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0);
$w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return array('message' => t('Error reading wiki'), 'success' => false);
}
$mimetype = $w['mimeType'];
// fetch the most recently saved revision.
@ -367,6 +352,7 @@ class NativeWikiPage {
$item['author_xchan'] = $observer_hash;
$item['revision'] = (($arr['revision']) ? intval($arr['revision']) + 1 : intval($item['revision']) + 1);
$item['edited'] = datetime_convert();
$item['mimetype'] = $mimetype;
if($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
for($x = 0; $x < count($item['iconfig']); $x ++) {
@ -534,6 +520,29 @@ class NativeWikiPage {
}
return $s;
}
static public function render_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = self::page_history([
'channel_id' => \App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
return replace_macros(get_markup_template('nwiki_page_history.tpl'), array(
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
'$msg_label' => t('Message','wiki_history')
));
}
/**
* Replace the instances of the string [toc] with a list element that will be populated by

View File

@ -82,7 +82,8 @@ class ThreadItem {
$dropping = false;
$star = false;
$isstarred = "unstarred fa-star-o";
$indent = '';
$is_comment = false;
$is_item = false;
$osparkle = '';
$total_children = $this->count_descendants();
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
@ -183,7 +184,7 @@ class ThreadItem {
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
if (count($like_list) > MAX_LIKERS) {
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$like_list_part = '';
}
@ -195,7 +196,7 @@ class ThreadItem {
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
if (count($dislike_list) > MAX_LIKERS) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$dislike_list_part = '';
}
@ -232,7 +233,7 @@ class ThreadItem {
}
}
else {
$indent = 'comment';
$is_comment = true;
}
@ -276,13 +277,13 @@ class ThreadItem {
$keep_reports = intval(get_config('system','expire_delivery_reports'));
if($keep_reports === 0)
$keep_reports = 30;
$keep_reports = 10;
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
$dreport = t('Delivery Report');
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$indent .= ' shiny';
$is_new = true;
localize_item($item);
@ -337,7 +338,6 @@ class ThreadItem {
'profile_url' => $profile_link,
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
'item_photo_menu' => item_photo_menu($item),
'dreport' => $dreport,
'name' => $profile_name,
'thumb' => $profile_avatar,
@ -361,7 +361,8 @@ class ThreadItem {
'attend_title' => t('Attendance Options'),
'vote_label' => t('Vote'),
'vote_title' => t('Voting Options'),
'indent' => $indent,
'is_comment' => $is_comment,
'is_new' => $is_new,
'owner_url' => $this->get_owner_url(),
'owner_photo' => $this->get_owner_photo(),
'owner_name' => $this->get_owner_name(),
@ -407,7 +408,7 @@ class ThreadItem {
'showlike' => $showlike,
'showdislike' => $showdislike,
'comment' => $this->get_comment_box($indent),
'previewing' => ($conv->is_preview() ? ' preview ' : ''),
'previewing' => ($conv->is_preview() ? true : false ),
'wait' => t('Please wait'),
'submid' => str_replace(['+','='], ['',''], base64_encode(substr($item['mid'],0,32))),
'thread_level' => $thread_level

View File

@ -3,10 +3,14 @@
namespace Zotlabs\Module\Admin;
use \Zotlabs\Storage\GitRepo as GitRepo;
use \Michelf\MarkdownExtra;
class Plugins {
/**
* @brief
*
*/
function post() {
if(argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")) {
@ -15,16 +19,15 @@ class Plugins {
$func = argv(2) . '_plugin_admin_post';
$func($a);
}
goaway(z_root() . '/admin/plugins/' . argv(2) );
goaway(z_root() . '/admin/plugins/' . argv(2) );
}
elseif(argc() > 2) {
switch(argv(2)) {
case 'updaterepo':
if (array_key_exists('repoName', $_REQUEST)) {
$repoName = $_REQUEST['repoName'];
}
}
else {
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
}
@ -101,16 +104,15 @@ class Plugins {
logger('Repo directory not writable to web server: ' . $repoDir);
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
}
// TODO: remove directory and unlink /addon/files
/// @TODO remove directory and unlink /addon/files
if (rrmdir($repoDir)) {
json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
} else {
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
}
case 'installrepo':
require_once('library/markdown.php');
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
@ -170,9 +172,8 @@ class Plugins {
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
}
case 'addrepo':
require_once('library/markdown.php');
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
$repoURL = $_REQUEST['repoURL'];
$extendDir = 'store/[data]/git/sys/extend';
$addonDir = $extendDir . '/addon';
@ -225,7 +226,7 @@ class Plugins {
$repo['readme'] = $repo['manifest'] = null;
foreach ($git->git->tree('master') as $object) {
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
$repo['readme'] = Markdown($git->git->cat->blob($object['hash']));
$repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
} else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
$repo['manifest'] = $git->git->cat->blob($object['hash']);
}
@ -241,7 +242,11 @@ class Plugins {
}
}
/**
* @brief Plugins admin page.
*
* @return string with parsed HTML
*/
function get() {
/*
@ -254,13 +259,13 @@ class Plugins {
notice( t("Item not found.") );
return '';
}
$enabled = in_array($plugin,\App::$plugins);
$info = get_plugin_info($plugin);
$x = check_plugin_versions($info);
// disable plugins which are installed but incompatible versions
if($enabled && ! $x) {
$enabled = false;
$idz = array_search($plugin, \App::$plugins);
@ -271,7 +276,7 @@ class Plugins {
}
}
$info['disabled'] = 1-intval($x);
if (x($_GET,"a") && $_GET['a']=="t"){
check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't');
$pinstalled = false;
@ -297,9 +302,9 @@ class Plugins {
}
goaway(z_root() . '/admin/plugins' );
}
// display plugin details
require_once('library/markdown.php');
if (in_array($plugin, \App::$plugins)){
$status = 'on';
$action = t('Disable');
@ -307,21 +312,21 @@ class Plugins {
$status = 'off';
$action = t('Enable');
}
$readme = null;
if (is_file("addon/$plugin/README.md")){
$readme = file_get_contents("addon/$plugin/README.md");
$readme = Markdown($readme);
$readme = MarkdownExtra::defaultTransform($readme);
} else if (is_file("addon/$plugin/README")){
$readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
}
$admin_form = '';
$r = q("select * from addon where plugin_admin = 1 and aname = '%s' limit 1",
dbesc($plugin)
);
if($r) {
@require_once("addon/$plugin/$plugin.php");
if(function_exists($plugin.'_plugin_admin')) {
@ -329,8 +334,8 @@ class Plugins {
$func($a, $admin_form);
}
}
$t = get_markup_template('admin_plugins_details.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@ -338,7 +343,7 @@ class Plugins {
'$toggle' => t('Toggle'),
'$settings' => t('Settings'),
'$baseurl' => z_root(),
'$plugin' => $plugin,
'$status' => $status,
'$action' => $action,
@ -351,17 +356,17 @@ class Plugins {
'$str_serverroles' => t('Compatible Server Roles: '),
'$str_requires' => t('Requires: '),
'$disabled' => t('Disabled - version incompatibility'),
'$admin_form' => $admin_form,
'$function' => 'plugins',
'$screenshot' => '',
'$readme' => $readme,
'$form_security_token' => get_form_security_token('admin_plugins'),
));
}
/*
* List plugins
*/
@ -374,9 +379,9 @@ class Plugins {
$info = get_plugin_info($id);
$enabled = in_array($id,\App::$plugins);
$x = check_plugin_versions($info);
// disable plugins which are installed but incompatible versions
if($enabled && ! $x) {
$enabled = false;
$idz = array_search($id, \App::$plugins);
@ -387,19 +392,19 @@ class Plugins {
}
}
$info['disabled'] = 1-intval($x);
$plugins[] = array( $id, (($enabled)?"on":"off") , $info);
}
}
}
usort($plugins,'self::plugin_sort');
$allowManageRepos = false;
if(is_writable('extend/addon') && is_writable('store/[data]')) {
$allowManageRepos = true;
}
}
$admin_plugins_add_repo_form= replace_macros(
get_markup_template('admin_plugins_addrepo.tpl'), array(
'$post' => 'admin/plugins/addrepo',
@ -418,14 +423,14 @@ class Plugins {
'$cancel' => t('Cancel')
)
);
$reponames = $this->listAddonRepos();
$addonrepos = [];
foreach($reponames as $repo) {
$addonrepos[] = array('name' => $repo, 'description' => '');
// TODO: Parse repo info to provide more information about repos
/// @TODO Parse repo info to provide more information about repos
}
$t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@ -471,5 +476,4 @@ class Plugins {
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
}
}

View File

@ -48,6 +48,10 @@ class Site {
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
$from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name());
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
@ -77,8 +81,15 @@ class Site {
set_config('system', 'enable_context_help', $enable_context_help);
set_config('system', 'verify_email', $verify_email);
set_config('system', 'default_expire_days', $default_expire_days);
set_config('system', 'reply_address', $reply_address);
set_config('system', 'from_email', $from_email);
set_config('system', 'from_email_name' , $from_email_name);
set_config('system', 'techlevel_lock', $techlevel_lock);
if(! is_null($techlevel))
set_config('system', 'techlevel', $techlevel);
@ -304,6 +315,10 @@ class Site {
'$login_on_homepage' => array('login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.")),
'$enable_context_help' => array('enable_context_help', t("Enable context help"),((intval($enable_context_help) === 1 || $enable_context_help === false) ? 1 : 0) , t("Display contextual help for the current page when the help button is pressed.")),
'$reply_address' => [ 'reply_address', t('Reply-to email address for system generated email.'), get_config('system','reply_address','noreply@' . \App::get_hostname()),'' ],
'$from_email' => [ 'from_email', t('Sender (From) email address for system generated email.'), get_config('system','from_email','Administrator@' . \App::get_hostname()),'' ],
'$from_email_name' => [ 'from_email_name', t('Name of email sender for system generated email.'), get_config('system','from_email_name',\Zotlabs\Lib\System::get_site_name()),'' ],
'$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),

View File

@ -2,38 +2,41 @@
namespace Zotlabs\Module\Admin;
use \Michelf\MarkdownExtra;
/**
* @brief Admin area theme settings.
*/
class Themes {
/**
* @brief
*
*/
function post() {
$theme = argv(2);
if (is_file("view/theme/$theme/php/config.php")){
require_once("view/theme/$theme/php/config.php");
// fixme add parent theme if derived
if (function_exists("theme_admin_post")){
/// @FIXME add parent theme if derived
if (function_exists('theme_admin_post')){
theme_admin_post($a);
}
}
info(t('Theme settings updated.'));
if(is_ajax())
if(is_ajax())
return;
goaway(z_root() . '/admin/themes/' . $theme );
}
/**
* @brief Themes admin page.
*
* @return string
* @return string with parsed HTML
*/
function get(){
$allowed_themes_str = get_config('system', 'allowed_themes');
$allowed_themes_raw = explode(',', $allowed_themes_str);
$allowed_themes = array();
@ -41,7 +44,7 @@ class Themes {
foreach($allowed_themes_raw as $x)
if(strlen(trim($x)))
$allowed_themes[] = trim($x);
$themes = array();
$files = glob('view/theme/*');
if($files) {
@ -53,56 +56,55 @@ class Themes {
$themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
}
}
if(! count($themes)) {
notice( t('No themes found.'));
return '';
}
/*
* Single theme
*/
if (\App::$argc == 3){
$theme = \App::$argv[2];
if(! is_dir("view/theme/$theme")){
notice( t("Item not found.") );
return '';
}
if (x($_GET,"a") && $_GET['a']=="t"){
check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
// Toggle theme status
$this->toggle_theme($themes, $theme, $result);
$s = $this->rebuild_theme_table($themes);
if($result)
info( sprintf('Theme %s enabled.', $theme));
else
info( sprintf('Theme %s disabled.', $theme));
set_config('system', 'allowed_themes', $s);
goaway(z_root() . '/admin/themes' );
}
// display theme details
require_once('library/markdown.php');
if ($this->theme_status($themes,$theme)) {
$status="on"; $action= t("Disable");
} else {
$status="off"; $action= t("Enable");
}
$readme=Null;
if (is_file("view/theme/$theme/README.md")){
$readme = file_get_contents("view/theme/$theme/README.md");
$readme = Markdown($readme);
$readme = MarkdownExtra::defaultTransform($readme);
} else if (is_file("view/theme/$theme/README")){
$readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
$readme = '<pre>'. file_get_contents("view/theme/$theme/README") .'</pre>';
}
$admin_form = '';
if (is_file("view/theme/$theme/php/config.php")){
require_once("view/theme/$theme/php/config.php");
@ -110,11 +112,11 @@ class Themes {
$admin_form = theme_admin($a);
}
}
$screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
if(! stristr($screenshot[0],$theme))
$screenshot = null;
$t = get_markup_template('admin_plugins_details.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@ -122,7 +124,7 @@ class Themes {
'$toggle' => t('Toggle'),
'$settings' => t('Settings'),
'$baseurl' => z_root(),
'$plugin' => $theme,
'$status' => $status,
'$action' => $action,
@ -133,22 +135,22 @@ class Themes {
'$str_maintainer' => t('Maintainer: '),
'$screenshot' => $screenshot,
'$readme' => $readme,
'$form_security_token' => get_form_security_token('admin_themes'),
));
}
/*
* List themes
*/
$xthemes = array();
if($themes) {
foreach($themes as $th) {
$xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
}
}
$t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@ -162,13 +164,14 @@ class Themes {
'$form_security_token' => get_form_security_token('admin_themes'),
));
}
/**
* @param array $themes
* @param string $th
* @param int $result
* @brief Toggle a theme.
*
* @param array &$themes
* @param[in] string $th
* @param[out] int &$result
*/
function toggle_theme(&$themes, $th, &$result) {
for($x = 0; $x < count($themes); $x ++) {
@ -184,7 +187,7 @@ class Themes {
}
}
}
/**
* @param array $themes
* @param string $th
@ -203,8 +206,7 @@ class Themes {
}
return 0;
}
/**
* @param array $themes
* @return string
@ -222,12 +224,5 @@ class Themes {
}
return $o;
}
}

View File

@ -68,7 +68,8 @@ class Bookmarks extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
$o = profile_tabs($a,true,$channel['channel_address']);
//$o = profile_tabs($a,true,$channel['channel_address']);
$o = '';
$o .= '<div class="generic-content-wrapper-styled">';

View File

@ -86,7 +86,8 @@ class Cal extends \Zotlabs\Web\Controller {
$o = '';
$tabs = profile_tabs($a, True, $channel['channel_address']);
//$tabs = profile_tabs($a, True, $channel['channel_address']);
$tabs = '';
$mode = 'view';
$y = 0;

View File

@ -121,7 +121,7 @@ class Channel extends \Zotlabs\Web\Controller {
$static = channel_manual_conv_update(\App::$profile['profile_uid']);
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
//$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
@ -321,6 +321,7 @@ class Channel extends \Zotlabs\Web\Controller {
'$static' => $static,
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$xchan' => '',
'$order' => '',
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',

View File

@ -210,7 +210,8 @@ class Chat extends \Zotlabs\Web\Controller {
require_once('include/conversation.php');
$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
//$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
$o = '';
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) {
notice( t('Feature disabled.') . EOL);

View File

@ -60,11 +60,9 @@ class Cloud extends \Zotlabs\Web\Controller {
$_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);

View File

@ -5,10 +5,6 @@ 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 {

View File

@ -11,9 +11,6 @@ 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');
require_once('include/photos.php');
@ -391,30 +388,22 @@ class Connedit extends \Zotlabs\Web\Controller {
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
$channel = \App::get_channel();
$my_perms = get_channel_default_perms(local_channel());
$role = get_pconfig(local_channel(),'system','permissions_role');
if($role) {
$x = \Zotlabs\Access\PermissionRoles::role_perms($role);
if($x['perms_connect'])
$my_perms = $x['perms_connect'];
}
$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";
}
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
$o .= "<script>function connectDefaultShare() {
\$('.abook-edit-me').each(function() {
if(! $(this).is(':disabled'))
$(this).prop('checked', false);
});\n\n";
foreach($connect_perms['perms'] as $p => $v) {
if($v) {
$o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
}
$o .= " }\n</script>\n";
}
$o .= " }\n</script>\n";
if(argc() == 3) {
@ -441,6 +430,34 @@ class Connedit extends \Zotlabs\Web\Controller {
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'fetchvc') {
$url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard';
$recurse = 0;
$x = z_fetch_url(zid($url),false,$recurse,['session' => true]);
if($x['success']) {
$h = new \Zotlabs\Web\HTTPHeaders($x['header']);
$fields = $h->fetch();
if($fields) {
foreach($fields as $y) {
if(array_key_exists('content-type',$y)) {
$type = explode(';',trim($y['content-type']));
if($type && $type[0] === 'text/vcard' && $x['body']) {
$vc = \Sabre\VObject\Reader::read($x['body']);
$vcard = $vc->serialize();
if($vcard) {
set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard);
$this->connedit_clone($a);
}
}
}
}
}
}
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'resetphoto') {
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
dbesc($orig_record[0]['xchan_hash'])
@ -582,6 +599,13 @@ class Connedit extends \Zotlabs\Web\Controller {
'sel' => '',
'title' => t('Fetch updated permissions'),
),
'rephoto' => array(
'label' => t('Refresh Photo'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto',
'sel' => '',
'title' => t('Fetch updated photo'),
),
'recent' => array(
'label' => t('Recent Activity'),
@ -631,6 +655,17 @@ class Connedit extends \Zotlabs\Web\Controller {
);
if($contact['xchan_network'] === 'zot') {
$tools['fetchvc'] = [
'label' => t('Fetch Vcard'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
'sel' => '',
'title' => t('Fetch electronic calling card for this connection')
];
}
$sections = [];
$sections['perms'] = [

View File

@ -23,19 +23,17 @@ require_once('include/channel.php');
class Cover_photo extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
profile_load($channel['channel_address']);
profile_load($channel['channel_address']);
}
/* @brief Evaluate posted values
/**
* @brief Evaluate posted values
*
* @param $a Current application
* @return void
*
*/
@ -130,8 +128,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$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 = [
'aid' => $aid,
'uid' => local_channel(),
'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'],
'album' => t('Cover Photos'),
'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path']
];
$p['imgscale'] = 7;
$p['photo_usage'] = PHOTO_COVER;
@ -195,11 +200,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$os_storage = false;
foreach($i as $ii) {
$smallest = intval($ii['imgscale']);
$smallest = intval($ii['imgscale']);
$os_storage = intval($ii['os_storage']);
$imagedata = $ii['content'];
$filetype = $ii['mimetype'];
$imagedata = $ii['content'];
$filetype = $ii['mimetype'];
}
}
@ -263,10 +267,10 @@ class Cover_photo extends \Zotlabs\Web\Controller {
}
/* @brief Generate content of profile-photo view
/**
* @brief Generate content of profile-photo view
*
* @param $a Current application
* @return void
* @return string
*
*/
@ -350,15 +354,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$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,
'$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>')
/// @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);
@ -370,14 +374,14 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$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.'),
'$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')
'$done' => t('Done Editing')
));
return $o;
}
@ -393,8 +397,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
*
*/
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$max_length = get_config('system','max_image_length');

View File

@ -4,7 +4,6 @@ namespace Zotlabs\Module;
require_once('include/socgraph.php');
require_once('include/dir_fns.php');
require_once('include/widgets.php');
require_once('include/bbcode.php');

View File

@ -165,6 +165,7 @@ class Display extends \Zotlabs\Web\Controller {
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$xchan' => '',
'$order' => '',
'$file' => '',
'$cats' => '',

View File

@ -98,6 +98,11 @@ class Editblock extends \Zotlabs\Web\Controller {
$mimetype = $itm[0]['mimetype'];
$content = $itm[0]['body'];
if($itm[0]['mimetype'] === 'text/markdown')
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
$rp = 'blocks/' . $channel['channel_address'];
$x = array(
@ -117,7 +122,7 @@ class Editblock extends \Zotlabs\Web\Controller {
'ptyp' => $itm[0]['type'],
'mimeselect' => true,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($itm[0]['body']),
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),

View File

@ -119,6 +119,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'disable_comments' => true,
'ptyp' => $itm[0]['obj_type'],
'body' => undo_post_tagging($itm[0]['body']),
'post_id' => $post_id,

View File

@ -31,7 +31,10 @@ class Editpost extends \Zotlabs\Web\Controller {
dbesc(get_observer_hash())
);
if(! count($itm)) {
// don't allow web editing of potentially binary content (item_obscured = 1)
// @FIXME how do we do it instead?
if((! $itm) || intval($itm[0]['item_obscured'])) {
notice( t('Item is not editable') . EOL);
return;
}
@ -44,14 +47,6 @@ class Editpost extends \Zotlabs\Web\Controller {
$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($itm[0]['title'],true),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
}
$category = '';
$catsenabled = ((feature_enabled($owner_uid,'categories')) ? 'categories' : '');

View File

@ -100,19 +100,14 @@ class Editwebpage extends \Zotlabs\Web\Controller {
intval($owner)
);
if(! $itm) {
// don't allow web editing of potentially binary content (item_obscured = 1)
// @FIXME how do we do it instead?
if((! $itm) || intval($itm[0]['item_obscured'])) {
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($itm[0]['title'],true),$key);
if($itm[0]['body'])
$itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key);
}
$item_id = q("select * from iconfig where cat = 'system' and k = 'WEBPAGE' and iid = %d limit 1",
intval($itm[0]['id'])
);
@ -129,6 +124,10 @@ class Editwebpage extends \Zotlabs\Web\Controller {
}
$layout = $itm[0]['layout_mid'];
$content = $itm[0]['body'];
if($itm[0]['mimetype'] === 'text/markdown')
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
$rp = 'webpages/' . $which;
@ -145,7 +144,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
'hide_location' => true,
'hide_voting' => true,
'ptyp' => $itm[0]['type'],
'body' => undo_post_tagging($itm[0]['body']),
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => ($is_owner) ? true : false,
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),

View File

@ -92,6 +92,7 @@ class Embedphotos extends \Zotlabs\Web\Controller {
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
*/
if($album) {
require_once('include/attach.php');
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
dbesc($album),
intval($owner_uid)

View File

@ -1,40 +1,41 @@
<?php
namespace Zotlabs\Module;
require_once('include/items.php');
class Feed extends \Zotlabs\Web\Controller {
function init() {
$params = array();
$params = [];
$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 = '';
$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']) : '');
$params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0);
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)))
if(observer_prohibited(true)) {
killme();
$channel = $r[0];
if(observer_prohibited(true))
}
$channel = channelx_by_nick(argv(1));
if(! $channel) {
killme();
}
logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
echo get_public_feed($channel,$params);
@ -43,6 +44,4 @@ class Feed extends \Zotlabs\Web\Controller {
}
}

View File

@ -28,11 +28,12 @@ class File_upload extends \Zotlabs\Web\Controller {
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
if($_REQUEST['filename']) {
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
$r = attach_mkdir($channel,get_observer_hash(),$_REQUEST);
}
else {

View File

@ -49,8 +49,10 @@ class Filer extends \Zotlabs\Web\Controller {
}
$tpl = get_markup_template("filer_dialog.tpl");
$o = replace_macros($tpl, array(
'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
'$field' => array('term', t('Enter a folder name'), '', '', $filetags, 'placeholder="' . t('or select an existing folder (doubleclick)') . '"'),
'$submit' => t('Save'),
'$title' => t('Save to Folder'),
'$cancel' => t('Cancel')
));
echo $o;

View File

@ -130,7 +130,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
$f = $r[0];
$channel = \App::get_channel();
$cloudpath = get_cloudpath($f) . (intval($f['is_dir']) ? '?f=&davguest=1' : '');
$cloudpath = get_cloudpath($f);
$parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']);
$aclselect_e = populate_acl($f, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage'));

View File

@ -59,12 +59,10 @@ class Hcard extends \Zotlabs\Web\Controller {
}
function get() {
require_once('include/widgets.php');
return widget_profile(array());
function get() {
$x = new \Zotlabs\Widget\Profile();
return $x->widget(array());
}

View File

@ -144,18 +144,8 @@ class Impel extends \Zotlabs\Web\Controller {
// 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;
}
}
$execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['mid']),
intval(local_channel())

View File

@ -2,26 +2,32 @@
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');
require_once('include/perm_upgrade.php');
/**
* @brief Module for channel import.
*
* Import a channel, either by direct file upload or via
* connection to another server.
*/
class Import extends \Zotlabs\Web\Controller {
/**
* @brief Import channel into account.
*
* @param int $account_id
*/
function import_account($account_id) {
if(! $account_id){
logger("import_account: No account ID supplied");
logger('No account ID supplied');
return;
}
$max_friends = account_service_class_fetch($account_id,'total_channels');
$max_feeds = account_service_class_fetch($account_id,'total_feeds');
$data = null;
@ -32,35 +38,39 @@ class Import extends \Zotlabs\Web\Controller {
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
// import channel from file
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.
// 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);
}
// import channel from another server
if(! $src) {
$old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
if(! $old_address) {
logger('mod_import: nothing to import.');
logger('Nothing to import.');
notice( t('Nothing to import.') . EOL);
return;
} else if(strpos($old_address, '')) {
// if you copy the identity address from your profile page, make it work for convenience
$old_address = str_replace('', '@', $old_address);
}
$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);
@ -73,6 +83,7 @@ class Import extends \Zotlabs\Web\Controller {
$api_path .= 'channel/export/basic?f=&channel=' . $channelname;
if($import_posts)
$api_path .= '&posts=1';
$binary = false;
$redirects = 0;
$opts = array('http_auth' => $email . ':' . $password);
@ -85,19 +96,18 @@ class Import extends \Zotlabs\Web\Controller {
return;
}
}
if(! $data) {
logger('mod_import: empty file.');
logger('Empty import file.');
notice( t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data,true);
// logger('import: data: ' . print_r($data,true));
// print_r($data);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
if(! array_key_exists('compatibility',$data)) {
call_hooks('import_foreign_channel_data',$data);
if($data['handled'])
@ -108,24 +118,24 @@ class Import extends \Zotlabs\Web\Controller {
$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 );
$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
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
if(array_key_exists('channel',$data)) {
$max_identities = account_service_class_fetch($account_id,'total_identities');
if($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d",
intval($account_id)
@ -137,46 +147,40 @@ class Import extends \Zotlabs\Web\Controller {
}
$channel = import_channel($data['channel'], $account_id, $seize);
}
else {
$moving = false;
$channel = \App::get_channel();
}
if(! $channel) {
logger('mod_import: channel not found. ', print_r($channel,true));
logger('Channel not found. ', print_r($channel,true));
notice( t('No channel. Import failed.') . EOL);
return;
}
if(is_array($data['config'])) {
import_config($channel,$data['config']);
}
logger('import step 2');
logger('import step 2');
if(array_key_exists('channel',$data)) {
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');
if(is_array($data['hubloc'])) {
import_hublocs($channel,$data['hubloc'],$seize,$moving);
}
logger('import step 4');
// create new hubloc for the new channel at this site
@ -200,7 +204,7 @@ class Import extends \Zotlabs\Web\Controller {
);
// 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']),
@ -210,20 +214,18 @@ class Import extends \Zotlabs\Web\Controller {
}
logger('import step 5');
// import xchans and contact photos
if(array_key_exists('channel',$data) && $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 = xchan_store_lowlevel(
[
'xchan_hash' => $channel['channel_hash'],
@ -242,23 +244,22 @@ class Import extends \Zotlabs\Web\Controller {
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert()
]
);
);
}
logger('import step 6');
// import xchans
$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);
@ -268,22 +269,22 @@ class Import extends \Zotlabs\Web\Controller {
$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;
create_table_from_array('xchan',$xchan);
create_table_from_array('xchan',$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]),
@ -292,33 +293,32 @@ class Import extends \Zotlabs\Web\Controller {
dbesc($photodate),
dbesc($xchan['xchan_hash'])
);
}
logger('import step 7');
logger('import step 7');
}
$friends = 0;
$feeds = 0;
// import contacts
$abooks = $data['abook'];
if($abooks) {
foreach($abooks as $abook) {
$abook_copy = $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']);
unset($abook['abconfig']);
unset($abook['abook_their_perms']);
unset($abook['abook_my_perms']);
unset($abook['abook_not_here']);
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
@ -332,7 +332,7 @@ class Import extends \Zotlabs\Web\Controller {
$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)) {
@ -340,24 +340,24 @@ class Import extends \Zotlabs\Web\Controller {
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;
}
create_table_from_array('abook',$abook);
abook_store_lowlevel($abook);
$friends ++;
if(intval($abook['abook_feed']))
$feeds ++;
translate_abook_perms_inbound($channel,$abook_copy);
if($abconfig) {
// @fixme does not handle sync of del_abconfig
/// @FIXME does not handle sync of del_abconfig
foreach($abconfig as $abc) {
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
}
@ -366,20 +366,21 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 8');
}
// import groups
$groups = $data['group'];
if($groups) {
$saved = array();
foreach($groups as $group) {
$saved[$group['hash']] = array('old' => $group['id']);
if(array_key_exists('name',$group)) {
if(array_key_exists('name', $group)) {
$group['gname'] = $group['name'];
unset($group['name']);
}
unset($group['id']);
$group['uid'] = $channel['channel_id'];
create_table_from_array('groups',$group);
create_table_from_array('groups', $group);
}
$r = q("select * from groups where uid = %d",
intval($channel['channel_id'])
@ -388,10 +389,10 @@ class Import extends \Zotlabs\Web\Controller {
foreach($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id'];
}
}
}
}
// import group members
$group_members = $data['group_member'];
if($group_members) {
foreach($group_members as $group_member) {
@ -401,36 +402,36 @@ class Import extends \Zotlabs\Web\Controller {
if($x['old'] == $group_member['gid'])
$group_member['gid'] = $x['new'];
}
create_table_from_array('group_member',$group_member);
create_table_from_array('group_member', $group_member);
}
}
logger('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'],false,$relocate);
if(is_array($data['menu']))
import_menus($channel,$data['menu']);
@ -439,56 +440,62 @@ class Import extends \Zotlabs\Web\Controller {
if(is_array($data['webpages']))
import_items($channel,$data['webpages'],false,$relocate);
$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'],false,$relocate);
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']);
// 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']);
goaway(z_root() . '/network' );
}
/**
* @brief Handle POST action on channel import page.
*/
function post() {
$account_id = get_account_id();
if(! $account_id)
return;
check_form_security_token_redirectOnErr('/import', 'channel_import');
$this->import_account($account_id);
}
/**
* @brief Generate channel import page.
*
* @return string with parsed HTML.
*/
function get() {
if(! get_account_id()) {
notice( t('You must be logged in to use this feature.'));
notice( t('You must be logged in to use this feature.') . EOL);
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.'),
@ -501,14 +508,14 @@ class Import extends \Zotlabs\Web\Controller {
'$label_import_primary' => t('Make this hub my primary location'),
'$label_import_moving' => t('Move this channel (disable all previous locations)'),
'$label_import_posts' => t('Import a few months of posts if possible (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.'),
'$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' => '',
'$form_security_token' => get_form_security_token('channel_import'),
'$submit' => t('Submit')
));
return $o;
}
}

View File

@ -3,54 +3,60 @@ namespace Zotlabs\Module;
require_once('include/import.php');
/**
* @brief Module for importing items.
*
* Import existing posts and content from an export file.
*/
class Import_items extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel())
return;
check_form_security_token_redirectOnErr('/import_items', 'import_items');
$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.');
logger('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;
@ -64,68 +70,66 @@ class Import_items extends \Zotlabs\Web\Controller {
$data = $ret['body'];
else
notice( t('Unable to download data from old server') . EOL);
}
if(! $data) {
logger('mod_import: empty file.');
logger('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);
$data = json_decode($data, true);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
if(! is_array($data))
return;
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);
$t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
notice($t . EOL);
}
}
$channel = \App::get_channel();
if(array_key_exists('item',$data) && $data['item']) {
import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
}
if(array_key_exists('item_id',$data) && $data['item_id']) {
import_item_ids($channel,$data['item_id']);
}
info( t('Import completed') . EOL);
return;
}
/**
* @brief Generate item import page.
*
* @return string with parsed HTML.
*/
function get() {
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return login();
}
$o = replace_macros(get_markup_template('item_import.tpl'),array(
$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'),
'$form_security_token' => get_form_security_token('import_items'),
'$submit' => t('Submit')
));
return $o;
}
}

View File

@ -110,6 +110,7 @@ class Item extends \Zotlabs\Web\Controller {
$preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
$categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : '');
$webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0);
$item_obscured = ((x($_REQUEST,'obscured')) ? intval($_REQUEST['obscured']) : 0);
$pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
$layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): '');
$plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
@ -471,24 +472,16 @@ class Item extends \Zotlabs\Web\Controller {
if(! $mimetype)
$mimetype = 'text/bbcode';
$execflag = ((intval($uid) == intval($profile_uid)
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
if($preview) {
$body = z_input_filter($profile_uid,$body,$mimetype);
$body = z_input_filter($body,$mimetype,$execflag);
}
// Verify ability to use html or php!!!
$execflag = false;
$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($profile_uid)
);
if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
if($uid && (get_account_id() == $z[0]['account_id'])) {
$execflag = true;
}
}
$gacl = $acl->get();
$str_contact_allow = $gacl['allow_cid'];
$str_group_allow = $gacl['allow_gid'];
@ -852,18 +845,6 @@ class Item extends \Zotlabs\Web\Controller {
if(mb_strlen($datarray['title']) > 255)
$datarray['title'] = mb_substr($datarray['title'],0,255);
if(array_key_exists('item_private',$datarray) && $datarray['item_private']) {
$datarray['body'] = trim(z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype']));
if($uid) {
if($channel['channel_hash'] === $datarray['author_xchan']) {
$datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey']));
$datarray['item_verified'] = 1;
}
}
}
if($webpage) {
Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
(($pagetitle) ? $pagetitle : substr($datarray['mid'],0,16)),true);
@ -879,7 +860,17 @@ class Item extends \Zotlabs\Web\Controller {
$x = item_store_update($datarray,$execflag);
item_create_edit_activity($x);
// We only need edit activities for other federated protocols
// which do not support edits natively. While this does federate
// edits, it presents a number of issues locally - such as #757 and #758.
// The SQL check for an edit activity would not perform that well so to fix these issues
// requires an additional item flag (perhaps 'item_edit_activity') that we can add to the
// query for searches and notifications.
// For now we'll just forget about trying to make edits work on network protocols that
// don't support them.
// item_create_edit_activity($x);
if(! $parent) {
$r = q("select * from item where id = %d",

View File

@ -125,6 +125,7 @@ class Layouts extends \Zotlabs\Web\Controller {
'hide_weblink' => true,
'hide_attach' => true,
'hide_preview' => true,
'disable_comments' => true,
'ptlabel' => t('Layout Name'),
'profile_uid' => intval($owner),
'expanded' => true,

View File

@ -72,7 +72,7 @@ class Lockview extends \Zotlabs\Web\Controller {
}
if($uid != local_channel()) {
echo '<li>' . t('Remote privacy information not available.') . '</li>';
echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
killme();
}
@ -84,7 +84,7 @@ class Lockview extends \Zotlabs\Web\Controller {
// 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>';
echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
killme();
}
@ -93,7 +93,7 @@ class Lockview extends \Zotlabs\Web\Controller {
$deny_users = expand_acl($item['deny_cid']);
$deny_groups = expand_acl($item['deny_gid']);
$o = '<li>' . t('Visible to:') . '</li>';
$o = '<div class="dropdown-item">' . t('Visible to:') . '</div>';
$l = array();
stringify_array_elms($allowed_groups,true);
@ -114,24 +114,24 @@ class Lockview extends \Zotlabs\Web\Controller {
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></li>';
$l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
}
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>';
$l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
}
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>';
$l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
if($atokens) {
foreach($atokens as $at) {
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
$l[] = '<li>' . $at['xchan_name'] . '</li>';
$l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
}
}
}
@ -150,7 +150,7 @@ class Lockview extends \Zotlabs\Web\Controller {
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
if($r)
foreach($r as $rr)
$l[] = '<li><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></li>';
$l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
}
@ -159,18 +159,18 @@ class Lockview extends \Zotlabs\Web\Controller {
$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>';
$l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>';
}
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>';
$l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>';
if($atokens) {
foreach($atokens as $at) {
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
$l[] = '<li><strike>' . $at['xchan_name'] . '</strike></li>';
$l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
}
}
}

View File

@ -113,18 +113,18 @@ class Mail extends \Zotlabs\Web\Controller {
if($preview) {
$mail = [
'mailbox' => 'outbox',
'id' => 0,
'mid' => 'M0',
'from_name' => $channel['xchan_name'],
'from_url' => $channel['xchan_url'],
'from_photo' => $channel['xchan_photo_s'],
'subject' => zidify_links(smilies(bbcode($subject))),
'body' => zidify_links(smilies(bbcode($body))),
'mailbox' => 'outbox',
'id' => 0,
'mid' => 'M0',
'from_name' => $channel['xchan_name'],
'from_url' => $channel['xchan_url'],
'from_photo' => $channel['xchan_photo_s'],
'subject' => zidify_links(smilies(bbcode($subject))),
'body' => zidify_links(smilies(bbcode($body))),
'attachments' => '',
'can_recall' => false,
'can_recall' => false,
'is_recalled' => '',
'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c')
'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c')
];
echo replace_macros(get_markup_template('mail_conv.tpl'), [ '$mail' => $mail ] );
@ -178,6 +178,25 @@ class Mail extends \Zotlabs\Web\Controller {
'$header' => t('Messages'),
));
if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') {
$r = q("select * from mail where id = %d and channel_id = %d",
intval(argv(1)),
intval(local_channel())
);
if($r) {
header('Content-type: ' . $r[0]['mail_mimetype']);
header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' );
$body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']);
echo $body;
killme();
}
}
if((argc() == 4) && (argv(2) === 'drop')) {
if(! intval(argv(3)))
return;
@ -296,7 +315,9 @@ class Mail extends \Zotlabs\Web\Controller {
return $o;
}
$direct_mid = 0;
switch(argv(1)) {
case 'combined':
$mailbox = 'combined';
@ -309,12 +330,22 @@ class Mail extends \Zotlabs\Web\Controller {
break;
default:
$mailbox = 'combined';
// notifications direct to mail/nn
if(intval(argv(1)))
$direct_mid = intval(argv(1));
break;
}
$last_message = private_messages_list(local_channel(), $mailbox, 0, 1);
$mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id'];
if($direct_mid)
$mid = $direct_mid;
$plaintext = true;
@ -358,6 +389,11 @@ class Mail extends \Zotlabs\Web\Controller {
foreach($messages as $message) {
$s = theme_attachments($message);
if($message['mail_raw'])
$message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]);
else
$message['body'] = zidify_links(smilies(bbcode($message['body'])));
$mails[] = array(
'mailbox' => $mailbox,
@ -370,7 +406,7 @@ class Mail extends \Zotlabs\Web\Controller {
'to_url' => chanlink_hash($message['to_xchan']),
'to_photo' => $message['to']['xchan_photo_s'],
'subject' => $message['title'],
'body' => zidify_links(smilies(bbcode($message['body']))),
'body' => $message['body'],
'attachments' => $s,
'delete' => t('Delete message'),
'dreport' => t('Delivery report'),

View File

@ -46,107 +46,111 @@ class Manage extends \Zotlabs\Web\Controller {
$channels = null;
if(local_channel()) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
intval(get_account_id())
);
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
intval(get_account_id())
);
$account = \App::get_account();
$account = \App::get_account();
if($r && count($r)) {
$channels = $r;
for($x = 0; $x < count($channels); $x ++) {
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1';
if($r && count($r)) {
$channels = $r;
for($x = 0; $x < count($channels); $x ++) {
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1';
$c = q("SELECT id, item_wall FROM item
WHERE item_unseen = 1 and uid = %d " . item_normal(),
intval($channels[$x]['channel_id'])
);
$c = q("SELECT id, item_wall FROM item
WHERE item_unseen = 1 and uid = %d " . item_normal(),
intval($channels[$x]['channel_id'])
);
if($c) {
foreach ($c as $it) {
if(intval($it['item_wall']))
$channels[$x]['home'] ++;
else
$channels[$x]['network'] ++;
}
if($c) {
foreach ($c as $it) {
if(intval($it['item_wall']))
$channels[$x]['home'] ++;
else
$channels[$x]['network'] ++;
}
}
$intr = 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($channels[$x]['channel_id'])
);
$intr = 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($channels[$x]['channel_id'])
);
if($intr)
$channels[$x]['intros'] = intval($intr[0]['total']);
if($intr)
$channels[$x]['intros'] = intval($intr[0]['total']);
$mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
intval($channels[$x]['channel_id']),
dbesc($channels[$x]['channel_hash'])
);
$mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
intval($channels[$x]['channel_id']),
dbesc($channels[$x]['channel_hash'])
);
if($mails)
$channels[$x]['mail'] = intval($mails[0]['total']);
if($mails)
$channels[$x]['mail'] = intval($mails[0]['total']);
$events = q("SELECT etype, dtstart, adjust FROM event
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
ORDER BY dtstart ASC ",
intval($channels[$x]['channel_id']),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
$events = q("SELECT etype, dtstart, adjust FROM event
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
ORDER BY dtstart ASC ",
intval($channels[$x]['channel_id']),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')),
dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
);
if($events) {
$channels[$x]['all_events'] = count($events);
if($channels[$x]['all_events']) {
$str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
foreach($events as $e) {
$bd = false;
if($e['etype'] === 'birthday') {
$channels[$x]['birthdays'] ++;
$bd = true;
}
else {
$channels[$x]['events'] ++;
}
if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['dtstart'], 'Y-m-d') === $str_now) {
$channels[$x]['all_events_today'] ++;
if($bd)
$channels[$x]['birthdays_today'] ++;
else
$channels[$x]['events_today'] ++;
}
if($events) {
$channels[$x]['all_events'] = count($events);
if($channels[$x]['all_events']) {
$str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
foreach($events as $e) {
$bd = false;
if($e['etype'] === 'birthday') {
$channels[$x]['birthdays'] ++;
$bd = true;
}
else {
$channels[$x]['events'] ++;
}
if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['dtstart'], 'Y-m-d') === $str_now) {
$channels[$x]['all_events_today'] ++;
if($bd)
$channels[$x]['birthdays_today'] ++;
else
$channels[$x]['events_today'] ++;
}
}
}
}
}
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
intval(get_account_id())
);
$limit = account_service_class_fetch(get_account_id(),'total_identities');
if($limit !== false) {
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
}
else {
$channel_usage_message = '';
}
}
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
intval(get_account_id())
);
$limit = account_service_class_fetch(get_account_id(),'total_identities');
if($limit !== false) {
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
}
else {
$channel_usage_message = '';
}
$create = array( 'new_channel', t('Create a new channel'), t('Create New'));
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )",
intval(local_channel()),
intval(local_channel())
);
$delegates = null;
if(local_channel()) {
$delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where
abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )",
intval(local_channel()),
intval(local_channel())
);
}
if($delegates) {
for($x = 0; $x < count($delegates); $x ++) {

View File

@ -118,8 +118,8 @@ class Network extends \Zotlabs\Web\Controller {
$cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99);
$firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0);
$file = ((x($_GET,'file')) ? $_GET['file'] : '');
$xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : '');
$deftag = '';
if(x($_GET,'search') || x($_GET,'file'))
@ -257,6 +257,26 @@ class Network extends \Zotlabs\Web\Controller {
goaway(z_root() . '/network');
}
}
elseif($xchan) {
$r = q("select * from xchan where xchan_hash = '%s'",
dbesc($xchan)
);
if($r) {
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($xchan) . "' or owner_xchan = '" . dbesc($xchan) . "' ) $item_normal ) ";
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>'
));
$o = $tabs;
$o .= $title;
$o .= $status_editor;
}
else {
notice( t('Invalid channel.') . EOL);
goaway(z_root() . '/network');
}
}
if(x($category)) {
$sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY));
@ -302,6 +322,7 @@ class Network extends \Zotlabs\Web\Controller {
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => (($search) ? $search : ''),
'$xchan' => $xchan,
'$order' => $order,
'$file' => $file,
'$cats' => $category,

View File

@ -40,7 +40,7 @@ class Notifications extends \Zotlabs\Web\Controller {
$o .= replace_macros(get_markup_template('notifications.tpl'),array(
'$notif_header' => t('System Notifications'),
'$notif_link_mark_seen' => t('Mark all system notifications seen'),
'$notif_link_mark_seen' => t('Mark all seen'),
'$notif_content' => $notif_content,
'$notifications_available' => $notifications_available,
));

48
Zotlabs/Module/Ofeed.php Normal file
View File

@ -0,0 +1,48 @@
<?php
namespace Zotlabs\Module;
/* Ofeed: Broken feed for software which requires broken feeds */
require_once('include/items.php');
class Ofeed extends \Zotlabs\Web\Controller {
function init() {
$params = [];
$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']) : '');
$params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 1);
if(argc() > 1) {
if(observer_prohibited(true)) {
killme();
}
$channel = channelx_by_nick(argv(1));
if(! $channel) {
killme();
}
logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
echo get_public_feed($channel,$params);
killme();
}
}
}

View File

@ -127,7 +127,6 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
$r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
dbesc($photo),
intval($resolution)
@ -150,12 +149,14 @@ class Photo extends \Zotlabs\Web\Controller {
$channel = channelx_by_n($r[0]['uid']);
// Now we'll see if we can access the photo
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1",
dbesc($photo),
intval($resolution)
);
if($r && $r[0]['photo_usage'] == PHOTO_COVER)
$allowed = 1;
$d = [ 'imgscale' => $resolution, 'resource_id' => $photo, 'photo' => $r, 'allowed' => $allowed ];
call_hooks('get_photo',$d);

View File

@ -15,13 +15,10 @@ class Photos extends \Zotlabs\Web\Controller {
function init() {
if(observer_prohibited()) {
return;
}
$o = '';
if(argc() > 1) {
$nick = argv(1);
@ -54,7 +51,6 @@ class Photos extends \Zotlabs\Web\Controller {
logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA);
logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA);
@ -92,14 +88,9 @@ class Photos extends \Zotlabs\Web\Controller {
if((argc() > 3) && (argv(2) === 'album')) {
$album = hex2bin(argv(3));
if($album === t('Profile Photos')) {
// not allowed
goaway(z_root() . '/' . $_SESSION['photo_return']);
}
if(! photos_album_exists($page_owner_uid,$album)) {
$album = argv(3);
if(! photos_album_exists($page_owner_uid, get_observer_hash(), $album)) {
notice( t('Album not found.') . EOL);
goaway(z_root() . '/' . $_SESSION['photo_return']);
}
@ -121,7 +112,7 @@ class Photos extends \Zotlabs\Web\Controller {
$folder_hash = '';
$r = q("select * from attach where is_dir = 1 and uid = %d and filename = '%s'",
$r = q("select * from attach where is_dir = 1 and uid = %d and hash = '%s'",
intval($page_owner_uid),
dbesc($album)
);
@ -129,14 +120,7 @@ class Photos extends \Zotlabs\Web\Controller {
notice( t('Album not found.') . EOL);
return;
}
if(count($r) > 1) {
notice( t('Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager') . EOL);
return;
}
else {
$folder_hash = $r[0]['hash'];
}
$folder_hash = $r[0]['hash'];
$res = array();
@ -468,7 +452,7 @@ class Photos extends \Zotlabs\Web\Controller {
* default post action - upload a photo
*/
$channel = \App::$data['channel'];
$channel = \App::$data['channel'];
$observer = \App::$data['observer'];
$_REQUEST['source'] = 'photos';
@ -485,12 +469,10 @@ class Photos extends \Zotlabs\Web\Controller {
if(! $r['success']) {
notice($r['message'] . EOL);
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
if($_REQUEST['newalbum'])
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum']));
else
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y')));
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']);
}
@ -569,7 +551,9 @@ class Photos extends \Zotlabs\Web\Controller {
return;
}
$sql_extra = permissions_sql($owner_uid);
$sql_item = item_permissions_sql($owner_uid,get_observer_hash());
$sql_extra = permissions_sql($owner_uid,get_observer_hash(),'photo');
$sql_attach = permissions_sql($owner_uid,get_observer_hash(),'attach');
$o = "";
@ -579,7 +563,7 @@ class Photos extends \Zotlabs\Web\Controller {
// tabs
$_is_owner = (local_channel() && (local_channel() == $owner_uid));
$o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']);
//$o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']);
/**
* Display upload form
@ -628,8 +612,14 @@ class Photos extends \Zotlabs\Web\Controller {
if(! $aclselect) {
$aclselect = '<input id="group_allow" type="hidden" name="allow_gid[]" value="" /><input id="contact_allow" type="hidden" name="allow_cid[]" value="" /><input id="group_deny" type="hidden" name="deny_gid[]" value="" /><input id="contact_deny" type="hidden" name="deny_cid[]" value="" />';
}
$selname = (($datum) ? hex2bin($datum) : '');
$selname = '';
if($datum) {
$h = attach_by_hash_nodata($datum,get_observer_hash());
$selname = $h['data']['display_path'];
}
$albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
@ -680,29 +670,13 @@ class Photos extends \Zotlabs\Web\Controller {
if($datatype === 'album') {
if(strlen($datum)) {
if((strlen($datum) & 1) || (! ctype_xdigit($datum))) {
notice( t('Album name could not be decoded') . EOL);
logger('mod_photos: illegal album encoding: ' . $datum);
$datum = '';
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
}
$album = (($datum) ? hex2bin($datum) : '');
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
//check if the album exists and if we have perms
$r = q("SELECT album FROM photo WHERE uid = %d AND album = '%s' and is_nsfw = %d $sql_extra LIMIT 1",
intval($owner_uid),
dbesc($album),
intval($unsafe)
);
if($r) {
if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) {
\App::set_pager_itemspage(60);
} else {
$album = $x['display_path'];
}
else {
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
@ -712,26 +686,26 @@ class Photos extends \Zotlabs\Web\Controller {
$order = 'DESC';
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph
(SELECT resource_id, max(imgscale) imgscale FROM photo left join attach on folder = '%s' and photo.resource_id = attach.hash WHERE attach.uid = %d AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
ORDER BY created $order LIMIT %d OFFSET %d",
dbesc($datum),
intval($owner_uid),
dbesc($album),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE),
intval($unsafe),
intval(\App::$pager['itemspage']),
intval(\App::$pager['start'])
);
//edit album name
// edit album name
$album_edit = null;
if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
if($can_post) {
$album_e = $album;
$albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
if($can_post) {
$album_e = $album;
$albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer']));
// @fixme - syncronise actions with DAV
// @fixme - syncronise actions with DAV
// $edit_tpl = get_markup_template('album_edit.tpl');
// $album_edit = replace_macros($edit_tpl,array(
@ -745,13 +719,12 @@ class Photos extends \Zotlabs\Web\Controller {
// '$dropsubmit' => t('Delete Album')
// ));
}
}
if($_GET['order'] === 'posted')
$order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album));
$order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum);
else
$order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted');
$order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum . '?f=&order=posted');
$photos = array();
if(count($r)) {
@ -805,10 +778,10 @@ class Photos extends \Zotlabs\Web\Controller {
$o .= replace_macros($tpl, array(
'$photos' => $photos,
'$album' => $album,
'$album_id' => bin2hex($album),
'$album_id' => $datum,
'$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => $can_post,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . bin2hex($album)),
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum),
'$order' => $order,
'$upload_form' => $upload_form,
'$usage' => $usage_message
@ -822,8 +795,6 @@ class Photos extends \Zotlabs\Web\Controller {
killme();
}
// $o .= paginate($a);
return $o;
}
@ -836,6 +807,11 @@ class Photos extends \Zotlabs\Web\Controller {
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
$x = q("select folder from attach where hash = '%s' and uid = %d $sql_attach limit 1",
dbesc($datum),
intval($owner_uid)
);
// fetch image, item containing image, then comments
$ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM photo WHERE uid = %d AND resource_id = '%s'
@ -844,7 +820,7 @@ class Photos extends \Zotlabs\Web\Controller {
dbesc($datum)
);
if(! $ph) {
if(! ($ph && $x)) {
/* Check again - this time without specifying permissions */
@ -869,16 +845,16 @@ class Photos extends \Zotlabs\Web\Controller {
else
$order = 'DESC';
$prvnxt = q("SELECT resource_id FROM photo WHERE album = '%s' AND uid = %d AND imgscale = 0
$sql_extra ORDER BY created $order ",
dbesc($ph[0]['album']),
$prvnxt = q("SELECT hash FROM attach WHERE folder = '%s' AND uid = %d AND is_photo = 1
$sql_attach ORDER BY created $order ",
dbesc($x[0]['folder']),
intval($owner_uid)
);
if(count($prvnxt)) {
for($z = 0; $z < count($prvnxt); $z++) {
if($prvnxt[$z]['resource_id'] == $ph[0]['resource_id']) {
if($prvnxt[$z]['hash'] == $ph[0]['resource_id']) {
$prv = $z - 1;
$nxt = $z + 1;
if($prv < 0)
@ -889,8 +865,8 @@ class Photos extends \Zotlabs\Web\Controller {
}
}
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
}
@ -907,7 +883,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
}
$album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($ph[0]['album']);
$album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $x[0]['folder'];
$tools = Null;
$lock = Null;
@ -947,7 +923,7 @@ class Photos extends \Zotlabs\Web\Controller {
// Do we have an item for this photo?
$linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo'
$sql_extra LIMIT 1",
$sql_item LIMIT 1",
dbesc($datum)
);
@ -962,7 +938,7 @@ class Photos extends \Zotlabs\Web\Controller {
$item_normal = item_normal();
$r = q("select * from item where parent_mid = '%s'
$item_normal and uid = %d $sql_extra ",
$item_normal and uid = %d $sql_item ",
dbesc($link_item['mid']),
intval($link_item['uid'])
@ -1008,13 +984,6 @@ class Photos extends \Zotlabs\Web\Controller {
$edit = null;
if($can_post) {
$m = q("select folder from attach where hash = '%s' and uid = %d limit 1",
dbesc($ph[0]['resource_id']),
intval($ph[0]['uid'])
);
if($m)
$album_hash = $m[0]['folder'];
$album_e = $ph[0]['album'];
$caption_e = $ph[0]['description'];
$aclselect_e = (($_is_owner) ? populate_acl($ph[0], true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : '');
@ -1024,35 +993,35 @@ class Photos extends \Zotlabs\Web\Controller {
$folder_list = attach_folder_select_list($ph[0]['uid']);
$edit = array(
$edit = [
'edit' => t('Edit photo'),
'id' => $link_item['id'],
'rotatecw' => t('Rotate CW (right)'),
'rotateccw' => t('Rotate CCW (left)'),
'albums' => $albums['albums'],
'album' => $album_e,
'album_select' => [ 'move_to_album', t('Move photo to album'), $album_hash, '', $folder_list ],
'newalbum_label' => t('Enter a new album name'),
'rotatecw' => t('Rotate CW (right)'),
'rotateccw' => t('Rotate CCW (left)'),
'albums' => $albums['albums'],
'album' => $album_e,
'album_select' => [ 'move_to_album', t('Move photo to album'), $x[0]['folder'], '', $folder_list ],
'newalbum_label' => t('Enter a new album name'),
'newalbum_placeholder' => t('or select an existing one (doubleclick)'),
'nickname' => \App::$data['channel']['channel_address'],
'resource_id' => $ph[0]['resource_id'],
'capt_label' => t('Caption'),
'caption' => $caption_e,
'tag_label' => t('Add a Tag'),
'permissions' => t('Permissions'),
'aclselect' => $aclselect_e,
'allow_cid' => acl2json($ph[0]['allow_cid']),
'allow_gid' => acl2json($ph[0]['allow_gid']),
'deny_cid' => acl2json($ph[0]['deny_cid']),
'deny_gid' => acl2json($ph[0]['deny_gid']),
'lockstate' => $lockstate[0],
'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'),
'item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'),
'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''),
'submit' => t('Submit'),
'delete' => t('Delete Photo')
);
'nickname' => \App::$data['channel']['channel_address'],
'resource_id' => $ph[0]['resource_id'],
'capt_label' => t('Caption'),
'caption' => $caption_e,
'tag_label' => t('Add a Tag'),
'permissions' => t('Permissions'),
'aclselect' => $aclselect_e,
'allow_cid' => acl2json($ph[0]['allow_cid']),
'allow_gid' => acl2json($ph[0]['allow_gid']),
'deny_cid' => acl2json($ph[0]['deny_cid']),
'deny_gid' => acl2json($ph[0]['deny_gid']),
'lockstate' => $lockstate[0],
'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'),
'item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'),
'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''),
'submit' => t('Submit'),
'delete' => t('Delete Photo')
];
}
if(count($linked_items)) {
@ -1066,13 +1035,13 @@ class Photos extends \Zotlabs\Web\Controller {
$likebuttons = '';
if($can_post || $can_comment) {
$likebuttons = array(
'id' => $link_item['id'],
$likebuttons = [
'id' => $link_item['id'],
'likethis' => t("I like this \x28toggle\x29"),
'nolike' => t("I don't like this \x28toggle\x29"),
'share' => t('Share'),
'wait' => t('Please wait')
);
'nolike' => t("I don't like this \x28toggle\x29"),
'share' => t('Share'),
'wait' => t('Please wait')
];
}
$comments = '';
@ -1277,25 +1246,13 @@ class Photos extends \Zotlabs\Web\Controller {
\App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n";
/*
$r = q("SELECT resource_id, max(imgscale) AS imgscale FROM photo WHERE uid = %d
and photo_usage in ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id",
intval(\App::$data['channel']['channel_id']),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE),
intval($unsafe)
);
if($r) {
\App::set_pager_total(count($r));
\App::set_pager_itemspage(60);
}
*/
\App::set_pager_itemspage(60);
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created FROM photo p
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created, p.display_path
FROM photo p
INNER JOIN ( SELECT resource_id, max(imgscale) imgscale FROM photo
WHERE uid = %d AND photo_usage IN ( %d, %d )
WHERE photo.uid = %d AND photo_usage IN ( %d, %d )
AND is_nsfw = %d $sql_extra group by resource_id ) ph
ON (p.resource_id = ph.resource_id and p.imgscale = ph.imgscale)
ORDER by p.created DESC LIMIT %d OFFSET %d",
@ -1313,21 +1270,19 @@ class Photos extends \Zotlabs\Web\Controller {
if($r) {
$twist = 'rotright';
foreach($r as $rr) {
if(! attach_can_view_folder(\App::$data['channel']['channel_id'],get_observer_hash(),$rr['resource_id']))
continue;
if($twist == 'rotright')
$twist = 'rotleft';
else
$twist = 'rotright';
$ext = $phototypes[$rr['mimetype']];
if(\App::get_template_engine() === 'internal') {
$alt_e = template_escape($rr['filename']);
$name_e = template_escape($rr['album']);
}
else {
$alt_e = $rr['filename'];
$name_e = $rr['album'];
}
$alt_e = $rr['filename'];
$name_e = dirname($rr['display_path']);
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
@ -1336,9 +1291,7 @@ class Photos extends \Zotlabs\Web\Controller {
'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['imgscale']) == 6) ? 4 : $rr['imgscale']) . '.' . $ext,
'alt' => $alt_e,
'album' => array(
'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($rr['album']),
'name' => $name_e,
'alt' => t('View Album'),
),
);

View File

@ -101,7 +101,7 @@ class Profile extends \Zotlabs\Web\Controller {
return;
}
$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
//$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
\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";

View File

@ -108,11 +108,13 @@ class Profile_photo extends \Zotlabs\Web\Controller {
$aid = get_account_id();
$p = [
'aid' => $aid,
'uid' => local_channel(),
'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'],
'album' => t('Profile Photos')
'aid' => $aid,
'uid' => local_channel(),
'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'],
'album' => t('Profile Photos'),
'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path']
];
$p['imgscale'] = PHOTO_RES_PROFILE_300;

View File

@ -317,8 +317,10 @@ class Profiles extends \Zotlabs\Web\Controller {
$hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
// start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving
// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
$orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
$orig_vcard = null;
$channel = \App::get_channel();
@ -330,13 +332,7 @@ class Profiles extends \Zotlabs\Web\Controller {
'photo' => $channel['xchan_photo_l'],
'adr' => [],
'adr_type' => [ $default_vcard_cat ],
'tel' => [],
'tel_type' => [ $default_vcard_cat ],
'email' => [],
'email_type' => [ $default_vcard_cat ],
'impp' => [],
'impp_type' => [ $default_vcard_cat ],
'url' => [],
'url' => [ $homepage ],
'url_type' => [ $default_vcard_cat ]
];
@ -350,9 +346,12 @@ class Profiles extends \Zotlabs\Web\Controller {
6 => $country_name
];
$profile_vcard = update_vcard($defcard,$orig_vcard);
$orig_vcard = \Sabre\VObject\Reader::read($profile_vcard);
$profile_vcard = update_vcard($_REQUEST,$orig_vcard);
require_once('include/text.php');
linkify_tags($a, $likes, local_channel());
@ -700,6 +699,10 @@ class Profiles extends \Zotlabs\Web\Controller {
}
//logger('extra_fields: ' . print_r($extra_fields,true));
$vc = $r[0]['profile_vcard'];
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
$vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] );
$f = get_config('system','birthday_input_format');
if(! $f)
@ -717,6 +720,7 @@ class Profiles extends \Zotlabs\Web\Controller {
. get_form_security_token("profile_drop"),
'$fields' => $fields,
'$vcard' => $vcard,
'$guid' => $r[0]['profile_guid'],
'$banner' => t('Edit Profile Details'),
'$submit' => t('Submit'),
@ -776,11 +780,28 @@ class Profiles extends \Zotlabs\Web\Controller {
'$film' => array('film', t('Film/Dance/Culture/Entertainment'), $r[0]['film']),
'$interest' => array('interest', t('Hobbies/Interests'), $r[0]['interest']),
'$romance' => array('romance',t('Love/Romance'), $r[0]['romance']),
'$work' => array('work', t('Work/Employment'), $r[0]['employment']),
'$employ' => array('work', t('Work/Employment'), $r[0]['employment']),
'$education' => array('education', t('School/Education'), $r[0]['education']),
'$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']),
'$channels' => array('channels', t('My other channels'), $r[0]['channels']),
'$extra_fields' => $extra_fields,
'$comms' => t('Communications'),
'$tel_label' => t('Phone'),
'$email_label' => t('Email'),
'$impp_label' => t('Instant messenger'),
'$url_label' => t('Website'),
'$adr_label' => t('Address'),
'$note_label' => t('Note'),
'$mobile' => t('Mobile'),
'$home' => t('Home'),
'$work' => t('Work'),
'$other' => t('Other'),
'$add_card' => t('Add Contact'),
'$add_field' => t('Add Field'),
'$create' => t('Create'),
'$update' => t('Update'),
'$delete' => t('Delete'),
'$cancel' => t('Cancel'),
));
$arr = array('profile' => $r[0], 'entry' => $o);

View File

@ -57,6 +57,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
'$static' => $static,
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => '',
'$xchan' => '',
'$order' => 'comment',
'$file' => '',
'$cats' => '',

View File

@ -130,6 +130,7 @@ class Search extends \Zotlabs\Web\Controller {
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$search' => (($tag) ? urlencode('#') : '') . $search,
'$xchan' => '',
'$order' => '',
'$file' => '',
'$cats' => '',

View File

@ -277,8 +277,8 @@ class Channel {
if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
// FIXME - set to un-verified, blocked and redirect to logout
// Why? Are we verifying people or email addresses?
// Q: Why? Are we verifying people or email addresses?
// A: the policy is to verify email addresses
}
goaway(z_root() . '/settings' );
@ -575,7 +575,7 @@ class Channel {
'$removeme' => t('Remove Channel'),
'$removechannel' => t('Remove this channel.'),
'$firefoxshare' => t('Firefox Share $Projectname provider'),
'$cal_first_day' => array('first_day', t('Start calendar week on monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no),
'$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no),
));
call_hooks('settings_form',$o);

View File

@ -508,6 +508,7 @@ class Setup extends \Zotlabs\Web\Controller {
$this->check_add($ck_funcs, t('PDO database PHP module'), true, true);
$this->check_add($ck_funcs, t('mb_string PHP module'), true, true);
$this->check_add($ck_funcs, t('xml PHP module'), true, true);
$this->check_add($ck_funcs, t('zip PHP module'), true, true);
if(function_exists('apache_get_modules')){
if (! in_array('mod_rewrite', apache_get_modules())) {
@ -550,8 +551,12 @@ class Setup extends \Zotlabs\Web\Controller {
$ck_funcs[4]['help'] = t('Error: mb_string PHP module required but not installed.');
}
if(! extension_loaded('xml')) {
$ck_funcs[5]['status'] = false;
$ck_funcs[5]['help'] = t('Error: xml PHP module required for DAV but not installed.');
}
if(! extension_loaded('zip')) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = t('Error: xml PHP module required for DAV but not installed.');
$ck_funcs[6]['help'] = t('Error: zip PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);
@ -624,7 +629,6 @@ class Setup extends \Zotlabs\Web\Controller {
* @param[out] array &$checks
*/
function check_htaccess(&$checks) {
$a = get_app();
$status = true;
$help = '';
$ssl_error = false;
@ -718,7 +722,6 @@ class Setup extends \Zotlabs\Web\Controller {
* @return string with parsed HTML
*/
function what_next() {
$a = get_app();
// install the standard theme
set_config('system', 'allowed_themes', 'redbasic');

View File

@ -92,7 +92,8 @@ class Sharedwithme extends \Zotlabs\Web\Controller {
}
$o = profile_tabs($a, $is_owner, $channel['channel_address']);
//$o = profile_tabs($a, $is_owner, $channel['channel_address']);
$o = '';
$o .= replace_macros(get_markup_template('sharedwithme.tpl'), array(
'$header' => t('Files: shared with me'),

View File

@ -3,8 +3,6 @@ namespace Zotlabs\Module;
require_once('include/socgraph.php');
require_once('include/contact_widgets.php');
require_once('include/widgets.php');
class Suggest extends \Zotlabs\Web\Controller {
@ -23,7 +21,7 @@ class Suggest extends \Zotlabs\Web\Controller {
}
function get() {
function get() {
$o = '';
if(! local_channel()) {

View File

@ -13,6 +13,7 @@ class Viewsrc extends \Zotlabs\Web\Controller {
$item_id = ((argc() > 1) ? intval(argv(1)) : 0);
$json = ((argc() > 2 && argv(2) === 'json') ? true : false);
$dload = ((argc() > 2 && argv(2) === 'download') ? true : false);
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@ -27,7 +28,7 @@ class Viewsrc extends \Zotlabs\Web\Controller {
$item_normal = item_normal();
if(local_channel() && $item_id) {
$r = q("select id, item_flags, item_obscured, body from item where uid in (%d , %d) and id = %d $item_normal limit 1",
$r = q("select id, item_flags, mimetype, item_obscured, body from item where uid in (%d , %d) and id = %d $item_normal limit 1",
intval(local_channel()),
intval($sys['channel_id']),
intval($item_id)
@ -35,7 +36,15 @@ class Viewsrc extends \Zotlabs\Web\Controller {
if($r) {
if(intval($r[0]['item_obscured']))
$r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'],true),get_config('system','prvkey'));
$dload = true;
if($dload) {
header('Content-type: ' . $r[0]['mimetype']);
header('Content-disposition: attachment; filename="' . t('item') . '-' . $item_id . '"' );
echo $r[0]['body'];
killme();
}
$content = escape_tags($r[0]['body']);
$o = (($json) ? json_encode($content) : str_replace("\n",'<br />',$content));

View File

@ -142,7 +142,8 @@ class Webpages extends \Zotlabs\Web\Controller {
$is_owner = ($uid && $uid == $owner);
$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
//$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o = '';
$x = array(
'webpage' => ITEM_TYPE_WEBPAGE,
@ -693,7 +694,8 @@ class Webpages extends \Zotlabs\Web\Controller {
}
rrmdir($zip_folderpath); rrmdir($tmp_folderpath); // delete temporary files
killme();
break;
default :
break;

View File

@ -38,6 +38,9 @@ class Wfinger extends \Zotlabs\Web\Controller {
$channel = str_replace('acct:','',$resource);
if(strpos($channel,'@') !== false) {
$host = substr($channel,strpos($channel,'@')+1);
// If the webfinger address points off site, redirect to the correct site
if(strcasecmp($host,\App::get_hostname())) {
goaway('https://' . $host . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=' . $zot : ''));
}
@ -77,54 +80,60 @@ class Wfinger extends \Zotlabs\Web\Controller {
}
}
$result['aliases'] = array();
$result['aliases'] = [];
$result['properties'] = array(
'http://webfinger.net/ns/name' => $r[0]['channel_name'],
$result['properties'] = [
'http://webfinger.net/ns/name' => $r[0]['channel_name'],
'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name']
);
];
foreach($aliases as $alias)
if($alias != $resource)
$result['aliases'][] = $alias;
$result['links'] = array(
$result['links'] = [
array(
'rel' => 'http://webfinger.net/rel/avatar',
[
'rel' => 'http://webfinger.net/rel/avatar',
'type' => $r[0]['xchan_photo_mimetype'],
'href' => $r[0]['xchan_photo_l']
),
],
array(
'rel' => 'http://webfinger.net/rel/profile-page',
[
'rel' => 'http://webfinger.net/rel/profile-page',
'href' => z_root() . '/profile/' . $r[0]['channel_address'],
),
],
array(
'rel' => 'http://webfinger.net/rel/blog',
[
'rel' => 'http://schemas.google.com/g/2010#updates-from',
'type' => 'application/atom+xml',
'href' => z_root() . '/ofeed/' . $r[0]['channel_address']
],
[
'rel' => 'http://webfinger.net/rel/blog',
'href' => z_root() . '/channel/' . $r[0]['channel_address'],
),
],
array(
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
[
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
'template' => z_root() . '/follow/url={uri}',
),
],
array(
'rel' => 'http://purl.org/zot/protocol',
[
'rel' => 'http://purl.org/zot/protocol',
'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'],
),
],
array(
'rel' => 'magic-public-key',
[
'rel' => 'magic-public-key',
'href' => 'data:application/magic-public-key,' . salmon_key($r[0]['channel_pubkey']),
)
);
]
];
if($zot) {
// get a zotinfo packet and return it with webfinger
$result['zot'] = zotinfo(array('address' => $r[0]['xchan_addr']));
$result['zot'] = zotinfo( [ 'address' => $r[0]['xchan_addr'] ]);
}
}
else {
@ -132,7 +141,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
killme();
}
$arr = array('channel' => $r[0], 'request' => $_REQUEST, 'result' => $result);
$arr = [ 'channel' => $r[0], 'request' => $_REQUEST, 'result' => $result ];
call_hooks('webfinger',$arr);
json_return_and_die($arr['result'],'application/jrd+json');

View File

@ -3,6 +3,7 @@
namespace Zotlabs\Module;
use \Zotlabs\Lib as Zlib;
use \Michelf\MarkdownExtra;
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
@ -106,7 +107,8 @@ class Wiki extends \Zotlabs\Web\Controller {
}
$is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false);
$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
//$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
$o = '';
// Download a wiki
/*
@ -234,16 +236,17 @@ class Wiki extends \Zotlabs\Web\Controller {
$mimeType = $p['mimeType'];
$rawContent = htmlspecialchars_decode(json_decode($p['content']),ENT_COMPAT);
$sampleContent = (($mimeType == 'text/bbcode') ? '[h3]' . t('New page') . '[/h3]' : '### ' . t('New page'));
$content = (($p['content'] == '') ? $sampleContent : $p['content']);
$content = ($p['content'] !== '' ? $rawContent : '"# New page\n"');
// Render the Markdown-formatted page content in HTML
if($mimeType == 'text/bbcode') {
$renderedContent = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName);
}
else {
require_once('library/markdown.php');
$html = Zlib\NativeWikiPage::generate_toc(zidify_text(purify_html(Markdown(Zlib\NativeWikiPage::bbcode($content)))));
$content = Zlib\MarkdownSoap::unescape($content);
$html = Zlib\NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(Zlib\NativeWikiPage::bbcode($content))));
$renderedContent = Zlib\NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName);
}
$showPageControls = $wiki_editor;
@ -252,6 +255,7 @@ class Wiki extends \Zotlabs\Web\Controller {
goaway('/' . argv(0) . '/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName);
}
$wikiModalID = random_string(3);
$wikiModal = replace_macros(get_markup_template('generic_modal.tpl'), array(
@ -327,9 +331,12 @@ class Wiki extends \Zotlabs\Web\Controller {
$html = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL);
}
else {
require_once('library/markdown.php');
$content = Zlib\NativeWikiPage::bbcode($content);
$html = Zlib\NativeWikiPage::generate_toc(zidify_text(purify_html(Markdown($content))));
$bb = Zlib\NativeWikiPage::bbcode($content);
$x = new ZLib\MarkdownSoap($bb);
$md = $x->clean();
$md = ZLib\MarkdownSoap::unescape($md);
$html = MarkdownExtra::defaultTransform($md);
$html = Zlib\NativeWikiPage::generate_toc(zidify_text($html));
$html = Zlib\NativeWikiPage::convert_links($html,$wikiURL);
}
json_return_and_die(array('html' => $html, 'success' => true));
@ -356,6 +363,14 @@ class Wiki extends \Zotlabs\Web\Controller {
if($wiki['urlName'] === '') {
notice( t('Error creating wiki. Invalid name.') . EOL);
goaway('/wiki');
return; //not reached
}
$exists = Zlib\NativeWiki::exists_by_name($owner['channel_id'], $wiki['urlName']);
if($exists['id']) {
notice( t('A wiki with this name already exists.') . EOL);
goaway('/wiki');
return; //not reached
}
// Get ACL for permissions
@ -454,7 +469,11 @@ class Wiki extends \Zotlabs\Web\Controller {
json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false));
}
$page_list_html = widget_wiki_pages(array(
// @FIXME - we shouldn't invoke this if it isn't in the PDL or has been over-ridden
$x = new \Zotlabs\Widget\Wiki_pages();
$page_list_html = $x->widget(array(
'resource_id' => $resource_id,
'refresh' => true,
'channel' => argv(1)));
@ -512,7 +531,6 @@ class Wiki extends \Zotlabs\Web\Controller {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
// Determine if observer has permission to read content
$perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
@ -521,11 +539,12 @@ class Wiki extends \Zotlabs\Web\Controller {
json_return_and_die(array('historyHTML' => '', 'message' => 'Permission denied.', 'success' => false));
}
$historyHTML = widget_wiki_page_history(array(
$historyHTML = \Zotlabs\Lib\NativeWikiPage::render_page_history(array(
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName,
'permsWrite' => $perms['write']
));
json_return_and_die(array('historyHTML' => $historyHTML, 'message' => '', 'success' => true));
}

View File

@ -57,7 +57,7 @@ class Xrd extends \Zotlabs\Web\Controller {
'$aliases' => $aliases,
'$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'],
'$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'],
'$atom' => z_root() . '/feed/' . $r[0]['channel_address'],
'$atom' => z_root() . '/ofeed/' . $r[0]['channel_address'],
'$zot_post' => z_root() . '/post/' . $r[0]['channel_address'],
'$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'],
'$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'],

View File

@ -22,7 +22,8 @@ class Zotfeed extends \Zotlabs\Web\Controller {
$observer = \App::get_observer();
logger('observer: ' . get_observer_hash(), LOGGER_DEBUG);
$channel_address = ((argc() > 1) ? argv(1) : '');
if($channel_address) {
$r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1",

View File

@ -4,8 +4,6 @@ namespace Zotlabs\Render;
require_once('include/security.php');
require_once('include/menu.php');
require_once('include/widgets.php');
class Comanche {
@ -20,7 +18,49 @@ class Comanche {
$s = str_replace($mtch[0], '', $s);
}
}
/*
* This section supports the "switch" statement of the form given by the following
* example. The [default][/default] block must be the last in the arbitrary
* list of cases. The first case that matches the switch variable is used
* and the rest are not evaluated.
*
* [switch observer.language]
* [case de]
* [block]german-content[/block]
* [/case]
* [case es]
* [block]spanish-content[/block]
* [/case]
* [default]
* [block]english-content[/block]
* [/default]
* [/switch]
*/
$cnt = preg_match_all("/\[switch (.*?)\](.*?)\[default\](.*?)\[\/default\]\s*\[\/switch\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$switch_done = 0;
$switch_var = $this->get_condition_var($mtch[1]);
$default = $mtch[3];
$cases = array();
$cntt = preg_match_all("/\[case (.*?)\](.*?)\[\/case\]/ism", $mtch[2], $cases, PREG_SET_ORDER);
if($cntt) {
foreach($cases as $case) {
if($case[1] === $switch_var) {
$switch_done = 1;
$s = str_replace($mtch[0], $case[2], $s);
break;
}
}
if($switch_done === 0) {
$s = str_replace($mtch[0], $default, $s);
}
}
}
}
$cnt = preg_match_all("/\[if (.*?)\](.*?)\[else\](.*?)\[\/if\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
@ -410,6 +450,21 @@ class Comanche {
}
}
$clsname = ucfirst($name);
$nsname = "\\Zotlabs\\Widget\\" . $clsname;
if(file_exists('Zotlabs/SiteWidget/' . $clsname . '.php'))
require_once('Zotlabs/SiteWidget/' . $clsname . '.php');
elseif(file_exists('Zotlabs/Widget/' . $clsname . '.php'))
require_once('Zotlabs/Widget/' . $clsname . '.php');
if(class_exists($nsname)) {
$x = new $nsname;
$f = 'widget';
if(method_exists($x,$f)) {
return $x->$f($vars);
}
}
$func = 'widget_' . trim($name);
if(! function_exists($func)) {

View File

@ -84,7 +84,7 @@ class Browser extends DAV\Browser\Plugin {
require_once('include/conversation.php');
require_once('include/text.php');
if ($this->auth->owner_nick) {
$html = profile_tabs(get_app(), (($is_owner) ? true : false), $this->auth->owner_nick);
$html = '';
}
$files = $this->server->getPropertiesForPath($path, array(
@ -240,9 +240,11 @@ class Browser extends DAV\Browser\Plugin {
'$nick' => $this->auth->getCurrentUser()
));
$a = get_app();
$a = false;
\App::$page['content'] = $html;
load_pdl($a);
load_pdl();
$current_theme = \Zotlabs\Render\Theme::current();
@ -255,7 +257,7 @@ class Browser extends DAV\Browser\Plugin {
}
}
$this->server->httpResponse->setHeader('Content-Security-Policy', "script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
construct_page($a);
construct_page();
}
/**
@ -322,12 +324,16 @@ class Browser extends DAV\Browser\Plugin {
if(strpos($path,$special) === 0)
$path = trim(substr($path,$count),'/');
$info = t('Please use DAV to upload large (video, audio) files.<br>See <a class="zrl" href="help/member/member_guide#Cloud_Desktop_Clients">Cloud Desktop Clients</a>');
$output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array(
'$folder_header' => t('Create new folder'),
'$folder_submit' => t('Create'),
'$upload_header' => t('Upload file'),
'$upload_submit' => t('Upload'),
'$quota' => $quota,
'$info' => $info,
'$channick' => $this->auth->owner_nick,
'$aclselect' => $aclselect,
'$allow_cid' => acl2json($channel_acl['allow_cid']),

View File

@ -49,7 +49,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
* @param BasicAuth &$auth_plugin
*/
public function __construct($ext_path, &$auth_plugin) {
// $ext_path = urldecode($ext_path);
// $ext_path = urldecode($ext_path);
logger('directory ' . $ext_path, LOGGER_DATA);
$this->ext_path = $ext_path;
// remove "/cloud" from the beginning of the path
@ -167,6 +167,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
intval($this->auth->owner_id)
);
$x = attach_syspaths($this->auth->owner_id,$this->folder_hash);
$y = q("update attach set display_path = '%s where hash = '%s' and uid = %d",
dbesc($x['path']),
dbesc($this->folder_hash),
intval($this->auth->owner_id)
);
$ch = channelx_by_n($this->auth->owner_id);
if ($ch) {
$sync = attach_export_data($ch, $this->folder_hash);
@ -260,14 +268,18 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
dbesc($f),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
'', //TODO: use os_path
'', //TODO: use display_path
'',
'',
dbesc($allow_cid),
dbesc($allow_gid),
dbesc($deny_cid),
dbesc($deny_gid)
);
// fetch the actual storage paths
$xpath = attach_syspaths($this->auth->owner_id, $hash);
// returns the number of bytes that were written to the file, or FALSE on failure
$size = file_put_contents($f, $data);
// delete attach entry if file_put_contents() failed
@ -281,15 +293,17 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
$edited = datetime_convert();
$is_photo = 0;
$x = @getimagesize($f);
logger('getimagesize: ' . print_r($x,true), LOGGER_DATA);
if (($x) && ($x[2] === IMAGETYPE_GIF || $x[2] === IMAGETYPE_JPEG || $x[2] === IMAGETYPE_PNG)) {
$gis = @getimagesize($f);
logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA);
if (($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
$is_photo = 1;
}
// updates entry with filesize and timestamp
$d = q("UPDATE attach SET filesize = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d",
$d = q("UPDATE attach SET filesize = '%s', os_path = '%s', display_path = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d",
dbesc($size),
dbesc($xpath['os_path']),
dbesc($xpath['display_path']),
intval($is_photo),
dbesc($edited),
dbesc($hash),
@ -312,29 +326,29 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
// check against service class quota
$limit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit'));
if ($limit !== false) {
$x = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ",
$z = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ",
intval($c[0]['channel_account_id'])
);
if (($x) && ($x[0]['total'] + $size > $limit)) {
logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . userReadableSize($limit));
if (($z) && ($z[0]['total'] + $size > $limit)) {
logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $z[0]['total'] . ' limit is ' . userReadableSize($limit));
attach_delete($c[0]['channel_id'], $hash);
return;
}
}
if ($is_photo) {
if($is_photo) {
$album = '';
if ($this->folder_hash) {
$f1 = q("select filename from attach WHERE hash = '%s' AND uid = %d",
$f1 = q("select filename, display_path from attach WHERE hash = '%s' AND uid = %d",
dbesc($this->folder_hash),
intval($c[0]['channel_id'])
);
if ($f1)
$album = $f1[0]['filename'];
$album = (($f1[0]['display_path']) ? $f1[0]['display_path'] : $f1[0]['filename']);
}
require_once('include/photos.php');
$args = array( 'resource_id' => $hash, 'album' => $album, 'os_path' => $f, 'filename' => $name, 'getimagesize' => $x, 'directory' => $direct);
$args = array( 'resource_id' => $hash, 'album' => $album, 'os_syspath' => $f, 'os_path' => $xpath['os_path'], 'display_path' => $xpath['path'], 'filename' => $name, 'getimagesize' => $gis, 'directory' => $direct);
$p = photo_upload($c[0], \App::get_observer(), $args);
}
@ -646,20 +660,24 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
logger("Path mismatch: $path !== /$file");
return NULL;
}
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$prefix = 'DISTINCT ON (filename)';
$suffix = 'ORDER BY filename';
}
else {
$prefix = '';
$suffix = 'GROUP BY filename';
}
$prefix = '';
$suffix = '';
$r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix",
dbesc($folder),
intval($channel_id)
);
foreach ($r as $rr) {
// @FIXME I don't think we use revisions currently in attach structures.
// In case we see any in the wild provide a unique filename. This
// name may or may not be accessible
if($rr['revision'])
$rr['filename'] .= '-' . $rr['revision'];
//logger('filename: ' . $rr['filename'], LOGGER_DEBUG);
if (intval($rr['is_dir'])) {
$ret[] = new Directory($path . '/' . $rr['filename'], $auth);
@ -687,7 +705,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
$ret = array();
$r = q("SELECT channel_id, channel_address FROM channel WHERE channel_removed = 0
AND channel_system = 0 AND NOT (channel_pageflags & %d)>0",
AND channel_system = 0 AND (channel_pageflags & %d) = 0",
intval(PAGE_HIDDEN)
);

View File

@ -85,13 +85,23 @@ class File extends DAV\Node implements DAV\IFile {
intval($this->data['id'])
);
$x = attach_syspaths($this->auth->owner_id,$this->data['hash']);
$y = q("update attach set display_path = '%s where hash = '%s' and uid = %d",
dbesc($x['path']),
dbesc($this->data['hash']),
intval($this->auth->owner_id)
);
if($this->data->is_photo) {
$r = q("update photo set filename = '%s' where resource_id = '%s' and uid = %d",
$r = q("update photo set filename = '%s', display_path = '%s' where resource_id = '%s' and uid = %d",
dbesc($newName),
dbesc($x['path']),
dbesc($this->data['hash']),
intval($this->auth->owner_id)
);
}
$ch = channelx_by_n($this->auth->owner_id);
if($ch) {
$sync = attach_export_data($ch,$this->data['hash']);

View File

@ -62,12 +62,6 @@ class Router {
}
}
if((strpos($module,'admin') === 0) && (! is_site_admin())) {
\App::$module_loaded = false;
notice( t('Permission denied.') . EOL);
goaway(z_root());
}
/*
* If the site has a custom module to over-ride the standard module, use it.
* Otherwise, look for the standard program module
@ -208,7 +202,7 @@ class Router {
* The member may have also created a customised PDL that's stored in the config
*/
load_pdl($a);
load_pdl();
/*
* load current theme info

View File

@ -79,11 +79,6 @@ class WebServer {
if(! x($_SESSION, 'sysmsg_info'))
$_SESSION['sysmsg_info'] = array();
/*
* check_config() is responsible for running update scripts. These automatically
* update the DB schema whenever we push a new one out. It also checks to see if
* any plugins have been added or removed and reacts accordingly.
*/
if(\App::$install) {
@ -91,8 +86,16 @@ class WebServer {
if(\App::$module != 'view')
\App::$module = 'setup';
}
else
check_config($a);
else {
/*
* check_config() is responsible for running update scripts. These automatically
* update the DB schema whenever we push a new one out. It also checks to see if
* any plugins have been added or removed and reacts accordingly.
*/
check_config();
}
nav_set_selected('nothing');
@ -130,7 +133,7 @@ class WebServer {
call_hooks('page_end', \App::$page['content']);
construct_page($a);
construct_page();
killme();
}

View File

@ -0,0 +1,61 @@
<?php
namespace Zotlabs\Widget;
class Activity {
function widget($arr) {
if(! local_channel())
return '';
$o = '';
if(is_array($arr) && array_key_exists('limit',$arr))
$limit = " limit " . intval($limit) . " ";
else
$limit = '';
$perms_sql = item_permissions_sql(local_channel()) . item_normal();
$r = q("select author_xchan from item where item_unseen = 1 and uid = %d $perms_sql",
intval(local_channel())
);
$contributors = [];
$arr = [];
if($r) {
foreach($r as $rv) {
if(array_key_exists($rv['author_xchan'],$contributors)) {
$contributors[$rv['author_xchan']] ++;
}
else {
$contributors[$rv['author_xchan']] = 1;
}
}
foreach($contributors as $k => $v) {
$arr[] = [ 'author_xchan' => $k, 'total' => $v ];
}
usort($arr,'total_sort');
xchan_query($arr);
}
$x = [ 'entries' => $arr ];
call_hooks('activity_widget',$x);
$arr = $x['entries'];
if($arr) {
$o .= '<div class="widget">';
$o .= '<h3>' . t('Activity','widget') . '</h3><ul class="nav nav-pills flex-column">';
foreach($arr as $rv) {
$o .= '<li class="nav-item"><a class="nav-link" href="network?f=&xchan=' . urlencode($rv['author_xchan']) . '" ><span class="badge badge-default float-right">' . ((intval($rv['total'])) ? intval($rv['total']) : '') . '</span><img src="' . $rv['author']['xchan_photo_s'] . '" class="menu-img-1" /> ' . $rv['author']['xchan_name'] . '</a></li>';
}
$o .= '</ul></div>';
}
return $o;
}
}

68
Zotlabs/Widget/Admin.php Normal file
View File

@ -0,0 +1,68 @@
<?php
namespace Zotlabs\Widget;
class Admin {
function widget($arr) {
/*
* Side bar links
*/
if(! is_site_admin()) {
return '';
}
$o = '';
// array( url, name, extra css classes )
$aside = [
'site' => array(z_root() . '/admin/site/', t('Site'), 'site'),
'accounts' => array(z_root() . '/admin/accounts/', t('Accounts'), 'accounts', 'pending-update', t('Member registrations waiting for confirmation')),
'channels' => array(z_root() . '/admin/channels/', t('Channels'), 'channels'),
'security' => array(z_root() . '/admin/security/', t('Security'), 'security'),
'features' => array(z_root() . '/admin/features/', t('Features'), 'features'),
'plugins' => array(z_root() . '/admin/plugins/', t('Plugins'), 'plugins'),
'themes' => array(z_root() . '/admin/themes/', t('Themes'), 'themes'),
'queue' => array(z_root() . '/admin/queue', t('Inspect queue'), 'queue'),
'profs' => array(z_root() . '/admin/profs', t('Profile Fields'), 'profs'),
'dbsync' => array(z_root() . '/admin/dbsync/', t('DB updates'), 'dbsync')
];
/* get plugins admin page */
$r = q("SELECT * FROM addon WHERE plugin_admin = 1");
$plugins = array();
if($r) {
foreach ($r as $h){
$plugin = $h['aname'];
$plugins[] = array(z_root() . '/admin/plugins/' . $plugin, $plugin, 'plugin');
// temp plugins with admin
\App::$plugins_admin[] = $plugin;
}
}
$logs = array(z_root() . '/admin/logs/', t('Logs'), 'logs');
$arr = array('links' => $aside,'plugins' => $plugins,'logs' => $logs);
call_hooks('admin_aside',$arr);
$o .= replace_macros(get_markup_template('admin_aside.tpl'), array(
'$admin' => $aside,
'$admtxt' => t('Admin'),
'$plugadmtxt' => t('Plugin Features'),
'$plugins' => $plugins,
'$logtxt' => t('Logs'),
'$logs' => $logs,
'$h_pending' => t('Member registrations waiting for confirmation'),
'$admurl'=> z_root() . '/admin/'
));
return $o;
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace Zotlabs\Widget;
class Affinity {
function widget($arr) {
if(! local_channel())
return '';
// Get default cmin value from pconfig, but allow GET parameter to override
$cmin = intval(get_pconfig(local_channel(),'affinity','cmin'));
$cmin = (($cmin) ? $cmin : 0);
$cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $cmin);
// Get default cmax value from pconfig, but allow GET parameter to override
$cmax = intval(get_pconfig(local_channel(),'affinity','cmax'));
$cmax = (($cmax) ? $cmax : 99);
$cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $cmax);
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 . "'";
}
}
$tpl = get_markup_template('main_slider.tpl');
$x = replace_macros($tpl,array(
'$val' => $cmin . ',' . $cmax,
'$refresh' => t('Refresh'),
'$labels' => $label_str,
));
$arr = array('html' => $x);
call_hooks('main_slider',$arr);
return $arr['html'];
}
return '';
}
}

106
Zotlabs/Widget/Album.php Normal file
View File

@ -0,0 +1,106 @@
<?php
namespace Zotlabs\Widget;
require_once('include/attach.php');
class Album {
function widget($args) {
$owner_uid = \App::$profile_uid;
$sql_extra = permissions_sql($owner_uid);
if(! perm_is_allowed($owner_uid,get_observer_hash(),'view_storage'))
return '';
if($args['album'])
$album = $args['album'];
if($args['title'])
$title = $args['title'];
/**
* This may return incorrect permissions if you have multiple directories of the same name.
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
*/
if($album) {
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
dbesc($album),
intval($owner_uid)
);
if($x) {
$y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']);
if(! $y)
return '';
}
}
$order = 'DESC';
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
ORDER BY created $order ",
intval($owner_uid),
dbesc($album),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
);
//edit album name
$album_edit = null;
$photos = array();
if($r) {
$twist = 'rotright';
foreach($r as $rr) {
if($twist == 'rotright')
$twist = 'rotleft';
else
$twist = 'rotright';
$ext = $phototypes[$rr['mimetype']];
$imgalt_e = $rr['filename'];
$desc_e = $rr['description'];
$imagelink = (z_root() . '/photos/' . \App::$profile['channel_address'] . '/image/' . $rr['resource_id']);
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink,
'title' => t('View Photo'),
'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext,
'alt' => $imgalt_e,
'desc'=> $desc_e,
'ext' => $ext,
'hash'=> $rr['resource_id'],
'unknown' => t('Unknown')
);
}
}
$tpl = get_markup_template('photo_album.tpl');
$o .= replace_macros($tpl, array(
'$photos' => $photos,
'$album' => (($title) ? $title : $album),
'$album_id' => rand(),
'$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
'$order' => false,
'$upload_form' => $upload_form,
'$usage' => $usage_message
));
return $o;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Zotlabs\Widget;
class Appcategories {
function widget($arr) {
if(! local_channel())
return '';
$selected = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
// @FIXME ??? $srchurl undefined here - commented out until is reviewed
//$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
//$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
// Leaving this line which negates the effect of the two invalid lines prior
$srchurl = z_root() . '/apps';
$terms = array();
$r = q("select distinct(term.term)
from term join app on term.oid = app.id
where app_channel = %d
and term.uid = app_channel
and term.otype = %d
and term.term != 'nav_featured_app'
order by term.term asc",
intval(local_channel()),
intval(TERM_OBJ_APP)
);
if($r) {
foreach($r as $rr)
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('categories_widget.tpl'),array(
'$title' => t('Categories'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
'$terms' => $terms,
'$base' => $srchurl,
));
}
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Zotlabs\Widget;
class Appcloud {
function widget($arr) {
if(! local_channel())
return '';
return app_tagblock(z_root() . '/apps');
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Zotlabs\Widget;
class Archive {
function widget($arr) {
$o = '';
if(! \App::$profile_uid) {
return '';
}
$uid = \App::$profile_uid;
if(! feature_enabled($uid,'archives'))
return '';
if(! perm_is_allowed($uid,get_observer_hash(),'view_stream'))
return '';
$wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0);
$style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select');
$showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false);
$mindate = get_pconfig($uid,'system','archive_mindate');
$visible_years = get_pconfig($uid,'system','archive_visible_years');
if(! $visible_years)
$visible_years = 5;
$url = z_root() . '/' . \App::$cmd;
$ret = list_post_dates($uid,$wall,$mindate);
if(! count($ret))
return '';
$cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years;
$cutoff = ((array_key_exists($cutoff_year,$ret))? true : false);
$o = replace_macros(get_markup_template('posted_date_widget.tpl'),array(
'$title' => t('Archives'),
'$size' => $visible_years,
'$cutoff_year' => $cutoff_year,
'$cutoff' => $cutoff,
'$url' => $url,
'$style' => $style,
'$showend' => $showend,
'$dates' => $ret
));
return $o;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Zotlabs\Widget;
class Bookmarkedchats {
function widget($arr) {
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat'))
return '';
$h = get_observer_hash();
if(! $h)
return;
$r = q("select xchat_url, xchat_desc from xchat where xchat_xchan = '%s' order by xchat_desc",
dbesc($h)
);
if($r) {
for($x = 0; $x < count($r); $x ++) {
$r[$x]['xchat_url'] = zid($r[$x]['xchat_url']);
}
}
return replace_macros(get_markup_template('bookmarkedchats.tpl'),array(
'$header' => t('Bookmarked Chatrooms'),
'$rooms' => $r
));
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Zotlabs\Widget;
class Catcloud_wall {
function widget($arr) {
if((! \App::$profile['profile_uid']) || (! \App::$profile['channel_hash']))
return '';
if(! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_stream'))
return '';
$limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50);
return catblock(\App::$profile['profile_uid'], $limit, '', \App::$profile['channel_hash'], 'wall');
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
class Categories {
function widget($arr) {
if((! \App::$profile['profile_uid'])
|| (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_stream'))) {
return '';
}
$cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
$srchurl = \App::$query_string;
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
return categories_widget($srchurl, $cat);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Widget;
class Chatroom_list {
function widget($arr) {
if(! \App::$profile)
return '';
$r = \Zotlabs\Lib\Chatroom::roomlist(\App::$profile['profile_uid']);
if($r) {
return replace_macros(get_markup_template('chatroomlist.tpl'), array(
'$header' => t('Chatrooms'),
'$baseurl' => z_root(),
'$nickname' => \App::$profile['channel_address'],
'$items' => $r,
'$overview' => t('Overview')
));
}
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace Zotlabs\Widget;
class Chatroom_members {
// The actual contents are filled in via AJAX
function widget() {
return replace_macros(get_markup_template('chatroom_members.tpl'), array(
'$header' => t('Chat Members')
));
}
}

63
Zotlabs/Widget/Clock.php Normal file
View File

@ -0,0 +1,63 @@
<?php
namespace Zotlabs\Widget;
class Clock {
function widget($arr) {
$miltime = 0;
if(isset($arr['military']) && $arr['military'])
$miltime = 1;
$o = <<< EOT
<div class="widget">
<h3 class="clockface"></h3>
<script>
var timerID = null
var timerRunning = false
function stopclock(){
if(timerRunning)
clearTimeout(timerID)
timerRunning = false
}
function startclock(){
stopclock()
showtime()
}
function showtime(){
var now = new Date()
var hours = now.getHours()
var minutes = now.getMinutes()
var seconds = now.getSeconds()
var military = $miltime
var timeValue = ""
if(military)
timeValue = hours
else
timeValue = ((hours > 12) ? hours - 12 : hours)
timeValue += ((minutes < 10) ? ":0" : ":") + minutes
// timeValue += ((seconds < 10) ? ":0" : ":") + seconds
if(! military)
timeValue += (hours >= 12) ? " P.M." : " A.M."
$('.clockface').html(timeValue)
timerID = setTimeout("showtime()",1000)
timerRunning = true
}
$(document).ready(function() {
startclock();
});
</script>
</div>
EOT;
return $o;
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Zotlabs\Widget;
require_once('include/group.php');
class Collections {
function widget($args) {
$mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation');
switch($mode) {
case 'conversation':
$every = argv(0);
$each = argv(0);
$edit = true;
$current = $_REQUEST['gid'];
$abook_id = 0;
$wmode = 0;
break;
case 'connections':
$every = 'connections';
$each = 'group';
$edit = true;
$current = $_REQUEST['gid'];
$abook_id = 0;
$wmode = 0;
case 'groups':
$every = 'connections';
$each = argv(0);
$edit = false;
$current = intval(argv(1));
$abook_id = 0;
$wmode = 1;
break;
case 'abook':
$every = 'connections';
$each = 'group';
$edit = false;
$current = 0;
$abook_id = \App::$poi['abook_xchan'];
$wmode = 1;
break;
default:
return '';
break;
}
return group_side($every, $each, $edit, $current, $abook_id, $wmode);
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace Zotlabs\Widget;
class Conversations {
function widget($arr) {
if (! local_channel())
return;
if(argc() > 1) {
switch(argv(1)) {
case 'combined':
$mailbox = 'combined';
$header = t('Conversations');
break;
case 'inbox':
$mailbox = 'inbox';
$header = t('Received Messages');
break;
case 'outbox':
$mailbox = 'outbox';
$header = t('Sent Messages');
break;
default:
$mailbox = 'combined';
$header = t('Conversations');
break;
}
require_once('include/message.php');
// private_messages_list() can do other more complicated stuff, for now keep it simple
$r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']);
if(! $r) {
info( t('No messages.') . EOL);
return $o;
}
$messages = array();
foreach($r as $rr) {
$messages[] = array(
'mailbox' => $mailbox,
'id' => $rr['id'],
'from_name' => $rr['from']['xchan_name'],
'from_url' => chanlink_hash($rr['from_xchan']),
'from_photo' => $rr['from']['xchan_photo_s'],
'to_name' => $rr['to']['xchan_name'],
'to_url' => chanlink_hash($rr['to_xchan']),
'to_photo' => $rr['to']['xchan_photo_s'],
'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'),
'delete' => t('Delete conversation'),
'body' => $rr['body'],
'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], 'c'),
'seen' => $rr['seen'],
'selected' => ((argv(2)) ? (argv(2) == $rr['id']) : ($r[0]['id'] == $rr['id']))
);
}
$tpl = get_markup_template('mail_head.tpl');
$o .= replace_macros($tpl, array(
'$header' => $header,
'$messages' => $messages
));
}
return $o;
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace Zotlabs\Widget;
class Cover_photo {
function widget($arr) {
require_once('include/channel.php');
$o = '';
if(\App::$module == 'channel' && $_REQUEST['mid'])
return '';
$channel_id = 0;
if(array_key_exists('channel_id', $arr) && intval($arr['channel_id']))
$channel_id = intval($arr['channel_id']);
if(! $channel_id)
$channel_id = \App::$profile_uid;
if(! $channel_id)
return '';
$channel = channelx_by_n($channel_id);
if(array_key_exists('style', $arr) && isset($arr['style']))
$style = $arr['style'];
else
$style = 'width:100%; height: auto;';
// ensure they can't sneak in an eval(js) function
if(strpbrk($style,'(\'"<>') !== false)
$style = '';
if(array_key_exists('title', $arr) && isset($arr['title']))
$title = $arr['title'];
else
$title = $channel['channel_name'];
if(array_key_exists('subtitle', $arr) && isset($arr['subtitle']))
$subtitle = $arr['subtitle'];
else
$subtitle = str_replace('@','&#x40;',$channel['xchan_addr']);
$c = get_cover_photo($channel_id,'html');
if($c) {
$photo_html = (($style) ? str_replace('alt=',' style="' . $style . '" alt=',$c) : $c);
$o = replace_macros(get_markup_template('cover_photo_widget.tpl'),array(
'$photo_html' => $photo_html,
'$title' => $title,
'$subtitle' => $subtitle,
'$hovertitle' => t('Click to show more'),
));
}
return $o;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Zotlabs\Widget;
class Design_tools {
function widget($arr) {
// mod menu doesn't load a profile. For any modules which load a profile, check it.
// otherwise local_channel() is sufficient for permissions.
if(\App::$profile['profile_uid'])
if((\App::$profile['profile_uid'] != local_channel()) && (! \App::$is_sys))
return '';
if(! local_channel())
return '';
return design_tools();
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Zotlabs\Widget;
require_once('include/dir_fns.php');
class Dirsort {
function widget($arr) {
return dir_sort_links();
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Zotlabs\Widget;
require_once('include/dir_fns.php');
class Dirtags {
function widget($arr) {
return dir_tagblock(z_root() . '/directory', null);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Zotlabs\Widget;
class Eventstools {
function widget($arr) {
if(! local_channel())
return;
return replace_macros(get_markup_template('events_tools_side.tpl'), array(
'$title' => t('Events Tools'),
'$export' => t('Export Calendar'),
'$import' => t('Import Calendar'),
'$submit' => t('Submit')
));
}
}

36
Zotlabs/Widget/Filer.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
class Filer {
function widget($arr) {
if(! local_channel())
return '';
$selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : '');
$terms = 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(! $r)
return;
foreach($r as $rr)
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('fileas_widget.tpl'),array(
'$title' => t('Saved Folders'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
'$terms' => $terms,
'$base' => z_root() . '/' . \App::$cmd
));
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
class Findpeople {
function widget($arr) {
return findpeople_widget();
}
}

37
Zotlabs/Widget/Follow.php Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace Zotlabs\Widget;
class Follow {
function widget($args) {
if(! local_channel())
return '';
$uid = \App::$channel['channel_id'];
$r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ",
intval($uid)
);
if($r)
$total_channels = $r[0]['total'];
$limit = service_class_fetch($uid,'total_channels');
if($limit !== false) {
$abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total_channels, $limit);
}
else {
$abook_usage_message = '';
}
return replace_macros(get_markup_template('follow.tpl'),array(
'$connect' => t('Add New Connection'),
'$desc' => t('Enter channel address'),
'$hint' => t('Examples: bob@example.com, https://example.com/barbara'),
'$follow' => t('Connect'),
'$abook_usage_message' => $abook_usage_message
));
}
}

97
Zotlabs/Widget/Forums.php Normal file
View File

@ -0,0 +1,97 @@
<?php
namespace Zotlabs\Widget;
class Forums {
function widget($arr) {
if(! local_channel())
return '';
$o = '';
if(is_array($arr) && array_key_exists('limit',$arr))
$limit = " limit " . intval($limit) . " ";
else
$limit = '';
$unseen = 0;
if(is_array($arr) && array_key_exists('unseen',$arr) && intval($arr['unseen']))
$unseen = 1;
$perms_sql = item_permissions_sql(local_channel()) . item_normal();
$xf = false;
$x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = '0'",
intval(local_channel())
);
if($x1) {
$xc = ids_to_querystr($x1,'xchan',true);
$x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = '1' and xchan in (" . $xc . ") ",
intval(local_channel())
);
if($x2)
$xf = ids_to_querystr($x2,'xchan',true);
}
$sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
$r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d $sql_extra order by xchan_name $limit ",
intval(local_channel())
);
if(! $r1)
return $o;
$str = '';
// Trying to cram all this into a single query with joins and the proper group by's is tough.
// There also should be a way to update this via ajax.
for($x = 0; $x < count($r1); $x ++) {
$r = q("select sum(item_unseen) as unseen from item where owner_xchan = '%s' and uid = %d and item_unseen = 1 $perms_sql ",
dbesc($r1[$x]['xchan_hash']),
intval(local_channel())
);
if($r)
$r1[$x]['unseen'] = $r[0]['unseen'];
/**
* @FIXME
* This SQL makes the counts correct when you get forum posts arriving from different routes/sources
* (like personal channels). However the network query for these posts doesn't yet include this
* correction and it makes the SQL for that query pretty hairy so this is left as a future exercise.
* It may make more sense in that query to look for the mention in the body rather than another join,
* but that makes it very inefficient.
*
$r = q("select sum(item_unseen) as unseen from item left join term on oid = id where otype = %d and owner_xchan != '%s' and item.uid = %d and url = '%s' and ttype = %d $perms_sql ",
intval(TERM_OBJ_POST),
dbesc($r1[$x]['xchan_hash']),
intval(local_channel()),
dbesc($r1[$x]['xchan_url']),
intval(TERM_MENTION)
);
if($r)
$r1[$x]['unseen'] = ((array_key_exists('unseen',$r1[$x])) ? $r1[$x]['unseen'] + $r[0]['unseen'] : $r[0]['unseen']);
*
* end @FIXME
*/
}
if($r1) {
$o .= '<div class="widget">';
$o .= '<h3>' . t('Forums') . '</h3><ul class="nav nav-pills flex-column">';
foreach($r1 as $rr) {
if($unseen && (! intval($rr['unseen'])))
continue;
$o .= '<li class="nav-item"><a class="nav-link" href="network?f=&pf=1&cid=' . $rr['abook_id'] . '" ><span class="badge badge-default float-right">' . ((intval($rr['unseen'])) ? intval($rr['unseen']) : '') . '</span><img class ="menu-img-1" src="' . $rr['xchan_photo_s'] . '" /> ' . $rr['xchan_name'] . '</a></li>';
}
$o .= '</ul></div>';
}
return $o;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Zotlabs\Widget;
class Fullprofile {
function widget($arr) {
if(! \App::$profile['profile_uid'])
return;
$block = observer_prohibited();
return profile_sidebar(\App::$profile, $block);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace Zotlabs\Widget;
class Helpindex {
function widget($arr) {
$o .= '<div class="widget">';
$level_0 = get_help_content('sitetoc');
if(! $level_0)
$level_0 = get_help_content('toc');
$level_0 = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$level_0);
$levels = array();
if(argc() > 2) {
$path = '';
for($x = 1; $x < argc(); $x ++) {
$path .= argv($x) . '/';
$y = get_help_content($path . 'sitetoc');
if(! $y)
$y = get_help_content($path . 'toc');
if($y)
$levels[] = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$y);
}
}
if($level_0)
$o .= $level_0;
if($levels) {
foreach($levels as $l) {
$o .= '<br /><br />';
$o .= $l;
}
}
$o .= '</div>';
return $o;
}
}

54
Zotlabs/Widget/Item.php Normal file
View File

@ -0,0 +1,54 @@
<?php
namespace Zotlabs\Widget;
require_once('include/security.php');
class Item {
function widget($arr) {
$channel_id = 0;
if(array_key_exists('channel_id',$arr) && intval($arr['channel_id']))
$channel_id = intval($arr['channel_id']);
if(! $channel_id)
$channel_id = \App::$profile_uid;
if(! $channel_id)
return '';
if((! $arr['mid']) && (! $arr['title']))
return '';
if(! perm_is_allowed($channel_id, get_observer_hash(), 'view_pages'))
return '';
$sql_extra = item_permissions_sql($channel_id);
if($arr['title']) {
$r = q("select item.* from item left join iconfig on item.id = iconfig.iid
where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s'
and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1",
intval($channel_id),
dbesc($arr['title']),
intval(ITEM_TYPE_WEBPAGE)
);
}
else {
$r = q("select * from item where mid = '%s' and uid = %d and item_type = "
. intval(ITEM_TYPE_WEBPAGE) . " $sql_extra limit 1",
dbesc($arr['mid']),
intval($channel_id)
);
}
if(! $r)
return '';
xchan_query($r);
$r = fetch_post_tags($r, true);
$o = prepare_page($r[0]);
return $o;
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Widget;
class Mailmenu {
function widget($arr) {
if (! local_channel())
return;
return replace_macros(get_markup_template('message_side.tpl'), array(
'$title' => t('Private Mail Menu'),
'$combined' => array(
'label' => t('Combined View'),
'url' => z_root() . '/mail/combined',
'sel' => (argv(1) == 'combined'),
),
'$inbox' => array(
'label' => t('Inbox'),
'url' => z_root() . '/mail/inbox',
'sel' => (argv(1) == 'inbox'),
),
'$outbox' => array(
'label' => t('Outbox'),
'url' => z_root() . '/mail/outbox',
'sel' => (argv(1) == 'outbox'),
),
'$new' => array(
'label' => t('New Message'),
'url' => z_root() . '/mail/new',
'sel'=> (argv(1) == 'new'),
)
));
}
}

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