aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/BaseObject.php38
-rw-r--r--include/ConversationObject.php225
-rwxr-xr-xinclude/ITemplateEngine.php10
-rw-r--r--include/Import/import_diaspora.php1
-rw-r--r--include/ItemObject.php773
-rw-r--r--include/ProtoDriver.php43
-rw-r--r--include/account.php32
-rw-r--r--include/acl_selectors.php81
-rw-r--r--include/activities.php3
-rw-r--r--include/api.php107
-rw-r--r--include/api_auth.php14
-rw-r--r--include/apps.php511
-rw-r--r--include/attach.php50
-rw-r--r--include/auth.php159
-rw-r--r--include/bb2diaspora.php38
-rw-r--r--include/bbcode.php187
-rw-r--r--include/cache.php44
-rw-r--r--include/channel.php (renamed from include/identity.php)499
-rw-r--r--include/chat.php262
-rw-r--r--include/checksites.php62
-rw-r--r--include/cli_startup.php31
-rw-r--r--include/cli_suggest.php22
-rw-r--r--include/comanche.php383
-rw-r--r--include/config.php581
-rw-r--r--include/connections.php (renamed from include/Contact.php)61
-rw-r--r--include/contact_selectors.php97
-rw-r--r--include/contact_widgets.php14
-rw-r--r--include/conversation.php184
-rw-r--r--include/cronhooks.php23
-rw-r--r--include/crypto.php24
-rw-r--r--include/datetime.php9
-rwxr-xr-xinclude/dba/dba_driver.php201
-rwxr-xr-xinclude/dba/dba_mysqli.php26
-rwxr-xr-xinclude/dba/dba_pdo.php95
-rw-r--r--include/dba/dba_postgres.php4
-rw-r--r--include/deliver.php87
-rw-r--r--include/deliver_hooks.php29
-rw-r--r--include/dir_fns.php8
-rw-r--r--include/directory.php113
-rw-r--r--include/enotify.php652
-rw-r--r--include/environment.php2
-rw-r--r--include/event.php252
-rw-r--r--include/expire.php98
-rw-r--r--include/externals.php103
-rw-r--r--include/features.php2
-rw-r--r--include/feedutils.php1315
-rw-r--r--include/follow.php59
-rw-r--r--include/gprobe.php38
-rw-r--r--include/group.php38
-rw-r--r--include/help.php149
-rw-r--r--include/hubloc.php2
-rw-r--r--include/import.php280
-rwxr-xr-xinclude/importdoc.php41
-rwxr-xr-xinclude/items.php1806
-rw-r--r--include/js_strings.php8
-rw-r--r--include/language.php12
-rw-r--r--include/message.php2
-rw-r--r--include/nav.php38
-rw-r--r--include/network.php158
-rw-r--r--include/notifier.php646
-rw-r--r--include/notify.php37
-rw-r--r--include/oauth.php14
-rwxr-xr-xinclude/oembed.php183
-rw-r--r--include/onedirsync.php82
-rw-r--r--include/onepoll.php159
-rw-r--r--include/page_widgets.php11
-rw-r--r--include/perm_upgrade.php236
-rw-r--r--include/permissions.php519
-rw-r--r--include/photo/photo_driver.php56
-rw-r--r--include/photos.php145
-rwxr-xr-xinclude/plugin.php169
-rw-r--r--include/poller.php436
-rw-r--r--include/queue.php95
-rw-r--r--include/ratenotif.php119
-rw-r--r--include/reddav.php299
-rw-r--r--include/security.php96
-rw-r--r--include/selectors.php (renamed from include/profile_selectors.php)44
-rw-r--r--include/sharedwithme.php4
-rwxr-xr-xinclude/smarty.php114
-rw-r--r--include/socgraph.php10
-rw-r--r--include/spam.php35
-rw-r--r--include/taxonomy.php108
-rwxr-xr-xinclude/template_processor.php307
-rw-r--r--include/text.php492
-rw-r--r--include/widgets.php248
-rw-r--r--include/wiki.php571
-rw-r--r--include/zot.php364
87 files changed, 5649 insertions, 10136 deletions
diff --git a/include/BaseObject.php b/include/BaseObject.php
deleted file mode 100644
index a88978a83..000000000
--- a/include/BaseObject.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php /** @file */
-
-if(class_exists('BaseObject'))
- return;
-
-require_once('boot.php');
-
-/**
- * Basic object
- *
- * Contains what is usefull to any object
- */
-class BaseObject {
- private static $app = null;
-
- /**
- * Get the app
- *
- * Same as get_app from boot.php
- */
- public function get_app() {
- if(self::$app)
- return self::$app;
-
- global $a;
- self::$app = $a;
-
- return self::$app;
- }
-
- /**
- * Set the app
- */
- public static function set_app($app) {
- self::$app = $app;
- }
-}
-
diff --git a/include/ConversationObject.php b/include/ConversationObject.php
deleted file mode 100644
index 82f381b0c..000000000
--- a/include/ConversationObject.php
+++ /dev/null
@@ -1,225 +0,0 @@
-<?php /** @file */
-
-if(class_exists('Conversation'))
- return;
-
-require_once('boot.php');
-require_once('include/BaseObject.php');
-require_once('include/ItemObject.php');
-require_once('include/text.php');
-require_once('include/items.php');
-
-/**
- * A list of threads
- *
- */
-
-class Conversation extends BaseObject {
-
- private $threads = array();
- private $mode = null;
- private $observer = null;
- private $writable = false;
- private $commentable = false;
- private $profile_owner = 0;
- private $preview = false;
- private $prepared_item = '';
- private $cipher = 'aes256';
-
- // $prepared_item is for use by alternate conversation structures such as photos
- // wherein we've already prepared a top level item which doesn't look anything like
- // a normal "post" item
-
- public function __construct($mode, $preview, $prepared_item = '') {
- $this->set_mode($mode);
- $this->preview = $preview;
- $this->prepared_item = $prepared_item;
- $c = ((local_channel()) ? get_pconfig(local_channel(),'system','default_cipher') : '');
- if($c)
- $this->cipher = $c;
- }
-
- /**
- * Set the mode we'll be displayed on
- */
- private function set_mode($mode) {
- if($this->get_mode() == $mode)
- return;
-
- $a = $this->get_app();
-
- $this->observer = App::get_observer();
- $ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
-
- switch($mode) {
- case 'network':
- $this->profile_owner = local_channel();
- $this->writable = true;
- break;
- case 'channel':
- $this->profile_owner = App::$profile['profile_uid'];
- $this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
- break;
- case 'display':
- // in this mode we set profile_owner after initialisation (from conversation()) and then
- // pull some trickery which allows us to re-invoke this function afterward
- // it's an ugly hack so FIXME
- $this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
- break;
- case 'page':
- $this->profile_owner = App::$profile['uid'];
- $this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
- break;
- default:
- logger('[ERROR] Conversation::set_mode : Unhandled mode ('. $mode .').', LOGGER_DEBUG);
- return false;
- break;
- }
- $this->mode = $mode;
- }
-
- /**
- * Get mode
- */
- public function get_mode() {
- return $this->mode;
- }
-
- /**
- * Check if page is writable
- */
- public function is_writable() {
- return $this->writable;
- }
-
- public function is_commentable() {
- return $this->commentable;
- }
-
- /**
- * Check if page is a preview
- */
- public function is_preview() {
- return $this->preview;
- }
-
- /**
- * Get profile owner
- */
- public function get_profile_owner() {
- return $this->profile_owner;
- }
-
- public function set_profile_owner($uid) {
- $this->profile_owner = $uid;
- $mode = $this->get_mode();
- $this->mode = null;
- $this->set_mode($mode);
- }
-
- public function get_observer() {
- return $this->observer;
- }
-
- public function get_cipher() {
- return $this->cipher;
- }
-
-
- /**
- * Add a thread to the conversation
- *
- * Returns:
- * _ The inserted item on success
- * _ false on failure
- */
- public function add_thread($item) {
- $item_id = $item->get_id();
- if(!$item_id) {
- logger('Item has no ID!!', LOGGER_DEBUG, LOG_ERR);
- return false;
- }
- if($this->get_thread($item->get_id())) {
- logger('Thread already exists ('. $item->get_id() .').', LOGGER_DEBUG, LOG_WARNING);
- return false;
- }
-
- /*
- * Only add things that will be displayed
- */
-
-
- if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
- return false;
- }
-
- $item->set_commentable(false);
- $ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
-
- if(! comments_are_now_closed($item->get_data())) {
- if(($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash))
- $item->set_commentable(true);
-
- if(intval($item->get_data_value('item_nocomment'))) {
- $item->set_commentable(false);
- }
- elseif(($this->observer) && (! $item->is_commentable())) {
- if((array_key_exists('owner',$item->data)) && intval($item->data['owner']['abook_self']))
- $item->set_commentable(perm_is_allowed($this->profile_owner,$this->observer['xchan_hash'],'post_comments'));
- else
- $item->set_commentable(can_comment_on_post($this->observer['xchan_hash'],$item->data));
- }
- }
- require_once('include/identity.php');
-
- $item->set_conversation($this);
- $this->threads[] = $item;
- return end($this->threads);
- }
-
- /**
- * Get data in a form usable by a conversation template
- *
- * We should find a way to avoid using those arguments (at least most of them)
- *
- * Returns:
- * _ The data requested on success
- * _ false on failure
- */
- public function get_template_data($conv_responses) {
- $result = array();
-
- foreach($this->threads as $item) {
-
- if(($item->get_data_value('id') == $item->get_data_value('parent')) && $this->prepared_item) {
- $item_data = $this->prepared_item;
- }
- else {
- $item_data = $item->get_template_data($conv_responses);
- }
- if(!$item_data) {
- logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
- return false;
- }
- $result[] = $item_data;
- }
-
- return $result;
- }
-
- /**
- * Get a thread based on its item id
- *
- * Returns:
- * _ The found item on success
- * _ false on failure
- */
- private function get_thread($id) {
- foreach($this->threads as $item) {
- if($item->get_id() == $id)
- return $item;
- }
-
- return false;
- }
-}
diff --git a/include/ITemplateEngine.php b/include/ITemplateEngine.php
deleted file mode 100755
index 7bd559a63..000000000
--- a/include/ITemplateEngine.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-require_once 'boot.php';
-
-/**
- * @brief Interface for template engines.
- */
-interface ITemplateEngine {
- public function replace_macros($s, $v);
- public function get_markup_template($file, $root='');
-}
diff --git a/include/Import/import_diaspora.php b/include/Import/import_diaspora.php
index a94e73395..b664badf1 100644
--- a/include/Import/import_diaspora.php
+++ b/include/Import/import_diaspora.php
@@ -6,7 +6,6 @@ require_once('include/follow.php');
require_once('include/photo/photo_driver.php');
function import_diaspora($data) {
- $a = get_app();
$account = App::get_account();
if(! $account)
diff --git a/include/ItemObject.php b/include/ItemObject.php
deleted file mode 100644
index 9d5acd95f..000000000
--- a/include/ItemObject.php
+++ /dev/null
@@ -1,773 +0,0 @@
-<?php /** @file */
-
-if(class_exists('Item'))
- return;
-
-require_once('include/BaseObject.php');
-require_once('include/text.php');
-require_once('boot.php');
-
-/**
- * An item
- */
-
-class Item extends BaseObject {
- public $data = array();
- private $template = 'conv_item.tpl';
- private $comment_box_template = 'comment_item.tpl';
- private $commentable = false;
- private $toplevel = false;
- private $children = array();
- private $parent = null;
- private $conversation = null;
- private $redirect_url = null;
- private $owner_url = '';
- private $owner_photo = '';
- private $owner_name = '';
- private $wall_to_wall = false;
- private $threaded = false;
- private $visiting = false;
- private $channel = null;
- private $display_mode = 'normal';
-
-
- public function __construct($data) {
- $a = $this->get_app();
-
- $this->data = $data;
- $this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
-
- // Prepare the children
- if(count($data['children'])) {
- foreach($data['children'] as $item) {
-
- /*
- * Only add those that will be displayed
- */
-
- if((! visible_activity($item)) || array_key_exists('author_blocked',$item)) {
- continue;
- }
-
- $child = new Item($item);
- $this->add_child($child);
- }
- }
- }
-
- /**
- * Get data in a form usable by a conversation template
- *
- * Returns:
- * _ The data requested on success
- * _ false on failure
- */
-
- public function get_template_data($conv_responses, $thread_level=1) {
-
- $result = array();
-
- $a = $this->get_app();
- $item = $this->get_data();
-
- $commentww = '';
- $sparkle = '';
- $buttons = '';
- $dropping = false;
- $star = false;
- $isstarred = "unstarred icon-star-empty";
- $indent = '';
- $osparkle = '';
- $total_children = $this->count_descendants();
- $unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
-
- $conv = $this->get_conversation();
- $observer = $conv->get_observer();
-
- $lock = ((($item['item_private'] == 1) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
- || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
- ? t('Private Message')
- : false);
- $shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
-
- // allow an exemption for sharing stuff from your private feeds
- if($item['author']['xchan_network'] === 'rss')
- $shareable = true;
-
- $mode = $conv->get_mode();
-
- if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
- $edpost = array(z_root()."/editpost/".$item['id'], t("Edit"));
- else
- $edpost = false;
-
-
- if($observer['xchan_hash'] == $this->get_data_value('author_xchan')
- || $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
- || $this->get_data_value('uid') == local_channel())
- $dropping = true;
-
-
- if(array_key_exists('real_uid',$item)) {
- $edpost = false;
- $dropping = false;
- }
-
-
- if($dropping) {
- $drop = array(
- 'dropping' => $dropping,
- 'delete' => t('Delete'),
- );
- }
-// FIXME
- if($observer_is_pageowner) {
- $multidrop = array(
- 'select' => t('Select'),
- );
- }
-
- $filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
-
- $profile_avatar = $item['author']['xchan_photo_m'];
- $profile_link = chanlink_url($item['author']['xchan_url']);
- $profile_name = $item['author']['xchan_name'];
-
- $location = format_location($item);
- $isevent = false;
- $attend = null;
- $canvote = false;
-
- // process action responses - e.g. like/dislike/attend/agree/whatever
- $response_verbs = array('like');
- if(feature_enabled($conv->get_profile_owner(),'dislike'))
- $response_verbs[] = 'dislike';
- if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
- $response_verbs[] = 'attendyes';
- $response_verbs[] = 'attendno';
- $response_verbs[] = 'attendmaybe';
- if($this->is_commentable()) {
- $isevent = true;
- $attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
- }
- }
-
- $consensus = (intval($item['item_consensus']) ? true : false);
- if($consensus) {
- $response_verbs[] = 'agree';
- $response_verbs[] = 'disagree';
- $response_verbs[] = 'abstain';
- if($this->is_commentable()) {
- $conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
- $canvote = true;
- }
- }
-
- if(! feature_enabled($conv->get_profile_owner(),'dislike'))
- unset($conv_responses['dislike']);
-
- $responses = get_responses($conv_responses,$response_verbs,$this,$item);
-
- $like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
- $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>');
- } else {
- $like_list_part = '';
- }
- $like_button_label = tt('Like','Likes',$like_count,'noun');
-
- if (feature_enabled($conv->get_profile_owner(),'dislike')) {
- $dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
- $dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
- $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>');
- } else {
- $dislike_list_part = '';
- }
- }
-
- $showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
- $showdislike = ((x($conv_responses['dislike'],$item['mid']) && feature_enabled($conv->get_profile_owner(),'dislike'))
- ? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
-
- /*
- * We should avoid doing this all the time, but it depends on the conversation mode
- * And the conv mode may change when we change the conv, or it changes its mode
- * Maybe we should establish a way to be notified about conversation changes
- */
-
- $this->check_wall_to_wall();
-
- if($this->is_toplevel()) {
- // FIXME check this permission
- if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
-
-// FIXME we don't need all this stuff, some can be done in the template
-
- $star = array(
- 'do' => t("Add Star"),
- 'undo' => t("Remove Star"),
- 'toggle' => t("Toggle Star Status"),
- 'classdo' => (intval($item['item_starred']) ? "hidden" : ""),
- 'classundo' => (intval($item['item_starred']) ? "" : "hidden"),
- 'isstarred' => (intval($item['item_starred']) ? "starred icon-star" : "unstarred icon-star-empty"),
- 'starred' => t('starred'),
- );
-
- }
- } else {
- $indent = 'comment';
- }
-
-
- $verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
- $forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
- $unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
-
-
-
- // FIXME - check this permission
- if($conv->get_profile_owner() == local_channel()) {
- $tagger = array(
- 'tagit' => t("Add Tag"),
- 'classtagger' => "",
- );
- }
-
- $has_bookmarks = false;
- if(is_array($item['term'])) {
- foreach($item['term'] as $t) {
- if(!UNO && $t['type'] == TERM_BOOKMARK)
- $has_bookmarks = true;
- }
- }
-
- $has_event = false;
- if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
- $has_event = true;
-
- if($this->is_commentable()) {
- $like = array( t("I like this \x28toggle\x29"), t("like"));
- $dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
- }
-
- if ($shareable)
- $share = array( t('Share This'), t('share'));
-
- $dreport = '';
-
- $keep_reports = intval(get_config('system','expire_delivery_reports'));
- if($keep_reports === 0)
- $keep_reports = 30;
-
- 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';
-
-
- localize_item($item);
-
- $body = prepare_body($item,true);
-
- // $viewthread (below) is only valid in list mode. If this is a channel page, build the thread viewing link
- // since we can't depend on llink or plink pointing to the right local location.
-
- $owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
- $viewthread = $item['llink'];
- if($conv->get_mode() === 'channel')
- $viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . $item['mid'];
-
- $comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
- $list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
-
-
-
-
-
- $children = $this->get_children();
-
- $has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
-
- $tmp_item = array(
- 'template' => $this->get_template(),
- 'mode' => $mode,
- 'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
- 'body' => $body['html'],
- 'tags' => $body['tags'],
- 'categories' => $body['categories'],
- 'mentions' => $body['mentions'],
- 'attachments' => $body['attachments'],
- 'folders' => $body['folders'],
- 'text' => strip_tags($body['html']),
- 'id' => $this->get_id(),
- 'mid' => $item['mid'],
- 'isevent' => $isevent,
- 'attend' => $attend,
- 'consensus' => $consensus,
- 'conlabels' => $conlabels,
- 'canvote' => $canvote,
- 'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
- 'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
- 'llink' => $item['llink'],
- 'viewthread' => $viewthread,
- 'to' => t('to'),
- 'via' => t('via'),
- 'wall' => t('Wall-to-Wall'),
- 'vwall' => t('via Wall-To-Wall:'),
- 'profile_url' => $profile_link,
- 'item_photo_menu' => item_photo_menu($item),
- 'dreport' => $dreport,
- 'name' => $profile_name,
- 'thumb' => $profile_avatar,
- 'osparkle' => $osparkle,
- 'sparkle' => $sparkle,
- 'title' => $item['title'],
- 'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
- 'ago' => relative_date($item['created']),
- 'app' => $item['app'],
- 'str_app' => sprintf( t('from %s'), $item['app']),
- 'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
- 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
- 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
- 'expiretime' => (($item['expires'] !== NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
- 'lock' => $lock,
- 'verified' => $verified,
- 'unverified' => $unverified,
- 'forged' => $forged,
- 'location' => $location,
- 'indent' => $indent,
- 'owner_url' => $this->get_owner_url(),
- 'owner_photo' => $this->get_owner_photo(),
- 'owner_name' => $this->get_owner_name(),
- 'photo' => $body['photo'],
- 'event' => $body['event'],
- 'has_tags' => $has_tags,
-
-// Item toolbar buttons
- 'like' => $like,
- 'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
- 'share' => $share,
- 'rawmid' => $item['mid'],
- 'plink' => get_plink($item),
- 'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
- 'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
- 'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
- 'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
- 'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
- 'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
- 'drop' => $drop,
- 'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
-// end toolbar buttons
-
- 'unseen_comments' => $unseen_comments,
- 'comment_count' => $total_children,
- 'comment_count_txt' => $comment_count_txt,
- 'list_unseen_txt' => $list_unseen_txt,
- 'markseen' => t('Mark all seen'),
- 'responses' => $responses,
- 'like_count' => $like_count,
- 'like_list' => $like_list,
- 'like_list_part' => $like_list_part,
- 'like_button_label' => $like_button_label,
- 'like_modal_title' => t('Likes','noun'),
- 'dislike_modal_title' => t('Dislikes','noun'),
- 'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
- 'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
- 'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
- 'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
- 'modal_dismiss' => t('Close'),
- 'showlike' => $showlike,
- 'showdislike' => $showdislike,
- 'comment' => $this->get_comment_box($indent),
- 'previewing' => ($conv->is_preview() ? ' preview ' : ''),
- 'wait' => t('Please wait'),
- 'thread_level' => $thread_level
- );
-
- $arr = array('item' => $item, 'output' => $tmp_item);
- call_hooks('display_item', $arr);
-
- $result = $arr['output'];
-
- $result['children'] = array();
- $nb_children = count($children);
-
- $visible_comments = get_config('system','expanded_comments');
- if($visible_comments === false)
- $visible_comments = 3;
-
- if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
- foreach($children as $child) {
- $result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1);
- }
- // Collapse
- if(($nb_children > $visible_comments) || ($thread_level > 1)) {
- $result['children'][0]['comment_firstcollapsed'] = true;
- $result['children'][0]['num_comments'] = $comment_count_txt;
- $result['children'][0]['hide_text'] = t('[+] show all');
- if($thread_level > 1) {
- $result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
- }
- else {
- $result['children'][$nb_children - ($visible_comments + 1)]['comment_lastcollapsed'] = true;
- }
- }
- }
-
- $result['private'] = $item['item_private'];
- $result['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : '');
-
- if($this->is_threaded()) {
- $result['flatten'] = false;
- $result['threaded'] = true;
- }
- else {
- $result['flatten'] = true;
- $result['threaded'] = false;
- }
-
- return $result;
- }
-
- public function get_id() {
- return $this->get_data_value('id');
- }
-
- public function get_display_mode() {
- return $this->display_mode;
- }
-
- public function set_display_mode($mode) {
- $this->display_mode = $mode;
- }
-
- public function is_threaded() {
- return $this->threaded;
- }
-
- public function set_commentable($val) {
- $this->commentable = $val;
- foreach($this->get_children() as $child)
- $child->set_commentable($val);
- }
-
- public function is_commentable() {
- return $this->commentable;
- }
-
- /**
- * Add a child item
- */
- public function add_child($item) {
- $item_id = $item->get_id();
- if(!$item_id) {
- logger('[ERROR] Item::add_child : Item has no ID!!', LOGGER_DEBUG);
- return false;
- }
- if($this->get_child($item->get_id())) {
- logger('[WARN] Item::add_child : Item already exists ('. $item->get_id() .').', LOGGER_DEBUG);
- return false;
- }
- /*
- * Only add what will be displayed
- */
-
- if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
- return false;
- }
-
- $item->set_parent($this);
- $this->children[] = $item;
- return end($this->children);
- }
-
- /**
- * Get a child by its ID
- */
- public function get_child($id) {
- foreach($this->get_children() as $child) {
- if($child->get_id() == $id)
- return $child;
- }
- return null;
- }
-
- /**
- * Get all our children
- */
- public function get_children() {
- return $this->children;
- }
-
- /**
- * Set our parent
- */
- protected function set_parent($item) {
- $parent = $this->get_parent();
- if($parent) {
- $parent->remove_child($this);
- }
- $this->parent = $item;
- $this->set_conversation($item->get_conversation());
- }
-
- /**
- * Remove our parent
- */
- protected function remove_parent() {
- $this->parent = null;
- $this->conversation = null;
- }
-
- /**
- * Remove a child
- */
- public function remove_child($item) {
- $id = $item->get_id();
- foreach($this->get_children() as $key => $child) {
- if($child->get_id() == $id) {
- $child->remove_parent();
- unset($this->children[$key]);
- // Reindex the array, in order to make sure there won't be any trouble on loops using count()
- $this->children = array_values($this->children);
- return true;
- }
- }
- logger('[WARN] Item::remove_child : Item is not a child ('. $id .').', LOGGER_DEBUG);
- return false;
- }
-
- /**
- * Get parent item
- */
- protected function get_parent() {
- return $this->parent;
- }
-
- /**
- * set conversation
- */
- public function set_conversation($conv) {
- $previous_mode = ($this->conversation ? $this->conversation->get_mode() : '');
-
- $this->conversation = $conv;
-
- // Set it on our children too
- foreach($this->get_children() as $child)
- $child->set_conversation($conv);
- }
-
- /**
- * get conversation
- */
- public function get_conversation() {
- return $this->conversation;
- }
-
- /**
- * Get raw data
- *
- * We shouldn't need this
- */
- public function get_data() {
- return $this->data;
- }
-
- /**
- * Get a data value
- *
- * Returns:
- * _ value on success
- * _ false on failure
- */
- public function get_data_value($name) {
- if(!isset($this->data[$name])) {
-// logger('[ERROR] Item::get_data_value : Item has no value name "'. $name .'".', LOGGER_DEBUG);
- return false;
- }
-
- return $this->data[$name];
- }
-
- /**
- * Get template
- */
- public function get_template() {
- return $this->template;
- }
-
-
- public function set_template($t) {
- $this->template = $t;
- }
-
- /**
- * Check if this is a toplevel post
- */
- private function is_toplevel() {
- return $this->toplevel;
- }
-
- /**
- * Count the total of our descendants
- */
- private function count_descendants() {
- $children = $this->get_children();
- $total = count($children);
- if($total > 0) {
- foreach($children as $child) {
- $total += $child->count_descendants();
- }
- }
- return $total;
- }
-
- private function count_unseen_descendants() {
- $children = $this->get_children();
- $total = count($children);
- if($total > 0) {
- $total = 0;
- foreach($children as $child) {
- if((! visible_activity($child->data)) || array_key_exists('author_blocked',$child->data)) {
- continue;
- }
- if(intval($child->data['item_unseen']))
- $total ++;
- }
- }
- return $total;
- }
-
-
- /**
- * Get the template for the comment box
- */
- private function get_comment_box_template() {
- return $this->comment_box_template;
- }
-
- /**
- * Get the comment box
- *
- * Returns:
- * _ The comment box string (empty if no comment box)
- * _ false on failure
- */
- private function get_comment_box($indent) {
-
- if(!$this->is_toplevel() && !get_config('system','thread_allow')) {
- return '';
- }
-
- $comment_box = '';
- $conv = $this->get_conversation();
-
-// logger('Commentable conv: ' . $conv->is_commentable());
-
- if(! $this->is_commentable())
- return;
-
- $template = get_markup_template($this->get_comment_box_template());
-
- $a = $this->get_app();
- $observer = $conv->get_observer();
-
- $qc = ((local_channel()) ? get_pconfig(local_channel(),'system','qcomment') : null);
- $qcomment = (($qc) ? explode("\n",$qc) : null);
-
- $arr = array('comment_buttons' => '','id' => $this->get_id());
- call_hooks('comment_buttons',$arr);
- $comment_buttons = $arr['comment_buttons'];
-
-
- $comment_box = replace_macros($template,array(
- '$return_path' => '',
- '$threaded' => $this->is_threaded(),
- '$jsreload' => '', //(($conv->get_mode() === 'display') ? $_SESSION['return_url'] : ''),
- '$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'),
- '$id' => $this->get_id(),
- '$parent' => $this->get_id(),
- '$qcomment' => $qcomment,
- '$comment_buttons' => $comment_buttons,
- '$profile_uid' => $conv->get_profile_owner(),
- '$mylink' => $observer['xchan_url'],
- '$mytitle' => t('This is you'),
- '$myphoto' => $observer['xchan_photo_s'],
- '$comment' => t('Comment'),
- '$submit' => t('Submit'),
- '$edbold' => t('Bold'),
- '$editalic' => t('Italic'),
- '$eduline' => t('Underline'),
- '$edquote' => t('Quote'),
- '$edcode' => t('Code'),
- '$edimg' => t('Image'),
- '$edurl' => t('Insert Link'),
- '$edvideo' => t('Video'),
- '$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
- '$indent' => $indent,
- '$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
- '$encrypt' => t('Encrypt text'),
- '$cipher' => $conv->get_cipher(),
- '$sourceapp' => App::$sourcename
-
- ));
-
- return $comment_box;
- }
-
- private function get_redirect_url() {
- return $this->redirect_url;
- }
-
- /**
- * Check if we are a wall to wall item and set the relevant properties
- */
- protected function check_wall_to_wall() {
- $conv = $this->get_conversation();
- $this->wall_to_wall = false;
- $this->owner_url = '';
- $this->owner_photo = '';
- $this->owner_name = '';
-
- if($conv->get_mode() === 'channel')
- return;
-
- if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) {
- $this->owner_url = chanlink_url($this->data['owner']['xchan_url']);
- $this->owner_photo = $this->data['owner']['xchan_photo_m'];
- $this->owner_name = $this->data['owner']['xchan_name'];
- $this->wall_to_wall = true;
- }
- }
-
- private function is_wall_to_wall() {
- return $this->wall_to_wall;
- }
-
- private function get_owner_url() {
- return $this->owner_url;
- }
-
- private function get_owner_photo() {
- return $this->owner_photo;
- }
-
- private function get_owner_name() {
- return $this->owner_name;
- }
-
- private function is_visiting() {
- return $this->visiting;
- }
-
-
-
-
-}
-
diff --git a/include/ProtoDriver.php b/include/ProtoDriver.php
deleted file mode 100644
index 7585a0135..000000000
--- a/include/ProtoDriver.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php /** @file */
-
-/*
- * Abstraction class for dealing with alternate networks (which of course do not exist, hence the abstraction)
- */
-
-
-abstract class ProtoDriver {
- abstract protected function discover($channel,$location);
- abstract protected function deliver($item,$channel,$recipients);
- abstract protected function collect($channel,$connection);
- abstract protected function change_permissions($permissions,$channel,$recipient);
- abstract protected function acknowledge_permissions($permissions,$channel,$recipient);
- abstract protected function deliver_private($item,$channel,$recipients);
- abstract protected function collect_private($channel,$connection);
-
-}
-
-class ZotDriver extends ProtoDriver {
-
- protected function discover($channel,$location) {
-
- }
- protected function deliver($item,$channel,$recipients) {
-
- }
- protected function collect($channel,$connection) {
-
- }
- protected function change_permissions($permissions,$channel,$recipient) {
-
- }
- protected function acknowledge_permissions($permissions,$channel,$recipient) {
-
- }
- protected function deliver_private($item,$channel,$recipients) {
-
- }
- protected function collect_private($channel,$connection) {
-
- }
-
-}
diff --git a/include/account.php b/include/account.php
index c64197b49..142ad1bea 100644
--- a/include/account.php
+++ b/include/account.php
@@ -11,7 +11,7 @@ require_once('include/text.php');
require_once('include/language.php');
require_once('include/datetime.php');
require_once('include/crypto.php');
-require_once('include/identity.php');
+require_once('include/channel.php');
function check_account_email($email) {
@@ -229,7 +229,7 @@ function verify_email_address($arr) {
$hash = random_string();
- $r = q("INSERT INTO register ( hash, created, uid, password, language ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
+ $r = q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
dbesc($hash),
dbesc(datetime_convert()),
intval($arr['account']['account_id']),
@@ -283,7 +283,7 @@ function send_reg_approval_email($arr) {
$hash = random_string();
- $r = q("INSERT INTO register ( hash, created, uid, password, language ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
+ $r = q("INSERT INTO register ( hash, created, uid, password, lang ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
dbesc($hash),
dbesc(datetime_convert()),
intval($arr['account']['account_id']),
@@ -387,7 +387,7 @@ function account_allow($hash) {
intval($register[0]['uid'])
);
- push_lang($register[0]['language']);
+ push_lang($register[0]['lang']);
$email_tpl = get_intltext_template("register_open_eml.tpl");
$email_tpl = replace_macros($email_tpl, array(
@@ -499,11 +499,27 @@ function account_approve($hash) {
intval($register[0]['uid'])
);
+ // get a fresh copy after we've modified it.
+
+ $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
+ intval($register[0]['uid'])
+ );
+
+ if(! $account)
+ return $ret;
+
+
+
if(get_config('system','auto_channel_create') || UNO)
auto_channel_create($register[0]['uid']);
+ else {
+ $_SESSION['login_return_url'] = 'new_channel';
+ authenticate_success($account[0],null,true,true,false,true);
+ }
+
- info( t('Account verified. Please login.') . EOL );
+ // info( t('Account verified. Please login.') . EOL );
return true;
}
@@ -591,6 +607,7 @@ function service_class_allows($uid, $property, $usage = false) {
if($limit === false)
return true; // No service class set => everything is allowed
+ $limit = engr_units_to_bytes($limit);
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
@@ -627,6 +644,8 @@ function account_service_class_allows($aid, $property, $usage = false) {
if($limit === false)
return true; // No service class is set => everything is allowed
+ $limit = engr_units_to_bytes($limit);
+
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
@@ -653,7 +672,8 @@ function account_service_class_allows($aid, $property, $usage = false) {
* @todo Should we merge this with account_service_class_fetch()?
*/
function service_class_fetch($uid, $property) {
- $a = get_app();
+
+
if($uid == local_channel()) {
$service_class = App::$account['account_service_class'];
}
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index 92f9436a2..148c67a6c 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -6,15 +6,14 @@
/**
* @package acl_selectors
*/
-function group_select($selname,$selclass,$preselected = false,$size = 4) {
- $a = get_app();
+function group_select($selname,$selclass,$preselected = false,$size = 4) {
$o = '';
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
- $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `gname` ASC",
intval(local_channel())
);
@@ -31,7 +30,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
$selected = " selected=\"selected\" ";
else
$selected = '';
- $trimmed = mb_substr($rr['name'],0,12);
+ $trimmed = mb_substr($rr['gname'],0,12);
$o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}\" >$trimmed</option>\r\n";
}
@@ -48,7 +47,6 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
/* MicMee 20130114 function contact_selector no longer in use, sql table contact does no longer exist
function contact_selector($selname, $selclass, $preselected = false, $options) {
- $a = get_app();
$mutual = false;
$networks = null;
@@ -154,7 +152,6 @@ function contact_selector($selname, $selclass, $preselected = false, $options) {
function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false, $tabindex = null) {
- $a = get_app();
$o = '';
@@ -210,12 +207,38 @@ function fixacl(&$item) {
$item = str_replace(array('<','>'),array('',''),$item);
}
-function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
+/**
+* Builds a modal dialog for editing permissions, using acl_selector.tpl as the template.
+*
+* @param array $default Optional access control list for the initial state of the dialog.
+* @param boolean $show_jotnets Whether plugins for federated networks should be included in the permissions dialog
+* @param PermissionDescription $emptyACL_description - An optional description for the permission implied by selecting an empty ACL. Preferably an instance of PermissionDescription.
+* @param string $dialog_description Optional message to include at the top of the dialog. E.g. "Warning: Post permissions cannot be changed once sent".
+* @param string $context_help Allows the dialog to present a help icon. E.g. "acl_dialog_post"
+* @param boolean $readonly Not implemented yet. When implemented, the dialog will use acl_readonly.tpl instead, so that permissions may be viewed for posts that can no longer have their permissions changed.
+*
+* @return string html modal dialog built from acl_selector.tpl
+*/
+function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_description = '', $dialog_description = '', $context_help = '', $readonly = false) {
$allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
+ $showall_origin = '';
+ $showall_icon = 'fa-globe';
+ $role = get_pconfig(local_channel(),'system','permissions_role');
+
+ if(! $emptyACL_description) {
+ $showall_caption = t('Visible to your default audience');
+
+ } else if (is_a($emptyACL_description, '\\Zotlabs\\Lib\\PermissionDescription')) {
+ $showall_caption = $emptyACL_description->get_permission_description();
+ $showall_origin = (($role === 'custom') ? $emptyACL_description->get_permission_origin_description() : '');
+ $showall_icon = $emptyACL_description->get_permission_icon();
+
+ } else {
+ // For backwards compatibility we still accept a string... for now!
+ $showall_caption = $emptyACL_description;
+ }
- if(! $showall)
- $showall = t('Visible to your default audience');
if(is_array($defaults)) {
$allow_cid = ((strlen($defaults['allow_cid']))
@@ -239,9 +262,16 @@ function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
$tpl = get_markup_template("acl_selector.tpl");
$o = replace_macros($tpl, array(
- '$showall' => $showall,
+ '$showall' => $showall_caption,
+ '$onlyme' => t('Only me'),
+ '$showallOrigin' => $showall_origin,
+ '$showallIcon' => $showall_icon,
+ '$select_label' => t('Who can see this?'),
+ '$showlimited' => t('Custom selection'),
+ '$showlimitedDesc' => t('Select "Show" to allow viewing. "Don\'t show" lets you override and limit the scope of "Show".'),
'$show' => t("Show"),
'$hide' => t("Don't show"),
+ '$search' => t("Search"),
'$allowcid' => json_encode($allow_cid),
'$allowgid' => json_encode($allow_gid),
'$denycid' => json_encode($deny_cid),
@@ -249,10 +279,39 @@ function populate_acl($defaults = null,$show_jotnets = true, $showall = '') {
'$jnetModalTitle' => t('Other networks and post services'),
'$jotnets' => $jotnets,
'$aclModalTitle' => t('Permissions'),
- '$aclModalDismiss' => t('Close')
+ '$aclModalDesc' => $dialog_description,
+ '$aclModalDismiss' => t('Close'),
+ '$helpUrl' => (($context_help == '') ? '' : (z_root() . '/help/' . $context_help))
));
return $o;
}
+/**
+* Returns a string that's suitable for passing as the $dialog_description argument to a
+* populate_acl() call for wall posts or network posts.
+*
+* This string is needed in 3 different files, and our .po translation system currently
+* cannot be used as a string table (because the value is always the key in english) so
+* I've centralized the value here (making this function name the "key") until we have a
+* better way.
+*
+* @return string Description to present to user in modal permissions dialog
+*/
+function get_post_aclDialogDescription() {
+
+ // I'm trying to make two points in this description text - warn about finality of wall
+ // post permissions, and try to clear up confusion that these permissions set who is
+ // *shown* the post, istead of who is able to see the post, i.e. make it clear that clicking
+ // the "Show" button on a group does not post it to the feed of people in that group, it
+ // mearly allows those people to view the post if they are viewing/following this channel.
+ $description = t('Post permissions %s cannot be changed %s after a post is shared.</br />These permissions set who is allowed to view the post.');
+
+ // Lets keep the emphasis styling seperate from the translation. It may change.
+ $emphasisOpen = '<b><a href="' . z_root() . '/help/acl_dialog_post" target="hubzilla-help">';
+ $emphasisClose = '</a></b>';
+
+ return sprintf($description, $emphasisOpen, $emphasisClose);
+}
+
diff --git a/include/activities.php b/include/activities.php
index 9ba191391..3271db993 100644
--- a/include/activities.php
+++ b/include/activities.php
@@ -1,7 +1,6 @@
<?php /** @file */
function profile_activity($changed, $value) {
- $a = get_app();
if(! local_channel() || ! is_array($changed) || ! count($changed))
return;
@@ -89,7 +88,7 @@ function profile_activity($changed, $value) {
if($i) {
// FIXME - limit delivery in notifier.php to those specificed in the perms argument
- proc_run('php',"include/notifier.php","activity","$i", 'PERMS_R_PROFILE');
+ Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $i, 'PERMS_R_PROFILE'));
}
}
diff --git a/include/api.php b/include/api.php
index fd644947c..8d475c5fa 100644
--- a/include/api.php
+++ b/include/api.php
@@ -282,7 +282,8 @@ require_once('include/api_auth.php');
intval($uinfo[0]['xchan_hash'])
);
$countitms = $r[0]['count'];
- $following = (($uinfo[0]['abook_myperms'] & PERMS_R_STREAM) ? true : false );
+
+ $following = ((get_abconfig($uinfo[0]['abook_channel'],$uinfo[0]['abook_xchan'],'my_perms','view_stream')) ? true : false );
}
@@ -368,7 +369,7 @@ require_once('include/api_auth.php');
else
$redirect = trim($_REQUEST['redirect_uris']);
$icon = trim($_REQUEST['logo_uri']);
- $r = q("INSERT INTO clients (client_id, pw, name, redirect_uri, icon, uid)
+ $r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid)
VALUES ('%s','%s','%s','%s','%s',%d)",
dbesc($key),
dbesc($secret),
@@ -451,8 +452,6 @@ require_once('include/api_auth.php');
*/
function api_apply_template($templatename, $type, $data){
- $a = get_app();
-
switch($type){
case "atom":
case "rss":
@@ -486,7 +485,7 @@ require_once('include/api_auth.php');
function api_account_logout(&$a, $type){
require_once('include/auth.php');
- \Zotlabs\Web\Session::nuke();
+ App::$session->nuke();
return api_apply_template("user", $type, array('$user' => null));
}
@@ -514,7 +513,7 @@ require_once('include/api_auth.php');
return false;
}
- require_once('include/identity.php');
+ require_once('include/channel.php');
json_return_and_die(identity_basic_export(api_user(),(($_REQUEST['posts']) ? intval($_REQUEST['posts']) : 0 )));
}
@@ -556,7 +555,7 @@ require_once('include/api_auth.php');
dbesc($_REQUEST['file_id'])
);
if($r) {
- unset($r[0]['data']);
+ unset($r[0]['content']);
$ret = array('attach' => $r[0]);
json_return_and_die($ret);
}
@@ -582,21 +581,21 @@ require_once('include/api_auth.php');
$length = intval($ptr['filesize']);
if($ptr['is_dir'])
- $ptr['data'] = '';
+ $ptr['content'] = '';
elseif(! intval($r[0]['os_storage'])) {
$ptr['start'] = $start;
- $x = substr(dbunescbin($ptr['data'],$start,$length));
+ $x = substr(dbunescbin($ptr['content'],$start,$length));
$ptr['length'] = strlen($x);
- $ptr['data'] = base64_encode($x);
+ $ptr['content'] = base64_encode($x);
}
else {
- $fp = fopen(dbunescbin($ptr['data']),'r');
+ $fp = fopen(dbunescbin($ptr['content']),'r');
if($fp) {
$seek = fseek($fp,$start,SEEK_SET);
$x = fread($fp,$length);
$ptr['start'] = $start;
$ptr['length'] = strlen($x);
- $ptr['data'] = base64_encode($x);
+ $ptr['content'] = base64_encode($x);
}
}
@@ -619,11 +618,11 @@ require_once('include/api_auth.php');
);
if($r) {
if($r[0]['is_dir'])
- $r[0]['data'] = '';
+ $r[0]['content'] = '';
elseif(intval($r[0]['os_storage']))
- $r[0]['data'] = base64_encode(file_get_contents(dbunescbin($r[0]['data'])));
+ $r[0]['content'] = base64_encode(file_get_contents(dbunescbin($r[0]['content'])));
else
- $r[0]['data'] = base64_encode(dbunescbin($r[0]['data']));
+ $r[0]['content'] = base64_encode(dbunescbin($r[0]['content']));
$ret = array('attach' => $r[0]);
json_return_and_die($ret);
@@ -649,16 +648,16 @@ require_once('include/api_auth.php');
if (api_user()===false) return false;
if(! $_REQUEST['photo_id']) return false;
$scale = ((array_key_exists('scale',$_REQUEST)) ? intval($_REQUEST['scale']) : 0);
- $r = q("select * from photo where uid = %d and resource_id = '%s' and scale = %d limit 1",
+ $r = q("select * from photo where uid = %d and resource_id = '%s' and imgscale = %d limit 1",
intval(local_channel()),
dbesc($_REQUEST['photo_id']),
intval($scale)
);
if($r) {
- $data = dbunescbin($r[0]['data']);
+ $data = dbunescbin($r[0]['content']);
if(array_key_exists('os_storage',$r[0]) && intval($r[0]['os_storage']))
$data = file_get_contents($data);
- $r[0]['data'] = base64_encode($data);
+ $r[0]['content'] = base64_encode($data);
$ret = array('photo' => $r[0]);
$i = q("select id from item where uid = %d and resource_type = 'photo' and resource_id = '%s' limit 1",
intval(local_channel()),
@@ -772,13 +771,15 @@ require_once('include/api_auth.php');
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
$_FILES['userfile'] = $_FILES['media'];
- require_once('mod/wall_attach.php');
- $posted = wall_attach_post($a);
-
- //now that we have the img url in bbcode we can add it to the status and insert the wall item.
+
+ $mod = new Zotlabs\Module\Wall_attach();
+ $mod->post();
+
+
$_REQUEST['body']=$txt."\n\n".$posted;
- require_once('mod/item.php');
- item_post($a);
+
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -839,7 +840,7 @@ require_once('include/api_auth.php');
$_REQUEST['parent_mid'] = $parent;
if($_REQUEST['namespace'] && $parent) {
- $x = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
+ $x = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1",
dbesc($_REQUEST['namespace']),
dbesc($parent)
);
@@ -871,9 +872,9 @@ require_once('include/api_auth.php');
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -884,9 +885,9 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -896,8 +897,8 @@ require_once('include/api_auth.php');
// call out normal post function
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -926,14 +927,14 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload the image if we have one
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_upload.php');
- $media = wall_upload_post($a);
+ $mod = new Zotlabs\Module\Wall_upload();
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n".$media;
}
- require_once('mod/item.php');
- $x = item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $x = $mod->post();
json_return_and_die($x);
}
@@ -967,20 +968,10 @@ require_once('include/api_auth.php');
$ret = array();
$tmp = array();
- $str = '';
foreach($i as $ii) {
$tmp[] = encode_item($ii,true);
- if($str)
- $str .= ',';
- $str .= $ii['id'];
}
$ret['item'] = $tmp;
- if($str) {
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item.id in ( $str ) ");
-
- if($r)
- $ret['item_id'] = $r;
- }
json_return_and_die($ret);
}
@@ -1423,9 +1414,8 @@ require_once('include/api_auth.php');
$_REQUEST['profile_uid'] = api_user();
$_REQUEST['type'] = 'wall';
$_REQUEST['api_source'] = true;
-
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
}
}
else
@@ -1463,7 +1453,8 @@ require_once('include/api_auth.php');
}
else {
if($_REQUEST['namespace'] && $_REQUEST['remote_id']) {
- $r = q("select * from item_id where service = '%s' and sid = '%s' and uid = %d limit 1",
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id
+ where cat = 'system' and k = '%s' and v = '%s' and item.uid = %d limit 1",
dbesc($_REQUEST['namespace']),
dbesc($_REQUEST['remote_id']),
intval($user_info['uid'])
@@ -1473,7 +1464,7 @@ require_once('include/api_auth.php');
$id = $r[0]['iid'];
}
if($_REQUEST['namespace'] && $_REQUEST['comment_id']) {
- $r = q("select * from item_id left join item on item.id = item_id.iid where service = '%s' and sid = '%s' and uid = %d and item.id != item.parent limit 1",
+ $r = q("select * from iconfig left join item on item.id = iconfig.iid where cat = 'system' and k = '%s' and v = '%s' and uid = %d and item.id != item.parent limit 1",
dbesc($_REQUEST['namespace']),
dbesc($_REQUEST['comment_id']),
intval($user_info['uid'])
@@ -1903,13 +1894,17 @@ require_once('include/api_auth.php');
//logger('api_format_items: ' . print_r($user_info,true));
- $a = get_app();
$ret = array();
+ $x = array('items' => $r,'api_user' => api_user(),'user_info' => $user_info);
+ call_hooks('api_format_items',$x);
+ $r = $x['items'];
+
if(! $r)
return $ret;
foreach($r as $item) {
+
localize_item($item);
$status_user = (($item['author_xchan']==$user_info['guid'])?$user_info: api_item_get_user($a,$item));
@@ -2106,10 +2101,10 @@ require_once('include/api_auth.php');
'private' => $private, 'textlimit' => $textlimit, 'sslserver' => $sslserver, 'ssl' => $ssl,
'shorturllength' => '30',
'hubzilla' => array(
- 'PLATFORM_NAME' => Zotlabs\Project\System::get_platform_name(),
- 'RED_VERSION' => Zotlabs\Project\System::get_project_version(),
+ 'PLATFORM_NAME' => Zotlabs\Lib\System::get_platform_name(),
+ 'STD_VERSION' => Zotlabs\Lib\System::get_project_version(),
'ZOT_REVISION' => ZOT_REVISION,
- 'DB_UPDATE_VERSION' => Zotlabs\Project\System::get_update_version()
+ 'DB_UPDATE_VERSION' => Zotlabs\Lib\System::get_update_version()
)
));
@@ -2142,12 +2137,12 @@ require_once('include/api_auth.php');
if($type === 'xml') {
header("Content-type: application/xml");
- echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . Zotlabs\Project\System::get_project_version() . '</version>' . "\r\n";
+ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . Zotlabs\Lib\System::get_project_version() . '</version>' . "\r\n";
killme();
}
elseif($type === 'json') {
header("Content-type: application/json");
- echo '"' . Zotlabs\Project\System::get_project_version() . '"';
+ echo '"' . Zotlabs\Lib\System::get_project_version() . '"';
killme();
}
}
diff --git a/include/api_auth.php b/include/api_auth.php
index dc8492b20..7a71bad73 100644
--- a/include/api_auth.php
+++ b/include/api_auth.php
@@ -59,20 +59,12 @@ function api_login(&$a){
if(isset($_SERVER['PHP_AUTH_USER'])) {
$channel_login = 0;
$record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
- if(! $record) {
- $r = q("select * from channel left join account on account.account_id = channel.channel_account_id
- where channel.channel_address = '%s' limit 1",
- dbesc($_SERVER['PHP_AUTH_USER'])
- );
- if ($r) {
- $record = account_verify_password($r[0]['account_email'],$_SERVER['PHP_AUTH_PW']);
- if($record)
- $channel_login = $r[0]['channel_id'];
- }
+ if($record && $record['channel']) {
+ $channel_login = $record['channel']['channel_id'];
}
}
- if($record) {
+ if($record['account']) {
authenticate_success($record);
if($channel_login)
diff --git a/include/apps.php b/include/apps.php
deleted file mode 100644
index fac58b850..000000000
--- a/include/apps.php
+++ /dev/null
@@ -1,511 +0,0 @@
-<?php /** @file */
-
-/**
- * apps
- *
- */
-
-require_once('include/plugin.php');
-require_once('include/identity.php');
-
-function get_system_apps() {
-
- $ret = array();
- if(is_dir('apps'))
- $files = glob('apps/*.apd');
- else
- $files = glob('app/*.apd');
- if($files) {
- foreach($files as $f) {
- $x = parse_app_description($f);
- if($x) {
- $ret[] = $x;
- }
- }
- }
- $files = glob('addon/*/*.apd');
- if($files) {
- foreach($files as $f) {
- $n = basename($f,'.apd');
- if(plugin_is_installed($n)) {
- $x = parse_app_description($f);
- if($x) {
- $ret[] = $x;
- }
- }
- }
- }
-
- return $ret;
-
-}
-
-function app_name_compare($a,$b) {
- return strcmp($a['name'],$b['name']);
-}
-
-function parse_app_description($f) {
- $ret = array();
-
- $baseurl = z_root();
- $channel = App::get_channel();
- $address = (($channel) ? $channel['channel_address'] : '');
-
- //future expansion
-
- $observer = App::get_observer();
-
-
- $lines = @file($f);
- if($lines) {
- foreach($lines as $x) {
- if(preg_match('/^([a-zA-Z].*?):(.*?)$/ism',$x,$matches)) {
- $ret[$matches[1]] = trim(str_replace(array('$baseurl','$nick'),array($baseurl,$address),$matches[2]));
- }
- }
- }
-
-
- if(! $ret['photo'])
- $ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
-
- $ret['type'] = 'system';
-
- foreach($ret as $k => $v) {
- if(strpos($v,'http') === 0)
- $ret[$k] = zid($v);
- }
-
- if(array_key_exists('desc',$ret))
- $ret['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['desc']);
-
- if(array_key_exists('target',$ret))
- $ret['target'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['target']);
-
- if(array_key_exists('requires',$ret)) {
- $requires = explode(',',$ret['requires']);
- foreach($requires as $require) {
- $require = trim(strtolower($require));
- switch($require) {
- case 'nologin':
- if(local_channel())
- unset($ret);
- break;
- case 'admin':
- if(! is_site_admin())
- unset($ret);
- break;
- case 'local_channel':
- if(! local_channel())
- unset($ret);
- break;
- case 'public_profile':
- if(! is_public_profile())
- unset($ret);
- break;
- case 'observer':
- if(! $observer)
- unset($ret);
- break;
- default:
- if(! (local_channel() && feature_enabled(local_channel(),$require)))
- unset($ret);
- break;
-
- }
- }
- }
- if($ret) {
- translate_system_apps($ret);
- return $ret;
- }
- return false;
-}
-
-
-function translate_system_apps(&$arr) {
- $apps = array(
- 'Site Admin' => t('Site Admin'),
- 'Bookmarks' => t('Bookmarks'),
- 'Address Book' => t('Address Book'),
- 'Login' => t('Login'),
- 'Channel Manager' => t('Channel Manager'),
- 'Grid' => t('Grid'),
- 'Settings' => t('Settings'),
- 'Files' => t('Files'),
- 'Webpages' => t('Webpages'),
- 'Channel Home' => t('Channel Home'),
- 'Profile' => t('Profile'),
- 'Photos' => t('Photos'),
- 'Events' => t('Events'),
- 'Directory' => t('Directory'),
- 'Help' => t('Help'),
- 'Mail' => t('Mail'),
- 'Mood' => t('Mood'),
- 'Poke' => t('Poke'),
- 'Chat' => t('Chat'),
- 'Search' => t('Search'),
- 'Probe' => t('Probe'),
- 'Suggest' => t('Suggest'),
- 'Random Channel' => t('Random Channel'),
- 'Invite' => t('Invite'),
- 'Features' => t('Features'),
- 'Language' => t('Language'),
- 'Post' => t('Post'),
- 'Profile Photo' => t('Profile Photo')
- );
-
- if(array_key_exists($arr['name'],$apps))
- $arr['name'] = $apps[$arr['name']];
-
-}
-
-
-// papp is a portable app
-
-function app_render($papp,$mode = 'view') {
-
- /**
- * modes:
- * view: normal mode for viewing an app via bbcode from a conversation or page
- * provides install/update button if you're logged in locally
- * list: normal mode for viewing an app on the app page
- * no buttons are shown
- * edit: viewing the app page in editing mode provides a delete button
- */
-
- $installed = false;
-
- if(! $papp)
- return;
-
- if(! $papp['photo'])
- $papp['photo'] = z_root() . '/' . get_default_profile_photo(80);
-
-
-
- $papp['papp'] = papp_encode($papp);
-
- if(! strstr($papp['url'],'://'))
- $papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url'];
-
- foreach($papp as $k => $v) {
- if(strpos($v,'http') === 0 && $k != 'papp')
- $papp[$k] = zid($v);
- if($k === 'desc')
- $papp['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$papp['desc']);
-
- if($k === 'requires') {
- $requires = explode(',',$v);
- foreach($requires as $require) {
- $require = trim(strtolower($require));
- switch($require) {
- case 'nologin':
- if(local_channel())
- return '';
- break;
- case 'admin':
- if(! is_site_admin())
- return '';
- break;
- case 'local_channel':
- if(! local_channel())
- return '';
- break;
- case 'public_profile':
- if(! is_public_profile())
- return '';
- break;
- case 'observer':
- $observer = App::get_observer();
- if(! $observer)
- return '';
- break;
- default:
- if(! (local_channel() && feature_enabled(local_channel(),$require)))
- return '';
- break;
-
- }
- }
-
- }
- }
-
- $hosturl = '';
-
- if(local_channel()) {
- $installed = app_installed(local_channel(),$papp);
- $hosturl = z_root() . '/';
- }
- elseif(remote_channel()) {
- $observer = App::get_observer();
- if($observer && $observer['xchan_network'] === 'zot') {
- // some folks might have xchan_url redirected offsite, use the connurl
- $x = parse_url($observer['xchan_connurl']);
- if($x) {
- $hosturl = $x['scheme'] . '://' . $x['host'] . '/';
- }
- }
- }
-
- $install_action = (($installed) ? t('Update') : t('Install'));
-
- return replace_macros(get_markup_template('app.tpl'),array(
- '$app' => $papp,
- '$hosturl' => $hosturl,
- '$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''),
- '$install' => (($hosturl && $mode == 'view') ? $install_action : ''),
- '$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
- '$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : '')
- ));
-}
-
-
-function app_install($uid,$app) {
- $app['uid'] = $uid;
- if(app_installed($uid,$app))
- $x = app_update($app);
- else
- $x = app_store($app);
-
- if($x['success']) {
- $r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
- dbesc($x['app_id']),
- intval($uid)
- );
- if($r)
- build_sync_packet($uid,array('app' => $r[0]));
-
- return $x['app_id'];
- }
- return false;
-}
-
-function app_destroy($uid,$app) {
-
-
- if($uid && $app['guid']) {
-
- $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
- dbesc($app['guid']),
- intval($uid)
- );
- $x[0]['app_deleted'] = 1;
-
-
- $r = q("delete from app where app_id = '%s' and app_channel = %d",
- dbesc($app['guid']),
- intval($uid)
- );
-
- build_sync_packet($uid,array('app' => $x));
- }
-}
-
-
-function app_installed($uid,$app) {
-
- $r = q("select id from app where app_id = '%s' and app_version = '%s' and app_channel = %d limit 1",
- dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''),
- dbesc((array_key_exists('version',$app)) ? $app['version'] : ''),
- intval($uid)
- );
- return(($r) ? true : false);
-
-}
-
-
-function app_list($uid) {
- $r = q("select * from app where app_channel = %d order by app_name asc",
- intval($uid)
- );
- if($r) {
- for($x = 0; $x < count($r); $x ++) {
- $r[$x]['type'] = 'personal';
- }
- }
- return($r);
-}
-
-
-function app_decode($s) {
- $x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s));
- return json_decode($x,true);
-}
-
-
-function app_store($arr) {
-
- // logger('app_store: ' . print_r($arr,true));
-
- $darray = array();
- $ret = array('success' => false);
-
- $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
- $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
-
- if((! $darray['app_url']) || (! $darray['app_channel']))
- return $ret;
-
- if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
- $x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
- $arr['photo'] = $x[1];
- }
-
-
- $darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . App::get_hostname());
- $darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
- $darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
- $darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
- $darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
- $darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
- $darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
- $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
- $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
- $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
- $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
-
- $created = datetime_convert();
-
- $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
- dbesc($darray['app_id']),
- dbesc($darray['app_sig']),
- dbesc($darray['app_author']),
- dbesc($darray['app_name']),
- dbesc($darray['app_desc']),
- dbesc($darray['app_url']),
- dbesc($darray['app_photo']),
- dbesc($darray['app_version']),
- intval($darray['app_channel']),
- dbesc($darray['app_addr']),
- dbesc($darray['app_price']),
- dbesc($darray['app_page']),
- dbesc($darray['app_requires']),
- dbesc($created),
- dbesc($created)
- );
- if($r) {
- $ret['success'] = true;
- $ret['app_id'] = $darray['app_id'];
- }
- return $ret;
-}
-
-
-function app_update($arr) {
-
- $darray = array();
- $ret = array('success' => false);
-
- $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
- $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
- $darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : 0);
-
- if((! $darray['app_url']) || (! $darray['app_channel']) || (! $darray['app_id']))
- return $ret;
-
- if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
- $x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
- $arr['photo'] = $x[1];
- }
-
- $darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
- $darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
- $darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
- $darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
- $darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
- $darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
- $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
- $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
- $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
- $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
-
- $edited = datetime_convert();
-
- $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s' where app_id = '%s' and app_channel = %d",
- dbesc($darray['app_sig']),
- dbesc($darray['app_author']),
- dbesc($darray['app_name']),
- dbesc($darray['app_desc']),
- dbesc($darray['app_url']),
- dbesc($darray['app_photo']),
- dbesc($darray['app_version']),
- dbesc($darray['app_addr']),
- dbesc($darray['app_price']),
- dbesc($darray['app_page']),
- dbesc($darray['app_requires']),
- dbesc($edited),
- dbesc($darray['app_id']),
- intval($darray['app_channel'])
- );
- if($r) {
- $ret['success'] = true;
- $ret['app_id'] = $darray['app_id'];
- }
-
- return $ret;
-
-}
-
-
-function app_encode($app,$embed = false) {
-
- $ret = array();
-
- $ret['type'] = 'personal';
-
- if($app['app_id'])
- $ret['guid'] = $app['app_id'];
-
- if($app['app_id'])
- $ret['guid'] = $app['app_id'];
-
- if($app['app_sig'])
- $ret['sig'] = $app['app_sig'];
-
- if($app['app_author'])
- $ret['author'] = $app['app_author'];
-
- if($app['app_name'])
- $ret['name'] = $app['app_name'];
-
- if($app['app_desc'])
- $ret['desc'] = $app['app_desc'];
-
- if($app['app_url'])
- $ret['url'] = $app['app_url'];
-
- if($app['app_photo'])
- $ret['photo'] = $app['app_photo'];
-
- if($app['app_version'])
- $ret['version'] = $app['app_version'];
-
- if($app['app_addr'])
- $ret['addr'] = $app['app_addr'];
-
- if($app['app_price'])
- $ret['price'] = $app['app_price'];
-
- if($app['app_page'])
- $ret['page'] = $app['app_page'];
-
- if($app['app_requires'])
- $ret['requires'] = $app['app_requires'];
-
- if(! $embed)
- return $ret;
-
- $j = json_encode($ret);
- return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
-
-}
-
-
-function papp_encode($papp) {
- return chunk_split(base64_encode(json_encode($papp)),72,"\n");
-
-}
-
-
diff --git a/include/attach.php b/include/attach.php
index ae4681994..b3ddfee88 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -423,6 +423,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$observer = array();
+ $dosync = ((array_key_exists('nosync',$arr) && $arr['nosync']) ? 0 : 1);
+
if($observer_hash) {
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($observer_hash)
@@ -616,7 +618,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
);
if($r) {
$overwrite = get_pconfig($channel_id,'system','overwrite_dup_files');
- if($overwrite) {
+ if(($overwrite) || ($options === 'import')) {
$options = 'replace';
$existing_id = $x[0]['id'];
$existing_size = intval($x[0]['filesize']);
@@ -720,7 +722,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$edited = $created;
if($options === 'replace') {
- $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, data = '%s', edited = '%s' where id = %d and uid = %d",
+ $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, content = '%s', edited = '%s' where id = %d and uid = %d",
dbesc($filename),
dbesc($mimetype),
dbesc($folder_hash),
@@ -734,7 +736,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
);
}
elseif($options === 'revise') {
- $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
+ $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($x[0]['aid']),
intval($channel_id),
@@ -775,7 +777,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
}
else {
- $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )
+ $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($channel['channel_account_id']),
intval($channel_id),
@@ -800,7 +802,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if($is_photo) {
- $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct);
+ $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options );
if($arr['contact_allow'])
$args['contact_allow'] = $arr['contact_allow'];
if($arr['group_allow'])
@@ -829,6 +831,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if($arr['description'])
$args['description'] = $arr['description'];
+ $args['deliver'] = $dosync;
+
$p = photo_upload($channel,$observer,$args);
if($p['success']) {
$ret['body'] = $p['body'];
@@ -865,10 +869,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
call_hooks('photo_upload_end',$ret);
}
- $sync = attach_export_data($channel,$hash);
+ if($dosync) {
+ $sync = attach_export_data($channel,$hash);
- if($sync)
- build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ if($sync)
+ build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ }
return $ret;
}
@@ -1032,7 +1038,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
$created = datetime_convert();
- $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_dir, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
+ $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_dir, content, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($channel['channel_account_id']),
intval($channel_id),
@@ -1275,16 +1281,16 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
// delete a file from filesystem
if(intval($r[0]['os_storage'])) {
- $y = q("SELECT data FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1",
+ $y = q("SELECT content FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1",
dbesc($resource),
intval($channel_id)
);
if($y) {
- if(strpos($y[0]['data'],'store') === false)
- $f = 'store/' . $channel_address . '/' . $y[0]['data'];
+ if(strpos($y[0]['content'],'store') === false)
+ $f = 'store/' . $channel_address . '/' . $y[0]['content'];
else
- $f = $y[0]['data'];
+ $f = $y[0]['content'];
if(is_dir($f))
@rmdir($f);
@@ -1462,7 +1468,7 @@ function find_filename_by_hash($channel_id, $attachHash) {
function pipe_streams($in, $out) {
$size = 0;
while (!feof($in))
- $size += fwrite($out, fread($in, 8192));
+ $size += fwrite($out, fread($in, 16384));
return $size;
}
@@ -1585,13 +1591,13 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$arr['deny_gid'] = perms2str($u_arr_deny_gid);
$arr['item_private'] = $private;
$arr['verb'] = ACTIVITY_UPDATE;
- $arr['object'] = $u_jsonobject;
+ $arr['obj'] = $u_jsonobject;
$arr['body'] = '';
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
- proc_run('php',"include/notifier.php","activity",$item_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$item_id));
}
call_hooks('post_local_end', $arr);
@@ -1620,14 +1626,14 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$arr['deny_gid'] = perms2str($arr_deny_gid);
$arr['item_private'] = $private;
$arr['verb'] = (($update) ? ACTIVITY_UPDATE : ACTIVITY_POST);
- $arr['object'] = (($update) ? $u_jsonobject : $jsonobject);
+ $arr['obj'] = (($update) ? $u_jsonobject : $jsonobject);
$arr['body'] = '';
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
- proc_run('php',"include/notifier.php","activity",$item_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$item_id));
}
call_hooks('post_local_end', $arr);
@@ -1854,21 +1860,19 @@ function attach_export_data($channel, $resource_id, $deleted = false) {
} while($hash_ptr);
-
-
$paths = array_reverse($paths);
$ret['attach'] = $paths;
if($attach_ptr['is_photo']) {
- $r = q("select * from photo where resource_id = '%s' and uid = %d order by scale asc",
+ $r = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale asc",
dbesc($resource_id),
intval($channel['channel_id'])
);
if($r) {
for($x = 0; $x < count($r); $x ++) {
- $r[$x]['data'] = base64_encode($r[$x]['data']);
+ $r[$x]['content'] = base64_encode($r[$x]['content']);
}
$ret['photo'] = $r;
}
@@ -1905,4 +1909,4 @@ function get_attach_binname($s) {
$p = substr($p,strpos($p,'/')+1);
}
return $p;
-} \ No newline at end of file
+}
diff --git a/include/auth.php b/include/auth.php
index 9643da8eb..f3592cee3 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -16,55 +16,97 @@ require_once('include/security.php');
/**
* @brief Verify login credentials.
*
- * If system <i>authlog</i> is set a log entry will be added for failed login
+ * If system.authlog is set a log entry will be added for failed login
* attempts.
*
- * @param string $email
- * The email address to verify.
+ * @param string $login
+ * The login to verify (channel address, account email or guest login token).
* @param string $pass
* The provided password to verify.
* @return array|null
* Returns account record on success, null on failure.
+ * The return array is dependent on the login mechanism.
+ * $ret['account'] will be set if either an email or channel address validation was successful (local login).
+ * $ret['channel'] will be set if a channel address validation was successful.
+ * $ret['xchan'] will be set if a guest access token validation was successful.
+ * Keys will exist for invalid return arrays but will be set to null.
+ * This function does not perform a login. It merely validates systems passwords and tokens.
+ *
*/
-function account_verify_password($email, $pass) {
+
+function account_verify_password($login, $pass) {
+
+ $ret = [ 'account' => null, 'channel' => null, 'xchan' => null ];
$email_verify = get_config('system', 'verify_email');
$register_policy = get_config('system', 'register_policy');
+ if(! $login)
+ return null;
+
+ $account = null;
+ $channel = null;
+ $xchan = null;
+
+ if(! strpos($login,'@')) {
+ $channel = channelx_by_nick($login);
+ if(! $channel) {
+ $x = q("select * from atoken where atoken_name = '%s' and atoken_token = '%s' limit 1",
+ dbesc($login),
+ dbesc($pass)
+ );
+ if($x) {
+ $ret['xchan'] = atoken_xchan($x[0]);
+ return $ret;
+ }
+ }
+ }
+ if($channel) {
+ $where = " where account_id = " . intval($channel['channel_account_id']) . " ";
+ }
+ else {
+ $where = " where account_email = '" . dbesc($login) . "' ";
+ }
+
+ $a = q("select * from account $where");
+ if(! $a) {
+ return null;
+ }
+
+ $account = $a[0];
+
// Currently we only verify email address if there is an open registration policy.
// This isn't because of any policy - it's because the workflow gets too complicated if
// you have to verify the email and then go through the account approval workflow before
// letting them login.
- if(($email_verify) && ($register_policy == REGISTER_OPEN) && ($record['account_flags'] & ACCOUNT_UNVERIFIED))
- return null;
-
- $r = q("select * from account where account_email = '%s'",
- dbesc($email)
- );
- if(! ($r && count($r)))
+ if(($email_verify) && ($register_policy == REGISTER_OPEN) && ($account['account_flags'] & ACCOUNT_UNVERIFIED)) {
+ logger('email verification required for ' . $login);
return null;
+ }
- foreach($r as $record) {
- if(($record['account_flags'] == ACCOUNT_OK)
- && (hash('whirlpool', $record['account_salt'] . $pass) === $record['account_password'])) {
- logger('password verified for ' . $email);
- return $record;
- }
+ if(($account['account_flags'] == ACCOUNT_OK)
+ && (hash('whirlpool',$account['account_salt'] . $pass) === $account['account_password'])) {
+ logger('password verified for ' . $login);
+ $ret['account'] = $account;
+ if($channel)
+ $ret['channel'] = $channel;
+ return $ret;
}
- $error = 'password failed for ' . $email;
+
+ $error = 'password failed for ' . $login;
logger($error);
- if($record['account_flags'] & ACCOUNT_UNVERIFIED)
- logger('Account is unverified. account_flags = ' . $record['account_flags']);
- if($record['account_flags'] & ACCOUNT_BLOCKED)
- logger('Account is blocked. account_flags = ' . $record['account_flags']);
- if($record['account_flags'] & ACCOUNT_EXPIRED)
- logger('Account is expired. account_flags = ' . $record['account_flags']);
- if($record['account_flags'] & ACCOUNT_REMOVED)
- logger('Account is removed. account_flags = ' . $record['account_flags']);
- if($record['account_flags'] & ACCOUNT_PENDING)
- logger('Account is pending. account_flags = ' . $record['account_flags']);
+ if($account['account_flags'] & ACCOUNT_UNVERIFIED)
+ logger('Account is unverified. account_flags = ' . $account['account_flags']);
+ if($account['account_flags'] & ACCOUNT_BLOCKED)
+ logger('Account is blocked. account_flags = ' . $account['account_flags']);
+ if($account['account_flags'] & ACCOUNT_EXPIRED)
+ logger('Account is expired. account_flags = ' . $account['account_flags']);
+ if($account['account_flags'] & ACCOUNT_REMOVED)
+ logger('Account is removed. account_flags = ' . $account['account_flags']);
+ if($account['account_flags'] & ACCOUNT_PENDING)
+ logger('Account is pending. account_flags = ' . $account['account_flags']);
log_failed_login($error);
@@ -101,7 +143,7 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
// process logout request
$args = array('channel_id' => local_channel());
call_hooks('logging_out', $args);
- \Zotlabs\Web\Session::nuke();
+ App::$session->nuke();
info( t('Logged out.') . EOL);
goaway(z_root());
}
@@ -117,16 +159,24 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
intval(ACCOUNT_ROLE_ADMIN)
);
if($x) {
- \Zotlabs\Web\Session::new_cookie(60 * 60 * 24); // one day
+ App::$session->new_cookie(60 * 60 * 24); // one day
$_SESSION['last_login_date'] = datetime_convert();
unset($_SESSION['visitor_id']); // no longer a visitor
- authenticate_success($x[0], true, true);
+ authenticate_success($x[0], null, true, true);
}
}
-
- $r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where xchan_hash = '%s' limit 1",
- dbesc($_SESSION['visitor_id'])
- );
+ if(array_key_exists('atoken',$_SESSION)) {
+ $y = q("select * from atoken where atoken_id = %d limit 1",
+ intval($_SESSION['atoken'])
+ );
+ if($y)
+ $r = array(atoken_xchan($y[0]));
+ }
+ else {
+ $r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where xchan_hash = '%s' limit 1",
+ dbesc($_SESSION['visitor_id'])
+ );
+ }
if($r) {
App::set_observer($r[0]);
}
@@ -141,7 +191,7 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
if(x($_SESSION, 'uid') || x($_SESSION, 'account_id')) {
- Zotlabs\Web\Session::return_check();
+ App::$session->return_check();
$r = q("select * from account where account_id = %d limit 1",
intval($_SESSION['account_id'])
@@ -155,14 +205,15 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
}
if(strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0 ) {
$_SESSION['last_login_date'] = datetime_convert();
- Zotlabs\Web\Session::extend_cookie();
+ App::$session->extend_cookie();
$login_refresh = true;
}
- authenticate_success($r[0], false, false, false, $login_refresh);
+ $ch = (($_SESSION['uid']) ? channelx_by_n($_SESSION['uid']) : null);
+ authenticate_success($r[0], null, $ch, false, false, $login_refresh);
}
else {
$_SESSION['account_id'] = 0;
- \Zotlabs\Web\Session::nuke();
+ App::$session->nuke();
goaway(z_root());
}
} // end logged in user returning
@@ -170,7 +221,7 @@ if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) &&
else {
if(isset($_SESSION)) {
- \Zotlabs\Web\Session::nuke();
+ App::$session->nuke();
}
// handle a fresh login request
@@ -199,30 +250,38 @@ else {
call_hooks('authenticate', $addon_auth);
+ $atoken = null;
+ $account = null;
+
if(($addon_auth['authenticated']) && (count($addon_auth['user_record']))) {
- $record = $addon_auth['user_record'];
+ $account = $addon_auth['user_record'];
}
else {
- $record = App::$account = account_verify_password($_POST['username'], $_POST['password']);
+ $verify = account_verify_password($_POST['username'], $_POST['password']);
+ if($verify) {
+ $atoken = $verify['xchan'];
+ $channel = $verify['channel'];
+ $account = App::$account = $verify['account'];
+ }
if(App::$account) {
$_SESSION['account_id'] = App::$account['account_id'];
}
+ elseif($atoken) {
+ atoken_login($atoken);
+ }
else {
notice( t('Failed authentication') . EOL);
}
-
- logger('authenticate: ' . print_r(App::$account, true), LOGGER_ALL);
}
- if((! $record) || (! count($record))) {
+ if(! ($account || $atoken)) {
$error = 'authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR'];
logger($error);
// Also log failed logins to a separate auth log to reduce overhead for server side intrusion prevention
$authlog = get_config('system', 'authlog');
if ($authlog)
@file_put_contents($authlog, datetime_convert() . ':' . session_id() . ' ' . $error . "\n", FILE_APPEND);
-
notice( t('Login failed.') . EOL );
goaway(z_root() . '/login');
}
@@ -242,17 +301,18 @@ else {
if($_POST['remember_me']) {
$_SESSION['remember_me'] = 1;
- \Zotlabs\Web\Session::new_cookie(31449600); // one year
+ App::$session->new_cookie(31449600); // one year
}
else {
$_SESSION['remember_me'] = 0;
- \Zotlabs\Web\Session::new_cookie(0); // 0 means delete on browser exit
+ App::$session->new_cookie(0); // 0 means delete on browser exit
}
// if we haven't failed up this point, log them in.
$_SESSION['last_login_date'] = datetime_convert();
- authenticate_success($record, true, true);
+ if(! $atoken)
+ authenticate_success($account,$channel,true, true);
}
}
@@ -270,6 +330,7 @@ else {
* @return int|bool
* Return channel_id from pconfig or false.
*/
+
function match_openid($authid) {
// Query the uid/channel_id from pconfig for a given value.
$r = q("SELECT uid FROM pconfig WHERE cat = 'system' AND k = 'openid' AND v = '%s' LIMIT 1",
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 1ed57bfd4..16f67dc4a 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -270,7 +270,14 @@ function bb2dmention_callback($match) {
function bb2diaspora_itemwallwall(&$item) {
+ // We will provide wallwall (embedded author on the Diaspora side) if
+ // 1. It is a wall-to-wall post
+ // 2. A comment arrived which has no Diaspora signature info
+
+
+ $wallwall = false;
$author_exists = true;
+
if(! array_key_exists('author',$item)) {
$author_exists = false;
logger('bb2diaspora_itemwallwall: no author');
@@ -281,15 +288,25 @@ function bb2diaspora_itemwallwall(&$item) {
$item['author'] = $r[0];
}
- if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author']))) {
- logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DATA);
+ $has_meta = false;
+ if($item['diaspora_meta'] || get_iconfig($item,'diaspora','fields'))
+ $has_meta = true;
+
+ if($item['author_xchan'] != $item['owner_xchan']) {
+ if($item['mid'] == $item['parent_mid'])
+ $wallwall = true;
+ else {
+ if(! $has_meta) {
+ $wallwall = true;
+ }
+ }
}
- if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
+ if(($wallwall) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_s']) {
logger('bb2diaspora_itemwallwall: wall to wall post',LOGGER_DEBUG);
// post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author.
$item['body'] = "\n\n"
- . '[img]' . $item['author']['xchan_photo_m'] . '[/img]'
+ . '[img]' . $item['author']['xchan_photo_s'] . '[/img]'
. '[url=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/url]' . "\n\n"
. $item['body'];
}
@@ -301,7 +318,12 @@ function bb2diaspora_itemwallwall(&$item) {
}
-function bb2diaspora_itembody($item, $force_update = false) {
+function bb2diaspora_itembody($item, $force_update = false, $have_channel = false) {
+
+
+ if(! get_iconfig($item,'diaspora','fields')) {
+ $force_update = true;
+ }
$matches = array();
@@ -339,8 +361,8 @@ function bb2diaspora_itembody($item, $force_update = false) {
}
}
-
- bb2diaspora_itemwallwall($newitem);
+ if(! $have_channel)
+ bb2diaspora_itemwallwall($newitem);
$title = $newitem['title'];
$body = preg_replace('/\#\^http/i', 'http', $newitem['body']);
@@ -457,8 +479,6 @@ function unescape_underscores_in_links($m) {
function format_event_diaspora($ev) {
- $a = get_app();
-
if(! ((is_array($ev)) && count($ev)))
return '';
diff --git a/include/bbcode.php b/include/bbcode.php
index 78a2759c1..7f7be4300 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -165,11 +165,10 @@ function bb_parse_crypt($match) {
}
function bb_parse_app($match) {
- require_once('include/apps.php');
- $app = app_decode($match[1]);
+ $app = Zotlabs\Lib\Apps::app_decode($match[1]);
if ($app)
- return app_render($app);
+ return Zotlabs\Lib\Apps::app_render($app);
}
function bb_parse_element($match) {
@@ -243,6 +242,13 @@ function bb_ShareAttributes($match) {
if ($matches[1] != "")
$message_id = $matches[1];
+ if(! $message_id) {
+ preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+ if ($matches[1] != "")
+ $message_id = $matches[1];
+ }
+
+
$reldate = '<span class="autotime" title="' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'c') . '" >' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . '</span>';
$headline = '<div class="shared_container"> <div class="shared_header">';
@@ -276,7 +282,6 @@ function bb_location($match) {
* @return string HTML iframe with content of $match[1]
*/
function bb_iframe($match) {
- $a = get_app();
$sandbox = ((strpos($match[1], App::get_hostname())) ? ' sandbox="allow-scripts" ' : '');
@@ -330,8 +335,61 @@ function bb_map_location($match) {
}
function bb_opentag($match) {
+ $openclose = (($match[2]) ? '<span class="bb-open" title="' . t('Click to open/close') . '">' . $match[1] . '</span>' : t('Click to open/close'));
+ $text = (($match[2]) ? $match[2] : $match[1]);
+ $rnd = mt_rand();
+
+ return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><div id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</div>';
+}
+
+function bb_spoilertag($match) {
+ $openclose = (($match[2]) ? '<span class="bb-spoiler" title="' . t('Click to open/close') . '">' . $match[1] . ' ' . t('spoiler') . '</span>' : t('Click to open/close'));
+ $text = (($match[2]) ? $match[2] : $match[1]);
$rnd = mt_rand();
- return "<br /><div onclick=\"openClose('opendiv-" . $rnd . "');return false;\" class=\"fakelink\">" . $match[1] . "</div><div id=\"opendiv-" . $rnd . "\" style=\"display: none;\">" . $match[2] . "</div>";
+
+ return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><blockquote id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</blockquote>';
+}
+
+function bb_definitionList($match) {
+ // $match[1] is the markup styles for the "terms" in the definition list.
+ // $match[2] is the content between the [dl]...[/dl] tags
+
+ $classes = '';
+ if (stripos($match[1], "b") !== false) $classes .= 'dl-terms-bold ';
+ if (stripos($match[1], "i") !== false) $classes .= 'dl-terms-italic ';
+ if (stripos($match[1], "u") !== false) $classes .= 'dl-terms-underline ';
+ if (stripos($match[1], "l") !== false) $classes .= 'dl-terms-large ';
+ if (stripos($match[1], "m") !== false) $classes .= 'dl-terms-monospace ';
+ if (stripos($match[1], "h") !== false) $classes .= 'dl-horizontal '; // dl-horizontal is already provided by bootstrap
+ if (strlen($classes) === 0) $classes = "dl-terms-plain";
+
+ // The bbcode transformation will be:
+ // [*=term-text] description-text => </dd> <dt>term-text<dt><dd> description-text
+ // then after all replacements have been made, the extra </dd> at the start of the
+ // first line can be removed. HTML5 allows the tag to be missing from the end of the last line.
+ // Using '(?<!\\\)' to allow backslash-escaped closing braces to appear in the term-text.
+ $closeDescriptionTag = "</dd>\n";
+ $eatLeadingSpaces = '(?:&nbsp;|[ \t])*'; // prevent spaces infront of [*= from adding another line to the previous element
+ $listElements = preg_replace('/^(\n|<br \/>)/', '', $match[2]); // ltrim the first newline
+ $listElements = preg_replace(
+ '/' . $eatLeadingSpaces . '\[\*=([[:print:]]*?)(?<!\\\)\]/ism',
+ $closeDescriptionTag . '<dt>$1</dt><dd>',
+ $listElements
+ );
+ // Unescape any \] inside the <dt> tags
+ $listElements = preg_replace_callback('/<dt>(.*?)<\/dt>/ism', 'bb_definitionList_unescapeBraces', $listElements);
+
+ // Remove the extra </dd> at the start of the string, if there is one.
+ $firstOpenTag = strpos($listElements, '<dd>');
+ $firstCloseTag = strpos($listElements, $closeDescriptionTag);
+ if ($firstCloseTag !== false && ($firstOpenTag === false || ($firstCloseTag < $firstOpenTag))) {
+ $listElements = preg_replace( '/<\/dd>/ism', '', $listElements, 1);
+ }
+
+ return '<dl class="bb-dl ' . rtrim($classes) . '">' . $listElements . '</dl>';;
+}
+function bb_definitionList_unescapeBraces($match) {
+ return '<dt>' . str_replace('\]', ']', $match[1]) . '</dt>';
}
/**
@@ -397,8 +455,6 @@ function bb_sanitize_style($input) {
function bb_observer($Text) {
- $a = get_app();
-
$observer = App::get_observer();
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
@@ -428,9 +484,30 @@ function bb_observer($Text) {
return $Text;
}
+function bb_code($match) {
+ if(strpos($match[0], "<br />"))
+ return '<code>' . trim($match[1]) . '</code>';
+ else
+ return '<code class="inline-code">' . trim($match[1]) . '</code>';
+}
+function bb_highlight($match) {
+ if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
+ 'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','json','sh']))
+ return text_highlight($match[2],strtolower($match[1]));
+ return $match[0];
+}
+function bb_fixtable_lf($match) {
+ // remove extraneous whitespace between table element tags since newlines will all
+ // be converted to '<br />' and turn your neatly crafted tables into a whole lot of
+ // empty space.
+
+ $x = preg_replace("/\]\s+\[/",'][',$match[1]);
+ return '[table]' . $x . '[/table]';
+
+}
@@ -439,18 +516,6 @@ function bb_observer($Text) {
function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) {
- $a = get_app();
-
- // Move all spaces out of the tags
- // ....Uhm why?
- // This is basically doing a trim() on the stuff in between tags, but it messes up
- // carefully crafted bbcode and especially other pre-formatted code.
- // Commenting out until we come up with a use case where it's needed. Then let's try and
- // special case rather than a heavy-handed approach like this.
-
-// $Text = preg_replace("/\[(\w*)\](\s*)/ism", '$2[$1]', $Text);
-// $Text = preg_replace("/(\s*)\[\/(\w*)\]/ism", '[/$2]$1', $Text);
-
// Hide all [noparse] contained bbtags by spacefying them
if (strpos($Text,'[noparse]') !== false) {
$Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_spacefy',$Text);
@@ -519,6 +584,15 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = str_replace(">", "&gt;", $Text);
+ // Check for [code] text here, before the linefeeds are messed with.
+ // The highlighter will unescape and re-escape the content.
+
+ if (strpos($Text,'[code=') !== false) {
+ $Text = preg_replace_callback("/\[code=(.*?)\](.*?)\[\/code\]/ism", 'bb_highlight', $Text);
+ }
+
+ $Text = preg_replace_callback("/\[table\](.*?)\[\/table\]/ism",'bb_fixtable_lf',$Text);
+
// Convert new line chars to html <br /> tags
// nlbr seems to be hopelessly messed up
@@ -576,7 +650,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
}
if($tryoembed) {
if (strpos($Text,'[/url]') !== false) {
- $Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'tryoembed', $Text);
+ $Text = preg_replace_callback("/[^\^]\[url\]([$URLSearchString]*)\[\/url\]/ism", 'tryoembed', $Text);
}
}
if (strpos($Text,'[/url]') !== false) {
@@ -702,6 +776,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
while ((((strpos($Text, "[/list]") !== false) && (strpos($Text, "[list") !== false)) ||
((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) ||
((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false)) ||
+ ((strpos($Text, "[/dl]") !== false) && (strpos($Text, "[dl") !== false)) ||
((strpos($Text, "[/li]") !== false) && (strpos($Text, "[li]") !== false))) && (++$endlessloop < 20)) {
$Text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text);
$Text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>', $Text);
@@ -713,6 +788,13 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text);
$Text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $Text);
$Text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>', $Text);
+
+ // [dl] tags have an optional [dl terms="bi"] form where bold/italic/underline/mono/large
+ // etc. style may be specified for the "terms" in the definition list. The quotation marks
+ // are also optional. The regex looks intimidating, but breaks down as:
+ // "[dl" <optional-whitespace> <optional-termStyles> "]" <matchGroup2> "[/dl]"
+ // where optional-termStyles are: "terms=" <optional-quote> <matchGroup1> <optional-quote>
+ $Text = preg_replace_callback('/\[dl[[:space:]]*(?:terms=(?:&quot;|")?([a-zA-Z]+)(?:&quot;|")?)?\](.*?)\[\/dl\]/ism', 'bb_definitionList', $Text);
}
if (strpos($Text,'[th]') !== false) {
$Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>', $Text);
@@ -740,35 +822,30 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm", "<span style=\"font-family: $1;\">$2</span>", $Text);
}
- // Declare the format for [code] layout
- $CodeLayout = '<code>$1</code>';
-
// Check for [code] text
if (strpos($Text,'[code]') !== false) {
- $Text = preg_replace("/\[code\](.*?)\[\/code\]/ism", "$CodeLayout", $Text);
+ $Text = preg_replace_callback("/\[code\](.*?)\[\/code\]/ism", 'bb_code', $Text);
}
- // Declare the format for [spoiler] layout
- $SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>';
-
// Check for [spoiler] text
- // handle nested quotes
$endlessloop = 0;
- while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20))
- $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism", "$SpoilerLayout", $Text);
+ while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[spoiler\](.*?)\[\/spoiler\]/ism", 'bb_spoilertag', $Text);
+ }
// Check for [spoiler=Author] text
-
- $t_wrote = t('$1 spoiler');
-
- // handle nested quotes
$endlessloop = 0;
- while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20))
- $Text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism",
- "<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>",
- $Text);
+ while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[spoiler=(.*?)\](.*?)\[\/spoiler\]/ism", 'bb_spoilertag', $Text);
+ }
+ // Check for [open] text
+ $endlessloop = 0;
+ while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open]") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[open\](.*?)\[\/open\]/ism", 'bb_opentag', $Text);
+ }
+ // Check for [open=Title] text
$endlessloop = 0;
while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open=") !== false) and (++$endlessloop < 20)) {
$Text = preg_replace_callback("/\[open=(.*?)\](.*?)\[\/open\]/ism", 'bb_opentag', $Text);
@@ -792,7 +869,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$endlessloop = 0;
while ((strpos($Text, "[/quote]")!== false) and (strpos($Text, "[quote=") !== false) and (++$endlessloop < 20))
$Text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism",
- "<br /><strong class=".'"author"'.">" . $t_wrote . "</strong><blockquote>$2</blockquote>",
+ "<span class=".'"bb-quote"'.">" . $t_wrote . "</span><blockquote>$2</blockquote>",
$Text);
// Images
@@ -916,37 +993,6 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
}
}
- // Youtube extensions
-// if (strpos($Text,'[youtube]') !== false) {
-// if ($tryoembed) {
-// $Text = preg_replace_callback("/\[youtube\](https?:\/\/www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
-// $Text = preg_replace_callback("/\[youtube\](www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
-// $Text = preg_replace_callback("/\[youtube\](https?:\/\/youtu.be\/.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
-// }
-// $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
-// $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
-// $Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
-
-// if ($tryoembed)
-// $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . App::$videowidth . '" height="' . App::$videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', $Text);
-// else
-// $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", "http://www.youtube.com/watch?v=$1", $Text);
-// }
-// if (strpos($Text,'[vimeo]') !== false) {
-// if ($tryoembed) {
-// $Text = preg_replace_callback("/\[vimeo\](https?:\/\/player.vimeo.com\/video\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text);
-// $Text = preg_replace_callback("/\[vimeo\](https?:\/\/vimeo.com\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text);
-// }
-
-// $Text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text);
-// $Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text);
-
-// if ($tryoembed)
-// $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . App::$videowidth . '" height="' . App::$videoheight . '" src="http://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $Text);
-// else
-// $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", "http://vimeo.com/$1", $Text);
-// }
-
// oembed tag
$Text = oembed_bbcode2html($Text);
@@ -969,6 +1015,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism",'',$Text);
$Text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/ism",'',$Text);
$Text = preg_replace("/\[event\-finish\](.*?)\[\/event\-finish\]/ism",'',$Text);
+ $Text = preg_replace("/\[event\-id\](.*?)\[\/event\-id\]/ism",'',$Text);
$Text = preg_replace("/\[event\-location\](.*?)\[\/event\-location\]/ism",'',$Text);
$Text = preg_replace("/\[event\-adjust\](.*?)\[\/event\-adjust\]/ism",'',$Text);
diff --git a/include/cache.php b/include/cache.php
deleted file mode 100644
index 4a3f453e1..000000000
--- a/include/cache.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php /** @file */
-
- /**
- * cache api
- */
-
- class Cache {
- public static function get($key){
- $r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
- dbesc($key)
- );
-
- if ($r)
- return $r[0]['v'];
- return null;
- }
-
- public static function set($key,$value) {
-
- $r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
- dbesc($key)
- );
- if($r) {
- q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
- dbesc($value),
- dbesc(datetime_convert()),
- dbesc($key));
- }
- else {
- q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
- dbesc($key),
- dbesc($value),
- dbesc(datetime_convert()));
- }
- }
-
-
- public static function clear(){
- q("DELETE FROM cache WHERE updated < '%s'",
- dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
- }
-
- }
-
diff --git a/include/identity.php b/include/channel.php
index 1c899048a..a5233743d 100644
--- a/include/identity.php
+++ b/include/channel.php
@@ -1,11 +1,12 @@
<?php
/**
- * @file include/identity.php
+ * @file include/channel.php
*/
require_once('include/zot.php');
require_once('include/crypto.php');
require_once('include/menu.php');
+require_once('include/perm_upgrade.php');
/**
* @brief Called when creating a new channel.
@@ -16,7 +17,7 @@ require_once('include/menu.php');
* @param int $account_id
* Account_id used for this request
*
- * @returns assoziative array with:
+ * @returns associative array with:
* * \e boolean \b success boolean true if creating a new channel is allowed for this account
* * \e string \b message (optional) if success is false, optional error text
* * \e int \b total_identities
@@ -225,42 +226,26 @@ function create_identity($arr) {
if(array_key_exists('publish', $arr))
$publish = intval($arr['publish']);
- $primary = true;
-
- if(array_key_exists('primary', $arr))
- $primary = intval($arr['primary']);
-
$role_permissions = null;
- $global_perms = get_perms();
if(array_key_exists('permissions_role',$arr) && $arr['permissions_role']) {
- $role_permissions = get_role_perms($arr['permissions_role']);
-
- if($role_permissions) {
- foreach($role_permissions as $p => $v) {
- if(strpos($p,'channel_') !== false) {
- $perms_keys .= ', ' . $p;
- $perms_vals .= ', ' . intval($v);
- }
- if($p === 'directory_publish')
- $publish = intval($v);
- }
- }
- }
- else {
- $defperms = site_default_perms();
- foreach($defperms as $p => $v) {
- $perms_keys .= ', ' . $global_perms[$p][0];
- $perms_vals .= ', ' . intval($v);
- }
+ $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($arr['permissions_role']);
}
+ if($role_permissions && array_key_exists('directory_publish',$role_permissions))
+ $publish = intval($role_permissions['directory_publish']);
+
+ $primary = true;
+
+ if(array_key_exists('primary', $arr))
+ $primary = intval($arr['primary']);
+
$expire = 0;
$r = q("insert into channel ( channel_account_id, channel_primary,
channel_name, channel_address, channel_guid, channel_guid_sig,
- channel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_system, channel_expire_days, channel_timezone $perms_keys )
- values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' $perms_vals ) ",
+ channel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_system, channel_expire_days, channel_timezone )
+ values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' ) ",
intval($arr['account_id']),
intval($primary),
@@ -288,6 +273,17 @@ function create_identity($arr) {
return $ret;
}
+ if($role_permissions && array_key_exists('limits',$role_permissions))
+ $perm_limits = $role_permissions['limits'];
+ else
+ $perm_limits = site_default_perms();
+
+ foreach($perm_limits as $p => $v)
+ \Zotlabs\Access\PermissionLimits::Set($r[0]['channel_id'],$p,$v);
+
+ if($role_permissions && array_key_exists('perms_auto',$role_permissions))
+ set_pconfig($r[0]['channel_id'],'system','autoperms',intval($role_permissions['perms_auto']));
+
$ret['channel'] = $r[0];
if(intval($arr['account_id']))
@@ -337,7 +333,7 @@ function create_identity($arr) {
// Not checking return value.
// It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate
- $r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, name, photo, thumb)
+ $r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, fullname, photo, thumb)
VALUES ( %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s') ",
intval($ret['channel']['channel_account_id']),
intval($newuid),
@@ -351,25 +347,29 @@ function create_identity($arr) {
);
if($role_permissions) {
- $myperms = ((array_key_exists('perms_accept',$role_permissions)) ? intval($role_permissions['perms_accept']) : 0);
+ $myperms = ((array_key_exists('perms_connect',$role_permissions)) ? $role_permissions['perms_connect'] : array());
+ }
+ else {
+ $x = \Zotlabs\Access\PermissionRoles::role_perms('social');
+ $myperms = $x['perms_connect'];
}
- else
- $myperms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_self, abook_my_perms )
- values ( %d, %d, '%s', %d, '%s', '%s', %d, %d ) ",
+ $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_self )
+ values ( %d, %d, '%s', %d, '%s', '%s', %d ) ",
intval($ret['channel']['channel_account_id']),
intval($newuid),
dbesc($hash),
intval(0),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
- intval(1),
- intval($myperms)
+ intval(1)
);
+ $x = \Zotlabs\Access\Permissions::FilledPerms($myperms);
+ foreach($x as $k => $v) {
+ set_abconfig($newuid,$hash,'my_perms',$k,$v);
+ }
+
if(intval($ret['channel']['channel_account_id'])) {
// Save our permissions role so we can perhaps call it up and modify it later.
@@ -378,8 +378,21 @@ function create_identity($arr) {
set_pconfig($newuid,'system','permissions_role',$arr['permissions_role']);
if(array_key_exists('online',$role_permissions))
set_pconfig($newuid,'system','hide_presence',1-intval($role_permissions['online']));
- if(array_key_exists('perms_auto',$role_permissions))
- set_pconfig($newuid,'system','autoperms',(($role_permissions['perms_auto']) ? $role_permissions['perms_accept'] : 0));
+ if(array_key_exists('perms_auto',$role_permissions)) {
+ $autoperms = intval($role_permissions['perms_auto']);
+ set_pconfig($newuid,'system','autoperms',$autoperms);
+ if($autoperms) {
+ $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
+ foreach($x as $k => $v) {
+ set_pconfig($newuid,'autoperms',$k,$v);
+ }
+ }
+ else {
+ $r = q("delete from pconfig where uid = %d and cat = 'autoperms'",
+ intval($newuid)
+ );
+ }
+ }
}
// Create a group with yourself as a member. This allows somebody to use it
@@ -392,7 +405,7 @@ function create_identity($arr) {
// if our role_permissions indicate that we're using a default collection ACL, add it.
if(is_array($role_permissions) && $role_permissions['default_collection']) {
- $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
+ $r = q("select hash from groups where uid = %d and gname = '%s' limit 1",
intval($newuid),
dbesc( t('Friends') )
);
@@ -436,7 +449,7 @@ function create_identity($arr) {
call_hooks('create_identity', $newuid);
- proc_run('php','include/directory.php', $ret['channel']['channel_id']);
+ Zotlabs\Daemon\Master::Summon(array('Directory', $ret['channel']['channel_id']));
}
$ret['success'] = true;
@@ -491,13 +504,16 @@ function identity_basic_export($channel_id, $items = false) {
// use constants here as otherwise we will have no idea if we can import from a site
// with a non-standard platform and version.
- $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => RED_VERSION, 'database' => DB_UPDATE_VERSION, 'server_role' => Zotlabs\Project\System::get_server_role());
+ $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => STD_VERSION, 'database' => DB_UPDATE_VERSION, 'server_role' => Zotlabs\Lib\System::get_server_role());
$r = q("select * from channel where channel_id = %d limit 1",
intval($channel_id)
);
- if($r)
- $ret['channel'] = $r[0];
+ if($r) {
+ translate_channel_perms_outbound($r[0]);
+ $ret['channel'] = $r[0];
+ $ret['relocate'] = [ 'channel_address' => $r[0]['channel_address'], 'url' => z_root()];
+ }
$r = q("select * from profile where uid = %d",
intval($channel_id)
@@ -514,9 +530,10 @@ function identity_basic_export($channel_id, $items = false) {
for($x = 0; $x < count($ret['abook']); $x ++) {
$xchans[] = $ret['abook'][$x]['abook_chan'];
- $abconfig = load_abconfig($ret['channel']['channel_hash'],$ret['abook'][$x]['abook_xchan']);
+ $abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
if($abconfig)
$ret['abook'][$x]['abconfig'] = $abconfig;
+ translate_abook_perms_outbound($ret['abook'][$x]);
}
stringify_array_elms($xchans);
}
@@ -550,18 +567,18 @@ function identity_basic_export($channel_id, $items = false) {
if($r)
$ret['config'] = $r;
- $r = q("select type, data, os_storage from photo where scale = 4 and photo_usage = %d and uid = %d limit 1",
+ $r = q("select mimetype, content, os_storage from photo where imgscale = 4 and photo_usage = %d and uid = %d limit 1",
intval(PHOTO_PROFILE),
intval($channel_id)
);
if($r) {
- $ret['photo'] = array('type' => $r[0]['type'], 'data' => (($r[0]['os_storage']) ? base64url_encode(file_get_contents($r[0]['data'])) : base64url_encode($r[0]['data'])));
+ $ret['photo'] = array('type' => $r[0]['mimetype'], 'data' => (($r[0]['os_storage']) ? base64url_encode(file_get_contents($r[0]['content'])) : base64url_encode($r[0]['content'])));
}
// All other term types will be included in items, if requested.
- $r = q("select * from term where type in (%d,%d) and uid = %d",
+ $r = q("select * from term where ttype in (%d,%d) and uid = %d",
intval(TERM_SAVEDSEARCH),
intval(TERM_THING),
intval($channel_id)
@@ -580,11 +597,18 @@ function identity_basic_export($channel_id, $items = false) {
if($r)
$ret['obj'] = $r;
- $r = q("select * from app where app_channel = %d",
+ $r = q("select * from app where app_channel = %d and app_system = 0",
intval($channel_id)
);
- if($r)
+ if($r) {
+ for($x = 0; $x < count($r); $x ++) {
+ $r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
+ intval(TERM_OBJ_APP),
+ intval($r[$x]['id'])
+ );
+ }
$ret['app'] = $r;
+ }
$r = q("select * from chatroom where cr_uid = %d",
intval($channel_id)
@@ -669,14 +693,6 @@ function identity_basic_export($channel_id, $items = false) {
$ret['mail'] = $m;
}
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d",
- intval($channel_id)
- );
-
- if($r)
- $ret['item_id'] = $r;
-
- //$key = get_config('system','prvkey');
/** @warning this may run into memory limits on smaller systems */
@@ -718,6 +734,10 @@ function identity_export_year($channel_id,$year,$month = 0) {
$ret = array();
+ $ch = channelx_by_n($channel_id);
+ if($ch) {
+ $ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
+ }
$mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00');
if($month && $month < 12)
$maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00');
@@ -739,16 +759,43 @@ function identity_export_year($channel_id,$year,$month = 0) {
$ret['item'][] = encode_item($rr,true);
}
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d
- and item.created >= '%s' and item.created < '%s' order by created ",
+ return $ret;
+}
+
+// export items within an arbitrary date range. Date/time is in UTC.
+
+function channel_export_items($channel_id,$start,$finish) {
+
+ if(! $start)
+ return array();
+ else
+ $start = datetime_convert('UTC','UTC',$start);
+
+ $finish = datetime_convert('UTC','UTC',(($finish) ? $finish : 'now'));
+ if($finish < $start)
+ return array();
+
+ $ret = array();
+
+ $ch = channelx_by_n($channel_id);
+ if($ch) {
+ $ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
+ }
+
+ $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
+ intval(ITEM_TYPE_POST),
intval($channel_id),
- dbesc($mindate),
- dbesc($maxdate)
+ dbesc($start),
+ dbesc($finish)
);
- if($r)
- $ret['item_id'] = $r;
-
+ if($r) {
+ $ret['item'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rr)
+ $ret['item'][] = encode_item($rr,true);
+ }
return $ret;
}
@@ -767,11 +814,10 @@ function identity_export_year($channel_id,$year,$month = 0) {
*
* The channel default theme is also selected for use, unless over-riden elsewhere.
*
- * @param[in,out] App &$a
* @param string $nickname
* @param string $profile
*/
-function profile_load(&$a, $nickname, $profile = '') {
+function profile_load($nickname, $profile = '') {
// logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : ''));
@@ -840,7 +886,7 @@ function profile_load(&$a, $nickname, $profile = '') {
$extra_fields = array();
- require_once('include/identity.php');
+ require_once('include/channel.php');
$profile_fields_basic = get_profile_fields_basic();
$profile_fields_advanced = get_profile_fields_advanced();
@@ -868,7 +914,7 @@ function profile_load(&$a, $nickname, $profile = '') {
);
if($z) {
$p[0]['picdate'] = $z[0]['xchan_photo_date'];
- $p[0]['reddress'] = str_replace('@','&#xff20;',$z[0]['xchan_addr']);
+ $p[0]['reddress'] = str_replace('@','&#x40;',$z[0]['xchan_addr']);
}
// fetch user tags if this isn't the default profile
@@ -997,8 +1043,6 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
call_hooks('profile_sidebar_enter', $profile);
- require_once('include/Contact.php');
-
if($show_connect) {
// This will return an empty string if we're already connected.
@@ -1041,6 +1085,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
$diaspora = array(
'podloc' => z_root(),
+ 'guid' => $profile['channel_guid'] . str_replace('.','',App::get_hostname()),
'searchable' => (($block) ? 'false' : 'true'),
'nickname' => $profile['channel_address'],
'fullname' => $profile['channel_name'],
@@ -1063,8 +1108,8 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
}
$menublock = get_pconfig($profile['uid'],'system','channel_menublock');
if ($menublock && (! $block)) {
- require_once('include/comanche.php');
- $channel_menu .= comanche_block($menublock);
+ $comanche = new Zotlabs\Render\Comanche();
+ $channel_menu .= $comanche->block($menublock);
}
if($zcard)
@@ -1103,156 +1148,12 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
}
-/**
- * @FIXME or remove
- */
- function get_birthdays() {
-
- $o = '';
-
- if(! local_channel())
- return $o;
-
- $bd_format = t('g A l F d') ; // 8 AM Friday January 18
- $bd_short = t('F d');
-
- $r = q("SELECT `event`.*, `event`.`id` AS `eid`, `contact`.* FROM `event`
- LEFT JOIN `contact` ON `contact`.`id` = `event`.`cid`
- WHERE `event`.`uid` = %d AND `type` = 'birthday' AND `start` < '%s' AND `finish` > '%s'
- ORDER BY `start` ASC ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC','UTC','now + 6 days')),
- dbesc(datetime_convert('UTC','UTC','now'))
- );
-
- if($r && count($r)) {
- $total = 0;
- $now = strtotime('now');
- $cids = array();
-
- $istoday = false;
- foreach($r as $rr) {
- if(strlen($rr['name']))
- $total ++;
- if((strtotime($rr['start'] . ' +00:00') < $now) && (strtotime($rr['finish'] . ' +00:00') > $now))
- $istoday = true;
- }
- $classtoday = $istoday ? ' birthday-today ' : '';
- if($total) {
- foreach($r as &$rr) {
- if(! strlen($rr['name']))
- continue;
-
- // avoid duplicates
-
- if(in_array($rr['cid'],$cids))
- continue;
- $cids[] = $rr['cid'];
-
- $today = (((strtotime($rr['start'] . ' +00:00') < $now) && (strtotime($rr['finish'] . ' +00:00') > $now)) ? true : false);
- $sparkle = '';
- $url = $rr['url'];
- if($rr['network'] === NETWORK_DFRN) {
- $sparkle = " sparkle";
- $url = z_root() . '/redir/' . $rr['cid'];
- }
-
- $rr['link'] = $url;
- $rr['title'] = $rr['name'];
- $rr['date'] = day_translate(datetime_convert('UTC', App::$timezone, $rr['start'], $rr['adjust'] ? $bd_format : $bd_short)) . (($today) ? ' ' . t('[today]') : '');
- $rr['startime'] = Null;
- $rr['today'] = $today;
- }
- }
- }
- $tpl = get_markup_template("birthdays_reminder.tpl");
- return replace_macros($tpl, array(
- '$baseurl' => z_root(),
- '$classtoday' => $classtoday,
- '$count' => $total,
- '$event_reminders' => t('Birthday Reminders'),
- '$event_title' => t('Birthdays this week:'),
- '$events' => $r,
- '$lbr' => '{', // raw brackets mess up if/endif macro processing
- '$rbr' => '}'
- ));
- }
-
-
-/**
- * @FIXME
- */
- function get_events() {
-
- require_once('include/bbcode.php');
-
- if(! local_channel())
- return $o;
-
- $bd_format = t('g A l F d') ; // 8 AM Friday January 18
- $bd_short = t('F d');
-
- $r = q("SELECT `event`.* FROM `event`
- WHERE `event`.`uid` = %d AND `type` != 'birthday' AND `start` < '%s' AND `start` > '%s'
- ORDER BY `start` ASC ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC','UTC','now + 6 days')),
- dbesc(datetime_convert('UTC','UTC','now - 1 days'))
- );
-
- if($r && count($r)) {
- $now = strtotime('now');
- $istoday = false;
- foreach($r as $rr) {
- if(strlen($rr['name']))
- $total ++;
-
- $strt = datetime_convert('UTC',$rr['convert'] ? App::$timezone : 'UTC',$rr['start'],'Y-m-d');
- if($strt === datetime_convert('UTC',App::$timezone,'now','Y-m-d'))
- $istoday = true;
- }
- $classtoday = (($istoday) ? 'event-today' : '');
-
- foreach($r as &$rr) {
- if($rr['adjust'])
- $md = datetime_convert('UTC',App::$timezone,$rr['start'],'Y/m');
- else
- $md = datetime_convert('UTC','UTC',$rr['start'],'Y/m');
- $md .= "/#link-".$rr['id'];
-
- $title = substr(strip_tags(bbcode($rr['desc'])),0,32) . '... ';
- if(! $title)
- $title = t('[No description]');
-
- $strt = datetime_convert('UTC',$rr['convert'] ? App::$timezone : 'UTC',$rr['start']);
- $today = ((substr($strt,0,10) === datetime_convert('UTC',App::$timezone,'now','Y-m-d')) ? true : false);
-
- $rr['link'] = $md;
- $rr['title'] = $title;
- $rr['date'] = day_translate(datetime_convert('UTC', $rr['adjust'] ? App::$timezone : 'UTC', $rr['start'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
- $rr['startime'] = $strt;
- $rr['today'] = $today;
- }
- }
-
- $tpl = get_markup_template("events_reminder.tpl");
- return replace_macros($tpl, array(
- '$baseurl' => z_root(),
- '$classtoday' => $classtoday,
- '$count' => count($r),
- '$event_reminders' => t('Event Reminders'),
- '$event_title' => t('Events this week:'),
- '$events' => $r,
- ));
- }
-
-
function advanced_profile(&$a) {
require_once('include/text.php');
if(! perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),'view_profile'))
return '';
- if(App::$profile['name']) {
+ if(App::$profile['fullname']) {
$profile_fields_basic = get_profile_fields_basic();
$profile_fields_advanced = get_profile_fields_advanced();
@@ -1276,7 +1177,7 @@ function advanced_profile(&$a) {
$profile = array();
- $profile['fullname'] = array( t('Full Name:'), App::$profile['name'] ) ;
+ $profile['fullname'] = array( t('Full Name:'), App::$profile['fullname'] ) ;
if(App::$profile['gender']) $profile['gender'] = array( t('Gender:'), App::$profile['gender'] );
@@ -1324,8 +1225,8 @@ function advanced_profile(&$a) {
if(App::$profile['marital'])
$profile['marital'] = array( t('Status:'), App::$profile['marital']);
- if(App::$profile['with'])
- $profile['marital']['with'] = bbcode(App::$profile['with']);
+ if(App::$profile['partner'])
+ $profile['marital']['partner'] = bbcode(App::$profile['partner']);
if(strlen(App::$profile['howlong']) && App::$profile['howlong'] !== NULL_DATE) {
$profile['howlong'] = relative_date(App::$profile['howlong'], t('for %1$d %2$s'));
@@ -1365,7 +1266,7 @@ function advanced_profile(&$a) {
if($txt = prepare_text(App::$profile['romance'])) $profile['romance'] = array( t('Love/Romance:'), $txt);
- if($txt = prepare_text(App::$profile['work'])) $profile['work'] = array( t('Work/employment:'), $txt);
+ if($txt = prepare_text(App::$profile['employment'])) $profile['employment'] = array( t('Work/employment:'), $txt);
if($txt = prepare_text(App::$profile['education'])) $profile['education'] = array( t('School/education:'), $txt );
@@ -1382,6 +1283,7 @@ function advanced_profile(&$a) {
$things = get_things(App::$profile['profile_guid'],App::$profile['profile_uid']);
+
// logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);
return replace_macros($tpl, array(
@@ -1423,16 +1325,15 @@ function get_my_address() {
* If somebody arrives at our site using a zid, add their xchan to our DB if we don't have it already.
* And if they aren't already authenticated here, attempt reverse magic auth.
*
- * @param App &$a
*
* @hooks 'zid_init'
* string 'zid' - their zid
* string 'url' - the destination url
*/
-function zid_init(&$a) {
+function zid_init() {
$tmp_str = get_my_address();
if(validate_email($tmp_str)) {
- proc_run('php','include/gprobe.php',bin2hex($tmp_str));
+ Zotlabs\Daemon\Master::Summon(array('Gprobe',bin2hex($tmp_str)));
$arr = array('zid' => $tmp_str, 'url' => App::$cmd);
call_hooks('zid_init',$arr);
if(! local_channel()) {
@@ -1456,6 +1357,29 @@ function zid_init(&$a) {
}
/**
+ * @brief
+ *
+ * If somebody arrives at our site using a zat, authenticate them
+ *
+ */
+
+function zat_init() {
+ if(local_channel() || remote_channel())
+ return;
+
+ $r = q("select * from atoken where atoken_token = '%s' limit 1",
+ dbesc($_REQUEST['zat'])
+ );
+ if($r) {
+ $xchan = atoken_xchan($r[0]);
+ atoken_login($xchan);
+ }
+
+}
+
+
+
+/**
* @brief Adds a zid parameter to a url.
*
* @param string $s
@@ -1562,7 +1486,7 @@ function get_online_status($nick) {
$ret = array('result' => false);
- if(get_config('system','block_public') && ! local_channel() && ! remote_channel())
+ if(observer_prohibited())
return $ret;
$r = q("select channel_id, channel_hash from channel where channel_address = '%s' limit 1",
@@ -1643,9 +1567,11 @@ function is_public_profile() {
if(intval(get_config('system','block_public')))
return false;
$channel = App::get_channel();
- if($channel && $channel['channel_r_profile'] == PERMS_PUBLIC)
- return true;
-
+ if($channel) {
+ $perm = \Zotlabs\Access\PermissionLimit::Get($channel['channel_id'],'view_profile');
+ if($perm == PERMS_PUBLIC)
+ return true;
+ }
return false;
}
@@ -1653,7 +1579,7 @@ function get_profile_fields_basic($filter = 0) {
$profile_fields_basic = (($filter == 0) ? get_config('system','profile_fields_basic') : null);
if(! $profile_fields_basic)
- $profile_fields_basic = array('name','pdesc','chandesc','gender','dob','dob_tz','address','locality','region','postal_code','country_name','marital','sexual','homepage','hometown','keywords','about','contact');
+ $profile_fields_basic = array('fullname','pdesc','chandesc','gender','dob','dob_tz','address','locality','region','postal_code','country_name','marital','sexual','homepage','hometown','keywords','about','contact');
$x = array();
if($profile_fields_basic)
@@ -1668,7 +1594,7 @@ function get_profile_fields_advanced($filter = 0) {
$basic = get_profile_fields_basic($filter);
$profile_fields_advanced = (($filter == 0) ? get_config('system','profile_fields_advanced') : null);
if(! $profile_fields_advanced)
- $profile_fields_advanced = array('with','howlong','politic','religion','likes','dislikes','interest','channels','music','book','film','tv','romance','work','education');
+ $profile_fields_advanced = array('partner','howlong','politic','religion','likes','dislikes','interest','channels','music','book','film','tv','romance','employment','education');
$x = array();
if($basic)
@@ -1717,13 +1643,13 @@ function notifications_on($channel_id,$value) {
function get_channel_default_perms($uid) {
- $r = q("select abook_my_perms from abook where abook_channel = %d and abook_self = 1 limit 1",
+ $r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 1 limit 1",
intval($uid)
);
if($r)
- return $r[0]['abook_my_perms'];
+ return load_abconfig($uid,$r[0]['abook_xchan'],'my_perms');
- return 0;
+ return array();
}
@@ -1780,7 +1706,7 @@ function auto_channel_create($account_id) {
function get_cover_photo($channel_id,$format = 'bbcode', $res = PHOTO_RES_COVER_1200) {
- $r = q("select height, width, resource_id, type from photo where uid = %d and scale = %d and photo_usage = %d",
+ $r = q("select height, width, resource_id, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d",
intval($channel_id),
intval($res),
intval(PHOTO_COVER)
@@ -1803,8 +1729,8 @@ function get_cover_photo($channel_id,$format = 'bbcode', $res = PHOTO_RES_COVER_
default:
$output = array(
'width' => $r[0]['width'],
- 'height' => $r[0]['type'],
- 'type' => $r[0]['type'],
+ 'height' => $r[0]['height'],
+ 'type' => $r[0]['mimetype'],
'url' => $url
);
break;
@@ -1829,19 +1755,19 @@ function get_zcard($channel,$observer_hash = '',$args = array()) {
$width = 425;
$size = 'hz_small';
$cover_size = PHOTO_RES_COVER_425;
- $pphoto = array('type' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
}
elseif($maxwidth <= 900) {
$width = 900;
$size = 'hz_medium';
$cover_size = PHOTO_RES_COVER_850;
- $pphoto = array('type' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
}
elseif($maxwidth <= 1200) {
$width = 1200;
$size = 'hz_large';
$cover_size = PHOTO_RES_COVER_1200;
- $pphoto = array('type' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
}
// $scale = (float) $maxwidth / $width;
@@ -1851,7 +1777,7 @@ function get_zcard($channel,$observer_hash = '',$args = array()) {
$channel['channel_addr'] = $channel['channel_address'] . '@' . App::get_hostname();
$zcard = array('chan' => $channel);
- $r = q("select height, width, resource_id, scale, type from photo where uid = %d and scale = %d and photo_usage = %d",
+ $r = q("select height, width, resource_id, imgscale, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d",
intval($channel['channel_id']),
intval($cover_size),
intval(PHOTO_COVER)
@@ -1859,7 +1785,7 @@ function get_zcard($channel,$observer_hash = '',$args = array()) {
if($r) {
$cover = $r[0];
- $cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['scale'];
+ $cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
}
else {
$cover = $pphoto;
@@ -1878,3 +1804,88 @@ function get_zcard($channel,$observer_hash = '',$args = array()) {
return $o;
}
+
+
+function get_zcard_embed($channel,$observer_hash = '',$args = array()) {
+
+ logger('get_zcard_embed');
+
+ $maxwidth = (($args['width']) ? intval($args['width']) : 0);
+ $maxheight = (($args['height']) ? intval($args['height']) : 0);
+
+
+ if(($maxwidth > 1200) || ($maxwidth < 1))
+ $maxwidth = 1200;
+
+ if($maxwidth <= 425) {
+ $width = 425;
+ $size = 'hz_small';
+ $cover_size = PHOTO_RES_COVER_425;
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
+ }
+ elseif($maxwidth <= 900) {
+ $width = 900;
+ $size = 'hz_medium';
+ $cover_size = PHOTO_RES_COVER_850;
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
+ }
+ elseif($maxwidth <= 1200) {
+ $width = 1200;
+ $size = 'hz_large';
+ $cover_size = PHOTO_RES_COVER_1200;
+ $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
+ }
+
+ $channel['channel_addr'] = $channel['channel_address'] . '@' . App::get_hostname();
+ $zcard = array('chan' => $channel);
+
+ $r = q("select height, width, resource_id, imgscale, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d",
+ intval($channel['channel_id']),
+ intval($cover_size),
+ intval(PHOTO_COVER)
+ );
+
+ if($r) {
+ $cover = $r[0];
+ $cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
+ }
+ else {
+ $cover = $pphoto;
+ }
+
+ $o .= replace_macros(get_markup_template('zcard_embed.tpl'),array(
+ '$maxwidth' => $maxwidth,
+ '$scale' => $scale,
+ '$translate' => $translate,
+ '$size' => $size,
+ '$cover' => $cover,
+ '$pphoto' => $pphoto,
+ '$zcard' => $zcard
+ ));
+
+ return $o;
+
+}
+
+
+function channelx_by_nick($nick) {
+ $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_address = '%s' and channel_removed = 0 LIMIT 1",
+ dbesc($nick)
+ );
+ return(($r) ? $r[0] : false);
+}
+
+function channelx_by_hash($hash) {
+ $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_hash = '%s' and channel_removed = 0 LIMIT 1",
+ dbesc($hash)
+ );
+ return(($r) ? $r[0] : false);
+}
+
+function channelx_by_n($id) {
+ $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_id = %d and channel_removed = 0 LIMIT 1",
+ dbesc($id)
+ );
+ return(($r) ? $r[0] : false);
+}
+
diff --git a/include/chat.php b/include/chat.php
deleted file mode 100644
index 604402045..000000000
--- a/include/chat.php
+++ /dev/null
@@ -1,262 +0,0 @@
-<?php
-/**
- * @file include/chat.php
- * @brief Chat related functions.
- */
-
-
-/**
- * @brief Creates a chatroom.
- *
- * @param array $channel
- * @param array $arr
- * @return An associative array containing:
- * - success: A boolean
- * - message: (optional) A string
- */
-function chatroom_create($channel, $arr) {
-
- $ret = array('success' => false);
-
- $name = trim($arr['name']);
- if(! $name) {
- $ret['message'] = t('Missing room name');
- return $ret;
- }
-
- $r = q("select cr_id from chatroom where cr_uid = %d and cr_name = '%s' limit 1",
- intval($channel['channel_id']),
- dbesc($name)
- );
- if($r) {
- $ret['message'] = t('Duplicate room name');
- return $ret;
- }
-
- $r = q("select count(cr_id) as total from chatroom where cr_aid = %d",
- intval($channel['channel_account_id'])
- );
- if($r)
- $limit = service_class_fetch($channel['channel_id'], 'chatrooms');
-
- if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
- $ret['message'] = upgrade_message();
- return $ret;
- }
-
- if(! array_key_exists('expire', $arr))
- $arr['expire'] = 120; // minutes, e.g. 2 hours
-
- $created = datetime_convert();
-
- $x = q("insert into chatroom ( cr_aid, cr_uid, cr_name, cr_created, cr_edited, cr_expire, allow_cid, allow_gid, deny_cid, deny_gid )
- values ( %d, %d , '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' ) ",
- intval($channel['channel_account_id']),
- intval($channel['channel_id']),
- dbesc($name),
- dbesc($created),
- dbesc($created),
- intval($arr['expire']),
- dbesc($arr['allow_cid']),
- dbesc($arr['allow_gid']),
- dbesc($arr['deny_cid']),
- dbesc($arr['deny_gid'])
- );
-
- if($x)
- $ret['success'] = true;
-
- return $ret;
-}
-
-
-function chatroom_destroy($channel,$arr) {
-
- $ret = array('success' => false);
-
- if(intval($arr['cr_id']))
- $sql_extra = " and cr_id = " . intval($arr['cr_id']) . " ";
- elseif(trim($arr['cr_name']))
- $sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' ";
- else {
- $ret['message'] = t('Invalid room specifier.');
- return $ret;
- }
-
- $r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1",
- intval($channel['channel_id'])
- );
- if(! $r) {
- $ret['message'] = t('Invalid room specifier.');
- return $ret;
- }
-
- build_sync_packet($channel['channel_id'],array('chatroom' => $r));
-
- q("delete from chatroom where cr_id = %d",
- intval($r[0]['cr_id'])
- );
- if($r[0]['cr_id']) {
- q("delete from chatpresence where cp_room = %d",
- intval($r[0]['cr_id'])
- );
- q("delete from chat where chat_room = %d",
- intval($r[0]['cr_id'])
- );
- }
-
- $ret['success'] = true;
- return $ret;
-}
-
-
-function chatroom_enter($observer_xchan, $room_id, $status, $client) {
-
- if(! $room_id || ! $observer_xchan)
- return;
-
- $r = q("select * from chatroom where cr_id = %d limit 1",
- intval($room_id)
- );
- if(! $r) {
- notice( t('Room not found.') . EOL);
- return false;
- }
- require_once('include/security.php');
- $sql_extra = permissions_sql($r[0]['cr_uid']);
-
- $x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
- intval($room_id),
- intval($r[0]['cr_uid'])
- );
- if(! $x) {
- notice( t('Permission denied.') . EOL);
- return false;
- }
-
- $limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom');
- if($limit !== false) {
- $y = q("select count(*) as total from chatpresence where cp_room = %d",
- intval($room_id)
- );
- if($y && $y[0]['total'] > $limit) {
- notice( t('Room is full') . EOL);
- return false;
- }
- }
-
- if(intval($x[0]['cr_expire'])) {
- $r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
- db_utcnow(),
- db_quoteinterval( intval($x[0]['cr_expire']) . ' MINUTE' ),
- intval($x[0]['cr_id'])
- );
- }
-
- $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
- dbesc($observer_xchan),
- intval($room_id)
- );
- if($r) {
- q("update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s'",
- dbesc(datetime_convert()),
- intval($r[0]['cp_id']),
- dbesc($client)
- );
- return true;
- }
-
- $r = q("insert into chatpresence ( cp_room, cp_xchan, cp_last, cp_status, cp_client )
- values ( %d, '%s', '%s', '%s', '%s' )",
- intval($room_id),
- dbesc($observer_xchan),
- dbesc(datetime_convert()),
- dbesc($status),
- dbesc($client)
- );
-
- return $r;
-}
-
-
-function chatroom_leave($observer_xchan, $room_id, $client) {
- if(! $room_id || ! $observer_xchan)
- return;
-
- $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1",
- dbesc($observer_xchan),
- intval($room_id),
- dbesc($client)
- );
- if($r) {
- q("delete from chatpresence where cp_id = %d",
- intval($r[0]['cp_id'])
- );
- }
-
- return true;
-}
-
-
-function chatroom_list($uid) {
- require_once('include/security.php');
- $sql_extra = permissions_sql($uid);
-
- $r = q("select allow_cid, allow_gid, deny_cid, deny_gid, cr_name, cr_expire, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
- intval($uid)
- );
-
- return $r;
-}
-
-function chatroom_list_count($uid) {
- require_once('include/security.php');
- $sql_extra = permissions_sql($uid);
-
- $r = q("select count(*) as total from chatroom where cr_uid = %d $sql_extra",
- intval($uid)
- );
-
- return $r[0]['total'];
-}
-
-/**
- * create a chat message via API.
- * It is the caller's responsibility to enter the room.
- */
-
-function chat_message($uid, $room_id, $xchan, $text) {
-
- $ret = array('success' => false);
-
- if(! $text)
- return;
-
- $sql_extra = permissions_sql($uid);
-
- $r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
- intval($uid),
- intval($room_id)
- );
- if(! $r)
- return $ret;
-
- $arr = array(
- 'chat_room' => $room_id,
- 'chat_xchan' => $xchan,
- 'chat_text' => $text
- );
-
- call_hooks('chat_message', $arr);
-
- $x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
- values( %d, '%s', '%s', '%s' )",
- intval($room_id),
- dbesc($xchan),
- dbesc(datetime_convert()),
- dbesc($arr['chat_text'])
- );
-
- $ret['success'] = true;
- return $ret;
-}
diff --git a/include/checksites.php b/include/checksites.php
deleted file mode 100644
index e9c08c202..000000000
--- a/include/checksites.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/hubloc.php');
-
-
-
-function checksites_run($argv, $argc){
-
-
- cli_startup();
- $a = get_app();
-
- logger('checksites: start');
-
- if(($argc > 1) && ($argv[1]))
- $site_id = $argv[1];
-
- if($site_id)
- $sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
-
- $days = intval(get_config('system','sitecheckdays'));
- if($days < 1)
- $days = 30;
-
- $r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
- db_utcnow(), db_quoteinterval($days . ' DAY'),
- intval(SITE_TYPE_ZOT)
- );
-
- if(! $r)
- return;
-
- foreach($r as $rr) {
- if(! strcasecmp($rr['site_url'],z_root()))
- continue;
-
- $x = ping_site($rr['site_url']);
- if($x['success']) {
- logger('checksites: ' . $rr['site_url']);
- q("update site set site_update = '%s' where site_url = '%s' ",
- dbesc(datetime_convert()),
- dbesc($rr['site_url'])
- );
- }
- else {
- logger('marking dead site: ' . $x['message']);
- q("update site set site_dead = 1 where site_url = '%s' ",
- dbesc($rr['site_url'])
- );
- }
- }
-
- return;
-}
-
-if (array_search(__file__,get_included_files())===0){
- checksites_run($argv,$argc);
- killme();
-}
diff --git a/include/cli_startup.php b/include/cli_startup.php
index a99164d4c..a4c1f629a 100644
--- a/include/cli_startup.php
+++ b/include/cli_startup.php
@@ -6,36 +6,7 @@ require_once('boot.php');
function cli_startup() {
- global $a, $db, $default_timezone;
-
- if(is_null($a)) {
- $a = new miniApp;
- }
-
- App::init();
-
- if(is_null($db)) {
- @include(".htconfig.php");
-
- $a->convert();
-
- if(! defined('UNO'))
- define('UNO', 0);
-
- App::$timezone = ((x($default_timezone)) ? $default_timezone : 'UTC');
- date_default_timezone_set(App::$timezone);
-
- require_once('include/dba/dba_driver.php');
- $db = dba_factory($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
- unset($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
- };
-
- \Zotlabs\Web\Session::init();
-
- load_config('system');
-
+ sys_boot();
App::set_baseurl(get_config('system','baseurl'));
- load_hooks();
-
} \ No newline at end of file
diff --git a/include/cli_suggest.php b/include/cli_suggest.php
deleted file mode 100644
index 321ffd2e0..000000000
--- a/include/cli_suggest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-require_once('include/socgraph.php');
-
-
-function cli_suggest_run($argv, $argc){
-
- cli_startup();
-
- $a = get_app();
-
- update_suggestions();
-
-}
-
-if (array_search(__file__,get_included_files())===0){
- cli_suggest_run($argv,$argc);
- killme();
-}
-
diff --git a/include/comanche.php b/include/comanche.php
deleted file mode 100644
index 4d55aee19..000000000
--- a/include/comanche.php
+++ /dev/null
@@ -1,383 +0,0 @@
-<?php /** @file */
-
-require_once('include/security.php');
-require_once('include/menu.php');
-require_once('include/widgets.php');
-
-// When editing a webpage - a dropdown is needed to select a page layout
-// On submit, the pdl_select value (which is the mid of an item with item_type = ITEM_TYPE_PDL) is stored in
-// the webpage's resource_id, with resource_type 'pdl'.
-
-// Then when displaying a webpage, we can see if it has a pdl attached. If not we'll
-// use the default site/page layout.
-
-// If it has a pdl we'll load it as we know the mid and pass the body through comanche_parser() which will generate the
-// page layout from the given description
-
-
-function pdl_selector($uid, $current="") {
- $o = '';
-
- $sql_extra = item_permissions_sql($uid);
-
- $r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' $sql_extra order by sid asc",
- intval($uid)
- );
-
- $arr = array('channel_id' => $uid, 'current' => $current, 'entries' => $r);
- call_hooks('pdl_selector',$arr);
-
- $entries = $arr['entries'];
- $current = $arr['current'];
-
- $o .= '<select name="pdl_select" id="pdl_select" size="1">';
- $entries[] = array('title' => t('Default'), 'mid' => '');
- foreach($entries as $selection) {
- $selected = (($selection == $current) ? ' selected="selected" ' : '');
- $o .= "<option value=\"{$selection['mid']}\" $selected >{$selection['sid']}</option>";
- }
-
- $o .= '</select>';
- return $o;
-}
-
-
-
-function comanche_parser(&$a, $s, $pass = 0) {
- $matches = array();
-
- $cnt = preg_match_all("/\[comment\](.*?)\[\/comment\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0], '', $s);
- }
- }
-
- if($pass == 0) {
- $cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches);
- if($cnt)
- App::$page['template'] = trim($matches[1]);
-
- $cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches);
- if($cnt) {
- App::$page['template'] = trim($matches[2]);
- App::$page['template_style'] = trim($matches[2]) . '_' . $matches[1];
- }
-
- $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches);
- if($cnt) {
- App::$page['template'] = trim($matches[1]);
- }
-
- $cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches);
- if($cnt) {
- App::$layout['schema'] = trim($matches[1]);
- App::$layout['theme'] = trim($matches[2]);
- }
-
- $cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches);
- if($cnt)
- App::$layout['theme'] = trim($matches[1]);
-
- $cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- // only the last webpage definition is used if there is more than one
- foreach($matches as $mtch) {
- App::$layout['webpage'] = comanche_webpage($a,$mtch[1]);
- }
- }
-
- }
- else {
- $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- App::$layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
- }
- }
-
- }
-
-}
-
-
-function comanche_menu($s, $class = '') {
-
- $channel_id = comanche_get_channel_id();
- $name = $s;
-
- $cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $var[$mtch[1]] = $mtch[2];
- $name = str_replace($mtch[0], '', $name);
- }
- }
-
- if($channel_id) {
- $m = menu_fetch($name,$channel_id, get_observer_hash());
- return menu_render($m, $class, $edit = false, $var);
- }
-}
-
-function comanche_replace_region($match) {
- $a = get_app();
- if (array_key_exists($match[1], App::$page)) {
- return App::$page[$match[1]];
- }
-}
-
-/**
- * @brief Returns the channel_id of the profile owner of the page.
- *
- * Returns the channel_id of the profile owner of the page, or the local_channel
- * if there is no profile owner. Otherwise returns 0.
- *
- * @return channel_id
- */
-function comanche_get_channel_id() {
- $channel_id = ((is_array(App::$profile)) ? App::$profile['profile_uid'] : 0);
-
- if ((! $channel_id) && (local_channel()))
- $channel_id = local_channel();
-
- return $channel_id;
-}
-
-function comanche_block($s, $class = '') {
- $var = array();
- $matches = array();
- $name = $s;
- $class = (($class) ? $class : 'bblock widget');
-
- $cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $var[$mtch[1]] = $mtch[2];
- $name = str_replace($mtch[0], '', $name);
- }
- }
-
- $o = '';
- $channel_id = comanche_get_channel_id();
-
- if($channel_id) {
- $r = q("select * from item inner join item_id on iid = item.id and item_id.uid = item.uid and item.uid = %d and service = 'BUILDBLOCK' and sid = '%s' limit 1",
- intval($channel_id),
- dbesc($name)
- );
-
- if($r) {
- //check for eventual menus in the block and parse them
- $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $r[0]['body'], $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $r[0]['body'] = str_replace($mtch[0], comanche_menu(trim($mtch[1])), $r[0]['body']);
- }
- }
- $cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $r[0]['body'], $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $r[0]['body'] = str_replace($mtch[0],comanche_menu(trim($mtch[2]),$mtch[1]),$r[0]['body']);
- }
- }
-
- //emit the block
- $o .= (($var['wrap'] == 'none') ? '' : '<div class="' . $class . '">');
-
- if($r[0]['title'] && trim($r[0]['body']) != '$content') {
- $o .= '<h3>' . $r[0]['title'] . '</h3>';
- }
-
- if(trim($r[0]['body']) === '$content') {
- $o .= App::$page['content'];
- }
- else {
- $o .= prepare_text($r[0]['body'], $r[0]['mimetype']);
- }
-
- $o .= (($var['wrap'] == 'none') ? '' : '</div>');
- }
- }
-
- return $o;
-}
-
-function comanche_js($s) {
-
- switch($s) {
- case 'jquery':
- $path = 'view/js/jquery.js';
- break;
- case 'bootstrap':
- $path = 'library/bootstrap/js/bootstrap.min.js';
- break;
- case 'foundation':
- $path = 'library/foundation/js/foundation.min.js';
- $init = "\r\n" . '<script>$(document).ready(function() { $(document).foundation(); });</script>';
- break;
- }
-
- $ret = '<script src="' . z_root() . '/' . $path . '" ></script>';
- if($init)
- $ret .= $init;
-
- return $ret;
-
-}
-
-function comanche_css($s) {
-
- switch($s) {
- case 'bootstrap':
- $path = 'library/bootstrap/css/bootstrap.min.css';
- break;
- case 'foundation':
- $path = 'library/foundation/css/foundation.min.css';
- break;
- }
-
- $ret = '<link rel="stylesheet" href="' . z_root() . '/' . $path . '" type="text/css" media="screen">';
-
- return $ret;
-
-}
-
-// This doesn't really belong in Comanche, but it could also be argued that it is the perfect place.
-// We need to be able to select what kind of template and decoration to use for the webpage at the heart of our content.
-// For now we'll allow an '[authored]' element which defaults to name and date, or 'none' to remove these, and perhaps
-// 'full' to provide a social network style profile photo.
-// But leave it open to have richer templating options and perhaps ultimately discard this one, once we have a better idea
-// of what template and webpage options we might desire.
-
-function comanche_webpage(&$a,$s) {
- $ret = array();
- $matches = array();
-
- $cnt = preg_match_all("/\[authored\](.*?)\[\/authored\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $ret['authored'] = $mtch[1];
- }
- }
- return $ret;
-}
-
-
-/**
- * Widgets will have to get any operational arguments from the session, the
- * global app environment, or config storage until we implement argument passing
- *
- * @param string $name
- * @param string $text
- */
-function comanche_widget($name, $text) {
- $vars = array();
- $matches = array();
-
-
- $cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $text, $matches, PREG_SET_ORDER);
- if ($cnt) {
- foreach ($matches as $mtch) {
- $vars[$mtch[1]] = $mtch[2];
- }
- }
-
- $func = 'widget_' . trim($name);
-
- if(! function_exists($func)) {
- if(file_exists('widget/' . trim($name) . '.php'))
- require_once('widget/' . trim($name) . '.php');
- elseif(file_exists('widget/' . trim($name) . '/' . trim($name) . '.php'))
- require_once('widget/' . trim($name) . '/' . trim($name) . '.php');
- }
- else {
- $theme_widget = $func . '.php';
- if((! function_exists($func)) && theme_include($theme_widget))
- require_once(theme_include($theme_widget));
- }
-
- if (function_exists($func))
- return $func($vars);
-}
-
-
-function comanche_region(&$a, $s) {
- $matches = array();
-
- $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0], comanche_menu(trim($mtch[1])), $s);
- }
- }
-
- // menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu]
- // allows different menu renderings to be applied
-
- $cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_menu(trim($mtch[2]),$mtch[1]),$s);
- }
- }
- $cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_block(trim($mtch[1])),$s);
- }
- }
-
- $cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_block(trim($mtch[2]),trim($mtch[1])),$s);
- }
- }
-
- $cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_js(trim($mtch[1])),$s);
- }
- }
-
- $cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_css(trim($mtch[1])),$s);
- }
- }
- // need to modify this to accept parameters
-
- $cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $s, $matches, PREG_SET_ORDER);
- if($cnt) {
- foreach($matches as $mtch) {
- $s = str_replace($mtch[0],comanche_widget(trim($mtch[1]),$mtch[2]),$s);
- }
- }
-
- return $s;
-}
-
-
-/*
- * @function register_page_template($arr)
- * Registers a page template/variant for use by Comanche selectors
- * @param array $arr
- * 'template' => template name
- * 'variant' => array(
- * 'name' => variant name
- * 'desc' => text description
- * 'regions' => array(
- * 'name' => name
- * 'desc' => text description
- * )
- * )
- */
-
-
-function register_page_template($arr) {
- App::$page_layouts[$arr['template']] = array($arr['variant']);
- return;
-}
diff --git a/include/config.php b/include/config.php
index 712b4ca11..8c0469392 100644
--- a/include/config.php
+++ b/include/config.php
@@ -1,17 +1,13 @@
<?php
+
/**
* @file include/config.php
* @brief Arbitrary configuration storage.
*
- * @note Please do not store booleans - convert to 0/1 integer values.
- * The get_?config() functions return boolean false for keys that are unset,
- * and this could lead to subtle bugs.
- *
- * Arrays get stored as serialize strings.
- *
- * @todo There are a few places in the code (such as the admin panel) where
- * boolean configurations need to be fixed as of 10/08/2011.
+ * Arrays get stored as serialized strings.
+ * Booleans are stored as integer 0/1.
*
+
* - <b>config</b> is used for hub specific configurations. It overrides the
* configurations from .htconfig file. The storage is of size TEXT.
* - <b>pconfig</b> is used for channel specific configurations and takes a
@@ -34,594 +30,101 @@
*
*/
-/**
- * @brief Loads the hub's configuration from database to a cached storage.
- *
- * Retrieve a category ($family) of config variables from database to a cached
- * storage in the global App::$config[$family].
- *
- * @param string $family
- * The category of the configuration value
- */
-function load_config($family) {
- global $a;
- if(! array_key_exists($family, App::$config))
- App::$config[$family] = array();
+use Zotlabs\Lib as Zlib;
- if(! array_key_exists('config_loaded', App::$config[$family])) {
- $r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
- if($r !== false) {
- if($r) {
- foreach($r as $rr) {
- $k = $rr['k'];
- App::$config[$family][$k] = $rr['v'];
- }
- }
- App::$config[$family]['config_loaded'] = true;
- }
- }
+function load_config($family) {
+ Zlib\Config::Load($family);
}
-/**
- * @brief Get a particular config variable given the category name ($family)
- * and a key.
- *
- * Get a particular config variable from the given category ($family) and the
- * $key from a cached storage in App::$config[$family]. If a key is found in the
- * DB but does not exist in local config cache, pull it into the cache so we
- * do not have to hit the DB again for this item.
- *
- * Returns false if not set.
- *
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to query
- * @return mixed Return value or false on error or if not set
- */
function get_config($family, $key) {
- global $a;
-
- if((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family])))
- load_config($family);
-
- if(array_key_exists('config_loaded', App::$config[$family])) {
- if(! array_key_exists($key, App::$config[$family])) {
- return false;
- }
- return ((! is_array(App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$family][$key]))
- ? unserialize(App::$config[$family][$key])
- : App::$config[$family][$key]
- );
- }
- return false;
+ return Zlib\Config::Get($family,$key);
}
-/**
- * @brief Returns a value directly from the database configuration storage.
- *
- * This function queries directly the database and bypasses the chached storage
- * from get_config($family, $key).
- *
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to query
- * @return mixed
- */
-function get_config_from_storage($family, $key) {
- $ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
- dbesc($family),
- dbesc($key)
- );
- return $ret;
-}
-
-/**
- * @brief Sets a configuration value for the hub.
- *
- * Stores a config value ($value) in the category ($family) under the key ($key).
- *
- * @note Please do not store booleans - convert to 0/1 integer values!
- *
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to set
- * @param mixed $value
- * The value to store in the configuration
- * @return mixed
- * Return the set value, or false if the database update failed
- */
function set_config($family, $key, $value) {
- global $a;
-
- // manage array value
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- if(get_config($family, $key) === false || (! get_config_from_storage($family, $key))) {
- $ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue)
- );
- if($ret) {
- App::$config[$family][$key] = $value;
- $ret = $value;
- }
- return $ret;
- }
-
- $ret = q("UPDATE config SET v = '%s' WHERE cat = '%s' AND k = '%s'",
- dbesc($dbvalue),
- dbesc($family),
- dbesc($key)
- );
-
- if($ret) {
- App::$config[$family][$key] = $value;
- $ret = $value;
- }
- return $ret;
+ return Zlib\Config::Set($family,$key,$value);
}
-/**
- * @brief Deletes the given key from the hub's configuration database.
- *
- * Removes the configured value from the stored cache in App::$config[$family]
- * and removes it from the database.
- *
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to delete
- * @return mixed
- */
function del_config($family, $key) {
- global $a;
- $ret = false;
-
- if(array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family]))
- unset(App::$config[$family][$key]);
- $ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
- dbesc($family),
- dbesc($key)
- );
- return $ret;
+ return Zlib\Config::Delete($family,$key);
}
-
-/**
- * @brief Loads all configuration values of a channel into a cached storage.
- *
- * All configuration values of the given channel are stored in global cache
- * which is available under the global variable App::$config[$uid].
- *
- * @param string $uid
- * The channel_id
- * @return void|false Nothing or false if $uid is false
- */
function load_pconfig($uid) {
- global $a;
-
- if($uid === false)
- return false;
-
- if(! array_key_exists($uid, App::$config))
- App::$config[$uid] = array();
-
- $r = q("SELECT * FROM pconfig WHERE uid = %d",
- intval($uid)
- );
-
- if($r) {
- foreach($r as $rr) {
- $k = $rr['k'];
- $c = $rr['cat'];
- if(! array_key_exists($c, App::$config[$uid])) {
- App::$config[$uid][$c] = array();
- App::$config[$uid][$c]['config_loaded'] = true;
- }
- App::$config[$uid][$c][$k] = $rr['v'];
- }
- }
+ Zlib\PConfig::Load($uid);
}
-/**
- * @brief Get a particular channel's config variable given the category name
- * ($family) and a key.
- *
- * Get a particular channel's config value from the given category ($family)
- * and the $key from a cached storage in App::$config[$uid].
- *
- * Returns false if not set.
- *
- * @param string $uid
- * The channel_id
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to query
- * @param boolean $instore (deprecated, without function)
- * @return mixed Stored value or false if it does not exist
- */
function get_pconfig($uid, $family, $key, $instore = false) {
-// logger('include/config.php: get_pconfig() deprecated instore param used', LOGGER_DEBUG);
- global $a;
-
- if($uid === false)
- return false;
-
- if(! array_key_exists($uid, App::$config))
- load_pconfig($uid);
-
- if((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family])))
- return false;
-
- return ((! is_array(App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$uid][$family][$key]))
- ? unserialize(App::$config[$uid][$family][$key])
- : App::$config[$uid][$family][$key]
- );
+ return Zlib\PConfig::Get($uid,$family,$key,$instore = false);
}
-/**
- * @brief Sets a configuration value for a channel.
- *
- * Stores a config value ($value) in the category ($family) under the key ($key)
- * for the channel_id $uid.
- *
- * @note Please do not store booleans - convert to 0/1 integer values!
- *
- * @param string $uid
- * The channel_id
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to set
- * @param string $value
- * The value to store
- * @return mixed Stored $value or false
- */
function set_pconfig($uid, $family, $key, $value) {
- global $a;
-
- // this catches subtle errors where this function has been called
- // with local_channel() when not logged in (which returns false)
- // and throws an error in array_key_exists below.
- // we provide a function backtrace in the logs so that we can find
- // and fix the calling function.
-
- if($uid === false) {
- btlogger('UID is FALSE!', LOGGER_NORMAL, LOG_ERR);
- return;
- }
-
- // manage array value
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- if(get_pconfig($uid, $family, $key) === false) {
- if(! array_key_exists($uid, App::$config))
- App::$config[$uid] = array();
- if(! array_key_exists($family, App::$config[$uid]))
- App::$config[$uid][$family] = array();
-
- // keep a separate copy for all variables which were
- // set in the life of this page. We need this to
- // synchronise channel clones.
-
- if(! array_key_exists('transient', App::$config[$uid]))
- App::$config[$uid]['transient'] = array();
- if(! array_key_exists($family, App::$config[$uid]['transient']))
- App::$config[$uid]['transient'][$family] = array();
-
- App::$config[$uid][$family][$key] = $value;
- App::$config[$uid]['transient'][$family][$key] = $value;
-
- $ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
- intval($uid),
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue)
- );
- if($ret)
- return $value;
-
- return $ret;
- }
-
- $ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
- dbesc($dbvalue),
- intval($uid),
- dbesc($family),
- dbesc($key)
- );
-
- // keep a separate copy for all variables which were
- // set in the life of this page. We need this to
- // synchronise channel clones.
-
- if(! array_key_exists('transient', App::$config[$uid]))
- App::$config[$uid]['transient'] = array();
- if(! array_key_exists($family, App::$config[$uid]['transient']))
- App::$config[$uid]['transient'][$family] = array();
-
- App::$config[$uid][$family][$key] = $value;
- App::$config[$uid]['transient'][$family][$key] = $value;
-
- if($ret)
- return $value;
-
- return $ret;
+ return Zlib\PConfig::Set($uid,$family,$key,$value);
}
-/**
- * @brief Deletes the given key from the channel's configuration.
- *
- * Removes the configured value from the stored cache in App::$config[$uid]
- * and removes it from the database.
- *
- * @param string $uid
- * The channel_id
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to delete
- * @return mixed
- */
function del_pconfig($uid, $family, $key) {
- global $a;
- $ret = false;
-
- if (x(App::$config[$uid][$family], $key))
- unset(App::$config[$uid][$family][$key]);
- $ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
- intval($uid),
- dbesc($family),
- dbesc($key)
- );
-
- return $ret;
+ return Zlib\PConfig::Delete($uid,$family,$key);
}
-
-/**
- * @brief Loads a full xchan's configuration into a cached storage.
- *
- * All configuration values of the given observer hash are stored in global
- * cache which is available under the global variable App::$config[$xchan].
- *
- * @param string $xchan
- * The observer's hash
- * @return void|false Returns false if xchan is not set
- */
function load_xconfig($xchan) {
- global $a;
-
- if(! $xchan)
- return false;
-
- if(! array_key_exists($xchan, App::$config))
- App::$config[$xchan] = array();
-
- $r = q("SELECT * FROM xconfig WHERE xchan = '%s'",
- dbesc($xchan)
- );
-
- if($r) {
- foreach($r as $rr) {
- $k = $rr['k'];
- $c = $rr['cat'];
- if(! array_key_exists($c, App::$config[$xchan])) {
- App::$config[$xchan][$c] = array();
- App::$config[$xchan][$c]['config_loaded'] = true;
- }
- App::$config[$xchan][$c][$k] = $rr['v'];
- }
- }
+ Zlib\XConfig::Load($xchan);
}
-/**
- * @brief Get a particular observer's config variable given the category
- * name ($family) and a key.
- *
- * Get a particular observer's config value from the given category ($family)
- * and the $key from a cached storage in App::$config[$xchan].
- *
- * Returns false if not set.
- *
- * @param string $xchan
- * The observer's hash
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to query
- * @return mixed Stored $value or false if it does not exist
- */
function get_xconfig($xchan, $family, $key) {
- global $a;
-
- if(! $xchan)
- return false;
-
- if(! array_key_exists($xchan, App::$config))
- load_xconfig($xchan);
-
- if((! array_key_exists($family, App::$config[$xchan])) || (! array_key_exists($key, App::$config[$xchan][$family])))
- return false;
-
- return ((! is_array(App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$xchan][$family][$key]))
- ? unserialize(App::$config[$xchan][$family][$key])
- : App::$config[$xchan][$family][$key]
- );
+ return Zlib\XConfig::Get($xchan,$family,$key);
}
-/**
- * @brief Sets a configuration value for an observer.
- *
- * Stores a config value ($value) in the category ($family) under the key ($key)
- * for the observer's $xchan hash.
- *
- * @note Please do not store booleans - convert to 0/1 integer values!
- *
- * @param string $xchan
- * The observer's hash
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to set
- * @param string $value
- * The value to store
- * @return mixed Stored $value or false
- */
function set_xconfig($xchan, $family, $key, $value) {
- global $a;
-
- // manage array value
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- if(get_xconfig($xchan, $family, $key) === false) {
- if(! array_key_exists($xchan, App::$config))
- App::$config[$xchan] = array();
- if(! array_key_exists($family, App::$config[$xchan]))
- App::$config[$xchan][$family] = array();
-
- App::$config[$xchan][$family][$key] = $value;
- $ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' ) ",
- dbesc($xchan),
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue)
- );
- if($ret)
- return $value;
- return $ret;
- }
-
- $ret = q("UPDATE xconfig SET v = '%s' WHERE xchan = '%s' and cat = '%s' AND k = '%s'",
- dbesc($dbvalue),
- dbesc($xchan),
- dbesc($family),
- dbesc($key)
- );
-
- App::$config[$xchan][$family][$key] = $value;
-
- if($ret)
- return $value;
- return $ret;
+ return Zlib\XConfig::Set($xchan,$family,$key,$value);
}
-/**
- * @brief Deletes the given key from the observer's config.
- *
- * Removes the configured value from the stored cache in App::$config[$xchan]
- * and removes it from the database.
- *
- * @param string $xchan
- * The observer's hash
- * @param string $family
- * The category of the configuration value
- * @param string $key
- * The configuration key to delete
- * @return mixed
- */
function del_xconfig($xchan, $family, $key) {
- global $a;
- $ret = false;
-
- if(x(App::$config[$xchan][$family], $key))
- unset(App::$config[$xchan][$family][$key]);
- $ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
- dbesc($xchan),
- dbesc($family),
- dbesc($key)
- );
- return $ret;
+ return Zlib\XConfig::Delete($xchan,$family,$key);
}
-
-// account configuration storage is built on top of the under-utilised xconfig
-
function load_aconfig($account_id) {
- load_xconfig('a_' . $account_id);
+ Zlib\AConfig::Load($account_id);
}
function get_aconfig($account_id, $family, $key) {
- return get_xconfig('a_' . $account_id, $family, $key);
+ return Zlib\AConfig::Get($account_id, $family, $key);
}
function set_aconfig($account_id, $family, $key, $value) {
- return set_xconfig('a_' . $account_id, $family, $key, $value);
+ return Zlib\AConfig::Set($account_id, $family, $key, $value);
}
function del_aconfig($account_id, $family, $key) {
- return del_xconfig('a_' . $account_id, $family, $key);
+ return Zlib\AConfig::Delete($account_id, $family, $key);
}
-
-function load_abconfig($chash,$xhash) {
- $r = q("select * from abconfig where chan = '%s' and xchan = '%s'",
- dbesc($chash),
- dbesc($xhash)
- );
- return $r;
+function load_abconfig($chan, $xhash, $family = '') {
+ return Zlib\AbConfig::Load($chan,$xhash,$family);
}
-function get_abconfig($chash,$xhash,$family,$key) {
- $r = q("select * from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
- dbesc($chash),
- dbesc($xhash),
- dbesc($family),
- dbesc($key)
- );
- if($r) {
- return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
- }
- return false;
+function get_abconfig($chan,$xhash,$family,$key) {
+ return Zlib\AbConfig::Get($chan,$xhash,$family,$key);
}
+function set_abconfig($chan,$xhash,$family,$key,$value) {
+ return Zlib\AbConfig::Set($chan,$xhash,$family,$key,$value);
+}
-function set_abconfig($chash,$xhash,$family,$key,$value) {
-
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- if(get_abconfig($chash,$xhash,$family,$key) === false) {
- $r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( '%s', '%s', '%s', '%s', '%s' ) ",
- dbesc($chash),
- dbesc($xhash),
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue)
- );
- }
- else {
- $r = q("update abconfig set v = '%s' where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
- dbesc($dbvalue),
- dbesc($chash),
- dbesc($xhash),
- dbesc($family),
- dbesc($key)
- );
- }
- if($r)
- return $value;
- return false;
+function del_abconfig($chan,$xhash,$family,$key) {
+ return Zlib\AbConfig::Delete($chan,$xhash,$family,$key);
}
+function load_iconfig(&$item) {
+ Zlib\IConfig::Load($item);
+}
-function del_abconfig($chash,$xhash,$family,$key) {
+function get_iconfig(&$item, $family, $key) {
+ return Zlib\IConfig::Get($item, $family, $key);
+}
- $r = q("delete from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
- dbesc($chash),
- dbesc($xhash),
- dbesc($family),
- dbesc($key)
- );
+function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
+ return Zlib\IConfig::Set($item, $family, $key, $value, $sharing);
+}
- return $r;
+function del_iconfig(&$item, $family, $key) {
+ return Zlib\IConfig::Delete($item, $family, $key);
}
diff --git a/include/Contact.php b/include/connections.php
index e011c60c8..9f55820cc 100644
--- a/include/Contact.php
+++ b/include/connections.php
@@ -48,32 +48,9 @@ function abook_self($channel_id) {
return(($r) ? $r[0] : array());
}
-function channelx_by_nick($nick) {
- $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_address = '%s' and channel_removed = 0 LIMIT 1",
- dbesc($nick)
- );
- return(($r) ? $r[0] : false);
-}
-
-function channelx_by_hash($hash) {
- $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_hash = '%s' and channel_removed = 0 LIMIT 1",
- dbesc($hash)
- );
- return(($r) ? $r[0] : false);
-}
-
-function channelx_by_n($id) {
- $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_id = %d and channel_removed = 0 LIMIT 1",
- dbesc($id)
- );
- return(($r) ? $r[0] : false);
-}
-
function vcard_from_xchan($xchan, $observer = null, $mode = '') {
- $a = get_app();
-
if(! $xchan) {
if(App::$poi) {
$xchan = App::$poi;
@@ -198,7 +175,7 @@ function account_remove($account_id,$local = true,$unset_session=true) {
// Don't let anybody nuke the only admin account.
- $r = q("select account_id from account where (account_roles & %d)>0",
+ $r = q("select account_id from account where (account_roles & %d) > 0",
intval(ACCOUNT_ROLE_ADMIN)
);
@@ -267,7 +244,7 @@ function channel_remove($channel_id, $local = true, $unset_session=false) {
if(! $channel_id)
return;
- $a = get_app();
+
logger('Removing channel: ' . $channel_id);
logger('channel_remove: local only: ' . intval($local));
@@ -283,15 +260,15 @@ function channel_remove($channel_id, $local = true, $unset_session=false) {
if(! $local) {
- $r = q("update channel set channel_deleted = '%s', channel_removed = 1, channel_r_stream = 0, channel_r_profile = 0,
- channel_r_photos = 0, channel_r_abook = 0, channel_w_stream = 0, channel_w_wall = 0, channel_w_tagwall = 0,
- channel_w_comment = 0, channel_w_mail = 0, channel_w_photos = 0, channel_w_chat = 0, channel_a_delegate = 0,
- channel_r_storage = 0, channel_w_storage = 0, channel_r_pages = 0, channel_w_pages = 0, channel_a_republish = 0
- where channel_id = %d",
+ $r = q("update channel set channel_deleted = '%s', channel_removed = 1 where channel_id = %d",
dbesc(datetime_convert()),
intval($channel_id)
);
+ q("delete from pconfig where uid = %d",
+ intval($channel_id)
+ );
+
logger('deleting hublocs',LOGGER_DEBUG);
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_hash = '%s'",
@@ -303,22 +280,33 @@ function channel_remove($channel_id, $local = true, $unset_session=false) {
dbesc($channel['channel_hash'])
);
- proc_run('php','include/notifier.php','purge_all',$channel_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','purge_all',$channel_id));
+ }
+
+ $r = q("select * from iconfig left join item on item.id = iconfig.iid
+ where item.uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ q("delete from iconfig where iid = %d",
+ intval($rr['iid'])
+ );
+ }
}
+
q("DELETE FROM `groups` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `group_member` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `event` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `item` WHERE `uid` = %d", intval($channel_id));
- q("DELETE FROM `item_id` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `mail` WHERE `channel_id` = %d", intval($channel_id));
q("DELETE FROM `notify` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `photo` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `attach` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `profile` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `pconfig` WHERE `uid` = %d", intval($channel_id));
- q("DELETE FROM `spam` WHERE `uid` = %d", intval($channel_id));
// @FIXME At this stage we need to remove the file resources located under /store/$nickname
@@ -386,10 +374,10 @@ function channel_remove($channel_id, $local = true, $unset_session=false) {
@rrmdir($f);
}
- proc_run('php','include/directory.php',$channel_id);
+ Zotlabs\Daemon\Master::Summon(array('Directory',$channel_id));
if($channel_id == local_channel() && $unset_session) {
- \Zotlabs\Web\Session::nuke();
+ App::$session->nuke();
goaway(z_root());
}
@@ -614,7 +602,8 @@ function random_profile() {
for($i = 0; $i < $retryrandom; $i++) {
- $r = q("select xchan_url from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_connected > %s - interval %s order by $randfunc limit 1",
+ $r = q("select xchan_url from xchan left join hubloc on hubloc_hash = xchan_hash where xchan_addr not like '%s' and hubloc_connected > %s - interval %s order by $randfunc limit 1",
+ dbesc('sys@%'),
db_utcnow(), db_quoteinterval('30 day')
);
diff --git a/include/contact_selectors.php b/include/contact_selectors.php
deleted file mode 100644
index 0de4ece00..000000000
--- a/include/contact_selectors.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php /** @file */
-
-
-function contact_profile_assign($current) {
-
- $o = '';
-
- $o .= "<select id=\"contact-profile-selector\" name=\"profile_assign\" class=\"form-control\"/>\r\n";
-
- $r = q("SELECT profile_guid, profile_name FROM `profile` WHERE `uid` = %d",
- intval($_SESSION['uid']));
-
- if($r) {
- foreach($r as $rr) {
- $selected = (($rr['profile_guid'] == $current) ? " selected=\"selected\" " : "");
- $o .= "<option value=\"{$rr['profile_guid']}\" $selected >{$rr['profile_name']}</option>\r\n";
- }
- }
- $o .= "</select>\r\n";
- return $o;
-}
-
-/* unused currently
-
-function contact_reputation($current) {
-
- $o = '';
- $o .= "<select id=\"contact-reputation-selector\" name=\"reputation\" />\r\n";
-
- $rep = array(
- 0 => t('Unknown | Not categorized'),
- 1 => t('Block immediately'),
- 2 => t('Shady, spammer, self-marketer'),
- 3 => t('Known to me, but no opinion'),
- 4 => t('OK, probably harmless'),
- 5 => t('Reputable, has my trust')
- );
-
- foreach($rep as $k => $v) {
- $selected = (($k == $current) ? " selected=\"selected\" " : "");
- $o .= "<option value=\"$k\" $selected >$v</option>\r\n";
- }
- $o .= "</select>\r\n";
- return $o;
-}
-
-*/
-
-function contact_poll_interval($current, $disabled = false) {
-
- $dis = (($disabled) ? ' disabled="disabled" ' : '');
- $o = '';
- $o .= "<select id=\"contact-poll-interval\" name=\"poll\" $dis />" . "\r\n";
-
- $rep = array(
- 0 => t('Frequently'),
- 1 => t('Hourly'),
- 2 => t('Twice daily'),
- 3 => t('Daily'),
- 4 => t('Weekly'),
- 5 => t('Monthly')
- );
-
- foreach($rep as $k => $v) {
- $selected = (($k == $current) ? " selected=\"selected\" " : "");
- $o .= "<option value=\"$k\" $selected >$v</option>\r\n";
- }
- $o .= "</select>\r\n";
- return $o;
-}
-
-
-function network_to_name($s) {
-
- $nets = array(
- NETWORK_DFRN => t('Friendica'),
- NETWORK_FRND => t('Friendica'),
- NETWORK_OSTATUS => t('OStatus'),
- NETWORK_GNUSOCIAL => t('GNU-Social'),
- NETWORK_FEED => t('RSS/Atom'),
- NETWORK_MAIL => t('Email'),
- NETWORK_DIASPORA => t('Diaspora'),
- NETWORK_FACEBOOK => t('Facebook'),
- NETWORK_ZOT => t('Zot'),
- NETWORK_LINKEDIN => t('LinkedIn'),
- NETWORK_XMPP => t('XMPP/IM'),
- NETWORK_MYSPACE => t('MySpace'),
- );
-
- call_hooks('network_to_name', $nets);
-
- $search = array_keys($nets);
- $replace = array_values($nets);
-
- return str_replace($search,$replace,$s);
-
-}
diff --git a/include/contact_widgets.php b/include/contact_widgets.php
index ba1241fcb..85c46b0d1 100644
--- a/include/contact_widgets.php
+++ b/include/contact_widgets.php
@@ -3,9 +3,6 @@
function findpeople_widget() {
- require_once('include/Contact.php');
-
- $a = get_app();
if(get_config('system','invitation_only')) {
$x = get_pconfig(local_channel(),'system','invites_remaining');
@@ -37,13 +34,12 @@ function findpeople_widget() {
function fileas_widget($baseurl,$selected = '') {
- $a = get_app();
if(! local_channel())
return '';
$terms = array();
- $r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
+ $r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
intval(local_channel()),
intval(TERM_FILE)
);
@@ -65,8 +61,6 @@ function fileas_widget($baseurl,$selected = '') {
}
function categories_widget($baseurl,$selected = '') {
-
- $a = get_app();
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
return '';
@@ -78,13 +72,15 @@ function categories_widget($baseurl,$selected = '') {
from term join item on term.oid = item.id
where item.uid = %d
and term.uid = item.uid
- and term.type = %d
+ and term.ttype = %d
+ and term.otype = %d
and item.owner_xchan = '%s'
and item.item_wall = 1
$item_normal
order by term.term asc",
intval(App::$profile['profile_uid']),
intval(TERM_CATEGORY),
+ intval(TERM_OBJ_POST),
dbesc(App::$profile['channel_hash'])
);
if($r && count($r)) {
@@ -106,8 +102,6 @@ function categories_widget($baseurl,$selected = '') {
function common_friends_visitor_widget($profile_uid) {
- $a = get_app();
-
if(local_channel() == $profile_uid)
return;
diff --git a/include/conversation.php b/include/conversation.php
index 7d80b08fc..1efca37f3 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -93,15 +93,15 @@ function localize_item(&$item){
if (activity_match($item['verb'],ACTIVITY_LIKE) || activity_match($item['verb'],ACTIVITY_DISLIKE)){
- if(! $item['object'])
+ if(! $item['obj'])
return;
if(intval($item['item_thread_top']))
return;
- $obj = json_decode_plus($item['object']);
- if((! $obj) && ($item['object'])) {
- logger('localize_item: failed to decode object: ' . print_r($item['object'],true));
+ $obj = json_decode($item['obj'],true);
+ if((! $obj) && ($item['obj'])) {
+ logger('localize_item: failed to decode object: ' . print_r($item['obj'],true));
}
if($obj['author'] && $obj['author']['link'])
@@ -186,7 +186,7 @@ function localize_item(&$item){
$Alink = $item['author']['xchan_url'];
- $obj= json_decode_plus($item['object']);
+ $obj= json_decode($item['obj'],true);
$Blink = $Bphoto = '';
@@ -219,7 +219,7 @@ function localize_item(&$item){
$Aname = $item['author']['xchan_name'];
$Alink = $item['author']['xchan_url'];
- $obj= json_decode_plus($item['object']);
+ $obj= json_decode($item['obj'],true);
$Blink = $Bphoto = '';
@@ -299,7 +299,7 @@ function localize_item(&$item){
}
$plink = '[zrl=' . $obj['plink'] . ']' . $post_type . '[/zrl]';
- $parsedobj = parse_xml_string($xmlhead.$item['object']);
+ $parsedobj = parse_xml_string($xmlhead.$item['obj']);
$tag = sprintf('#[zrl=%s]%s[/zrl]', $parsedobj->id, $parsedobj->content);
$item['body'] = sprintf( t('%1$s tagged %2$s\'s %3$s with %4$s'), $author, $objauthor, $plink, $tag );
@@ -316,7 +316,7 @@ function localize_item(&$item){
$xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
- $obj = parse_xml_string($xmlhead.$item['object']);
+ $obj = parse_xml_string($xmlhead.$item['obj']);
if(strlen($obj->id)) {
$r = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($obj->id),
@@ -403,9 +403,12 @@ function count_descendants($item) {
* @return boolean
*/
function visible_activity($item) {
- $hidden_activities = array(ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
+ $hidden_activities = [ ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ];
- $post_types = array(ACTIVITY_OBJ_NOTE,ACTIVITY_OBJ_COMMENT,basename(ACTIVITY_OBJ_NOTE),basename(ACTIVITY_OBJ_COMMENT));
+ $post_types = [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT, basename(ACTIVITY_OBJ_NOTE), basename(ACTIVITY_OBJ_COMMENT)];
+
+ if(intval($item['item_notshown']))
+ return false;
foreach ($hidden_activities as $act) {
if ((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) {
@@ -658,7 +661,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
);
$star = false;
- $isstarred = "unstarred icon-star-empty";
+ $isstarred = "unstarred fa-star-o";
$lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
? t('Private Message')
@@ -754,10 +757,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
// Normal View
// logger('conv: items: ' . print_r($items,true));
- require_once('include/ConversationObject.php');
- require_once('include/ItemObject.php');
-
- $conv = new Conversation($mode, $preview, $prepared_item);
+ $conv = new Zotlabs\Lib\ThreadStream($mode, $preview, $prepared_item);
// In the display mode we don't have a profile owner.
@@ -806,7 +806,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
if($item['id'] == $item['parent']) {
- $item_object = new Item($item);
+ $item_object = new Zotlabs\Lib\ThreadItem($item);
$conv->add_thread($item_object);
if($page_mode === 'list') {
$item_object->set_template('conv_list.tpl');
@@ -861,8 +861,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
function best_link_url($item) {
- $a = get_app();
-
$best_url = '';
$sparkle = false;
@@ -891,7 +889,7 @@ function best_link_url($item) {
function item_photo_menu($item){
- $a = get_app();
+
$contact = null;
$ssl_state = false;
@@ -1110,82 +1108,95 @@ function status_editor($a, $x, $popup = false) {
$o = '';
- require_once('include/Contact.php');
$c = channelx_by_n($x['profile_uid']);
if($c && $c['channel_moved'])
return $o;
- $geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
-
$plaintext = true;
// if(feature_enabled(local_channel(),'richtext'))
// $plaintext = false;
- $voting = feature_enabled(local_channel(), 'consensus_tools');
- if(x($x, 'novoting'))
- $voting = false;
+ $feature_voting = feature_enabled($x['profile_uid'], 'consensus_tools');
+ if(x($x, 'hide_voting'))
+ $feature_voting = false;
- $mimeselect = '';
- if(array_key_exists('mimetype', $x) && $x['mimetype']) {
- if($x['mimetype'] != 'text/bbcode')
- $plaintext = true;
- if($x['mimetype'] === 'choose') {
- $mimeselect = mimetype_select($x['profile_uid']);
- }
- else
- $mimeselect = '<input type="hidden" name="mimetype" value="' . $x['mimetype'] . '" />';
- }
+ $feature_expire = ((feature_enabled($x['profile_uid'], 'content_expire') && (! $webpage)) ? true : false);
+ if(x($x, 'hide_expire'))
+ $feature_expire = false;
- $layoutselect = '';
- if(array_key_exists('layout', $x) && $x['layout']) {
- if($x['layout'] === 'choose') {
- $layoutselect = layout_select($x['profile_uid']);
- }
- else
- $layoutselect = '<input type="hidden" name="layout_mid" value="' . $x['layout'] . '" />';
- }
+ $feature_future = ((feature_enabled($x['profile_uid'], 'delayed_posting') && (! $webpage)) ? true : false);
+ if(x($x, 'hide_future'))
+ $feature_future = false;
+
+ $geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
+ $setloc = t('Set your location');
+ $clearloc = ((get_pconfig($x['profile_uid'], 'system', 'use_browser_location')) ? t('Clear browser location') : '');
+ if(x($x, 'hide_location'))
+ $geotag = $setloc = $clearloc = '';
+
+ $mimetype = ((x($x,'mimetype')) ? $x['mimetype'] : 'text/bbcode');
+ $mimeselect = ((x($x,'mimeselect')) ? $x['mimeselect'] : false);
+ if($mimeselect)
+ $mimeselect = mimetype_select($x['profile_uid'], $mimetype);
+ else
+ $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
+
+ $weblink = (($mimetype === 'text/bbcode') ? t('Insert web link') : false);
+ if(x($x, 'hide_weblink'))
+ $weblink = false;
+
+ $embedPhotos = t('Embed image from photo albums');
+
+ $writefiles = (($mimetype === 'text/bbcode') ? perm_is_allowed($x['profile_uid'], get_observer_hash(), 'write_storage') : false);
+ if(x($x, 'hide_attach'))
+ $writefiles = false;
+
+ $layout = ((x($x,'layout')) ? $x['layout'] : '');
+
+ $layoutselect = ((x($x,'layoutselect')) ? $x['layoutselect'] : false);
+ if($layoutselect)
+ $layoutselect = layout_select($x['profile_uid'], $layout);
+ else
+ $layoutselect = '<input type="hidden" name="layout_mid" value="' . $layout . '" />';
if(array_key_exists('channel_select',$x) && $x['channel_select']) {
- require_once('include/identity.php');
+ require_once('include/channel.php');
$id_select = identity_selector();
}
else
$id_select = '';
-
$webpage = ((x($x,'webpage')) ? $x['webpage'] : '');
$tpl = get_markup_template('jot-header.tpl');
App::$page['htmlhead'] .= replace_macros($tpl, array(
- '$newpost' => 'true',
'$baseurl' => z_root(),
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
'$pretext' => ((x($x,'pretext')) ? $x['pretext'] : ''),
'$geotag' => $geotag,
'$nickname' => $x['nickname'],
- '$ispublic' => t('Visible to <strong>everybody</strong>'),
'$linkurl' => t('Please enter a link URL:'),
- '$vidurl' => t('Please enter a video link/URL:'),
- '$audurl' => t('Please enter an audio link/URL:'),
'$term' => t('Tag term:'),
- '$fileas' => t('Save to Folder:'),
'$whereareu' => t('Where are you right now?'),
- '$expireswhen' => t('Expires YYYY-MM-DD HH:MM'),
'$editor_autocomplete'=> ((x($x,'editor_autocomplete')) ? $x['editor_autocomplete'] : ''),
'$bbco_autocomplete'=> ((x($x,'bbco_autocomplete')) ? $x['bbco_autocomplete'] : ''),
+ '$modalchooseimages' => t('Choose images to embed'),
+ '$modalchoosealbum' => t('Choose an album'),
+ '$modaldiffalbum' => t('Choose a different album...'),
+ '$modalerrorlist' => t('Error getting album list'),
+ '$modalerrorlink' => t('Error getting photo link'),
+ '$modalerroralbum' => t('Error getting album'),
));
$tpl = get_markup_template('jot.tpl');
$jotplugins = '';
- $jotnets = '';
$preview = t('Preview');
-// $preview = ((feature_enabled($x['profile_uid'],'preview')) ? t('Preview') : '');
- if(x($x, 'nopreview'))
+ if(x($x, 'hide_preview'))
$preview = '';
$defexpire = ((($z = get_pconfig($x['profile_uid'], 'system', 'default_post_expire')) && (! $webpage)) ? $z : '');
@@ -1201,7 +1212,6 @@ function status_editor($a, $x, $popup = false) {
$cipher = 'aes256';
call_hooks('jot_tool', $jotplugins);
- call_hooks('jot_networks', $jotnets);
$o .= replace_macros($tpl, array(
'$return_path' => ((x($x, 'return_path')) ? $x['return_path'] : App::$query_string),
@@ -1212,48 +1222,35 @@ function status_editor($a, $x, $popup = false) {
'$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''),
'$id_select' => $id_select,
'$id_seltext' => t('Post as'),
- '$writefiles' => perm_is_allowed($x['profile_uid'], get_observer_hash(), 'write_storage'),
+ '$writefiles' => $writefiles,
'$bold' => t('Bold'),
'$italic' => t('Italic'),
'$underline' => t('Underline'),
'$quote' => t('Quote'),
'$code' => t('Code'),
- '$upload' => t('Upload photo'),
- '$shortupload' => t('upload photo'),
'$attach' => t('Attach file'),
- '$shortattach' => t('attach file'),
- '$weblink' => t('Insert web link'),
- '$shortweblink' => t('web link'),
- '$video' => t('Insert video link'),
- '$shortvideo' => t('video link'),
- '$audio' => t('Insert audio link'),
- '$shortaudio' => t('audio link'),
- '$setloc' => t('Set your location'),
- '$shortsetloc' => t('set location'),
+ '$weblink' => $weblink,
+ '$embedPhotos' => $embedPhotos,
+ '$embedPhotosModalTitle' => t('Embed an image from your albums'),
+ '$embedPhotosModalCancel' => t('Cancel'),
+ '$embedPhotosModalOK' => t('OK'),
+ '$setloc' => $setloc,
'$voting' => t('Toggle voting'),
- '$feature_voting' => $voting,
+ '$feature_voting' => $feature_voting,
'$consensus' => 0,
- '$noloc' => ((get_pconfig($x['profile_uid'], 'system', 'use_browser_location')) ? t('Clear browser location') : ''),
- '$shortnoloc' => t('clear location'),
+ '$clearloc' => $clearloc,
'$title' => ((x($x, 'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''),
'$placeholdertitle' => ((x($x, 'placeholdertitle')) ? $x['placeholdertitle'] : t('Title (optional)')),
- '$hidetitle' => ((x($x, 'hidetitle')) ? $x['hidetitle'] : false),
'$catsenabled' => ((feature_enabled($x['profile_uid'], 'categories') && (! $webpage)) ? 'categories' : ''),
- '$category' => "",
+ '$category' => ((x($x, 'category')) ? $x['category'] : ''),
'$placeholdercategory' => t('Categories (optional, comma-separated list)'),
- '$wait' => t('Please wait'),
'$permset' => t('Permission settings'),
- '$shortpermset' => t('permissions'),
- '$ptyp' => '',
+ '$ptyp' => ((x($x, 'ptyp')) ? $x['ptyp'] : ''),
'$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''),
'$attachment' => ((x($x, 'attachment')) ? $x['attachment'] : ''),
- '$post_id' => '',
- '$baseurl' => z_root(),
+ '$post_id' => ((x($x, 'post_id')) ? $x['post_id'] : ''),
'$defloc' => $x['default_location'],
'$visitor' => $x['visitor'],
- '$public' => t('Public post'),
- '$jotnets' => $jotnets,
- '$emtitle' => t('Example: bob@example.com, mary@example.com'),
'$lockstate' => $x['lockstate'],
'$acl' => $x['acl'],
'$mimeselect' => $mimeselect,
@@ -1265,10 +1262,10 @@ function status_editor($a, $x, $popup = false) {
'$source' => ((x($x, 'source')) ? $x['source'] : ''),
'$jotplugins' => $jotplugins,
'$defexpire' => $defexpire,
- '$feature_expire' => ((feature_enabled($x['profile_uid'], 'content_expire') && (! $webpage)) ? true : false),
+ '$feature_expire' => $feature_expire,
'$expires' => t('Set expiration date'),
'$defpublish' => $defpublish,
- '$feature_future' => ((feature_enabled($x['profile_uid'], 'delayed_posting') && (! $webpage)) ? true : false),
+ '$feature_future' => $feature_future,
'$future_txt' => t('Set publish date'),
'$feature_encrypt' => ((feature_enabled($x['profile_uid'], 'content_encrypt') && (! $webpage)) ? true : false),
'$encrypt' => t('Encrypt text'),
@@ -1424,7 +1421,7 @@ function render_location_default($item) {
function prepare_page($item) {
- $a = get_app();
+
$naked = 1;
// $naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
$observer = App::get_observer();
@@ -1458,7 +1455,7 @@ function prepare_page($item) {
function network_tabs() {
- $a = get_app();
+
$no_active='';
$starred_active = '';
$new_active = '';
@@ -1674,8 +1671,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
- require_once('include/chat.php');
- $has_chats = chatroom_list_count($uid);
+ $has_chats = Zotlabs\Lib\Chatroom::list_count($uid);
if ($has_chats) {
$tabs[] = array(
'label' => t('Chatrooms'),
@@ -1707,13 +1703,19 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
'title' => t('Manage Webpages'),
'id' => 'webpages-tab',
);
- } else {
- /**
- * @FIXME we probably need a listing of events that were created by
- * this channel and are visible to the observer
- */
+ }
+
+ if(feature_enabled($uid,'wiki') && (! UNO)) {
+ $tabs[] = array(
+ 'label' => t('Wiki'),
+ 'url' => z_root() . '/wiki/' . $nickname,
+ 'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
+ 'title' => t('Wiki'),
+ 'id' => 'wiki-tab',
+ );
}
+
$arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
call_hooks('profile_tabs', $arr);
diff --git a/include/cronhooks.php b/include/cronhooks.php
deleted file mode 100644
index a314593d2..000000000
--- a/include/cronhooks.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-
-
-function cronhooks_run($argv, $argc){
-
- cli_startup();
-
- logger('cronhooks: start');
-
- $d = datetime_convert();
-
- call_hooks('cron', $d);
-
- return;
-}
-
-if (array_search(__file__,get_included_files())===0){
- cronhooks_run($argv,$argc);
- killme();
-}
diff --git a/include/crypto.php b/include/crypto.php
index d636c6848..bc798d919 100644
--- a/include/crypto.php
+++ b/include/crypto.php
@@ -46,27 +46,15 @@ function pkcs5_unpad($text)
}
function AES256CBC_encrypt($data,$key,$iv) {
- if(get_config('system','openssl_encrypt')) {
- return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
- }
- return mcrypt_encrypt(
- MCRYPT_RIJNDAEL_128,
- str_pad($key,32,"\0"),
- pkcs5_pad($data,16),
- MCRYPT_MODE_CBC,
- str_pad($iv,16,"\0"));
+
+ return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+
}
function AES256CBC_decrypt($data,$key,$iv) {
- if(get_config('system','openssl_encrypt')) {
- return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
- }
- return pkcs5_unpad(mcrypt_decrypt(
- MCRYPT_RIJNDAEL_128,
- str_pad($key,32,"\0"),
- $data,
- MCRYPT_MODE_CBC,
- str_pad($iv,16,"\0")));
+
+ return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+
}
function crypto_encapsulate($data,$pubkey,$alg='aes256cbc') {
diff --git a/include/datetime.php b/include/datetime.php
index 83fb49d04..76bd6b8d6 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -119,7 +119,6 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
* @return string
*/
function dob($dob) {
- $a = get_app();
list($year, $month, $day) = sscanf($dob, '%4d-%2d-%2d');
$f = get_config('system', 'birthday_input_format');
@@ -225,7 +224,7 @@ function datetimesel($format, $min, $max, $default, $label, $id = 'datetimepicke
$pickers = '';
if(!$pickdate) $pickers .= ',datepicker: false';
- if(!$picktime) $pickers .= ',timepicker: false';
+ if(!$picktime) $pickers .= ',timepicker: false, closeOnDateSelect:true';
$extra_js = '';
if($minfrom != '')
@@ -557,13 +556,13 @@ function update_birthdays() {
$ev['uid'] = $rr['abook_channel'];
$ev['account'] = $rr['abook_account'];
$ev['event_xchan'] = $rr['xchan_hash'];
- $ev['start'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']);
- $ev['finish'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day ');
+ $ev['dtstart'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']);
+ $ev['dtend'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day ');
$ev['adjust'] = intval(feature_enabled($rr['abook_channel'],'smart_birthdays'));
$ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']);
$ev['description'] = sprintf( t('Happy Birthday %1$s'),
'[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ;
- $ev['type'] = 'birthday';
+ $ev['etype'] = 'birthday';
$z = event_store_event($ev);
if ($z) {
diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php
index 3c5b0b67e..f6091f6e1 100755
--- a/include/dba/dba_driver.php
+++ b/include/dba/dba_driver.php
@@ -1,50 +1,78 @@
<?php
-/**
- * @file dba_driver.php
- * @brief some database related functions and abstract driver class.
- *
- * This file contains the abstract database driver class dba_driver and some
- * functions for working with databases.
- */
-/**
- * @brief Returns the database driver object.
- *
- * If available it will use PHP's mysqli otherwise mysql driver.
- *
- * @param string $server DB server name
- * @param string $port DB port
- * @param string $user DB username
- * @param string $pass DB password
- * @param string $db database name
- * @param string $dbtype 0 for mysql, 1 for postgres
- * @param bool $install Defaults to false
- * @return null|dba_driver A database driver object (dba_mysql|dba_mysqli) or null if no driver found.
- */
-function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) {
- $dba = null;
-
- $dbtype = intval($dbtype);
-
- if($dbtype == DBTYPE_POSTGRES) {
- require_once('include/dba/dba_postgres.php');
- if(is_null($port)) $port = 5432;
- $dba = new dba_postgres($server, $port, $user, $pass, $db, $install);
- } else {
- if(class_exists('mysqli')) {
- if (is_null($port)) $port = ini_get("mysqli.default_port");
- require_once('include/dba/dba_mysqli.php');
- $dba = new dba_mysqli($server, $port,$user,$pass,$db,$install);
- } else {
- if (is_null($port)) $port = "3306";
- require_once('include/dba/dba_mysql.php');
- $dba = new dba_mysql($server, $port,$user,$pass,$db,$install);
+class DBA {
+
+ /**
+ * @file dba_driver.php
+ * @brief some database related functions and abstract driver class.
+ *
+ * This file contains the abstract database driver class dba_driver and some
+ * functions for working with databases.
+ */
+
+ static public $dba = null;
+ static public $dbtype = null;
+ static public $logging = false;
+
+ /**
+ * @brief Returns the database driver object.
+ *
+ * If available it will use PHP's mysqli otherwise mysql driver.
+ *
+ * @param string $server DB server name
+ * @param string $port DB port
+ * @param string $user DB username
+ * @param string $pass DB password
+ * @param string $db database name
+ * @param string $dbtype 0 for mysql, 1 for postgres
+ * @param bool $install Defaults to false
+ * @return null|dba_driver A database driver object (dba_mysql|dba_mysqli) or null if no driver found.
+ */
+
+ static public function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) {
+
+ self::$dba = null;
+
+ self::$dbtype = intval($dbtype);
+ $set_port = $port;
+
+ if(self::$dbtype == DBTYPE_POSTGRES) {
+ require_once('include/dba/dba_postgres.php');
+ if(is_null($port)) $set_port = 5432;
+ self::$dba = new dba_postgres($server, $set_port, $user, $pass, $db, $install);
}
+ else {
+
+// Highly experimental at the present time.
+// require_once('include/dba/dba_pdo.php');
+// self::$dba = new dba_pdo($server, $set_port,$user,$pass,$db,$install);
+// }
+
+ if(class_exists('mysqli')) {
+ if (is_null($port)) $set_port = ini_get("mysqli.default_port");
+ require_once('include/dba/dba_mysqli.php');
+ self::$dba = new dba_mysqli($server, $set_port,$user,$pass,$db,$install);
+ }
+ }
+
+ // Until we have a proper PDO driver, store the DB connection parameters for
+ // plugins/addons which use PDO natively (such as cdav). This is wasteful as
+ // it opens a separate connection to the DB, but saves a lot of effort re-writing
+ // third-party interfaces that are working and well tested.
+
+
+ if(is_object(self::$dba) && self::$dba->connected) {
+ $dns = ((self::$dbtype == DBTYPE_POSTGRES) ? 'postgres' : 'mysql')
+ . ':host=' . $server . (is_null($port) ? '' : ';port=' . $port)
+ . ';dbname=' . $db;
+ self::$dba->pdo_set(array($dns,$user,$pass));
+ }
+
+ define('NULL_DATE', self::$dba->get_null_date());
+ define('ACTIVE_DBTYPE', self::$dbtype);
+ return self::$dba;
}
- define('NULL_DATE', $dba->get_null_date());
- define('ACTIVE_DBTYPE', $dbtype);
- return $dba;
}
/**
@@ -59,8 +87,10 @@ abstract class dba_driver {
const NULL_DATE = '0000-00-00 00:00:00';
const UTC_NOW = 'UTC_TIMESTAMP()';
- protected $debug = 0;
protected $db;
+ protected $pdo = array();
+
+ public $debug = 0;
public $connected = false;
public $error = false;
@@ -182,6 +212,15 @@ abstract class dba_driver {
function unescapebin($str) {
return $str;
}
+
+ function pdo_set($x) {
+ $this->pdo = $x;
+ }
+
+ function pdo_get() {
+ return $this->pdo;
+ }
+
} // end abstract dba_driver class
@@ -205,8 +244,8 @@ function printable($s) {
function dbg($state) {
global $db;
- if($db)
- $db->dbg($state);
+ if(\DBA::$dba)
+ \DBA::$dba->dbg($state);
}
/**
@@ -220,21 +259,18 @@ function dbg($state) {
* @return Return an escaped string of the value to pass to a DB query.
*/
function dbesc($str) {
- global $db;
- if($db && $db->connected)
- return($db->escape($str));
+ if(\DBA::$dba && \DBA::$dba->connected)
+ return(\DBA::$dba->escape($str));
else
return(str_replace("'", "\\'", $str));
}
function dbescbin($str) {
- global $db;
- return $db->escapebin($str);
+ return \DBA::$dba->escapebin($str);
}
function dbunescbin($str) {
- global $db;
- return $db->unescapebin($str);
+ return \DBA::$dba->unescapebin($str);
}
function dbescdate($date) {
@@ -247,36 +283,25 @@ function dbescdate($date) {
}
function db_quoteinterval($txt) {
- global $db;
- return $db->quote_interval($txt);
+ return \DBA::$dba->quote_interval($txt);
}
function dbesc_identifier($str) {
- global $db;
- return $db->escape_identifier($str);
+ return \DBA::$dba->escape_identifier($str);
}
function db_utcnow() {
- global $db;
- return $db->utcnow();
+ return \DBA::$dba->utcnow();
}
function db_optimizetable($table) {
- global $db;
- $db->optimize_table($table);
+ \DBA::$dba->optimize_table($table);
}
function db_concat($fld, $sep) {
- global $db;
- return $db->concat($fld, $sep);
+ return \DBA::$dba->concat($fld, $sep);
}
-// Function: q($sql,$args);
-// Description: execute SQL query with printf style args.
-// Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
-// 'user', 1);
-
-
/**
* @brief Execute a SQL query with printf style args.
*
@@ -292,29 +317,33 @@ function db_concat($fld, $sep) {
* @param string $sql The SQL query to execute
* @return bool|array
*/
+
function q($sql) {
- global $db;
$args = func_get_args();
unset($args[0]);
- if($db && $db->connected) {
+ if(\DBA::$dba && \DBA::$dba->connected) {
$stmt = vsprintf($sql, $args);
if($stmt === false) {
if(version_compare(PHP_VERSION, '5.4.0') >= 0)
- logger('dba: vsprintf error: ' .
+ db_logger('dba: vsprintf error: ' .
print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1), true),LOGGER_NORMAL,LOG_CRIT);
else
- logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true),LOGGER_NORMAL,LOG_CRIT);
+ db_logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true),LOGGER_NORMAL,LOG_CRIT);
}
- return $db->q($stmt);
+ if(\DBA::$dba->debug)
+ db_logger('Sql: ' . $stmt, LOGGER_DEBUG, LOG_INFO);
+
+ return \DBA::$dba->q($stmt);
}
/*
* This will happen occasionally trying to store the
* session data after abnormal program termination
*/
- logger('dba: no database: ' . print_r($args,true),LOGGER_NORMAL,LOG_CRIT);
+
+ db_logger('dba: no database: ' . print_r($args,true),LOGGER_NORMAL,LOG_CRIT);
return false;
}
@@ -327,10 +356,9 @@ function q($sql) {
* @param string $sql The SQL query to execute
*/
function dbq($sql) {
- global $db;
- if($db && $db->connected)
- $ret = $db->q($sql);
+ if(\DBA::$dba && \DBA::$dba->connected)
+ $ret = \DBA::$dba->q($sql);
else
$ret = false;
@@ -385,7 +413,24 @@ function db_getfunc($f) {
if(isset($lookup[$f]) && isset($lookup[$f][ACTIVE_DBTYPE]))
return $lookup[$f][ACTIVE_DBTYPE];
- logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG, LOG_ERR);
+ db_logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG, LOG_ERR);
return $f;
}
+// The logger function may make DB calls internally to query the system logging parameters.
+// This can cause a recursion if database debugging is enabled.
+// So this function preserves the current database debugging state and then turns it off
+// temporarily while doing the logger() call
+
+function db_logger($s,$level = LOGGER_NORMAL,$syslog = LOG_INFO) {
+
+ if(\DBA::$logging)
+ return;
+
+ $saved = \DBA::$dba->debug;
+ \DBA::$dba->debug = false;
+ \DBA::$logging = true;
+ logger($s,$level,$syslog);
+ \DBA::$logging = false;
+ \DBA::$dba->debug = $saved;
+} \ No newline at end of file
diff --git a/include/dba/dba_mysqli.php b/include/dba/dba_mysqli.php
index 6986d4586..afd2aa642 100755
--- a/include/dba/dba_mysqli.php
+++ b/include/dba/dba_mysqli.php
@@ -4,20 +4,26 @@ require_once('include/dba/dba_driver.php');
class dba_mysqli extends dba_driver {
- function connect($server, $port, $user,$pass,$db) {
+ function connect($server,$port,$user,$pass,$db) {
if($port)
$this->db = new mysqli($server,$user,$pass,$db, $port);
else
$this->db = new mysqli($server,$user,$pass,$db);
- if(! mysqli_connect_errno()) {
- $this->connected = true;
+ if($this->db->connect_error) {
+ $this->connected = false;
+ $this->error = $this->db->connect_error;
+
+ if(file_exists('dbfail.out')) {
+ file_put_contents('dbfail.out', datetime_convert() . "\nConnect: " . $this->error . "\n", FILE_APPEND);
+ }
+
+ return false;
}
- if($this->connected) {
+ else {
+ $this->connected = true;
return true;
}
- $this->error = $this->db->connect_error;
- return false;
}
function q($sql) {
@@ -32,7 +38,7 @@ class dba_mysqli extends dba_driver {
if($this->error) {
- logger('dba_mysqli: ERROR: ' . printable($sql) . "\n" . $this->error, LOGGER_NORMAL, LOG_ERR);
+ db_logger('dba_mysqli: ERROR: ' . printable($sql) . "\n" . $this->error, LOGGER_NORMAL, LOG_ERR);
if(file_exists('dbfail.out')) {
file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . "\n" . $this->error . "\n", FILE_APPEND);
}
@@ -40,13 +46,13 @@ class dba_mysqli extends dba_driver {
if(($result === true) || ($result === false)) {
if($this->debug) {
- logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returns ' . (($result) ? 'true' : 'false'), LOGGER_NORMAL,(($result) ? LOG_INFO : LOG_ERR));
+ db_logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returns ' . (($result) ? 'true' : 'false'), LOGGER_NORMAL,(($result) ? LOG_INFO : LOG_ERR));
}
return $result;
}
if($this->debug) {
- logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returned ' . $result->num_rows . ' results.', LOGGER_NORMAL, LOG_INFO);
+ db_logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returned ' . $result->num_rows . ' results.', LOGGER_NORMAL, LOG_INFO);
}
$r = array();
@@ -55,7 +61,7 @@ class dba_mysqli extends dba_driver {
$r[] = $x;
$result->free_result();
if($this->debug) {
- logger('dba_mysqli: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO);
+ db_logger('dba_mysqli: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO);
}
}
return $r;
diff --git a/include/dba/dba_pdo.php b/include/dba/dba_pdo.php
new file mode 100755
index 000000000..7255a2b66
--- /dev/null
+++ b/include/dba/dba_pdo.php
@@ -0,0 +1,95 @@
+<?php /** @file */
+
+require_once('include/dba/dba_driver.php');
+
+class dba_pdo extends dba_driver {
+
+
+ public $driver_dbtype = null;
+
+ function connect($server,$port,$user,$pass,$db) {
+
+ $this->driver_dbtype = 'mysql'; // (($dbtype == DBTYPE_POSTGRES) ? 'postgres' : 'mysql');
+ $dns = $this->driver_dbtype
+ . ':host=' . $server . (is_null($port) ? '' : ';port=' . $port)
+ . ';dbname=' . $db;
+
+
+ try {
+ $this->db = new PDO($dns,$user,$pass);
+ $this->db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
+ }
+ catch(PDOException $e) {
+ if(file_exists('dbfail.out')) {
+ file_put_contents('dbfail.out', datetime_convert() . "\nConnect: " . $e->getMessage() . "\n", FILE_APPEND);
+ }
+
+ return false;
+ }
+
+ $this->connected = true;
+ return true;
+
+ }
+
+ function q($sql) {
+ if((! $this->db) || (! $this->connected))
+ return false;
+
+ $this->error = '';
+ $select = ((stripos($sql,'select') === 0) ? true : false);
+
+ try {
+ $result = $this->db->query($sql);
+ }
+ catch(PDOException $e) {
+
+ $this->error = $e->getMessage();
+ if($this->error) {
+ db_logger('dba_mysqli: ERROR: ' . printable($sql) . "\n" . $this->error, LOGGER_NORMAL, LOG_ERR);
+ if(file_exists('dbfail.out')) {
+ file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . "\n" . $this->error . "\n", FILE_APPEND);
+ }
+ }
+ }
+
+ if(!($select)) {
+ if($this->debug) {
+ db_logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returns ' . (($result) ? 'true' : 'false'), LOGGER_NORMAL,(($result) ? LOG_INFO : LOG_ERR));
+ }
+ return $result;
+ }
+
+ if($this->debug) {
+ db_logger('dba_mysqli: DEBUG: ' . printable($sql) . ' returned ' . count($result) . ' results.', LOGGER_NORMAL, LOG_INFO);
+ }
+
+ $r = array();
+ if($result) {
+ foreach($result as $x) {
+ $r[] = $x;
+ }
+ if($this->debug) {
+ db_logger('dba_pdo: ' . printable(print_r($r,true)), LOGGER_NORMAL, LOG_INFO);
+ }
+ }
+ return $r;
+ }
+
+ function escape($str) {
+ if($this->db && $this->connected) {
+ return substr(substr(@$this->db->quote($str),1),0,-1);
+ }
+ }
+
+ function close() {
+ if($this->db)
+ $this->db = null;
+ $this->connected = false;
+ }
+
+ function getdriver() {
+ return 'pdo';
+ }
+
+} \ No newline at end of file
diff --git a/include/dba/dba_postgres.php b/include/dba/dba_postgres.php
index ba4366d13..03b29d703 100644
--- a/include/dba/dba_postgres.php
+++ b/include/dba/dba_postgres.php
@@ -50,7 +50,7 @@ class dba_postgres extends dba_driver {
$this->error = pg_last_error($this->db);
if($result === false || $this->error) {
- //logger('dba_postgres: ' . printable($sql) . ' returned false.' . "\n" . $this->error);
+ //db_logger('dba_postgres: ' . printable($sql) . ' returned false.' . "\n" . $this->error);
if(file_exists('dbfail.out'))
file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . ' returned false' . "\n" . $this->error . "\n", FILE_APPEND);
}
@@ -67,7 +67,7 @@ class dba_postgres extends dba_driver {
$r[] = $x;
pg_free_result($result);
if($this->debug)
- logger('dba_postgres: ' . printable(print_r($r,true)));
+ db_logger('dba_postgres: ' . printable(print_r($r,true)));
}
return $r;
}
diff --git a/include/deliver.php b/include/deliver.php
deleted file mode 100644
index 40df543d5..000000000
--- a/include/deliver.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php /** @file */
-
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/queue_fn.php');
-
-
-function deliver_run($argv, $argc) {
-
- cli_startup();
-
- $a = get_app();
-
- if($argc < 2)
- return;
-
- logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA);
-
- for($x = 1; $x < $argc; $x ++) {
-
- $dresult = null;
- $r = q("select * from outq where outq_hash = '%s' limit 1",
- dbesc($argv[$x])
- );
- if($r) {
-
- $notify = json_decode($r[0]['outq_notify'],true);
-
- // Messages without an outq_msg will need to go via the web, even if it's a
- // local delivery. This includes conversation requests and refresh packets.
-
- if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) {
- logger('deliver: local delivery', LOGGER_DEBUG);
-
- // local delivery
- // we should probably batch these and save a few delivery processes
-
- if($r[0]['outq_msg']) {
- $m = json_decode($r[0]['outq_msg'],true);
- if(array_key_exists('message_list',$m)) {
- foreach($m['message_list'] as $mm) {
- $msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
- zot_import($msg,z_root());
- }
- }
- else {
- $msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
- $dresult = zot_import($msg,z_root());
- }
-
- remove_queue_item($r[0]['outq_hash']);
-
- if($dresult && is_array($dresult)) {
- foreach($dresult as $xx) {
- if(is_array($xx) && array_key_exists('message_id',$xx)) {
- if(delivery_report_is_storable($xx)) {
- q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
- dbesc($xx['message_id']),
- dbesc($xx['location']),
- dbesc($xx['recipient']),
- dbesc($xx['status']),
- dbesc(datetime_convert($xx['date'])),
- dbesc($xx['sender'])
- );
- }
- }
- }
- }
-
- q("delete from dreport where dreport_queue = '%s'",
- dbesc($argv[$x])
- );
- }
- }
-
- // otherwise it's a remote delivery - call queue_deliver() with the $immediate flag
-
- queue_deliver($r[0],true);
-
- }
- }
-}
-
-if (array_search(__file__,get_included_files())===0){
- deliver_run($argv,$argc);
- killme();
-}
diff --git a/include/deliver_hooks.php b/include/deliver_hooks.php
deleted file mode 100644
index f0d6ba1b1..000000000
--- a/include/deliver_hooks.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-
-
-function deliver_hooks_run($argv, $argc) {
-
- cli_startup();
-
- $a = get_app();
-
- if($argc < 2)
- return;
-
-
- $r = q("select * from item where id = '%d'",
- intval($argv[1])
- );
- if($r)
- call_hooks('notifier_normal',$r[0]);
-
-}
-
-if (array_search(__file__,get_included_files())===0){
- deliver_hooks_run($argv,$argc);
- killme();
-}
diff --git a/include/dir_fns.php b/include/dir_fns.php
index 1c3149081..9f1be1a42 100644
--- a/include/dir_fns.php
+++ b/include/dir_fns.php
@@ -69,9 +69,8 @@ function check_upstream_directory() {
if ($directory) {
$h = parse_url($directory);
if ($h) {
- $x = zot_finger('[system]@' . $h['host']);
- if ($x['success']) {
- $j = json_decode($x['body'], true);
+ $j = Zotlabs\Zot\Finger::run('[system]@' . $h['host']);
+ if ($j['success']) {
if (array_key_exists('site', $j) && array_key_exists('directory_mode', $j['site'])) {
if ($j['site']['directory_mode'] === 'normal') {
$isadir = false;
@@ -95,6 +94,9 @@ function get_directory_setting($observer, $setting) {
if($ret === false)
$ret = get_config('directory', $setting);
+
+ // 'safemode' is the default if there is no observer or no established preference.
+
if($setting == 'safemode' && $ret === false)
$ret = 1;
diff --git a/include/directory.php b/include/directory.php
deleted file mode 100644
index 8792a15e1..000000000
--- a/include/directory.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * @file include/directory.php
- * @brief executes directory_run()
- */
-
-require_once('boot.php');
-require_once('include/zot.php');
-require_once('include/cli_startup.php');
-require_once('include/dir_fns.php');
-require_once('include/queue_fn.php');
-
-/**
- * @brief
- *
- * @param array $argv
- * @param array $argc
- */
-function directory_run($argv, $argc){
-
- cli_startup();
-
- if($argc < 2)
- return;
-
- $force = false;
- $pushall = true;
-
- if($argc > 2) {
- if($argv[2] === 'force')
- $force = true;
- if($argv[2] === 'nopush')
- $pushall = false;
- }
-
- logger('directory update', LOGGER_DEBUG);
-
- $dirmode = get_config('system','directory_mode');
- if($dirmode === false)
- $dirmode = DIRECTORY_MODE_NORMAL;
-
- $x = q("select * from channel where channel_id = %d limit 1",
- intval($argv[1])
- );
- if(! $x)
- return;
-
- $channel = $x[0];
-
- if($dirmode != DIRECTORY_MODE_NORMAL) {
-
- // this is an in-memory update and we don't need to send a network packet.
-
- local_dir_update($argv[1],$force);
-
- q("update channel set channel_dirdate = '%s' where channel_id = %d",
- dbesc(datetime_convert()),
- intval($channel['channel_id'])
- );
-
- // Now update all the connections
- if($pushall)
- proc_run('php','include/notifier.php','refresh_all',$channel['channel_id']);
-
- return;
- }
-
- // otherwise send the changes upstream
-
- $directory = find_upstream_directory($dirmode);
- $url = $directory['url'] . '/post';
-
- // ensure the upstream directory is updated
-
- $packet = zot_build_packet($channel,(($force) ? 'force_refresh' : 'refresh'));
- $z = zot_zot($url,$packet);
-
- // re-queue if unsuccessful
-
- if(! $z['success']) {
-
- /** @FIXME we aren't updating channel_dirdate if we have to queue
- * the directory packet. That means we'll try again on the next poll run.
- */
-
- $hash = random_string();
-
- queue_insert(array(
- 'hash' => $hash,
- 'account_id' => $channel['channel_account_id'],
- 'channel_id' => $channel['channel_id'],
- 'posturl' => $url,
- 'notify' => $packet,
- ));
-
- }
- else {
- q("update channel set channel_dirdate = '%s' where channel_id = %d",
- dbesc(datetime_convert()),
- intval($channel['channel_id'])
- );
- }
-
- // Now update all the connections
- if($pushall)
- proc_run('php','include/notifier.php','refresh_all',$channel['channel_id']);
-
-}
-
-if (array_search(__file__, get_included_files()) === 0) {
- directory_run($argv, $argc);
- killme();
-}
diff --git a/include/enotify.php b/include/enotify.php
deleted file mode 100644
index d87c5af11..000000000
--- a/include/enotify.php
+++ /dev/null
@@ -1,652 +0,0 @@
-<?php
-/**
- * @file include/enotify.php
- *
- * @brief File with functions and a class for email notifications.
- */
-
-/**
- * @brief
- *
- * @param array $params an assoziative array with:
- * * \e string \b from_xchan sender xchan hash
- * * \e string \b to_xchan recipient xchan hash
- * * \e array \b item an assoziative array
- * * \e int \b type one of the NOTIFY_* constants from boot.php
- * * \e string \b link
- * * \e string \b parent_mid
- * * \e string \b otype
- * * \e string \b verb
- * * \e string \b activity
- */
-function notification($params) {
-
- logger('notification: entry', LOGGER_DEBUG);
-
- // throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant.
- usleep(mt_rand(0, 10000));
-
- $a = get_app();
-
-
- if ($params['from_xchan']) {
- $x = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($params['from_xchan'])
- );
- }
- if ($params['to_xchan']) {
- $y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id
- where channel_hash = '%s' and channel_removed = 0 limit 1",
- dbesc($params['to_xchan'])
- );
- }
- if ($x & $y) {
- $sender = $x[0];
- $recip = $y[0];
- } else {
- logger('notification: no sender or recipient.');
- logger('sender: ' . $params['from_xchan']);
- logger('recip: ' . $params['to_xchan']);
- return;
- }
-
- // from here on everything is in the recipients language
-
- push_lang($recip['account_language']); // should probably have a channel language
-
- $banner = t('$Projectname Notification');
- $product = t('$projectname'); // PLATFORM_NAME;
- $siteurl = z_root();
- $thanks = t('Thank You,');
- $sitename = get_config('system','sitename');
- $site_admin = sprintf( t('%s Administrator'), $sitename);
-
- $sender_name = $product;
- $hostname = App::get_hostname();
- if(strpos($hostname,':'))
- $hostname = substr($hostname,0,strpos($hostname,':'));
-
- // Do not translate 'noreply' as it must be a legal 7-bit email address
- $sender_email = 'noreply' . '@' . $hostname;
-
- $additional_mail_header = "";
-
- if (array_key_exists('item', $params)) {
- require_once('include/conversation.php');
- // if it's a normal item...
- if (array_key_exists('verb', $params['item'])) {
- // localize_item() alters the original item so make a copy first
- $i = $params['item'];
- logger('calling localize');
- localize_item($i);
- $title = $i['title'];
- $body = $i['body'];
- $private = (($i['item_private']) || intval($i['item_obscured']));
- }
- else {
- $title = $params['item']['title'];
- $body = $params['item']['body'];
- }
- } else {
- $title = $body = '';
- }
-
-
- // e.g. "your post", "David's photo", etc.
- $possess_desc = t('%s <!item_type!>');
-
- if ($params['type'] == NOTIFY_MAIL) {
- logger('notification: mail');
- $subject = sprintf( t('[Hubzilla:Notify] New mail received at %s'),$sitename);
-
- $preamble = sprintf( t('%1$s, %2$s sent you a new private message at %3$s.'),$recip['channel_name'], $sender['xchan_name'],$sitename);
- $epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
- $sitelink = t('Please visit %s to view and/or reply to your private messages.');
- $tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
- $itemlink = $siteurl . '/mail/' . $params['item']['id'];
- }
-
- if ($params['type'] == NOTIFY_COMMENT) {
-// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
-
- $itemlink = $params['link'];
-
- // ignore like/unlike activity on posts - they probably require a sepearate notification preference
-
- if (array_key_exists('item',$params) && (! visible_activity($params['item'])))
- return;
-
- $parent_mid = $params['parent_mid'];
-
- // Check to see if there was already a notify for this post.
- // If so don't create a second notification
-
- $p = null;
- $p = q("select id from notify where link = '%s' and uid = %d limit 1",
- dbesc($params['link']),
- intval($recip['channel_id'])
- );
- if ($p) {
- logger('notification: comment already notified');
- pop_lang();
- return;
- }
-
-
- // if it's a post figure out who's post it is.
-
- $p = null;
-
- if($params['otype'] === 'item' && $parent_mid) {
- $p = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($parent_mid),
- intval($recip['channel_id'])
- );
- }
-
- xchan_query($p);
-
-
- $item_post_type = item_post_type($p[0]);
-// $private = $p[0]['item_private'];
- $parent_id = $p[0]['id'];
-
- $parent_item = $p[0];
-
- //$possess_desc = str_replace('<!item_type!>',$possess_desc);
-
- // "a post"
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]a %4$s[/zrl]'),
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $itemlink,
- $item_post_type);
-
- // "George Bull's post"
- if($p)
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $itemlink,
- $p[0]['author']['xchan_name'],
- $item_post_type);
-
- // "your post"
- if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]your %4$s[/zrl]'),
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $itemlink,
- $item_post_type);
-
- // Some mail softwares relies on subject field for threading.
- // So, we cannot have different subjects for notifications of the same thread.
- // Before this we have the name of the replier on the subject rendering
- // differents subjects for messages on the same thread.
-
- $subject = sprintf( t('[Hubzilla:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
- $preamble = sprintf( t('%1$s, %2$s commented on an item/conversation you have been following.'), $recip['channel_name'], $sender['xchan_name']);
- $epreamble = $dest_str;
-
- $sitelink = t('Please visit %s to view and/or reply to the conversation.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- }
-
- if($params['type'] == NOTIFY_WALL) {
- $subject = sprintf( t('[Hubzilla:Notify] %s posted to your profile wall') , $sender['xchan_name']);
-
- $preamble = sprintf( t('%1$s, %2$s posted to your profile wall at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
-
- $epreamble = sprintf( t('%1$s, %2$s posted to [zrl=%3$s]your wall[/zrl]') ,
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $params['link']);
-
- $sitelink = t('Please visit %s to view and/or reply to the conversation.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_TAGSELF) {
-
- $p = null;
- $p = q("select id from notify where link = '%s' and uid = %d limit 1",
- dbesc($params['link']),
- intval($recip['channel_id'])
- );
- if ($p) {
- logger('enotify: tag: already notified about this post');
- pop_lang();
- return;
- }
-
- $subject = sprintf( t('[Hubzilla:Notify] %s tagged you') , $sender['xchan_name']);
- $preamble = sprintf( t('%1$s, %2$s tagged you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, %2$s [zrl=%3$s]tagged you[/zrl].') ,
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $params['link']);
-
- $sitelink = t('Please visit %s to view and/or reply to the conversation.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_POKE) {
- $subject = sprintf( t('[Hubzilla:Notify] %1$s poked you') , $sender['xchan_name']);
- $preamble = sprintf( t('%1$s, %2$s poked you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].') ,
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $params['link']);
-
- $subject = str_replace('poked', t($params['activity']), $subject);
- $preamble = str_replace('poked', t($params['activity']), $preamble);
- $epreamble = str_replace('poked', t($params['activity']), $epreamble);
-
- $sitelink = t('Please visit %s to view and/or reply to the conversation.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_TAGSHARE) {
- $subject = sprintf( t('[Hubzilla:Notify] %s tagged your post') , $sender['xchan_name']);
- $preamble = sprintf( t('%1$s, %2$s tagged your post at %3$s') , $recip['channel_name'],$sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]') ,
- $recip['channel_name'],
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
- $itemlink);
-
- $sitelink = t('Please visit %s to view and/or reply to the conversation.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_INTRO) {
- $subject = sprintf( t('[Hubzilla:Notify] Introduction received'));
- $preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'),
- $recip['channel_name'],
- $siteurl . '/connections/ifpending',
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
- $body = sprintf( t('You may visit their profile at %s'),$sender['xchan_url']);
-
- $sitelink = t('Please visit %s to approve or reject the connection request.');
- $tsitelink = sprintf( $sitelink, $siteurl . '/connections/ifpending');
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/connections/ifpending">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_SUGGEST) {
- $subject = sprintf( t('[Hubzilla:Notify] Friend suggestion received'));
- $preamble = sprintf( t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'),
- $recip['channel_name'],
- $itemlink,
- '[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]',
- '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
-
- $body = t('Name:') . ' ' . $params['item']['name'] . "\n";
- $body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
- $body .= sprintf( t('You may visit their profile at %s'),$params['item']['url']);
-
- $sitelink = t('Please visit %s to approve or reject the suggestion.');
- $tsitelink = sprintf( $sitelink, $siteurl );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
- }
-
- if ($params['type'] == NOTIFY_CONFIRM) {
- // ?
- }
-
- if ($params['type'] == NOTIFY_SYSTEM) {
- // ?
- }
-
- $h = array(
- 'params' => $params,
- 'subject' => $subject,
- 'preamble' => $preamble,
- 'epreamble' => $epreamble,
- 'body' => $body,
- 'sitelink' => $sitelink,
- 'sitename' => $sitename,
- 'tsitelink' => $tsitelink,
- 'hsitelink' => $hsitelink,
- 'itemlink' => $itemlink,
- 'sender' => $sender,
- 'recipient' => $recip
- );
-
- call_hooks('enotify', $h);
-
- $subject = $h['subject'];
- $preamble = $h['preamble'];
- $epreamble = $h['epreamble'];
- $body = $h['body'];
- $sitelink = $h['sitelink'];
- $tsitelink = $h['tsitelink'];
- $hsitelink = $h['hsitelink'];
- $itemlink = $h['itemlink'];
-
-
- require_once('include/html2bbcode.php');
-
- do {
- $dups = false;
- $hash = random_string();
- $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
- dbesc($hash));
- if (count($r))
- $dups = true;
- } while ($dups === true);
-
-
- $datarray = array();
- $datarray['hash'] = $hash;
- $datarray['sender_hash'] = $sender['xchan_hash'];
- $datarray['name'] = $sender['xchan_name'];
- $datarray['url'] = $sender['xchan_url'];
- $datarray['photo'] = $sender['xchan_photo_s'];
- $datarray['date'] = datetime_convert();
- $datarray['aid'] = $recip['channel_account_id'];
- $datarray['uid'] = $recip['channel_id'];
- $datarray['link'] = $itemlink;
- $datarray['parent'] = $parent_mid;
- $datarray['parent_item'] = $parent_item;
- $datarray['type'] = $params['type'];
- $datarray['verb'] = $params['verb'];
- $datarray['otype'] = $params['otype'];
- $datarray['abort'] = false;
-
- $datarray['item'] = $params['item'];
-
- call_hooks('enotify_store', $datarray);
-
- if ($datarray['abort']) {
- pop_lang();
- return;
- }
-
-
- // create notification entry in DB
- $seen = 0;
-
- // Mark some notifications as seen right away
- // Note! The notification have to be created, because they are used to send emails
- // So easiest solution to hide them from Notices is to mark them as seen right away.
- // Another option would be to not add them to the DB, and change how emails are handled (probably would be better that way)
- $always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
- if (!$always_show_in_notices) {
- if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
- $seen = 1;
- }
- }
-
- $r = q("insert into notify (hash,name,url,photo,date,aid,uid,link,parent,seen,type,verb,otype)
- values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')",
- dbesc($datarray['hash']),
- dbesc($datarray['name']),
- dbesc($datarray['url']),
- dbesc($datarray['photo']),
- dbesc($datarray['date']),
- intval($datarray['aid']),
- intval($datarray['uid']),
- dbesc($datarray['link']),
- dbesc($datarray['parent']),
- intval($seen),
- intval($datarray['type']),
- dbesc($datarray['verb']),
- dbesc($datarray['otype'])
- );
-
- $r = q("select id from notify where hash = '%s' and uid = %d limit 1",
- dbesc($hash),
- intval($recip['channel_id'])
- );
- if ($r) {
- $notify_id = $r[0]['id'];
- } else {
- logger('notification not found.');
- pop_lang();
- return;
- }
-
- $itemlink = z_root() . '/notify/view/' . $notify_id;
- $msg = str_replace('$itemlink',$itemlink,$epreamble);
-
- // wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
-
- if ((App::$language === 'en' || (! App::$language)) && strpos($msg,', '))
- $msg = substr($msg,strpos($msg,', ')+1);
-
- $r = q("update notify set msg = '%s' where id = %d and uid = %d",
- dbesc($msg),
- intval($notify_id),
- intval($datarray['uid'])
- );
-
- // send email notification if notification preferences permit
-
- require_once('bbcode.php');
- if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
-
- logger('notification: sending notification email');
-
- $hn = get_pconfig($recip['channel_id'],'system','email_notify_host');
- if($hn && (! stristr(App::get_hostname(),$hn))) {
- // this isn't the email notification host
- pop_lang();
- return;
- }
-
- $textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8'));
-
- $htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
-
-
- // use $_SESSION['zid_override'] to force zid() to use
- // the recipient address instead of the current observer
-
- $_SESSION['zid_override'] = $recip['channel_address'] . '@' . App::get_hostname();
- $_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
-
- $textversion = zidify_links($textversion);
- $htmlversion = zidify_links($htmlversion);
-
- // unset when done to revert to normal behaviour
-
- unset($_SESSION['zid_override']);
- unset($_SESSION['zrl_override']);
-
- $datarray = array();
- $datarray['banner'] = $banner;
- $datarray['product'] = $product;
- $datarray['preamble'] = $preamble;
- $datarray['sitename'] = $sitename;
- $datarray['siteurl'] = $siteurl;
- $datarray['type'] = $params['type'];
- $datarray['parent'] = $params['parent_mid'];
- $datarray['source_name'] = $sender['xchan_name'];
- $datarray['source_link'] = $sender['xchan_url'];
- $datarray['source_photo'] = $sender['xchan_photo_s'];
- $datarray['uid'] = $recip['channel_id'];
- $datarray['username'] = $recip['channel_name'];
- $datarray['hsitelink'] = $hsitelink;
- $datarray['tsitelink'] = $tsitelink;
- $datarray['hitemlink'] = '<a href="' . $itemlink . '">' . $itemlink . '</a>';
- $datarray['titemlink'] = $itemlink;
- $datarray['thanks'] = $thanks;
- $datarray['site_admin'] = $site_admin;
- $datarray['title'] = stripslashes($title);
- $datarray['htmlversion'] = $htmlversion;
- $datarray['textversion'] = $textversion;
- $datarray['subject'] = $subject;
- $datarray['headers'] = $additional_mail_header;
- $datarray['email_secure'] = false;
-
- call_hooks('enotify_mail', $datarray);
-
- // Default to private - don't disclose message contents over insecure channels (such as email)
- // Might be interesting to use GPG,PGP,S/MIME encryption instead
- // but we'll save that for a clever plugin developer to implement
-
- $private_activity = false;
-
- if (! $datarray['email_secure']) {
- switch ($params['type']) {
- case NOTIFY_WALL:
- case NOTIFY_TAGSELF:
- case NOTIFY_POKE:
- case NOTIFY_COMMENT:
- if (! $private)
- break;
- $private_activity = true;
- case NOTIFY_MAIL:
- $datarray['textversion'] = $datarray['htmlversion'] = $datarray['title'] = '';
- $datarray['subject'] = preg_replace('/' . preg_quote(t('[Hubzilla:Notify]')) . '/','$0*',$datarray['subject']);
- break;
- default:
- break;
- }
- }
-
- if ($private_activity
- && intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) {
-
- pop_lang();
- return;
- }
-
- // load the template for private message notifications
- $tpl = get_markup_template('email_notify_html.tpl');
- $email_html_body = replace_macros($tpl,array(
- '$banner' => $datarray['banner'],
- '$notify_icon' => Zotlabs\Project\System::get_notify_icon(),
- '$product' => $datarray['product'],
- '$preamble' => $datarray['preamble'],
- '$sitename' => $datarray['sitename'],
- '$siteurl' => $datarray['siteurl'],
- '$source_name' => $datarray['source_name'],
- '$source_link' => $datarray['source_link'],
- '$source_photo' => $datarray['source_photo'],
- '$username' => $datarray['to_name'],
- '$hsitelink' => $datarray['hsitelink'],
- '$hitemlink' => $datarray['hitemlink'],
- '$thanks' => $datarray['thanks'],
- '$site_admin' => $datarray['site_admin'],
- '$title' => $datarray['title'],
- '$htmlversion' => $datarray['htmlversion'],
- ));
-
- // load the template for private message notifications
- $tpl = get_markup_template('email_notify_text.tpl');
- $email_text_body = replace_macros($tpl, array(
- '$banner' => $datarray['banner'],
- '$product' => $datarray['product'],
- '$preamble' => $datarray['preamble'],
- '$sitename' => $datarray['sitename'],
- '$siteurl' => $datarray['siteurl'],
- '$source_name' => $datarray['source_name'],
- '$source_link' => $datarray['source_link'],
- '$source_photo' => $datarray['source_photo'],
- '$username' => $datarray['to_name'],
- '$tsitelink' => $datarray['tsitelink'],
- '$titemlink' => $datarray['titemlink'],
- '$thanks' => $datarray['thanks'],
- '$site_admin' => $datarray['site_admin'],
- '$title' => $datarray['title'],
- '$textversion' => $datarray['textversion'],
- ));
-
-// logger('text: ' . $email_text_body);
-
- // use the EmailNotification library to send the message
-
- enotify::send(array(
- 'fromName' => $sender_name,
- 'fromEmail' => $sender_email,
- 'replyTo' => $sender_email,
- 'toEmail' => $recip['account_email'],
- 'messageSubject' => $datarray['subject'],
- 'htmlVersion' => $email_html_body,
- 'textVersion' => $email_text_body,
- 'additionalMailHeader' => $datarray['headers'],
- ));
- }
-
- pop_lang();
-
-}
-
-
-/**
- * @brief A class for sending email notifications.
- *
- * @fixme Class names start mostly with capital letter to distinguish them easier.
- */
-class enotify {
- /**
- * @brief Send a multipart/alternative message with Text and HTML versions.
- *
- * @param array $params an assoziative array with:
- * * \e string \b fromName name of the sender
- * * \e string \b fromEmail email of the sender
- * * \e string \b replyTo replyTo address to direct responses
- * * \e string \b toEmail destination email address
- * * \e string \b messageSubject subject of the message
- * * \e string \b htmlVersion html version of the message
- * * \e string \b textVersion text only version of the message
- * * \e string \b additionalMailHeader additions to the smtp mail header
- */
- static public function send($params) {
-
- $fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
- $messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
-
- // generate a mime boundary
- $mimeBoundary = rand(0, 9) . "-"
- .rand(10000000000, 9999999999) . "-"
- .rand(10000000000, 9999999999) . "=:"
- .rand(10000, 99999);
-
- // generate a multipart/alternative message header
- $messageHeader =
- $params['additionalMailHeader'] .
- "From: $fromName <{$params['fromEmail']}>\n" .
- "Reply-To: $fromName <{$params['replyTo']}>\n" .
- "MIME-Version: 1.0\n" .
- "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
-
- // assemble the final multipart message body with the text and html types included
- $textBody = chunk_split(base64_encode($params['textVersion']));
- $htmlBody = chunk_split(base64_encode($params['htmlVersion']));
-
- $multipartMessageBody =
- "--" . $mimeBoundary . "\n" . // plain text section
- "Content-Type: text/plain; charset=UTF-8\n" .
- "Content-Transfer-Encoding: base64\n\n" .
- $textBody . "\n" .
- "--" . $mimeBoundary . "\n" . // text/html section
- "Content-Type: text/html; charset=UTF-8\n" .
- "Content-Transfer-Encoding: base64\n\n" .
- $htmlBody . "\n" .
- "--" . $mimeBoundary . "--\n"; // message ending
-
- // send the message
- $res = mail(
- $params['toEmail'], // send to address
- $messageSubject, // subject
- $multipartMessageBody, // message body
- $messageHeader // message headers
- );
- logger("notification: enotify::send returns " . $res, LOGGER_DEBUG);
- }
-}
diff --git a/include/environment.php b/include/environment.php
index 47ad241a7..11d465b84 100644
--- a/include/environment.php
+++ b/include/environment.php
@@ -60,6 +60,8 @@ function phpiniSizeToBytes($val) {
$val *= 1024;
case 'k':
$val *= 1024;
+ default:
+ break;
}
return (int)$val;
diff --git a/include/event.php b/include/event.php
index 7a99bc746..3d650cd14 100644
--- a/include/event.php
+++ b/include/event.php
@@ -25,25 +25,25 @@ function format_event_html($ev) {
$o = '<div class="vevent">' . "\r\n";
- $o .= '<div class="event-title"><h3><i class="icon-calendar"></i>&nbsp;' . bbcode($ev['summary']) . '</h3></div>' . "\r\n";
+ $o .= '<div class="event-title"><h3><i class="fa fa-calendar"></i>&nbsp;' . bbcode($ev['summary']) . '</h3></div>' . "\r\n";
$o .= '<div class="event-start"><span class="event-label">' . t('Starts:') . '</span>&nbsp;<span class="dtstart" title="'
- . datetime_convert('UTC', 'UTC', $ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
+ . datetime_convert('UTC', 'UTC', $ev['dtstart'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
- $ev['start'] , $bd_format ))
+ $ev['dtstart'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
- $ev['start'] , $bd_format)))
+ $ev['dtstart'] , $bd_format)))
. '</span></div>' . "\r\n";
if(! $ev['nofinish'])
$o .= '<div class="event-end" ><span class="event-label">' . t('Finishes:') . '</span>&nbsp;<span class="dtend" title="'
- . datetime_convert('UTC','UTC',$ev['finish'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
+ . datetime_convert('UTC','UTC',$ev['dtend'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
- $ev['finish'] , $bd_format ))
+ $ev['dtend'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
- $ev['finish'] , $bd_format )))
+ $ev['dtend'] , $bd_format )))
. '</span></div>' . "\r\n";
$o .= '<div class="event-description">' . bbcode($ev['description']) . '</div>' . "\r\n";
@@ -58,6 +58,37 @@ function format_event_html($ev) {
return $o;
}
+function format_event_obj($jobject) {
+ $event = array();
+
+ $object = json_decode($jobject,true);
+
+ //ensure compatibility with older items - this check can be removed at a later point
+ if(array_key_exists('description', $object)) {
+
+ $bd_format = t('l F d, Y \@ g:i A'); // Friday January 18, 2011 @ 8:01 AM
+
+ $event['header'] = replace_macros(get_markup_template('event_item_header.tpl'),array(
+ '$title' => bbcode($object['title']),
+ '$dtstart_label' => t('Starts:'),
+ '$dtstart_title' => datetime_convert('UTC', 'UTC', $object['dtstart'], (($object['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )),
+ '$dtstart_dt' => (($object['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $object['dtstart'] , $bd_format )) : day_translate(datetime_convert('UTC', 'UTC', $object['dtstart'] , $bd_format))),
+ '$finish' => (($object['nofinish']) ? false : true),
+ '$dtend_label' => t('Finishes:'),
+ '$dtend_title' => datetime_convert('UTC','UTC',$object['dtend'], (($object['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )),
+ '$dtend_dt' => (($object['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $object['dtend'] , $bd_format )) : day_translate(datetime_convert('UTC', 'UTC', $object['dtend'] , $bd_format )))
+ ));
+
+ $event['content'] = replace_macros(get_markup_template('event_item_content.tpl'),array(
+ '$description' => bbcode($object['description']),
+ '$location_label' => t('Location:'),
+ '$location' => bbcode($object['location'])
+ ));
+
+ }
+
+ return $event;
+}
function ical_wrapper($ev) {
@@ -67,8 +98,8 @@ function ical_wrapper($ev) {
$o .= "BEGIN:VCALENDAR";
$o .= "\r\nVERSION:2.0";
$o .= "\r\nMETHOD:PUBLISH";
- $o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . Zotlabs\Project\System::get_platform_name() . "//" . strtoupper(App::$language). "\r\n";
- if(array_key_exists('start', $ev))
+ $o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . Zotlabs\Lib\System::get_platform_name() . "//" . strtoupper(App::$language). "\r\n";
+ if(array_key_exists('dtstart', $ev))
$o .= format_event_ical($ev);
else {
foreach($ev as $e) {
@@ -82,7 +113,7 @@ function ical_wrapper($ev) {
function format_event_ical($ev) {
- if($ev['type'] === 'task')
+ if($ev['etype'] === 'task')
return format_todo_ical($ev);
$o = '';
@@ -92,10 +123,10 @@ function format_event_ical($ev) {
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
- if($ev['start'])
- $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['start'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
- if($ev['finish'] && ! $ev['nofinish'])
- $o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['finish'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
+ if($ev['dtstart'])
+ $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
+ if($ev['dtend'] && ! $ev['nofinish'])
+ $o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['summary'])
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
if($ev['location'])
@@ -119,10 +150,10 @@ function format_todo_ical($ev) {
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
- if($ev['start'])
- $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['start'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
- if($ev['finish'] && ! $ev['nofinish'])
- $o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['finish'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
+ if($ev['dtstart'])
+ $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
+ if($ev['dtend'] && ! $ev['nofinish'])
+ $o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['summary'])
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
if($ev['event_status']) {
@@ -152,7 +183,9 @@ function format_ical_text($s) {
require_once('include/bbcode.php');
require_once('include/html2plain.php');
- return(wordwrap(str_replace(array(',',';','\\'),array('\\,','\\;','\\\\'),html2plain(bbcode($s))),72,"\r\n ",true));
+ $s = html2plain(bbcode($s));
+ $s = str_replace(["\r\n","\n"],["",""],$s);
+ return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
}
@@ -166,15 +199,18 @@ function format_event_bbcode($ev) {
if($ev['description'])
$o .= '[event-description]' . $ev['description'] . '[/event-description]';
- if($ev['start'])
- $o .= '[event-start]' . $ev['start'] . '[/event-start]';
+ if($ev['dtstart'])
+ $o .= '[event-start]' . $ev['dtstart'] . '[/event-start]';
- if(($ev['finish']) && (! $ev['nofinish']))
- $o .= '[event-finish]' . $ev['finish'] . '[/event-finish]';
+ if(($ev['dtend']) && (! $ev['nofinish']))
+ $o .= '[event-finish]' . $ev['dtend'] . '[/event-finish]';
if($ev['location'])
$o .= '[event-location]' . $ev['location'] . '[/event-location]';
+ if($ev['event_hash'])
+ $o .= '[event-id]' . $ev['event_hash'] . '[/event-id]';
+
if($ev['adjust'])
$o .= '[event-adjust]' . $ev['adjust'] . '[/event-adjust]';
@@ -204,21 +240,24 @@ function bbtoevent($s) {
$ev['description'] = $match[1];
$match = '';
if(preg_match("/\[event\-start\](.*?)\[\/event\-start\]/is",$s,$match))
- $ev['start'] = $match[1];
+ $ev['dtstart'] = $match[1];
$match = '';
if(preg_match("/\[event\-finish\](.*?)\[\/event\-finish\]/is",$s,$match))
- $ev['finish'] = $match[1];
+ $ev['dtend'] = $match[1];
$match = '';
if(preg_match("/\[event\-location\](.*?)\[\/event\-location\]/is",$s,$match))
$ev['location'] = $match[1];
$match = '';
+ if(preg_match("/\[event\-id\](.*?)\[\/event\-id\]/is",$s,$match))
+ $ev['event_hash'] = $match[1];
+ $match = '';
if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match))
$ev['adjust'] = $match[1];
- if(array_key_exists('start',$ev)) {
- if(array_key_exists('finish',$ev)) {
- if($ev['finish'] === $ev['start'])
+ if(array_key_exists('dtstart',$ev)) {
+ if(array_key_exists('dtend',$ev)) {
+ if($ev['dtend'] === $ev['dtstart'])
$ev['nofinish'] = 1;
- elseif($ev['finish'])
+ elseif($ev['dtend'])
$ev['nofinish'] = 0;
else
$ev['nofinish'] = 1;
@@ -254,8 +293,8 @@ function sort_by_date($arr) {
*/
function ev_compare($a, $b) {
- $date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['start']) : $a['start']);
- $date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']);
+ $date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['dtstart']) : $a['dtstart']);
+ $date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['dtstart']) : $b['dtstart']);
if ($date_a === $date_b)
return strcasecmp($a['description'], $b['description']);
@@ -268,7 +307,7 @@ function event_store_event($arr) {
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
- $arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
+ $arr['etype'] = (($arr['etype']) ? $arr['etype'] : 'event' );
$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : '');
$arr['event_priority'] = (($arr['event_priority']) ? $arr['event_priority'] : 0);
@@ -278,45 +317,52 @@ function event_store_event($arr) {
else
$arr['event_status_date'] = NULL_DATE;
- // Existing event being modified
- if($arr['id'] || $arr['event_hash']) {
+ $existing_event = null;
- // has the event actually changed?
+ if($arr['event_hash']) {
+ $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
+ dbesc($arr['event_hash']),
+ intval($arr['uid'])
+ );
+ if($r) {
+ $existing_event = $r[0];
+ }
+ }
- if($arr['event_hash']) {
- $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
- dbesc($arr['event_hash']),
- intval($arr['uid'])
- );
+ if($arr['id']) {
+ $r = q("SELECT * FROM event WHERE id = %d AND uid = %d LIMIT 1",
+ intval($arr['id']),
+ intval($arr['uid'])
+ );
+ if($r) {
+ $existing_event = $r[0];
}
else {
- $r = q("SELECT * FROM event WHERE id = %d AND uid = %d LIMIT 1",
- intval($arr['id']),
- intval($arr['uid'])
- );
+ return false;
}
+ }
- if(! $r)
- return false;
- if($r[0]['edited'] === $arr['edited']) {
- // Nothing has changed. Return the ID.
- return $r[0];
+ if($existing_event) {
+
+ if($existing_event['edited'] >= $arr['edited']) {
+ // Nothing has changed.
+ return $existing_event;
}
- $hash = $r[0]['event_hash'];
+ $hash = $existing_event['event_hash'];
// The event changed. Update it.
$r = q("UPDATE `event` SET
`edited` = '%s',
- `start` = '%s',
- `finish` = '%s',
+ `dtstart` = '%s',
+ `dtend` = '%s',
`summary` = '%s',
`description` = '%s',
`location` = '%s',
- `type` = '%s',
+ `etype` = '%s',
`adjust` = %d,
`nofinish` = %d,
`event_status` = '%s',
@@ -332,12 +378,12 @@ function event_store_event($arr) {
WHERE `id` = %d AND `uid` = %d",
dbesc($arr['edited']),
- dbesc($arr['start']),
- dbesc($arr['finish']),
+ dbesc($arr['dtstart']),
+ dbesc($arr['dtend']),
dbesc($arr['summary']),
dbesc($arr['description']),
dbesc($arr['location']),
- dbesc($arr['type']),
+ dbesc($arr['etype']),
intval($arr['adjust']),
intval($arr['nofinish']),
dbesc($arr['event_status']),
@@ -350,7 +396,7 @@ function event_store_event($arr) {
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
- intval($r[0]['id']),
+ intval($existing_event['id']),
intval($arr['uid'])
);
} else {
@@ -360,10 +406,12 @@ function event_store_event($arr) {
if(array_key_exists('external_id',$arr))
$hash = $arr['external_id'];
+ elseif(array_key_exists('event_hash',$arr))
+ $hash = $arr['event_hash'];
else
$hash = random_string() . '@' . App::get_hostname();
- $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type,
+ $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,dtstart,dtend,summary,description,location,etype,
adjust,nofinish, event_status, event_status_date, event_percent, event_repeat, event_sequence, event_priority, allow_cid,allow_gid,deny_cid,deny_gid)
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s' ) ",
intval($arr['uid']),
@@ -372,12 +420,12 @@ function event_store_event($arr) {
dbesc($hash),
dbesc($arr['created']),
dbesc($arr['edited']),
- dbesc($arr['start']),
- dbesc($arr['finish']),
+ dbesc($arr['dtstart']),
+ dbesc($arr['dtend']),
dbesc($arr['summary']),
dbesc($arr['description']),
dbesc($arr['location']),
- dbesc($arr['type']),
+ dbesc($arr['etype']),
intval($arr['adjust']),
intval($arr['nofinish']),
dbesc($arr['event_status']),
@@ -426,7 +474,7 @@ function event_addtocal($item_id, $uid) {
$ev = bbtoevent($r[0]['body']);
- if(x($ev,'summary') && x($ev,'start')) {
+ if(x($ev,'summary') && x($ev,'dtstart')) {
$ev['event_xchan'] = $item['author_xchan'];
$ev['uid'] = $channel['channel_id'];
$ev['account'] = $channel['channel_account_id'];
@@ -436,7 +484,7 @@ function event_addtocal($item_id, $uid) {
// is this an edit?
- if($item['resource_type'] === 'event') {
+ if($item['resource_type'] === 'event' && (! $ev['event_hash'])) {
$ev['event_hash'] = $item['resource_id'];
}
@@ -472,7 +520,6 @@ function event_addtocal($item_id, $uid) {
if($z) {
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
}
-
return true;
}
}
@@ -536,34 +583,24 @@ function event_import_ical($ical, $uid) {
}
$dtstart = $ical->DTSTART->getDateTime();
+ $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 1 : 0);
// logger('dtstart: ' . var_export($dtstart,true));
-
- switch($dtstart->timezone_type) {
- case VObject\Property\DateTime::UTC :
- $ev['adjust'] = 0;
- break;
- case VObject\Property\DateTime::LOCALTZ :
- default:
- $ev['adjust'] = 1;
- break;
- }
-
- $ev['start'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
+ $ev['dtstart'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
$dtstart->format(\DateTime::W3C));
if(isset($ical->DTEND)) {
$dtend = $ical->DTEND->getDateTime();
- $ev['finish'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
+ $ev['dtend'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
$dtend->format(\DateTime::W3C));
}
else
$ev['nofinish'] = 1;
- if($ev['start'] === $ev['finish'])
+ if($ev['dtstart'] === $ev['dtend'])
$ev['nofinish'] = 1;
if(isset($ical->CREATED)) {
@@ -597,7 +634,7 @@ function event_import_ical($ical, $uid) {
$ev['external_id'] = $evuid;
}
- if($ev['summary'] && $ev['start']) {
+ if($ev['summary'] && $ev['dtstart']) {
$ev['event_xchan'] = $channel['channel_hash'];
$ev['uid'] = $channel['channel_id'];
$ev['account'] = $channel['channel_account_id'];
@@ -636,29 +673,24 @@ function event_import_ical_task($ical, $uid) {
$dtstart = $ical->DTSTART->getDateTime();
+ $ev['adjust'] = (($ical->DTSTART->isFloating()) ? 1 : 0);
+
// logger('dtstart: ' . var_export($dtstart,true));
- if(($dtstart->timezone_type == 2) || (($dtstart->timezone_type == 3) && ($dtstart->timezone === 'UTC'))) {
- $ev['adjust'] = 1;
- }
- else {
- $ev['adjust'] = 0;
- }
-
- $ev['start'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
+ $ev['dtstart'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
$dtstart->format(\DateTime::W3C));
if(isset($ical->DUE)) {
$dtend = $ical->DUE->getDateTime();
- $ev['finish'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
+ $ev['dtend'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
$dtend->format(\DateTime::W3C));
}
else
$ev['nofinish'] = 1;
- if($ev['start'] === $ev['finish'])
+ if($ev['dtstart'] === $ev['dtend'])
$ev['nofinish'] = 1;
if(isset($ical->CREATED)) {
@@ -723,9 +755,9 @@ function event_import_ical_task($ical, $uid) {
$ev['event_percent'] = (string) $ical->{'PERCENT-COMPLETE'} ;
}
- $ev['type'] = 'task';
+ $ev['etype'] = 'task';
- if($ev['summary'] && $ev['start']) {
+ if($ev['summary'] && $ev['dtstart']) {
$ev['event_xchan'] = $channel['channel_hash'];
$ev['uid'] = $channel['channel_id'];
$ev['account'] = $channel['channel_account_id'];
@@ -774,7 +806,10 @@ function event_store_item($arr, $event) {
$prefix = '';
// $birthday = false;
- if($event['type'] === 'birthday') {
+ if(($event) && array_key_exists('event_hash',$event) && (! array_key_exists('event_hash',$arr)))
+ $arr['event_hash'] = $event['event_hash'];
+
+ if($event['etype'] === 'birthday') {
if(! is_sys_channel($arr['uid']))
$prefix = t('This event has been added to your calendar.');
// $birthday = true;
@@ -798,21 +833,22 @@ function event_store_item($arr, $event) {
'type' => ACTIVITY_OBJ_EVENT,
'id' => z_root() . '/event/' . $r[0]['resource_id'],
'title' => $arr['summary'],
- 'start' => $arr['start'],
- 'finish' => $arr['finish'],
+ 'dtstart' => $arr['dtstart'],
+ 'dtend' => $arr['dtend'],
'nofinish' => $arr['nofinish'],
'description' => $arr['description'],
'location' => $arr['location'],
'adjust' => $arr['adjust'],
'content' => format_event_bbcode($arr),
'author' => array(
- 'name' => $r[0]['xchan_name'],
- 'address' => $r[0]['xchan_addr'],
- 'guid' => $r[0]['xchan_guid'],
- 'guid_sig' => $r[0]['xchan_guid_sig'],
- 'link' => array(
- array('rel' => 'alternate', 'type' => 'text/html', 'href' => $r[0]['xchan_url']),
- array('rel' => 'photo', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_m'])),
+ 'name' => $r[0]['xchan_name'],
+ 'address' => $r[0]['xchan_addr'],
+ 'guid' => $r[0]['xchan_guid'],
+ 'guid_sig' => $r[0]['xchan_guid_sig'],
+ 'link' => array(
+ array('rel' => 'alternate', 'type' => 'text/html', 'href' => $r[0]['xchan_url']),
+ array('rel' => 'photo', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_m'])
+ ),
),
));
@@ -823,7 +859,7 @@ function event_store_item($arr, $event) {
$sig = '';
- q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', sig = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
+ q("UPDATE item SET title = '%s', body = '%s', obj = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', sig = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
dbesc($arr['summary']),
dbesc($prefix . format_event_bbcode($arr)),
dbesc($object),
@@ -847,12 +883,12 @@ function event_store_item($arr, $event) {
if(($arr['term']) && (is_array($arr['term']))) {
foreach($arr['term'] as $t) {
- q("insert into term (uid,oid,otype,type,term,url)
+ q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
intval($arr['uid']),
intval($r[0]['id']),
intval(TERM_OBJ_POST),
- intval($t['type']),
+ intval($t['ttype']),
dbesc($t['term']),
dbesc($t['url'])
);
@@ -939,12 +975,12 @@ function event_store_item($arr, $event) {
dbesc($arr['event_xchan'])
);
if($x) {
- $item_arr['object'] = json_encode(array(
+ $item_arr['obj'] = json_encode(array(
'type' => ACTIVITY_OBJ_EVENT,
'id' => z_root() . '/event/' . $event['event_hash'],
'title' => $arr['summary'],
- 'start' => $arr['start'],
- 'finish' => $arr['finish'],
+ 'dtstart' => $arr['dtstart'],
+ 'dtend' => $arr['dtend'],
'nofinish' => $arr['nofinish'],
'description' => $arr['description'],
'location' => $arr['location'],
@@ -994,7 +1030,7 @@ function tasks_fetch($arr) {
if($arr && $arr['all'] == 1)
$sql_extra = '';
- $r = q("select * from event where type = 'task' and uid = %d $sql_extra order by created desc",
+ $r = q("select * from event where etype = 'task' and uid = %d $sql_extra order by created desc",
intval(local_channel())
);
diff --git a/include/expire.php b/include/expire.php
deleted file mode 100644
index e75594b5f..000000000
--- a/include/expire.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * @file include/expire.php
- */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-
-function expire_run($argv, $argc){
-
- cli_startup();
-
- // perform final cleanup on previously delete items
-
- $r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('10 DAY')
- );
- if ($r) {
- foreach ($r as $rr) {
- drop_item($rr['id'], false, DROPITEM_PHASE2);
- }
- }
-
- // physically remove anything that has been deleted for more than two months
- /** @FIXME - this is a wretchedly inefficient query */
-
- $r = q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('36 DAY')
- );
-
- /** @FIXME make this optional as it could have a performance impact on large sites */
-
- if (intval(get_config('system', 'optimize_items')))
- q("optimize table item");
-
- logger('expire: start', LOGGER_DEBUG);
-
- $site_expire = get_config('system', 'default_expire_days');
-
- logger('site_expire: ' . $site_expire);
-
- $r = q("SELECT channel_id, channel_address, channel_pageflags, channel_expire_days from channel where true");
-
- if ($r) {
- foreach ($r as $rr) {
-
- // expire the sys channel separately
- if (intval($rr['channel_system']))
- continue;
-
- // service class default (if non-zero) over-rides the site default
-
- $service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
- if (intval($service_class_expire))
- $channel_expire = $service_class_expire;
- else
- $channel_expire = $site_expire;
-
- if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
- intval($rr['channel_expire_days'] == 0)) {
- $expire_days = $channel_expire;
- } else {
- $expire_days = $rr['channel_expire_days'];
- }
-
- // if the site or service class expiration is non-zero and less than person expiration, use that
- logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $expire_days, LOGGER_DEBUG);
- item_expire($rr['channel_id'], $expire_days);
- }
- }
-
- $x = get_sys_channel();
- if ($x) {
-
- // this should probably just fetch the channel_expire_days from the sys channel,
- // but there's no convenient way to set it.
-
- $expire_days = get_config('system', 'sys_expire_days');
- if ($expire_days === false)
- $expire_days = 30;
-
- if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
- $expire_days = $site_expire;
- }
-
- logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
-
- if ($expire_days)
- item_expire($x['channel_id'], $expire_days);
-
- logger('Expire: sys: done', LOGGER_DEBUG);
- }
-}
-
-if (array_search(__file__, get_included_files()) === 0){
- expire_run($argv, $argc);
- killme();
-}
diff --git a/include/externals.php b/include/externals.php
deleted file mode 100644
index 3a3a32420..000000000
--- a/include/externals.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/identity.php');
-
-function externals_run($argv, $argc){
-
- cli_startup();
- $a = get_app();
-
-
- $total = 0;
- $attempts = 0;
-
- logger('externals: startup', LOGGER_DEBUG);
-
- // pull in some public posts
-
-
- while($total == 0 && $attempts < 3) {
- $arr = array('url' => '');
- call_hooks('externals_url_select',$arr);
-
- if($arr['url']) {
- $url = $arr['url'];
- }
- else {
- $randfunc = db_getfunc('RAND');
-
- // fixme this query does not deal with directory realms.
-
- $r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
- dbesc(z_root()),
- intval(DIRECTORY_MODE_STANDALONE),
- intval(SITE_TYPE_ZOT)
- );
- if($r)
- $url = $r[0]['site_url'];
- }
-
- $blacklisted = false;
-
- if(! check_siteallowed($url)) {
- logger('blacklisted site: ' . $url);
- $blacklisted = true;
- }
-
- $attempts ++;
-
- // make sure we can eventually break out if somebody blacklists all known sites
-
- if($blacklisted) {
- if($attempts > 20)
- break;
- $attempts --;
- continue;
- }
-
- if($url) {
- if($r[0]['site_pull'] !== NULL_DATE)
- $mindate = urlencode(datetime_convert('','',$r[0]['site_pull'] . ' - 1 day'));
- else {
- $days = get_config('externals','since_days');
- if($days === false)
- $days = 15;
- $mindate = urlencode(datetime_convert('','','now - ' . intval($days) . ' days'));
- }
-
- $feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
-
- logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
-
- $x = z_fetch_url($feedurl);
- if(($x) && ($x['success'])) {
-
- q("update site set site_pull = '%s' where site_url = '%s'",
- dbesc(datetime_convert()),
- dbesc($url)
- );
-
- $j = json_decode($x['body'],true);
- if($j['success'] && $j['messages']) {
- $sys = get_sys_channel();
- foreach($j['messages'] as $message) {
- // on these posts, clear any route info.
- $message['route'] = '';
- $results = process_delivery(array('hash' => 'undefined'), get_item_elements($message),
- array(array('hash' => $sys['xchan_hash'])), false, true);
- $total ++;
- }
- logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
- }
- }
- }
- }
-}
-
-if (array_search(__file__,get_included_files())===0){
- externals_run($argv,$argc);
- killme();
-}
diff --git a/include/features.php b/include/features.php
index 38700f9f5..2d71aa9be 100644
--- a/include/features.php
+++ b/include/features.php
@@ -52,6 +52,7 @@ function get_features($filtered = true) {
array('advanced_profiles', t('Advanced Profiles'), t('Additional profile sections and selections'),false,get_config('feature_lock','advanced_profiles')),
array('profile_export', t('Profile Import/Export'), t('Save and load profile details across sites/channels'),false,get_config('feature_lock','profile_export')),
array('webpages', t('Web Pages'), t('Provide managed web pages on your channel'),false,get_config('feature_lock','webpages')),
+ array('wiki', t('Wiki'), t('Provide a wiki for your channel'),((UNO) ? false : true),get_config('feature_lock','wiki')),
array('hide_rating', t('Hide Rating'), t('Hide the rating buttons on your channel and profile pages. Note: People can still rate you somewhere else.'),false,get_config('feature_lock','hide_rating')),
array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders (note: not encrypted)'),false,get_config('feature_lock','private_notes')),
array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false,get_config('feature_lock','nav_channel_select')),
@@ -94,6 +95,7 @@ function get_features($filtered = true) {
t('Post/Comment Tools'),
array('commtag', t('Community Tagging'), t('Ability to tag existing posts'),false,get_config('feature_lock','commtag')),
array('categories', t('Post Categories'), t('Add categories to your posts'),false,get_config('feature_lock','categories')),
+ array('emojis', t('Emoji Reactions'), t('Add emoji reaction ability to posts'),true,get_config('feature_lock','emojis')),
array('filing', t('Saved Folders'), t('Ability to file posts under folders'),false,get_config('feature_lock','filing')),
array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments'),false,get_config('feature_lock','dislike')),
array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'),false,get_config('feature_lock','star_posts')),
diff --git a/include/feedutils.php b/include/feedutils.php
new file mode 100644
index 000000000..01ec0687e
--- /dev/null
+++ b/include/feedutils.php
@@ -0,0 +1,1315 @@
+<?php
+
+
+/**
+ * @brief Generate an Atom feed.
+ *
+ * @param array $channel
+ * @param array $params
+ */
+function get_public_feed($channel, $params) {
+
+ $type = 'xml';
+ $begin = NULL_DATE;
+ $end = '';
+ $start = 0;
+ $records = 40;
+ $direction = 'desc';
+ $pages = 0;
+
+ if(! $params)
+ $params = array();
+
+ $params['type'] = ((x($params,'type')) ? $params['type'] : 'xml');
+ $params['begin'] = ((x($params,'begin')) ? $params['begin'] : NULL_DATE);
+ $params['end'] = ((x($params,'end')) ? $params['end'] : datetime_convert('UTC','UTC','now'));
+ $params['start'] = ((x($params,'start')) ? $params['start'] : 0);
+ $params['records'] = ((x($params,'records')) ? $params['records'] : 40);
+ $params['direction'] = ((x($params,'direction')) ? $params['direction'] : 'desc');
+ $params['pages'] = ((x($params,'pages')) ? intval($params['pages']) : 0);
+ $params['top'] = ((x($params,'top')) ? intval($params['top']) : 0);
+ $params['cat'] = ((x($params,'cat')) ? $params['cat'] : '');
+
+
+ // put a sane lower limit on feed requests if not specified
+
+// if($params['begin'] === NULL_DATE)
+// $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
+
+ switch($params['type']) {
+ case 'json':
+ header("Content-type: application/atom+json");
+ break;
+ case 'xml':
+ default:
+ header("Content-type: application/atom+xml");
+ break;
+ }
+
+ return get_feed_for($channel, get_observer_hash(), $params);
+}
+
+/**
+ * @brief
+ *
+ * @param array $channel
+ * @param string $observer_hash
+ * @param array $params
+ * @return string
+ */
+function get_feed_for($channel, $observer_hash, $params) {
+
+ if(! channel)
+ http_status_exit(401);
+
+ if($params['pages']) {
+ if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_pages'))
+ http_status_exit(403);
+ } else {
+ if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream'))
+ http_status_exit(403);
+ }
+ $items = items_fetch(array(
+ 'wall' => '1',
+ 'datequery' => $params['end'],
+ 'datequery2' => $params['begin'],
+ 'start' => $params['start'], // FIXME
+ 'records' => $params['records'], // FIXME
+ 'direction' => $params['direction'], // FIXME
+ 'pages' => $params['pages'],
+ 'order' => 'post',
+ 'top' => $params['top'],
+ 'cat' => $params['cat']
+ ), $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module);
+
+
+ $feed_template = get_markup_template('atom_feed.tpl');
+
+ $atom = '';
+
+ $atom .= replace_macros($feed_template, array(
+ '$version' => xmlify(Zotlabs\Lib\System::get_project_version()),
+ '$red' => xmlify(Zotlabs\Lib\System::get_platform_name()),
+ '$feed_id' => xmlify($channel['xchan_url']),
+ '$feed_title' => xmlify($channel['channel_name']),
+ '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) ,
+ '$hub' => '', // feed_hublinks(),
+ '$salmon' => '', // feed_salmonlinks($channel['channel_address']),
+ '$name' => xmlify($channel['channel_name']),
+ '$profile_page' => xmlify($channel['xchan_url']),
+ '$mimephoto' => xmlify($channel['xchan_photo_mimetype']),
+ '$photo' => xmlify($channel['xchan_photo_l']),
+ '$thumb' => xmlify($channel['xchan_photo_m']),
+ '$picdate' => '',
+ '$uridate' => '',
+ '$namdate' => '',
+ '$birthday' => '',
+ '$community' => '',
+ ));
+
+
+ call_hooks('atom_feed', $atom);
+
+ if($items) {
+ $type = 'html';
+ foreach($items as $item) {
+ if($item['item_private'])
+ continue;
+
+ /** @BUG $owner is undefined in this call */
+ $atom .= atom_entry($item, $type, null, $owner, true);
+ }
+ }
+
+ call_hooks('atom_feed_end', $atom);
+
+ $atom .= '</feed>' . "\r\n";
+
+ return $atom;
+}
+
+/**
+ * @brief
+ *
+ * @param array $item an associative array with
+ * * \b string \b verb
+ * @return string item's verb if set, default ACTIVITY_POST see boot.php
+ */
+function construct_verb($item) {
+ if ($item['verb'])
+ return $item['verb'];
+
+ return ACTIVITY_POST;
+}
+
+function construct_activity_object($item) {
+
+ if($item['obj']) {
+ $o = '<as:object>' . "\r\n";
+ $r = json_decode($item['obj'],false);
+
+ if(! $r)
+ return '';
+ if($r->type)
+ $o .= '<as:obj_type>' . xmlify($r->type) . '</as:obj_type>' . "\r\n";
+ if($r->id)
+ $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
+ if($r->title)
+ $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
+ if($r->links) {
+ /** @FIXME!! */
+ if(substr($r->link,0,1) === '<') {
+ $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
+ $o .= $r->link;
+ }
+ else
+ $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
+ }
+ if($r->content)
+ $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
+ $o .= '</as:object>' . "\r\n";
+ return $o;
+ }
+
+ return '';
+}
+
+function construct_activity_target($item) {
+
+ if($item['target']) {
+ $o = '<as:target>' . "\r\n";
+ $r = json_decode($item['target'],false);
+ if(! $r)
+ return '';
+ if($r->type)
+ $o .= '<as:obj_type>' . xmlify($r->type) . '</as:obj_type>' . "\r\n";
+ if($r->id)
+ $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
+ if($r->title)
+ $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
+ if($r->links) {
+ /** @FIXME !!! */
+ if(substr($r->link,0,1) === '<') {
+ if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
+ $r->link = str_replace('&','&amp;', $r->link);
+ $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
+ $o .= $r->link;
+ }
+ else
+ $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
+ }
+ if($r->content)
+ $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
+
+ $o .= '</as:target>' . "\r\n";
+
+ return $o;
+ }
+
+ return '';
+}
+
+/**
+ * @param object $feed
+ * @param array $item
+ * @param[out] array $author
+ * @return multitype:multitype: string NULL number Ambigous <NULL, string, number> Ambigous <mixed, string> Ambigous <multitype:multitype:string Ambigous <NULL, string> , multitype:multitype:string unknown > multitype:NULL unknown
+ */
+function get_atom_elements($feed, $item, &$author) {
+
+ //$best_photo = array();
+
+ $res = array();
+
+ $found_author = $item->get_author();
+ if($found_author) {
+ $author['author_name'] = unxmlify($found_author->get_name());
+ $author['author_link'] = unxmlify($found_author->get_link());
+ $author['author_is_feed'] = false;
+ }
+ else {
+ $author['author_name'] = unxmlify($feed->get_title());
+ $author['author_link'] = unxmlify($feed->get_permalink());
+ $author['author_is_feed'] = true;
+ }
+
+ if(substr($author['author_link'],-1,1) == '/')
+ $author['author_link'] = substr($author['author_link'],0,-1);
+
+ $res['mid'] = base64url_encode(unxmlify($item->get_id()));
+ $res['title'] = unxmlify($item->get_title());
+ $res['body'] = unxmlify($item->get_content());
+ $res['plink'] = unxmlify($item->get_link(0));
+ $res['item_rss'] = 1;
+
+
+ // removing the content of the title if its identically to the body
+ // This helps with auto generated titles e.g. from tumblr
+
+ if (title_is_body($res["title"], $res["body"]))
+ $res['title'] = "";
+
+ if($res['plink'])
+ $base_url = implode('/', array_slice(explode('/',$res['plink']),0,3));
+ else
+ $base_url = '';
+
+ // look for a photo. We should check media size and find the best one,
+ // but for now let's just find any author photo
+
+ $rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+
+ if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+ $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+ foreach($base as $link) {
+ if(!x($author, 'author_photo') || ! $author['author_photo']) {
+ if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ }
+ }
+ }
+
+ $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
+
+ if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['obj_type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
+ $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+ if($base && count($base)) {
+ foreach($base as $link) {
+ if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
+ $author['author_link'] = unxmlify($link['attribs']['']['href']);
+ if(!x($author, 'author_photo') || ! $author['author_photo']) {
+ if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ }
+ }
+ }
+ }
+
+ // check for a yahoo media element (github etc.)
+
+ if(! $author['author_photo']) {
+ $rawmedia = $item->get_item_tags(NAMESPACE_YMEDIA,'thumbnail');
+ if($rawmedia && $rawmedia[0]['attribs']['']['url']) {
+ $author['author_photo'] = strip_tags(unxmlify($rawmedia[0]['attribs']['']['url']));
+ }
+ }
+
+
+ // No photo/profile-link on the item - look at the feed level
+
+ if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) {
+ $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+ if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+ $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+ foreach($base as $link) {
+ if($link['attribs']['']['rel'] === 'alternate' && (! $author['author_link'])) {
+ $author['author_link'] = unxmlify($link['attribs']['']['href']);
+ $author['author_is_feed'] = true;
+ }
+ if(! $author['author_photo']) {
+ if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ }
+ }
+ }
+
+ $rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
+
+ if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['obj_type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
+ $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+
+ if($base && count($base)) {
+ foreach($base as $link) {
+ if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
+ $author['author_link'] = unxmlify($link['attribs']['']['href']);
+ if(! (x($author,'author_photo'))) {
+ if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ }
+ }
+ }
+ }
+ }
+
+ $apps = $item->get_item_tags(NAMESPACE_STATUSNET,'notice_info');
+ if($apps && $apps[0]['attribs']['']['source']) {
+ $res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source']));
+ }
+
+ /*
+ * If there's a copy of the body content which is guaranteed to have survived mangling in transit, use it.
+ */
+
+ $have_real_body = false;
+
+ $rawenv = $item->get_item_tags(NAMESPACE_DFRN, 'env');
+ if($rawenv) {
+ $have_real_body = true;
+ $res['body'] = $rawenv[0]['data'];
+ $res['body'] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$res['body']);
+ // make sure nobody is trying to sneak some html tags by us
+ $res['body'] = notags(base64url_decode($res['body']));
+
+ // We could probably turn these old Friendica bbcode bookmarks into bookmark tags but we'd have to
+ // create a term table item for them. For now just make sure they stay as links.
+
+ $res['body'] = preg_replace('/\[bookmark(.*?)\](.*?)\[\/bookmark\]/','[url$1]$2[/url]',$res['body']);
+ }
+
+ $res['body'] = limit_body_size($res['body']);
+
+ // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust
+ // the content type. Our own network only emits text normally, though it might have been converted to
+ // html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will
+ // have to assume it is all html and needs to be purified.
+
+ // It doesn't matter all that much security wise - because before this content is used anywhere, we are
+ // going to escape any tags we find regardless, but this lets us import a limited subset of html from
+ // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining
+ // html.
+
+ if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) {
+
+ $res['body'] = reltoabs($res['body'],$base_url);
+
+ $res['body'] = html2bb_video($res['body']);
+
+ $res['body'] = oembed_html2bbcode($res['body']);
+
+ $res['body'] = purify_html($res['body']);
+
+ $res['body'] = @html2bbcode($res['body']);
+ }
+ elseif(! $have_real_body) {
+
+ // it's not one of our messages and it has no tags
+ // so it's probably just text. We'll escape it just to be safe.
+
+ $res['body'] = escape_tags($res['body']);
+ }
+
+ if($res['plink'] && $res['title']) {
+ $res['body'] = '#^[url=' . $res['plink'] . ']' . $res['title'] . '[/url]' . "\n\n" . $res['body'];
+ $terms = array();
+ $terms[] = array(
+ 'otype' => TERM_OBJ_POST,
+ 'ttype' => TERM_BOOKMARK,
+ 'url' => $res['plink'],
+ 'term' => $res['title'],
+ );
+ }
+ elseif($res['plink']) {
+ $res['body'] = '#^[url]' . $res['plink'] . '[/url]' . "\n\n" . $res['body'];
+ $terms = array();
+ $terms[] = array(
+ 'otype' => TERM_OBJ_POST,
+ 'ttype' => TERM_BOOKMARK,
+ 'url' => $res['plink'],
+ 'term' => $res['plink'],
+ );
+ }
+
+ $private = $item->get_item_tags(NAMESPACE_DFRN,'private');
+ if($private && intval($private[0]['data']) > 0)
+ $res['item_private'] = ((intval($private[0]['data'])) ? 1 : 0);
+ else
+ $res['item_private'] = 0;
+
+ $rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location');
+ if($rawlocation)
+ $res['location'] = unxmlify($rawlocation[0]['data']);
+
+ $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published');
+ if($rawcreated)
+ $res['created'] = unxmlify($rawcreated[0]['data']);
+
+ $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated');
+ if($rawedited)
+ $res['edited'] = unxmlify($rawedited[0]['data']);
+
+ if((x($res,'edited')) && (! (x($res,'created'))))
+ $res['created'] = $res['edited'];
+
+ if(! $res['created'])
+ $res['created'] = $item->get_date('c');
+
+ if(! $res['edited'])
+ $res['edited'] = $item->get_date('c');
+
+
+ // Disallow time travelling posts
+
+ $d1 = strtotime($res['created']);
+ $d2 = strtotime($res['edited']);
+ $d3 = strtotime('now');
+
+ if($d1 > $d3)
+ $res['created'] = datetime_convert();
+ if($d2 > $d3)
+ $res['edited'] = datetime_convert();
+
+ $res['created'] = datetime_convert('UTC','UTC',$res['created']);
+ $res['edited'] = datetime_convert('UTC','UTC',$res['edited']);
+
+ $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
+ if(! $rawowner)
+ $rawowner = $item->get_item_tags(NAMESPACE_ZOT,'owner');
+
+ if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])
+ $author['owner_name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']);
+ elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data'])
+ $author['owner_name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
+ if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
+ $author['owner_link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
+ elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
+ $author['owner_link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
+
+ if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+ $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+
+ foreach($base as $link) {
+ if(!x($author, 'owner_photo') || ! $author['owner_photo']) {
+ if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
+ $author['owner_photo'] = unxmlify($link['attribs']['']['href']);
+ }
+ }
+ }
+
+ $rawgeo = $item->get_item_tags(NAMESPACE_GEORSS,'point');
+ if($rawgeo)
+ $res['coord'] = unxmlify($rawgeo[0]['data']);
+
+
+ $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
+
+ // select between supported verbs
+
+ if($rawverb) {
+ $res['verb'] = unxmlify($rawverb[0]['data']);
+ }
+
+ // translate OStatus unfollow to activity streams if it happened to get selected
+
+ if((x($res,'verb')) && ($res['verb'] === 'http://ostatus.org/schema/1.0/unfollow'))
+ $res['verb'] = ACTIVITY_UNFOLLOW;
+
+ $cats = $item->get_categories();
+ if($cats) {
+ if(is_null($terms))
+ $terms = array();
+ foreach($cats as $cat) {
+ $term = $cat->get_term();
+ if(! $term)
+ $term = $cat->get_label();
+ $scheme = $cat->get_scheme();
+ $termurl = '';
+ if($scheme && $term && stristr($scheme,'X-DFRN:')) {
+ $termtype = ((substr($scheme,7,1) === '#') ? TERM_HASHTAG : TERM_MENTION);
+ $termurl = unxmlify(substr($scheme,9));
+ }
+ else {
+ $termtype = TERM_CATEGORY;
+ }
+ $termterm = notags(trim(unxmlify($term)));
+
+ if($termterm) {
+ $terms[] = array(
+ 'otype' => TERM_OBJ_POST,
+ 'ttype' => $termtype,
+ 'url' => $termurl,
+ 'term' => $termterm,
+ );
+ }
+ }
+ }
+
+ if(! is_null($terms))
+ $res['term'] = $terms;
+
+ $attach = $item->get_enclosures();
+ if($attach) {
+ $res['attach'] = array();
+ foreach($attach as $att) {
+ $len = intval($att->get_length());
+ $link = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_link()))));
+ $title = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_title()))));
+ $type = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_type()))));
+ if(strpos($type,';'))
+ $type = substr($type,0,strpos($type,';'));
+ if((! $link) || (strpos($link,'http') !== 0))
+ continue;
+
+ if(! $title)
+ $title = ' ';
+ if(! $type)
+ $type = 'application/octet-stream';
+
+ $res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title );
+ }
+ }
+
+ $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
+
+ if($rawobj) {
+ $obj = array();
+
+ $child = $rawobj[0]['child'];
+ if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) {
+ $res['obj_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
+ }
+ if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
+ $res['obj_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ }
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
+ $obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
+ $obj['link'] = encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']);
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
+ $obj['title'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'];
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
+ $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
+ if(! $body)
+ $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
+ // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
+ $obj['orig'] = xmlify($body);
+ if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
+ $body = purify_html($body);
+ $body = html2bbcode($body);
+ }
+
+ $obj['content'] = $body;
+ }
+
+ $res['obj'] = $obj;
+ }
+
+ $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'target');
+
+ if($rawobj) {
+ $obj = array();
+
+ $child = $rawobj[0]['child'];
+ if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) {
+ $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
+ }
+ if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
+ $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
+ }
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
+ $obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
+ $obj['link'] = encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']);
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
+ $obj['title'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'];
+ if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
+ $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
+ if(! $body)
+ $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
+
+ // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
+ $obj['orig'] = xmlify($body);
+ if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
+ $body = purify_html($body);
+ $body = html2bbcode($body);
+ }
+
+ $obj['content'] = $body;
+ }
+
+ $res['target'] = $obj;
+ }
+
+ $arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
+
+ call_hooks('parse_atom', $arr);
+ logger('get_atom_elements: author: ' . print_r($author,true),LOGGER_DATA);
+
+ logger('get_atom_elements: ' . print_r($res,true),LOGGER_DATA);
+
+ return $res;
+}
+
+function encode_rel_links($links) {
+ $o = array();
+ if(! ((is_array($links)) && (count($links))))
+ return $o;
+
+ foreach($links as $link) {
+ $l = array();
+ if($link['attribs']['']['rel'])
+ $l['rel'] = $link['attribs']['']['rel'];
+ if($link['attribs']['']['type'])
+ $l['type'] = $link['attribs']['']['type'];
+ if($link['attribs']['']['href'])
+ $l['href'] = $link['attribs']['']['href'];
+ if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['width'])
+ $l['width'] = $link['attribs'][NAMESPACE_MEDIA]['width'];
+ if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['height'])
+ $l['height'] = $link['attribs'][NAMESPACE_MEDIA]['height'];
+
+ if($l)
+ $o[] = $l;
+ }
+ return $o;
+}
+
+/**
+ * @brief Process atom feed and update anything/everything we might need to update.
+ *
+ * @param array $xml
+ * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
+ * @param $importer
+ * The contact_record (joined to user_record) of the local user who owns this
+ * relationship. It is this person's stuff that is going to be updated.
+ * @param $contact
+ * The person who is sending us stuff. If not set, we MAY be processing a "follow" activity
+ * from an external network and MAY create an appropriate contact record. Otherwise, we MUST
+ * have a contact record.
+ * @param int $pass by default ($pass = 0) we cannot guarantee that a parent item has been
+ * imported prior to its children being seen in the stream unless we are certain
+ * of how the feed is arranged/ordered.
+ * * With $pass = 1, we only pull parent items out of the stream.
+ * * With $pass = 2, we only pull children (comments/likes).
+ *
+ * So running this twice, first with pass 1 and then with pass 2 will do the right
+ * thing regardless of feed ordering. This won't be adequate in a fully-threaded
+ * model where comments can have sub-threads. That would require some massive sorting
+ * to get all the feed items into a mostly linear ordering, and might still require
+ * recursion.
+ */
+function consume_feed($xml, $importer, &$contact, $pass = 0) {
+
+ require_once('library/simplepie/simplepie.inc');
+
+ if(! strlen($xml)) {
+ logger('consume_feed: empty input');
+ return;
+ }
+
+ $sys_expire = intval(get_config('system','default_expire_days'));
+ $chn_expire = intval($importer['channel_expire_days']);
+
+ $expire_days = $sys_expire;
+
+ if(($chn_expire != 0) && ($chn_expire < $sys_expire))
+ $expire_days = $chn_expire;
+
+ // logger('expire_days: ' . $expire_days);
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($xml);
+ $feed->init();
+
+ if($feed->error())
+ logger('consume_feed: Error parsing XML: ' . $feed->error());
+
+ $permalink = $feed->get_permalink();
+
+ // Check at the feed level for updated contact name and/or photo
+
+ // process any deleted entries
+
+ $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry');
+ if(is_array($del_entries) && count($del_entries) && $pass != 2) {
+ foreach($del_entries as $dentry) {
+ $deleted = false;
+ if(isset($dentry['attribs']['']['ref'])) {
+ $mid = $dentry['attribs']['']['ref'];
+ $deleted = true;
+ if(isset($dentry['attribs']['']['when'])) {
+ $when = $dentry['attribs']['']['when'];
+ $when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
+ }
+ else
+ $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
+ }
+
+ if($deleted && is_array($contact)) {
+ $r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1",
+ dbesc(base64url_encode($mid)),
+ dbesc($contact['xchan_hash']),
+ intval($importer['channel_id'])
+ );
+
+ if($r) {
+ $item = $r[0];
+
+ if(! intval($item['item_deleted'])) {
+ logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG);
+ drop_item($item['id'],false);
+ }
+ }
+ }
+ }
+ }
+
+ // Now process the feed
+
+ if($feed->get_item_quantity()) {
+
+ logger('consume_feed: feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
+
+ $items = $feed->get_items();
+
+ foreach($items as $item) {
+
+ $is_reply = false;
+ $item_id = base64url_encode($item->get_id());
+
+ logger('consume_feed: processing ' . $item_id, LOGGER_DEBUG);
+
+ $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
+ if(isset($rawthread[0]['attribs']['']['ref'])) {
+ $is_reply = true;
+ $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
+ }
+
+ if($is_reply) {
+
+ if($pass == 1)
+ continue;
+
+ // Have we seen it? If not, import it.
+
+ $item_id = base64url_encode($item->get_id());
+ $author = array();
+ $datarray = get_atom_elements($feed,$item,$author);
+
+ if($contact['xchan_network'] === 'rss') {
+ $datarray['public_policy'] = 'specific';
+ $datarray['comment_policy'] = 'none';
+ }
+
+ if((! x($author,'author_name')) || ($author['author_is_feed']))
+ $author['author_name'] = $contact['xchan_name'];
+ if((! x($author,'author_link')) || ($author['author_is_feed']))
+ $author['author_link'] = $contact['xchan_url'];
+ if((! x($author,'author_photo'))|| ($author['author_is_feed']))
+ $author['author_photo'] = $contact['xchan_photo_m'];
+
+ $datarray['author_xchan'] = '';
+
+ if($author['author_link'] != $contact['xchan_url']) {
+ $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo'])));
+ if($x)
+ $datarray['author_xchan'] = $x;
+ }
+ if(! $datarray['author_xchan'])
+ $datarray['author_xchan'] = $contact['xchan_hash'];
+
+ $datarray['owner_xchan'] = $contact['xchan_hash'];
+
+ $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
+ dbesc($item_id),
+ intval($importer['channel_id'])
+ );
+
+
+ // Update content if 'updated' changes
+
+ if($r) {
+ if((x($datarray,'edited') !== false)
+ && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {
+
+ // do not accept (ignore) an earlier edit than one we currently have.
+ if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
+ continue;
+
+ update_feed_item($importer['channel_id'],$datarray);
+ }
+ continue;
+ }
+
+ $datarray['parent_mid'] = $parent_mid;
+ $datarray['aid'] = $importer['channel_account_id'];
+ $datarray['uid'] = $importer['channel_id'];
+
+ logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);
+
+ $xx = item_store($datarray);
+ $r = $xx['item_id'];
+ continue;
+ }
+ else {
+
+ // Head post of a conversation. Have we seen it? If not, import it.
+
+ $item_id = base64url_encode($item->get_id());
+ $author = array();
+ $datarray = get_atom_elements($feed,$item,$author);
+
+ if($contact['xchan_network'] === 'rss') {
+ $datarray['public_policy'] = 'specific';
+ $datarray['comment_policy'] = 'none';
+ }
+
+
+ if(is_array($contact)) {
+ if((! x($author,'author_name')) || ($author['author_is_feed']))
+ $author['author_name'] = $contact['xchan_name'];
+ if((! x($author,'author_link')) || ($author['author_is_feed']))
+ $author['author_link'] = $contact['xchan_url'];
+ if((! x($author,'author_photo'))|| ($author['author_is_feed']))
+ $author['author_photo'] = $contact['xchan_photo_m'];
+ }
+
+ if((! x($author,'author_name')) || (! x($author,'author_link'))) {
+ logger('consume_feed: no author information! ' . print_r($author,true));
+ continue;
+ }
+
+ $datarray['author_xchan'] = '';
+
+ if(activity_match($datarray['verb'],ACTIVITY_FOLLOW) && $datarray['obj_type'] === ACTIVITY_OBJ_PERSON) {
+ $cb = array('item' => $datarray,'channel' => $importer, 'xchan' => null, 'author' => $author, 'caught' => false);
+ call_hooks('follow_from_feed',$cb);
+ if($cb['caught']) {
+ if($cb['return_code'])
+ http_status_exit($cb['return_code']);
+ continue;
+ }
+ }
+
+ if($author['author_link'] != $contact['xchan_url']) {
+ $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo'])));
+ if($x)
+ $datarray['author_xchan'] = $x;
+ }
+ if(! $datarray['author_xchan'])
+ $datarray['author_xchan'] = $contact['xchan_hash'];
+
+ $datarray['owner_xchan'] = $contact['xchan_hash'];
+
+ if(array_key_exists('created',$datarray) && $datarray['created'] != NULL_DATE && $expire_days) {
+ $t1 = $datarray['created'];
+ $t2 = datetime_convert('UTC','UTC','now - ' . $expire_days . 'days');
+ if($t1 < $t2) {
+ logger('feed content older than expiration. Ignoring.', LOGGER_DEBUG, LOG_INFO);
+ continue;
+ }
+ }
+
+
+
+ $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
+ dbesc($item_id),
+ intval($importer['channel_id'])
+ );
+
+ // Update content if 'updated' changes
+
+ if($r) {
+ if((x($datarray,'edited') !== false)
+ && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {
+
+ // do not accept (ignore) an earlier edit than one we currently have.
+ if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
+ continue;
+
+ update_feed_item($importer['channel_id'],$datarray);
+ }
+
+ continue;
+ }
+
+ $datarray['parent_mid'] = $item_id;
+ $datarray['uid'] = $importer['channel_id'];
+ $datarray['aid'] = $importer['channel_account_id'];
+
+ if(! link_compare($author['owner_link'],$contact['xchan_url'])) {
+ logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
+ $author['owner_name'] = $contact['name'];
+ $author['owner_link'] = $contact['url'];
+ $author['owner_avatar'] = $contact['thumb'];
+ }
+
+ if(! post_is_importable($datarray,$contact))
+ continue;
+
+ logger('consume_feed: author ' . print_r($author,true),LOGGER_DEBUG);
+
+ logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);
+
+ $xx = item_store($datarray);
+ $r = $xx['item_id'];
+ continue;
+ }
+ }
+ }
+}
+
+
+/**
+ * @brief Process atom feed and return the first post and structure
+ *
+ * @param array $xml
+ * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
+ * @param $importer
+ * The contact_record (joined to user_record) of the local user who owns this
+ * relationship. It is this person's stuff that is going to be updated.
+ */
+
+function process_salmon_feed($xml, $importer) {
+
+ $ret = array();
+
+ require_once('library/simplepie/simplepie.inc');
+
+ if(! strlen($xml)) {
+ logger('process_feed: empty input');
+ return;
+ }
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($xml);
+ $feed->init();
+
+ if($feed->error())
+ logger('Error parsing XML: ' . $feed->error());
+
+ $permalink = $feed->get_permalink();
+
+ if($feed->get_item_quantity()) {
+
+ // this should be exactly one
+
+ logger('feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
+
+ $items = $feed->get_items();
+
+ foreach($items as $item) {
+
+ $item_id = base64url_encode($item->get_id());
+
+ logger('processing ' . $item_id, LOGGER_DEBUG);
+
+ $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
+ if(isset($rawthread[0]['attribs']['']['ref'])) {
+ $is_reply = true;
+ $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
+ }
+
+ if($is_reply)
+ $ret['parent_mid'] = $parent_mid;
+
+ $ret['author'] = array();
+
+ $datarray = get_atom_elements($feed,$item,$ret['author']);
+
+ // reset policies which are restricted by default for RSS connections
+ // This item is likely coming from GNU-social via salmon and allows public interaction
+ $datarray['public_policy'] = '';
+ $datarray['comment_policy'] = '';
+
+ $ret['item'] = $datarray;
+ }
+ }
+
+ return $ret;
+}
+
+/*
+ * Given an xml (atom) feed, find author and hub links
+ */
+
+
+function feed_meta($xml) {
+ require_once('library/simplepie/simplepie.inc');
+
+ $ret = array();
+
+ if(! strlen($xml)) {
+ logger('empty input');
+ return $ret;
+ }
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($xml);
+ $feed->init();
+
+ if($feed->error()) {
+ logger('Error parsing XML: ' . $feed->error());
+ return $ret;
+ }
+
+ $ret['hubs'] = $feed->get_links('hub');
+
+// logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA);
+
+ $author = array();
+
+ $found_author = $feed->get_author();
+ if($found_author) {
+ $author['author_name'] = unxmlify($found_author->get_name());
+ $author['author_link'] = unxmlify($found_author->get_link());
+
+ $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
+ logger('rawauthor: ' . print_r($rawauthor,true));
+
+ if($rawauthor) {
+ if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
+ $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
+ foreach($base as $link) {
+ if(!x($author, 'author_photo') || ! $author['author_photo']) {
+ if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') {
+ $author['author_photo'] = unxmlify($link['attribs']['']['href']);
+ break;
+ }
+ }
+ }
+ }
+ if($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data'])
+ $author['full_name'] = unxmlify($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data']);
+ if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
+ $author['author_uri'] = unxmlify($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
+
+ }
+ }
+
+ if(substr($author['author_link'],-1,1) == '/')
+ $author['author_link'] = substr($author['author_link'],0,-1);
+
+ $ret['author'] = $author;
+
+ return $ret;
+}
+
+
+
+function update_feed_item($uid,$datarray) {
+ logger('update_feed_item: not implemented! ' . $uid . ' ' . print_r($datarray,true), LOGGER_DATA);
+}
+
+
+function handle_feed($uid,$abook_id,$url) {
+
+ $channel = channelx_by_n($uid);
+ if(! $channel)
+ return;
+
+ $x = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d limit 1",
+ dbesc($abook_id),
+ intval($uid)
+ );
+
+ $recurse = 0;
+ $z = z_fetch_url($url,false,$recurse,array('novalidate' => true));
+
+//logger('handle_feed:' . print_r($z,true));
+
+ if($z['success']) {
+ consume_feed($z['body'],$channel,$x[0],1);
+ consume_feed($z['body'],$channel,$x[0],2);
+ }
+}
+
+
+function atom_author($tag,$name,$uri,$h,$w,$type,$photo) {
+ $o = '';
+ if(! $tag)
+ return $o;
+
+ $name = xmlify($name);
+ $uri = xmlify($uri);
+ $h = intval($h);
+ $w = intval($w);
+ $photo = xmlify($photo);
+
+ $o .= "<$tag>\r\n";
+ $o .= "<name>$name</name>\r\n";
+ $o .= "<uri>$uri</uri>\r\n";
+ $o .= '<link rel="photo" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
+ $o .= '<link rel="avatar" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
+
+ call_hooks('atom_author', $o);
+
+ $o .= "</$tag>\r\n";
+
+ return $o;
+}
+
+function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
+
+ if(! $item['parent'])
+ return;
+
+ if($item['deleted'])
+ return '<at:deleted-entry ref="' . xmlify($item['mid']) . '" when="' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '" />' . "\r\n";
+
+
+ create_export_photo_body($item);
+
+ if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid'])
+ $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid);
+ else
+ $body = $item['body'];
+
+ $o = "\r\n\r\n<entry>\r\n";
+
+ if(is_array($author))
+ $o .= atom_author('author',$author['xchan_name'],$author['xchan_url'],80,80,$author['xchan_photo_mimetype'],$author['xchan_photo_m']);
+ else
+ $o .= atom_author('author',$item['author']['xchan_name'],$item['author']['xchan_url'],80,80,$item['author']['xchan_photo_mimetype'], $item['author']['xchan_photo_m']);
+
+ $o .= atom_author('zot:owner',$item['owner']['xchan_name'],$item['owner']['xchan_url'],80,80,$item['owner']['xchan_photo_mimetype'],$item['owner']['xchan_photo_m']);
+
+ if(($item['parent'] != $item['id']) || ($item['parent_mid'] !== $item['mid']) || (($item['thr_parent'] !== '') && ($item['thr_parent'] !== $item['mid']))) {
+ $parent_item = (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']);
+ $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+ }
+
+ if(activity_match($item['obj_type'],ACTIVITY_OBJ_EVENT) && activity_match($item['verb'],ACTIVITY_POST)) {
+ $obj = ((is_array($item['obj'])) ? $item['obj'] : json_decode($item['obj'],true));
+
+ $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
+ $o .= '<summary xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
+ $o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['dtstart'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtstart>' . "\r\n";
+ $o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['dtend'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtend>' . "\r\n";
+ $o .= '<location xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['location'])) . '</location>' . "\r\n";
+ $o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n";
+ }
+ else {
+ $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
+ $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
+ }
+
+ $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n";
+ $o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n";
+ $o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n";
+
+ $o .= '<link rel="alternate" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+
+ if($item['location']) {
+ $o .= '<zot:location>' . xmlify($item['location']) . '</zot:location>' . "\r\n";
+ $o .= '<poco:address><poco:formatted>' . xmlify($item['location']) . '</poco:formatted></poco:address>' . "\r\n";
+ }
+
+ if($item['coord'])
+ $o .= '<georss:point>' . xmlify($item['coord']) . '</georss:point>' . "\r\n";
+
+ if(($item['item_private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
+ $o .= '<zot:private>' . (($item['item_private']) ? $item['item_private'] : 1) . '</zot:private>' . "\r\n";
+
+ if($item['app'])
+ $o .= '<statusnet:notice_info local_id="' . $item['id'] . '" source="' . xmlify($item['app']) . '" ></statusnet:notice_info>' . "\r\n";
+
+ $verb = construct_verb($item);
+ $o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n";
+ $actobj = construct_activity_object($item);
+ if(strlen($actobj))
+ $o .= $actobj;
+ $actarg = construct_activity_target($item);
+ if(strlen($actarg))
+ $o .= $actarg;
+
+ // FIXME
+// $tags = item_getfeedtags($item);
+// if(count($tags)) {
+// foreach($tags as $t) {
+// $o .= '<category scheme="X-DFRN:' . xmlify($t[0]) . ':' . xmlify($t[1]) . '" term="' . xmlify($t[2]) . '" />' . "\r\n";
+// }
+// }
+
+// FIXME
+// $o .= item_getfeedattach($item);
+
+// $mentioned = get_mentions($item,$tags);
+// if($mentioned)
+// $o .= $mentioned;
+
+ call_hooks('atom_entry', $o);
+
+ $o .= '</entry>' . "\r\n";
+
+ return $o;
+}
+
+
+function gen_asld($items) {
+ $ret = array();
+ if(! $items)
+ return $ret;
+ foreach($items as $item) {
+ $ret[] = i2asld($item);
+ }
+ return $ret;
+}
+
+
+function i2asld($i) {
+
+ if(! $i)
+ return array();
+
+ $ret = array();
+
+ $ret['@context'] = array( 'http://www.w3.org/ns/activitystreams', 'zot' => 'http://purl.org/zot/protocol');
+
+ if($i['verb']) {
+ if(strpos(dirname($i['verb'],'activitystrea.ms/schema/1.0'))) {
+ $ret['@type'] = ucfirst(basename($i['verb']));
+ }
+ elseif(strpos(dirname($i['verb'],'purl.org/zot'))) {
+ $ret['@type'] = 'zot:' . ucfirst(basename($i['verb']));
+ }
+ }
+ $ret['@id'] = $i['plink'];
+
+ $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
+
+ // we need to pass the parent into this
+// if($i['id'] != $i['parent'] && $i['obj_type'] === ACTIVITY_OBJ_NOTE) {
+// $ret['inReplyTo'] = asencode_note
+// }
+
+ if($i['obj_type'] === ACTIVITY_OBJ_NOTE)
+ $ret['object'] = asencode_note($i);
+
+
+ $ret['actor'] = asencode_person($i['author']);
+
+
+ return $ret;
+
+}
+
+function asencode_note($i) {
+
+ $ret = array();
+
+ $ret['@type'] = 'Note';
+ $ret['@id'] = $i['plink'];
+ if($i['title'])
+ $ret['title'] = bbcode($i['title']);
+ $ret['content'] = bbcode($i['body']);
+ $ret['zot:owner'] = asencode_person($i['owner']);
+ $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
+ if($i['created'] !== $i['edited'])
+ $ret['updated'] = datetime_convert('UTC','UTC',$i['edited'],ATOM_TIME);
+
+ return $ret;
+}
+
+
+function asencode_person($p) {
+ $ret = array();
+ $ret['@type'] = 'Person';
+ $ret['@id'] = 'acct:' . $p['xchan_addr'];
+ $ret['displayName'] = $p['xchan_name'];
+ $ret['icon'] = array(
+ '@type' => 'Link',
+ 'mediaType' => $p['xchan_photo_mimetype'],
+ 'href' => $p['xchan_photo_m']
+ );
+ $ret['url'] = array(
+ '@type' => 'Link',
+ 'mediaType' => 'text/html',
+ 'href' => $p['xchan_url']
+ );
+
+ return $ret;
+}
diff --git a/include/follow.php b/include/follow.php
index 70e717cfc..5f63687f8 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -17,7 +17,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$result = array('success' => false,'message' => '');
- $a = get_app();
$is_red = false;
$is_http = ((strpos($url,'://') !== false) ? true : false);
@@ -56,23 +55,22 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if($arr['channel']['success'])
$ret = $arr['channel'];
elseif(! $is_http)
- $ret = zot_finger($url,$channel);
+ $ret = Zotlabs\Zot\Finger::run($url,$channel);
- if($ret && $ret['success']) {
+ if($ret && is_array($ret) && $ret['success']) {
$is_red = true;
- $j = json_decode($ret['body'],true);
+ $j = $ret;
}
$my_perms = get_channel_default_perms($uid);
$role = get_pconfig($uid,'system','permissions_role');
if($role) {
- $x = get_role_perms($role);
- if($x['perms_follow'])
- $my_perms = $x['perms_follow'];
+ $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
+ if($x['perms_connect'])
+ $my_perms = $x['perms_connect'];
}
-
if($is_red && $j) {
logger('follow: ' . $url . ' ' . print_r($j,true), LOGGER_DEBUG);
@@ -105,10 +103,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$xchan_hash = $x['hash'];
- $their_perms = 0;
-
- $global_perms = get_perms();
-
if( array_key_exists('permissions',$j) && array_key_exists('data',$j['permissions'])) {
$permissions = crypto_unencapsulate(array(
'data' => $j['permissions']['data'],
@@ -122,16 +116,14 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
else
$permissions = $j['permissions'];
-
- foreach($permissions as $k => $v) {
- if($v) {
- $their_perms = $their_perms | intval($global_perms[$k][1]);
+ if(is_array($permissions) && $permissions) {
+ foreach($permissions as $k => $v) {
+ set_abconfig($channel['channel_uid'],$xchan_hash,'their_perms',$k,intval($v));
}
}
}
else {
- $their_perms = 0;
$xchan_hash = '';
$r = q("select * from xchan where xchan_hash = '%s' or xchan_url = '%s' limit 1",
@@ -191,6 +183,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$result['message'] = t('Protocol disabled.');
return $result;
}
+
$singleton = intval($x['singleton']);
$aid = $channel['channel_account_id'];
@@ -223,6 +216,15 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
intval($uid)
);
+ if($is_http) {
+
+ // Always set these "remote" permissions for feeds since we cannot interact with them
+ // to negotiate a suitable permission response
+
+ set_abconfig($uid,$xchan_hash,'their_perms','view_stream',1);
+ set_abconfig($uid,$xchan_hash,'their_perms','republish',1);
+ }
+
if($r) {
$abook_instance = $r[0]['abook_instance'];
@@ -232,8 +234,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$abook_instance .= z_root();
}
- $x = q("update abook set abook_their_perms = %d, abook_instance = '%s' where abook_id = %d",
- intval($their_perms),
+ $x = q("update abook set abook_instance = '%s' where abook_id = %d",
dbesc($abook_instance),
intval($r[0]['abook_id'])
);
@@ -243,15 +244,13 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if($closeness === false)
$closeness = 80;
- $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_instance )
- values( %d, %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s' ) ",
+ $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_created, abook_updated, abook_instance )
+ values( %d, %d, %d, '%s', %d, '%s', '%s', '%s' ) ",
intval($aid),
intval($uid),
intval($closeness),
dbesc($xchan_hash),
intval(($is_http) ? 1 : 0),
- intval(($is_http) ? $their_perms|PERMS_R_STREAM|PERMS_A_REPUBLISH : $their_perms),
- intval($my_perms),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(($singleton) ? z_root() : '')
@@ -261,6 +260,16 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if(! $r)
logger('mod_follow: abook creation failed');
+ $all_perms = \Zotlabs\Access\Permissions::Perms();
+ if($all_perms) {
+ foreach($all_perms as $k => $v) {
+ if(in_array($k,$my_perms))
+ set_abconfig($uid,$xchan_hash,'my_perms',$k,1);
+ else
+ set_abconfig($uid,$xchan_hash,'my_perms',$k,0);
+ }
+ }
+
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($xchan_hash),
@@ -269,14 +278,14 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if($r) {
$result['abook'] = $r[0];
- proc_run('php', 'include/notifier.php', 'permission_create', $result['abook']['abook_id']);
+ Zotlabs\Daemon\Master::Summon(array('Notifier', 'permission_create', $result['abook']['abook_id']));
}
$arr = array('channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook']);
call_hooks('follow', $arr);
- /** If there is a default group for this channel, add this member to it */
+ /** If there is a default group for this channel, add this connection to it */
if($default_group) {
require_once('include/group.php');
diff --git a/include/gprobe.php b/include/gprobe.php
deleted file mode 100644
index d8d893d9e..000000000
--- a/include/gprobe.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php /** @file */
-
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-
-function gprobe_run($argv, $argc){
-
- cli_startup();
-
- $a = get_app();
-
- if($argc != 2)
- return;
-
- $url = hex2bin($argv[1]);
-
- if(! strpos($url,'@'))
- return;
-
- $r = q("select * from xchan where xchan_addr = '%s' limit 1",
- dbesc($url)
- );
-
- if(! $r) {
- $x = zot_finger($url,null);
- if($x['success']) {
- $j = json_decode($x['body'],true);
- $y = import_xchan($j);
- }
- }
-
- return;
-}
-
-if (array_search(__file__,get_included_files())===0){
- gprobe_run($argv,$argc);
- killme();
-}
diff --git a/include/group.php b/include/group.php
index 748ec0c13..10853ff6b 100644
--- a/include/group.php
+++ b/include/group.php
@@ -17,8 +17,8 @@ function group_add($uid,$name,$public = 0) {
$z = q("SELECT * FROM `groups` WHERE `id` = %d LIMIT 1",
intval($r)
);
- if(count($z) && $z[0]['deleted']) {
- /*$r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ if(($z) && $z[0]['deleted']) {
+ /*$r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `gname` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);*/
@@ -38,7 +38,7 @@ function group_add($uid,$name,$public = 0) {
} while($dups == true);
- $r = q("INSERT INTO `groups` ( hash, uid, visible, name )
+ $r = q("INSERT INTO `groups` ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -57,7 +57,7 @@ function group_add($uid,$name,$public = 0) {
function group_rmv($uid,$name) {
$ret = false;
if(x($uid) && x($name)) {
- $r = q("SELECT id, hash FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("SELECT id, hash FROM `groups` WHERE `uid` = %d AND `gname` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -108,7 +108,7 @@ function group_rmv($uid,$name) {
);
// remove group
- $r = q("UPDATE `groups` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s'",
+ $r = q("UPDATE `groups` SET `deleted` = 1 WHERE `uid` = %d AND `gname` = '%s'",
intval($uid),
dbesc($name)
);
@@ -125,11 +125,11 @@ function group_rmv($uid,$name) {
function group_byname($uid,$name) {
if((! $uid) || (! strlen($name)))
return false;
- $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `gname` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
- if(count($r))
+ if($r)
return $r[0]['id'];
return false;
}
@@ -178,11 +178,11 @@ function group_add_member($uid,$name,$member,$gid = 0) {
intval($gid),
dbesc($member)
);
- if(count($r))
+ if($r)
return true; // You might question this, but
// we indicate success because the group member was in fact created
// -- It was just created at another time
- if(! count($r))
+ if(! $r)
$r = q("INSERT INTO `group_member` (`uid`, `gid`, `xchan`)
VALUES( %d, %d, '%s' ) ",
intval($uid),
@@ -205,7 +205,7 @@ function group_get_members($gid) {
intval(local_channel()),
intval(local_channel())
);
- if(count($r))
+ if($r)
$ret = $r;
}
return $ret;
@@ -218,7 +218,7 @@ function group_get_members_xchan($gid) {
intval($gid),
intval(local_channel())
);
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
$ret[] = $rr['xchan'];
}
@@ -232,13 +232,13 @@ function mini_group_select($uid,$group = '') {
$grps = array();
$o = '';
- $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `gname` ASC",
intval($uid)
);
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
- $grps[] = array('name' => $rr['name'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
+ $grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
}
}
@@ -271,7 +271,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
);
- $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `gname` ASC",
intval($_SESSION['uid'])
);
$member_of = array();
@@ -279,7 +279,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$member_of = groups_containing(local_channel(),$cid);
}
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
@@ -296,7 +296,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
'id' => $rr['id'],
'enc_cid' => base64url_encode($cid),
'cid' => $cid,
- 'text' => $rr['name'],
+ 'text' => $rr['gname'],
'selected' => $selected,
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
'edit' => $groupedit,
@@ -340,7 +340,7 @@ function expand_groups($a) {
function member_of($c) {
- $r = q("SELECT `groups`.`name`, `groups`.`id` FROM `groups` LEFT JOIN `group_member` ON `group_member`.`gid` = `groups`.`id` WHERE `group_member`.`xchan` = '%s' AND `groups`.`deleted` = 0 ORDER BY `groups`.`name` ASC ",
+ $r = q("SELECT `groups`.`gname`, `groups`.`id` FROM `groups` LEFT JOIN `group_member` ON `group_member`.`gid` = `groups`.`id` WHERE `group_member`.`xchan` = '%s' AND `groups`.`deleted` = 0 ORDER BY `groups`.`gname` ASC ",
dbesc($c)
);
@@ -356,7 +356,7 @@ function groups_containing($uid,$c) {
);
$ret = array();
- if(count($r)) {
+ if($r) {
foreach($r as $rr)
$ret[] = $rr['gid'];
}
diff --git a/include/help.php b/include/help.php
new file mode 100644
index 000000000..7f57f3334
--- /dev/null
+++ b/include/help.php
@@ -0,0 +1,149 @@
+<?php
+
+function load_doc_file($s) {
+ $lang = \App::$language;
+ if(! isset($lang))
+ $lang = 'en';
+ $b = basename($s);
+ $d = dirname($s);
+
+ $c = find_doc_file("$d/$lang/$b");
+ if($c)
+ return $c;
+ $c = find_doc_file($s);
+ if($c)
+ return $c;
+ return '';
+}
+
+function find_doc_file($s) {
+ if(file_exists($s))
+ return file_get_contents($s);
+ return '';
+}
+
+function search_doc_files($s) {
+
+ $itemspage = get_pconfig(local_channel(),'system','itemspage');
+ \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
+ $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
+
+ $regexop = db_getfunc('REGEXP');
+
+ $r = q("select iconfig.v, item.* from item left join iconfig on item.id = iconfig.iid
+ where iconfig.cat = 'system' and iconfig.k = 'docfile' and
+ body $regexop '%s' and item_type = %d $pager_sql",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ $r = fetch_post_tags($r,true);
+
+ for($x = 0; $x < count($r); $x ++) {
+
+ $r[$x]['text'] = $r[$x]['body'];
+
+ $r[$x]['rank'] = 0;
+ if($r[$x]['term']) {
+ foreach($r[$x]['term'] as $t) {
+ if(stristr($t['term'],$s)) {
+ $r[$x]['rank'] ++;
+ }
+ }
+ }
+ if(stristr($r[$x]['v'],$s))
+ $r[$x]['rank'] ++;
+ $r[$x]['rank'] += substr_count(strtolower($r[$x]['text']),strtolower($s));
+ // bias the results to the observer's native language
+ if($r[$x]['lang'] === \App::$language)
+ $r[$x]['rank'] = $r[$x]['rank'] + 10;
+
+ }
+ usort($r,'doc_rank_sort');
+ return $r;
+}
+
+
+function doc_rank_sort($s1,$s2) {
+ if($s1['rank'] == $s2['rank'])
+ return 0;
+ return (($s1['rank'] < $s2['rank']) ? 1 : (-1));
+}
+
+
+function load_context_help() {
+
+ $path = App::$cmd;
+ $args = App::$argv;
+ $lang = App::$language;
+
+ if(! isset($lang) || !is_dir('doc/context/' . $lang . '/')) {
+ $lang = 'en';
+ }
+ while($path) {
+ $context_help = load_doc_file('doc/context/' . $lang . '/' . $path . '/help.html');
+ if(!$context_help) {
+ // Fallback to English if the translation is absent
+ $context_help = load_doc_file('doc/context/en/' . $path . '/help.html');
+ }
+ if($context_help)
+ break;
+ array_pop($args);
+ $path = implode($args,'/');
+ }
+
+ return $context_help;
+}
+
+
+function store_doc_file($s) {
+
+ if(is_dir($s))
+ return;
+
+ $item = array();
+ $sys = get_sys_channel();
+
+ $item['aid'] = 0;
+ $item['uid'] = $sys['channel_id'];
+
+
+ if(strpos($s,'.md'))
+ $mimetype = 'text/markdown';
+ elseif(strpos($s,'.html'))
+ $mimetype = 'text/html';
+ else
+ $mimetype = 'text/bbcode';
+
+ require_once('include/html2plain.php');
+
+ $item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, true));
+ $item['mimetype'] = 'text/plain';
+
+ $item['plink'] = z_root() . '/' . str_replace('doc','help',$s);
+ $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
+ $item['item_type'] = ITEM_TYPE_DOC;
+
+ $r = q("select item.* from item left join iconfig on item.id = iconfig.iid
+ where iconfig.cat = 'system' and iconfig.k = 'docfile' and
+ iconfig.v = '%s' and item_type = %d limit 1",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ \Zotlabs\Lib\IConfig::Set($item,'system','docfile',$s);
+
+ if($r) {
+ $item['id'] = $r[0]['id'];
+ $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
+ $x = item_store_update($item);
+ }
+ else {
+ $item['mid'] = $item['parent_mid'] = item_message_id();
+ $x = item_store($item);
+ }
+
+ return $x;
+
+}
+
diff --git a/include/hubloc.php b/include/hubloc.php
index 695cada3c..397646449 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -106,7 +106,7 @@ function remove_obsolete_hublocs() {
dbesc($rr['hubloc_hash'])
);
if($x) {
- proc_run('php','include/notifier.php','location',$x[0]['channel_id']);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','location',$x[0]['channel_id']));
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
diff --git a/include/import.php b/include/import.php
index 3b5c8508c..42c902a0a 100644
--- a/include/import.php
+++ b/include/import.php
@@ -1,6 +1,7 @@
<?php
require_once('include/menu.php');
+require_once('include/perm_upgrade.php');
function import_channel($channel, $account_id, $seize) {
@@ -9,15 +10,21 @@ function import_channel($channel, $account_id, $seize) {
$channel['channel_removed'] = (($channel['channel_pageflags'] & 0x8000) ? 1 : 0);
}
+ // Ignore the hash provided and re-calculate
+
+ $channel['channel_hash'] = make_xchan_hash($channel['channel_guid'],$channel['channel_guid_sig']);
+
+ // Check for duplicate channels
+
$r = q("select * from channel where (channel_guid = '%s' or channel_hash = '%s' or channel_address = '%s' ) limit 1",
dbesc($channel['channel_guid']),
dbesc($channel['channel_hash']),
dbesc($channel['channel_address'])
);
+ if($r && $r[0]['channel_guid'] == $channel['channel_guid'] && $r[0]['channel_pubkey'] === $channel['channel_pubkey'] && $r[0]['channel_hash'] === $channel['channel_hash'])
+ return $r[0];
- // We should probably also verify the hash
-
- if($r) {
+ if(($r) || (check_webbie(array($channel['channel_address'])) !== $channel['channel_address'])) {
if($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) {
logger('mod_import: duplicate channel. ', print_r($channel,true));
notice( t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL);
@@ -55,15 +62,35 @@ function import_channel($channel, $account_id, $seize) {
if(! is_site_admin())
$channel['channel_pageflags'] = $channel['channel_pageflags'] ^ PAGE_ALLOWCODE;
}
-
- dbesc_array($channel);
- $r = dbq("INSERT INTO channel (`"
- . implode("`, `", array_keys($channel))
- . "`) VALUES ('"
- . implode("', '", array_values($channel))
- . "')"
- );
+ // remove all the permissions related settings, we will import/upgrade them after the channel
+ // is created.
+
+ $disallowed = [
+ 'channel_id', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
+ 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
+ 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
+ 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
+ 'channel_a_delegate', 'perm_limits'
+ ];
+
+ $clean = array();
+ foreach($channel as $k => $v) {
+ if(in_array($k,$disallowed))
+ continue;
+ $clean[$k] = $v;
+ }
+
+ if($clean) {
+ dbesc_array($clean);
+
+ $r = dbq("INSERT INTO channel (`"
+ . implode("`, `", array_keys($clean))
+ . "`) VALUES ('"
+ . implode("', '", array_values($clean))
+ . "')"
+ );
+ }
if(! $r) {
logger('mod_import: channel clone failed. ', print_r($channel,true));
@@ -80,13 +107,20 @@ function import_channel($channel, $account_id, $seize) {
notice( t('Cloned channel not found. Import failed.') . EOL);
return false;
}
+
+ // extract the permissions from the original imported array and use our new channel_id to set them
+ // These could be in the old channel permission stule or the new pconfig. We have a function to
+ // translate and store them no matter which they throw at us.
+
+ $channel['channel_id'] = $r[0]['channel_id'];
+ translate_channel_perms_inbound($channel);
+
// reset
$channel = $r[0];
set_default_login_identity($account_id,$channel['channel_id'],false);
logger('import step 1');
$_SESSION['import_step'] = 1;
- ref_session_write(session_id(), serialize($_SESSION));
return $channel;
}
@@ -117,6 +151,11 @@ function import_profiles($channel,$profiles) {
$profile['aid'] = get_account_id();
$profile['uid'] = $channel['channel_id'];
+ convert_oldfields($profile,'name','fullname');
+ convert_oldfields($profile,'with','partner');
+ convert_oldfields($profile,'work','employment');
+
+
// we are going to reset all profile photos to the original
// somebody will have to fix this later and put all the applicable photos into the export
@@ -297,8 +336,11 @@ function import_apps($channel,$apps) {
if($channel && $apps) {
foreach($apps as $app) {
+ $term = ((array_key_exists('term',$app) && is_array($app['term'])) ? $app['term'] : null);
+
unset($app['id']);
unset($app['app_channel']);
+ unset($app['term']);
$app['app_channel'] = $channel['channel_id'];
@@ -307,6 +349,8 @@ function import_apps($channel,$apps) {
$app['app_photo'] = $x[0];
}
+ $hash = $app['app_id'];
+
dbesc_array($app);
$r = dbq("INSERT INTO app (`"
. implode("`, `", array_keys($app))
@@ -314,6 +358,23 @@ function import_apps($channel,$apps) {
. implode("', '", array_values($app))
. "')"
);
+
+ if($term) {
+ $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
+ dbesc($hash),
+ intval($channel['channel_id'])
+ );
+ if($x) {
+ foreach($term as $t) {
+ if(array_key_exists('type',$t))
+ $t['ttype'] = $t['type'];
+ store_item_tag($channel['channel_id'],$x[0]['id'],TERM_OBJ_APP,$t['ttype'],escape_tags($t['term']),escape_tags($t['url']));
+ }
+ }
+ }
+
+
+
}
}
}
@@ -325,16 +386,41 @@ function sync_apps($channel,$apps) {
if($channel && $apps) {
foreach($apps as $app) {
- if(array_key_exists('app_deleted',$app) && $app['app_deleted'] && $app['app_id']) {
+ $exists = false;
+ $term = ((array_key_exists('term',$app)) ? $app['term'] : null);
+
+ $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
+ dbesc($app['app_id']),
+ intval($channel['channel_id'])
+ );
+ if($x) {
+ $exists = $x[0];
+ }
+
+ if(array_key_exists('app_deleted',$app) && $app['app_deleted'] && $app['app_id']) {
q("delete from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($app['app_id']),
intval($channel['channel_id'])
);
+ if($exists) {
+ q("delete from term where otype = %d and oid = %d",
+ intval(TERM_OBJ_APP),
+ intval($exists['id'])
+ );
+ }
continue;
}
unset($app['id']);
unset($app['app_channel']);
+ unset($app['term']);
+
+ if($exists) {
+ q("delete from term where otype = %d and oid = %d",
+ intval(TERM_OBJ_APP),
+ intval($exists['id'])
+ );
+ }
if(! $app['app_created'] || $app['app_created'] === NULL_DATE)
$app['app_created'] = datetime_convert();
@@ -348,16 +434,17 @@ function sync_apps($channel,$apps) {
$app['app_photo'] = $x[0];
}
- $exists = false;
+ if($exists && $term) {
+ foreach($term as $t) {
+ if(array_key_exists('type',$t))
+ $t['ttype'] = $t['type'];
+ store_item_tag($channel['channel_id'],$exists['id'],TERM_OBJ_APP,$t['ttype'],escape_tags($t['term']),escape_tags($t['url']));
+ }
+ }
- $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
- dbesc($app['app_id']),
- intval($channel['channel_id'])
- );
- if($x) {
- if($x[0]['app_edited'] >= $app['app_edited'])
+ if($exists) {
+ if($exists['app_edited'] >= $app['app_edited'])
continue;
- $exists = true;
}
$hash = $app['app_id'];
@@ -380,6 +467,19 @@ function sync_apps($channel,$apps) {
. implode("', '", array_values($app))
. "')"
);
+ if($term) {
+ $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
+ dbesc($hash),
+ intval($channel['channel_id'])
+ );
+ if($x) {
+ foreach($term as $t) {
+ if(array_key_exists('type',$t))
+ $t['ttype'] = $t['type'];
+ store_item_tag($channel['channel_id'],$x[0]['id'],TERM_OBJ_APP,$t['ttype'],escape_tags($t['term']),escape_tags($t['url']));
+ }
+ }
+ }
}
}
}
@@ -482,7 +582,7 @@ function sync_chatrooms($channel,$chatrooms) {
-function import_items($channel,$items) {
+function import_items($channel,$items,$sync = false,$relocate = null) {
if($channel && $items) {
$allow_code = false;
@@ -499,20 +599,28 @@ function import_items($channel,$items) {
$deliver = false; // Don't deliver any messages or notifications when importing
foreach($items as $i) {
+ $item_result = false;
$item = get_item_elements($i,$allow_code);
if(! $item)
continue;
+ if($relocate && $item['mid'] === $item['parent_mid']) {
+ item_url_replace($channel,$item,$relocate['url'],z_root(),$relocate['channel_address']);
+ }
+
$r = q("select id, edited from item where mid = '%s' and uid = %d limit 1",
dbesc($item['mid']),
intval($channel['channel_id'])
);
if($r) {
- if($item['edited'] > $r[0]['edited']) {
+
+ // flags may have changed and we are probably relocating the post,
+ // so force an update even if we have the same timestamp
+
+ if($item['edited'] >= $r[0]['edited']) {
$item['id'] = $r[0]['id'];
$item['uid'] = $channel['channel_id'];
- item_store_update($item,$allow_code,$deliver);
- continue;
+ $item_result = item_store_update($item,$allow_code,$deliver);
}
}
else {
@@ -520,13 +628,20 @@ function import_items($channel,$items) {
$item['uid'] = $channel['channel_id'];
$item_result = item_store($item,$allow_code,$deliver);
}
+
+ if($sync && $item['item_wall']) {
+ // deliver singletons if we have any
+ if($item_result && $item_result['success']) {
+ Zotlabs\Daemon\Master::Summon( [ 'Notifier','single_activity',$item_result['item_id'] ]);
+ }
+ }
}
}
}
-function sync_items($channel,$items) {
- import_items($channel,$items);
+function sync_items($channel,$items,$relocate = null) {
+ import_items($channel,$items,true,$relocate);
}
@@ -540,19 +655,14 @@ function import_item_ids($channel,$itemids) {
);
if(! $r)
continue;
- $z = q("select * from item_id where service = '%s' and sid = '%s' and iid = %d and uid = %d limit 1",
+ $z = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = '%s'
+ and iconfig.v = '%s' and iid = %d limit 1",
dbesc($i['service']),
dbesc($i['sid']),
- intval($r[0]['id']),
- intval($channel['channel_id'])
+ intval($r[0]['id'])
);
if(! $z) {
- q("insert into item_id (iid,uid,sid,service) values(%d,%d,'%s','%s')",
- intval($r[0]['id']),
- intval($channel['channel_id']),
- dbesc($i['sid']),
- dbesc($i['service'])
- );
+ \Zotlabs\Lib\IConfig::Set($r[0]['id'],'system',$i['service'],$i['sid'],true);
}
}
}
@@ -565,6 +675,10 @@ function import_events($channel,$events) {
unset($event['id']);
$event['aid'] = $channel['channel_account_id'];
$event['uid'] = $channel['channel_id'];
+ convert_oldfields($event,'start','dtstart');
+ convert_oldfields($event,'finish','dtend');
+ convert_oldfields($event,'type','etype');
+ convert_oldfields($event,'ignore','dismissed');
dbesc_array($event);
$r = dbq("INSERT INTO event (`"
@@ -598,6 +712,12 @@ function sync_events($channel,$events) {
$event['aid'] = $channel['channel_account_id'];
$event['uid'] = $channel['channel_id'];
+ convert_oldfields($event,'start','dtstart');
+ convert_oldfields($event,'finish','dtend');
+ convert_oldfields($event,'type','etype');
+ convert_oldfields($event,'ignore','dismissed');
+
+
$exists = false;
$x = q("select * from event where event_hash = '%s' and uid = %d limit 1",
@@ -839,7 +959,7 @@ function import_conv($channel,$convs) {
-function import_mail($channel,$mails) {
+function import_mail($channel,$mails,$sync = false) {
if($channel && $mails) {
foreach($mails as $mail) {
if(array_key_exists('flags',$mail) && in_array('deleted',$mail['flags'])) {
@@ -863,12 +983,17 @@ function import_mail($channel,$mails) {
$m['aid'] = $channel['channel_account_id'];
$m['uid'] = $channel['channel_id'];
- mail_store($m);
+ $mail_id = mail_store($m);
+ if($sync && $mail_id) {
+ Zotlabs\Daemon\Master::Summon(array('Notifier','single_mail',$mail_id));
+ }
}
}
}
-
+function sync_mail($channel,$mails) {
+ import_mail($channel,$mails,true);
+}
function sync_files($channel,$files) {
@@ -890,6 +1015,8 @@ function sync_files($channel,$files) {
$attachment_stored = false;
foreach($f['attach'] as $att) {
+ convert_oldfields($att,'data','content');
+
if($att['deleted']) {
attach_delete($channel,$att['hash']);
continue;
@@ -897,13 +1024,16 @@ function sync_files($channel,$files) {
$attach_exists = false;
$x = attach_by_hash($att['hash']);
+ logger('sync_files duplicate check: attach_exists=' . $attach_exists, LOGGER_DEBUG);
+ logger('sync_files duplicate check: att=' . print_r($att,true), LOGGER_DEBUG);
+ logger('sync_files duplicate check: attach_by_hash() returned ' . print_r($x,true), LOGGER_DEBUG);
- if($x) {
+ if($x['success']) {
$attach_exists = true;
$attach_id = $x[0]['id'];
}
- $newfname = 'store/' . $channel['channel_address'] . '/' . get_attach_binname($att['data']);
+ $newfname = 'store/' . $channel['channel_address'] . '/' . get_attach_binname($att['content']);
unset($att['id']);
$att['aid'] = $channel['channel_account_id'];
@@ -956,7 +1086,7 @@ function sync_files($channel,$files) {
// @fixme - update attachment structures if they are modified rather than created
- $att['data'] = $newfname;
+ $att['content'] = $newfname;
// Note: we use $att['hash'] below after it has been escaped to
// fetch the file contents.
@@ -967,15 +1097,17 @@ function sync_files($channel,$files) {
if($attach_exists) {
- $str = '';
- foreach($att as $k => $v) {
- if($str)
- $str .= ",";
- $str .= " `" . $k . "` = '" . $v . "' ";
- }
- $r = dbq("update `attach` set " . $str . " where id = " . intval($attach_id) );
+ logger('sync_files attach exists: ' . print_r($att,true), LOGGER_DEBUG);
+ $str = '';
+ foreach($att as $k => $v) {
+ if($str)
+ $str .= ",";
+ $str .= " `" . $k . "` = '" . $v . "' ";
+ }
+ $r = dbq("update `attach` set " . $str . " where id = " . intval($attach_id) );
}
else {
+ logger('sync_files attach does not exists: ' . print_r($att,true), LOGGER_DEBUG);
$r = dbq("INSERT INTO attach (`"
. implode("`, `", array_keys($att))
. "`) VALUES ('"
@@ -988,6 +1120,7 @@ function sync_files($channel,$files) {
if($att['filetype'] === 'multipart/mixed' && $att['is_dir']) {
os_mkdir($newfname, STORAGE_DEFAULT_PERMISSIONS,true);
+ $attachment_stored = true;
continue;
}
else {
@@ -1035,6 +1168,11 @@ function sync_files($channel,$files) {
$p['aid'] = $channel['channel_account_id'];
$p['uid'] = $channel['channel_id'];
+ convert_oldfields($p,'data','content');
+ convert_oldfields($p,'scale','imgscale');
+ convert_oldfields($p,'size','filesize');
+ convert_oldfields($p,'type','mimetype');
+
// if this is a profile photo, undo the profile photo bit
// for any other photo which previously held it.
@@ -1060,15 +1198,15 @@ function sync_files($channel,$files) {
);
}
- if($p['scale'] === 0 && $p['os_storage'])
- $p['data'] = $store_path;
+ if($p['imgscale'] === 0 && $p['os_storage'])
+ $p['content'] = $store_path;
else
- $p['data'] = base64_decode($p['data']);
+ $p['content'] = base64_decode($p['content']);
- $exists = q("select * from photo where resource_id = '%s' and scale = %d and uid = %d limit 1",
+ $exists = q("select * from photo where resource_id = '%s' and imgscale = %d and uid = %d limit 1",
dbesc($p['resource_id']),
- intval($p['scale']),
+ intval($p['imgscale']),
intval($channel['channel_id'])
);
@@ -1093,34 +1231,18 @@ function sync_files($channel,$files) {
}
}
if($f['item']) {
- sync_items($channel,$f['item']);
- foreach($f['item'] as $i) {
- if($i['message_id'] !== $i['message_parent'])
- continue;
- $r = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($i['message_id']),
- intval($channel['channel_id'])
- );
- if($r) {
- $item = $r[0];
- item_url_replace($channel,$item,$oldbase,z_root(),$original_channel);
-
- dbesc_array($item);
- $item_id = $item['id'];
- unset($item['id']);
- $str = '';
- foreach($item as $k => $v) {
- if($str)
- $str .= ",";
- $str .= " `" . $k . "` = '" . $v . "' ";
- }
-
- $r = dbq("update `item` set " . $str . " where id = " . $item_id );
- }
- }
+ sync_items($channel,$f['item'],
+ ['channel_address' => $original_channel,'url' => $oldbase]
+ );
}
}
}
}
+function convert_oldfields(&$arr,$old,$new) {
+ if(array_key_exists($old,$arr)) {
+ $arr[$new] = $arr[$old];
+ unset($arr[$old]);
+ }
+}
diff --git a/include/importdoc.php b/include/importdoc.php
deleted file mode 100755
index 10f868697..000000000
--- a/include/importdoc.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-
-
-require_once('include/cli_startup.php');
-
-
-function importdoc_run($argv, $argc){
-
- cli_startup();
-
- require_once('mod/help.php');
-
-
- update_docs_dir('doc/*');
-
-}
-if (array_search(__file__,get_included_files())===0){
- importdoc_run($argv,$argc);
- killme();
-}
-
-function update_docs_dir($s) {
- $f = basename($s);
- $d = dirname($s);
- if($s === 'doc/html')
- return;
- $files = glob("$d/$f");
- if($files) {
- foreach($files as $fi) {
- if($fi === 'doc/html')
- continue;
- if(is_dir($fi))
- update_docs_dir("$fi/*");
- else
- store_doc_file($fi);
- }
- }
-}
-
-
diff --git a/include/items.php b/include/items.php
index 95822c0ba..178fb30d6 100755
--- a/include/items.php
+++ b/include/items.php
@@ -3,12 +3,15 @@
* @file include/items.php
*/
-/** @todo deprecated in newer SabreDAV releases Sabre\HTTP\URLUtil */
-use Sabre\DAV\URLUtil;
+// uncertain if this line is needed and why
+use Sabre\HTTP\URLUtil;
+
+use Zotlabs\Lib as Zlib;
require_once('include/bbcode.php');
require_once('include/oembed.php');
require_once('include/crypto.php');
+require_once('include/feedutils.php');
require_once('include/photo/photo_driver.php');
require_once('include/permissions.php');
@@ -33,7 +36,6 @@ function collect_recipients($item, &$private_envelope) {
$allow_people = expand_acl($item['allow_cid']);
$allow_groups = expand_groups(expand_acl($item['allow_gid']));
- $allow_groups = filter_insecure($item['uid'],$allow_groups);
$recipients = array_unique(array_merge($allow_people,$allow_groups));
@@ -77,7 +79,7 @@ function collect_recipients($item, &$private_envelope) {
// by the directives in $item['public_policy'].
$private_envelope = false;
- require_once('include/identity.php');
+ require_once('include/channel.php');
//$sys = get_sys_channel();
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
@@ -140,46 +142,6 @@ function collect_recipients($item, &$private_envelope) {
return $recipients;
}
-/**
- * If channel is configured to filter insecure members of privacy groups
- * (those whose networks leak privacy via email notifications or other criteria)
- * remove them from any privacy groups (collections) that were included in a post.
- * They can still be addressed individually.
- * Networks may need to be added or removed from this list as circumstances change.
- *
- * Update: this may need to be the default, which will force people to opt-in to
- * sending stuff privately to insecure platforms.
- *
- * @param int $channel_id
- * @param array $arr
- * @return array containing the sane xchan_hashes
- */
-function filter_insecure($channel_id, $arr) {
- $insecure_nets = " and not xchan_network in ('diaspora', 'friendica-over-diaspora') ";
-
- $ret = array();
-
- if((! intval(get_pconfig($channel_id, 'system', 'filter_insecure_privacy_groups'))) || (! $arr))
- return $arr;
-
- $str = '';
- foreach($arr as $rr) {
- if(strlen($str))
- $str .= ',';
-
- $str .= "'" . dbesc($rr) . "'";
- }
- $r = q("select xchan_hash from xchan where xchan_hash in ($str) $insecure_nets");
- if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['xchan_hash'];
- }
- }
-
- return $ret;
-}
-
-
function comments_are_now_closed($item) {
if($item['comments_closed'] !== NULL_DATE) {
$d = datetime_convert();
@@ -221,7 +183,7 @@ function is_item_normal($item) {
* This function examines the comment_policy attached to an item and decides if the current observer has
* sufficient privileges to comment. This will normally be called on a remote site where perm_is_allowed()
* will not be suitable because the post owner does not have a local channel_id.
- * Generally we should look at the item - in particular the author['book_flags'] and see if ABOOK_FLAG_SELF is set.
+ * Generally we should look at the item - in particular the author['abook_flags'] and see if ABOOK_FLAG_SELF is set.
* If it is, you should be able to use perm_is_allowed( ... 'post_comments'), and if it isn't you need to call
* can_comment_on_post()
* We also check the comments_closed date/time on the item if this is set.
@@ -262,8 +224,7 @@ function can_comment_on_post($observer_xchan, $item) {
case 'contacts':
case 'authenticated':
case '':
- if(array_key_exists('owner',$item)) {
- if(($item['owner']['abook_xchan']) && ($item['owner']['abook_their_perms'] & PERMS_W_COMMENT))
+ if(array_key_exists('owner',$item) && get_abconfig($item['uid'],$item['owner']['abook_xchan'],'their_perms','post_comments')) {
return true;
}
break;
@@ -424,7 +385,7 @@ function post_activity_item($arr) {
return $ret;
}
- $arr['public_policy'] = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'],true));
+ $arr['public_policy'] = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
if($arr['public_policy'])
$arr['item_private'] = 1;
@@ -460,7 +421,7 @@ function post_activity_item($arr) {
$arr['deny_cid'] = ((x($arr,'deny_cid')) ? $arr['deny_cid'] : $channel['channel_deny_cid']);
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? $arr['deny_gid'] : $channel['channel_deny_gid']);
- $arr['comment_policy'] = map_scope($channel['channel_w_comment']);
+ $arr['comment_policy'] = map_scope(\Zotlabs\Access/PermissionLimits::Get($channel['channel_id'],'post_comments'));
if ((! $arr['plink']) && (intval($arr['item_thread_top']))) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
@@ -485,13 +446,9 @@ function post_activity_item($arr) {
if($post_id) {
$arr['id'] = $post_id;
call_hooks('post_local_end', $arr);
- proc_run('php','include/notifier.php','activity',$post_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id));
$ret['success'] = true;
- $r = q("select * from item where id = %d limit 1",
- intval($post_id)
- );
- if($r)
- $ret['activity'] = $r[0];
+ $ret['activity'] = $post['item'];
}
return $ret;
@@ -524,214 +481,6 @@ function validate_item_elements($message,$arr) {
/**
- * @brief Generate an Atom feed.
- *
- * @param array $channel
- * @param array $params
- */
-function get_public_feed($channel, $params) {
-
- $type = 'xml';
- $begin = NULL_DATE;
- $end = '';
- $start = 0;
- $records = 40;
- $direction = 'desc';
- $pages = 0;
-
- if(! $params)
- $params = array();
-
- $params['type'] = ((x($params,'type')) ? $params['type'] : 'xml');
- $params['begin'] = ((x($params,'begin')) ? $params['begin'] : NULL_DATE);
- $params['end'] = ((x($params,'end')) ? $params['end'] : datetime_convert('UTC','UTC','now'));
- $params['start'] = ((x($params,'start')) ? $params['start'] : 0);
- $params['records'] = ((x($params,'records')) ? $params['records'] : 40);
- $params['direction'] = ((x($params,'direction')) ? $params['direction'] : 'desc');
- $params['pages'] = ((x($params,'pages')) ? intval($params['pages']) : 0);
- $params['top'] = ((x($params,'top')) ? intval($params['top']) : 0);
- $params['cat'] = ((x($params,'cat')) ? $params['cat'] : '');
-
-
- // put a sane lower limit on feed requests if not specified
-
- if($params['begin'] === NULL_DATE)
- $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
-
- switch($params['type']) {
- case 'json':
- header("Content-type: application/atom+json");
- break;
- case 'xml':
- default:
- header("Content-type: application/atom+xml");
- break;
- }
-
- return get_feed_for($channel, get_observer_hash(), $params);
-}
-
-/**
- * @brief
- *
- * @param array $channel
- * @param string $observer_hash
- * @param array $params
- * @return string
- */
-function get_feed_for($channel, $observer_hash, $params) {
-
- if(! channel)
- http_status_exit(401);
-
- if($params['pages']) {
- if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_pages'))
- http_status_exit(403);
- } else {
- if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream'))
- http_status_exit(403);
- }
- $items = items_fetch(array(
- 'wall' => '1',
- 'datequery' => $params['end'],
- 'datequery2' => $params['begin'],
- 'start' => $params['start'], // FIXME
- 'records' => $params['records'], // FIXME
- 'direction' => $params['direction'], // FIXME
- 'pages' => $params['pages'],
- 'order' => 'post',
- 'top' => $params['top'],
- 'cat' => $params['cat']
- ), $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module);
-
-
- $feed_template = get_markup_template('atom_feed.tpl');
-
- $atom = '';
-
- $atom .= replace_macros($feed_template, array(
- '$version' => xmlify(Zotlabs\Project\System::get_project_version()),
- '$red' => xmlify(Zotlabs\Project\System::get_platform_name()),
- '$feed_id' => xmlify($channel['xchan_url']),
- '$feed_title' => xmlify($channel['channel_name']),
- '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) ,
- '$hub' => '', // feed_hublinks(),
- '$salmon' => '', // feed_salmonlinks($channel['channel_address']),
- '$name' => xmlify($channel['channel_name']),
- '$profile_page' => xmlify($channel['xchan_url']),
- '$mimephoto' => xmlify($channel['xchan_photo_mimetype']),
- '$photo' => xmlify($channel['xchan_photo_l']),
- '$thumb' => xmlify($channel['xchan_photo_m']),
- '$picdate' => '',
- '$uridate' => '',
- '$namdate' => '',
- '$birthday' => '',
- '$community' => '',
- ));
-
-
- call_hooks('atom_feed', $atom);
-
- if($items) {
- $type = 'html';
- foreach($items as $item) {
- if($item['item_private'])
- continue;
-
- /** @BUG $owner is undefined in this call */
- $atom .= atom_entry($item, $type, null, $owner, true);
- }
- }
-
- call_hooks('atom_feed_end', $atom);
-
- $atom .= '</feed>' . "\r\n";
-
- return $atom;
-}
-
-/**
- * @brief
- *
- * @param array $item an associative array with
- * * \b string \b verb
- * @return string item's verb if set, default ACTIVITY_POST see boot.php
- */
-function construct_verb($item) {
- if ($item['verb'])
- return $item['verb'];
-
- return ACTIVITY_POST;
-}
-
-function construct_activity_object($item) {
-
- if($item['object']) {
- $o = '<as:object>' . "\r\n";
- $r = json_decode($item['object'],false);
-
- if(! $r)
- return '';
- if($r->type)
- $o .= '<as:obj_type>' . xmlify($r->type) . '</as:obj_type>' . "\r\n";
- if($r->id)
- $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
- if($r->title)
- $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
- if($r->links) {
- /** @FIXME!! */
- if(substr($r->link,0,1) === '<') {
- $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
- $o .= $r->link;
- }
- else
- $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
- }
- if($r->content)
- $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
- $o .= '</as:object>' . "\r\n";
- return $o;
- }
-
- return '';
-}
-
-function construct_activity_target($item) {
-
- if($item['target']) {
- $o = '<as:target>' . "\r\n";
- $r = json_decode($item['target'],false);
- if(! $r)
- return '';
- if($r->type)
- $o .= '<as:obj_type>' . xmlify($r->type) . '</as:obj_type>' . "\r\n";
- if($r->id)
- $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
- if($r->title)
- $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
- if($r->links) {
- /** @FIXME !!! */
- if(substr($r->link,0,1) === '<') {
- if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
- $r->link = str_replace('&','&amp;', $r->link);
- $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
- $o .= $r->link;
- }
- else
- $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
- }
- if($r->content)
- $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
-
- $o .= '</as:target>' . "\r\n";
-
- return $o;
- }
-
- return '';
-}
-
-/**
* @brief Limit lenght on imported system messages.
*
* The purpose of this function is to apply system message length limits to
@@ -912,7 +661,7 @@ function get_item_elements($x,$allow_code = false) {
$arr['diaspora_meta'] = (($x['diaspora_signature']) ? $x['diaspora_signature'] : '');
- $arr['object'] = activity_sanitise($x['object']);
+ $arr['obj'] = activity_sanitise($x['object']);
$arr['target'] = activity_sanitise($x['target']);
$arr['attach'] = activity_sanitise($x['attach']);
@@ -923,13 +672,23 @@ function get_item_elements($x,$allow_code = false) {
$arr['item_flags'] = 0;
- if(array_key_exists('flags',$x) && in_array('consensus',$x['flags']))
- $arr['item_consensus'] = 1;
+ if(array_key_exists('flags',$x)) {
- if(array_key_exists('flags',$x) && in_array('deleted',$x['flags']))
- $arr['item_deleted'] = 1;
- if(array_key_exists('flags',$x) && in_array('hidden',$x['flags']))
- $arr['item_hidden'] = 1;
+ if(in_array('consensus',$x['flags']))
+ $arr['item_consensus'] = 1;
+
+ if(in_array('deleted',$x['flags']))
+ $arr['item_deleted'] = 1;
+
+ if(in_array('notshown',$x['flags']))
+ $arr['item_notshown'] = 1;
+
+ // hidden item are no longer propagated - notshown may be a suitable alternative
+
+ if(in_array('hidden',$x['flags']))
+ $arr['item_hidden'] = 1;
+
+ }
// Here's the deal - the site might be down or whatever but if there's a new person you've never
// seen before sending stuff to your stream, we MUST be able to look them up and import their data from their
@@ -1211,12 +970,12 @@ function encode_item($item,$mirror = false) {
// logger('encode_item: ' . print_r($item,true));
- $r = q("select channel_r_stream, channel_w_comment from channel where channel_id = %d limit 1",
+ $r = q("select channel_id from channel where channel_id = %d limit 1",
intval($item['uid'])
);
if($r)
- $comment_scope = $r[0]['channel_w_comment'];
+ $comment_scope = \Zotlabs\Access\PermissionLimits::Get($item['uid'],'post_comments');
else
$comment_scope = 0;
@@ -1230,9 +989,9 @@ function encode_item($item,$mirror = false) {
if(array_key_exists('item_obscured',$item) && intval($item['item_obscured'])) {
if($item['title'])
- $item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key);
+ $item['title'] = crypto_unencapsulate(json_decode($item['title'],true),$key);
if($item['body'])
- $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key);
+ $item['body'] = crypto_unencapsulate(json_decode($item['body'],true),$key);
}
// If we're trying to backup an item so that it's recoverable or for export/imprt,
@@ -1301,12 +1060,12 @@ function encode_item($item,$mirror = false) {
$x['owner'] = encode_item_xchan($item['owner']);
$x['author'] = encode_item_xchan($item['author']);
- if($item['object'])
- $x['object'] = json_decode_plus($item['object']);
+ if($item['obj'])
+ $x['object'] = json_decode($item['obj'],true);
if($item['target'])
- $x['target'] = json_decode_plus($item['target']);
+ $x['target'] = json_decode($item['target'],true);
if($item['attach'])
- $x['attach'] = json_decode_plus($item['attach']);
+ $x['attach'] = json_decode($item['attach'],true);
if($y = encode_item_flags($item))
$x['flags'] = $y;
@@ -1428,8 +1187,8 @@ function encode_item_terms($terms,$mirror = false) {
if($terms) {
foreach($terms as $term) {
- if(in_array($term['type'],$allowed_export_terms))
- $ret[] = array('tag' => $term['term'], 'url' => $term['url'], 'type' => termtype($term['type']));
+ if(in_array($term['ttype'],$allowed_export_terms))
+ $ret[] = array('tag' => $term['term'], 'url' => $term['url'], 'type' => termtype($term['ttype']));
}
}
@@ -1490,35 +1249,35 @@ function decode_tags($t) {
$tag['url'] = htmlspecialchars($x['url'], ENT_COMPAT, 'UTF-8', false);
switch($x['type']) {
case 'hashtag':
- $tag['type'] = TERM_HASHTAG;
+ $tag['ttype'] = TERM_HASHTAG;
break;
case 'mention':
- $tag['type'] = TERM_MENTION;
+ $tag['ttype'] = TERM_MENTION;
break;
case 'category':
- $tag['type'] = TERM_CATEGORY;
+ $tag['ttype'] = TERM_CATEGORY;
break;
case 'private_category':
- $tag['type'] = TERM_PCATEGORY;
+ $tag['ttype'] = TERM_PCATEGORY;
break;
case 'file':
- $tag['type'] = TERM_FILE;
+ $tag['ttype'] = TERM_FILE;
break;
case 'search':
- $tag['type'] = TERM_SEARCH;
+ $tag['ttype'] = TERM_SEARCH;
break;
case 'thing':
- $tag['type'] = TERM_THING;
+ $tag['ttype'] = TERM_THING;
break;
case 'bookmark':
- $tag['type'] = TERM_BOOKMARK;
+ $tag['ttype'] = TERM_BOOKMARK;
break;
case 'communitytag':
- $tag['type'] = TERM_COMMUNITYTAG;
+ $tag['ttype'] = TERM_COMMUNITYTAG;
break;
default:
case 'unknown':
- $tag['type'] = TERM_UNKNOWN;
+ $tag['ttype'] = TERM_UNKNOWN;
break;
}
$ret[] = $tag;
@@ -1585,6 +1344,8 @@ function encode_item_flags($item) {
$ret[] = 'deleted';
if(intval($item['item_hidden']))
$ret[] = 'hidden';
+ if(intval($item['item_notshown']))
+ $ret[] = 'notshown';
if(intval($item['item_thread_top']))
$ret[] = 'thread_parent';
if(intval($item['item_nsfw']))
@@ -1620,7 +1381,7 @@ function encode_mail($item,$extended = false) {
$x['to'] = encode_item_xchan($item['to']);
if($item['attach'])
- $x['attach'] = json_decode_plus($item['attach']);
+ $x['attach'] = json_decode($item['attach'],true);
$x['flags'] = array();
@@ -1742,453 +1503,6 @@ function get_profile_elements($x) {
return $arr;
}
-/**
- * @param object $feed
- * @param array $item
- * @param[out] array $author
- * @return multitype:multitype: string NULL number Ambigous <NULL, string, number> Ambigous <mixed, string> Ambigous <multitype:multitype:string Ambigous <NULL, string> , multitype:multitype:string unknown > multitype:NULL unknown
- */
-function get_atom_elements($feed, $item, &$author) {
-
- //$best_photo = array();
-
- $res = array();
-
- $found_author = $item->get_author();
- if($found_author) {
- $author['author_name'] = unxmlify($found_author->get_name());
- $author['author_link'] = unxmlify($found_author->get_link());
- $author['author_is_feed'] = false;
- }
- else {
- $author['author_name'] = unxmlify($feed->get_title());
- $author['author_link'] = unxmlify($feed->get_permalink());
- $author['author_is_feed'] = true;
- }
-
- if(substr($author['author_link'],-1,1) == '/')
- $author['author_link'] = substr($author['author_link'],0,-1);
-
- $res['mid'] = base64url_encode(unxmlify($item->get_id()));
- $res['title'] = unxmlify($item->get_title());
- $res['body'] = unxmlify($item->get_content());
- $res['plink'] = unxmlify($item->get_link(0));
- $res['item_rss'] = 1;
-
-
- // removing the content of the title if its identically to the body
- // This helps with auto generated titles e.g. from tumblr
-
- if (title_is_body($res["title"], $res["body"]))
- $res['title'] = "";
-
- if($res['plink'])
- $base_url = implode('/', array_slice(explode('/',$res['plink']),0,3));
- else
- $base_url = '';
-
- // look for a photo. We should check media size and find the best one,
- // but for now let's just find any author photo
-
- $rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
-
- if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
- $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
- foreach($base as $link) {
- if(!x($author, 'author_photo') || ! $author['author_photo']) {
- if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
- $author['author_photo'] = unxmlify($link['attribs']['']['href']);
- }
- }
- }
-
- $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
-
- if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['obj_type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
- $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
- if($base && count($base)) {
- foreach($base as $link) {
- if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
- $author['author_link'] = unxmlify($link['attribs']['']['href']);
- if(!x($author, 'author_photo') || ! $author['author_photo']) {
- if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
- $author['author_photo'] = unxmlify($link['attribs']['']['href']);
- }
- }
- }
- }
-
- // check for a yahoo media element (github etc.)
-
- if(! $author['author_photo']) {
- $rawmedia = $item->get_item_tags(NAMESPACE_YMEDIA,'thumbnail');
- if($rawmedia && $rawmedia[0]['attribs']['']['url']) {
- $author['author_photo'] = strip_tags(unxmlify($rawmedia[0]['attribs']['']['url']));
- }
- }
-
-
- // No photo/profile-link on the item - look at the feed level
-
- if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) {
- $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
- if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
- $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
- foreach($base as $link) {
- if($link['attribs']['']['rel'] === 'alternate' && (! $author['author_link'])) {
- $author['author_link'] = unxmlify($link['attribs']['']['href']);
- $author['author_is_feed'] = true;
- }
- if(! $author['author_photo']) {
- if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
- $author['author_photo'] = unxmlify($link['attribs']['']['href']);
- }
- }
- }
-
- $rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
-
- if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['obj_type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
- $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-
- if($base && count($base)) {
- foreach($base as $link) {
- if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
- $author['author_link'] = unxmlify($link['attribs']['']['href']);
- if(! (x($author,'author_photo'))) {
- if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
- $author['author_photo'] = unxmlify($link['attribs']['']['href']);
- }
- }
- }
- }
- }
-
- $apps = $item->get_item_tags(NAMESPACE_STATUSNET,'notice_info');
- if($apps && $apps[0]['attribs']['']['source']) {
- $res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source']));
- }
-
- /*
- * If there's a copy of the body content which is guaranteed to have survived mangling in transit, use it.
- */
-
- $have_real_body = false;
-
- $rawenv = $item->get_item_tags(NAMESPACE_DFRN, 'env');
- if($rawenv) {
- $have_real_body = true;
- $res['body'] = $rawenv[0]['data'];
- $res['body'] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$res['body']);
- // make sure nobody is trying to sneak some html tags by us
- $res['body'] = notags(base64url_decode($res['body']));
-
- // We could probably turn these old Friendica bbcode bookmarks into bookmark tags but we'd have to
- // create a term table item for them. For now just make sure they stay as links.
-
- $res['body'] = preg_replace('/\[bookmark(.*?)\](.*?)\[\/bookmark\]/','[url$1]$2[/url]',$res['body']);
- }
-
- $res['body'] = limit_body_size($res['body']);
-
- // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust
- // the content type. Our own network only emits text normally, though it might have been converted to
- // html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will
- // have to assume it is all html and needs to be purified.
-
- // It doesn't matter all that much security wise - because before this content is used anywhere, we are
- // going to escape any tags we find regardless, but this lets us import a limited subset of html from
- // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining
- // html.
-
- if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) {
-
- $res['body'] = reltoabs($res['body'],$base_url);
-
- $res['body'] = html2bb_video($res['body']);
-
- $res['body'] = oembed_html2bbcode($res['body']);
-
- $res['body'] = purify_html($res['body']);
-
- $res['body'] = @html2bbcode($res['body']);
- }
- elseif(! $have_real_body) {
-
- // it's not one of our messages and it has no tags
- // so it's probably just text. We'll escape it just to be safe.
-
- $res['body'] = escape_tags($res['body']);
- }
-
- if($res['plink'] && $res['title']) {
- $res['body'] = '#^[url=' . $res['plink'] . ']' . $res['title'] . '[/url]' . "\n\n" . $res['body'];
- $terms = array();
- $terms[] = array(
- 'otype' => TERM_OBJ_POST,
- 'type' => TERM_BOOKMARK,
- 'url' => $res['plink'],
- 'term' => $res['title'],
- );
- }
- elseif($res['plink']) {
- $res['body'] = '#^[url]' . $res['plink'] . '[/url]' . "\n\n" . $res['body'];
- $terms = array();
- $terms[] = array(
- 'otype' => TERM_OBJ_POST,
- 'type' => TERM_BOOKMARK,
- 'url' => $res['plink'],
- 'term' => $res['plink'],
- );
- }
-
- $private = $item->get_item_tags(NAMESPACE_DFRN,'private');
- if($private && intval($private[0]['data']) > 0)
- $res['item_private'] = ((intval($private[0]['data'])) ? 1 : 0);
- else
- $res['item_private'] = 0;
-
- $rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location');
- if($rawlocation)
- $res['location'] = unxmlify($rawlocation[0]['data']);
-
- $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published');
- if($rawcreated)
- $res['created'] = unxmlify($rawcreated[0]['data']);
-
- $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated');
- if($rawedited)
- $res['edited'] = unxmlify($rawedited[0]['data']);
-
- if((x($res,'edited')) && (! (x($res,'created'))))
- $res['created'] = $res['edited'];
-
- if(! $res['created'])
- $res['created'] = $item->get_date('c');
-
- if(! $res['edited'])
- $res['edited'] = $item->get_date('c');
-
-
- // Disallow time travelling posts
-
- $d1 = strtotime($res['created']);
- $d2 = strtotime($res['edited']);
- $d3 = strtotime('now');
-
- if($d1 > $d3)
- $res['created'] = datetime_convert();
- if($d2 > $d3)
- $res['edited'] = datetime_convert();
-
- $res['created'] = datetime_convert('UTC','UTC',$res['created']);
- $res['edited'] = datetime_convert('UTC','UTC',$res['edited']);
-
- $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
- if(! $rawowner)
- $rawowner = $item->get_item_tags(NAMESPACE_ZOT,'owner');
-
- if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])
- $author['owner_name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']);
- elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data'])
- $author['owner_name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
- if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
- $author['owner_link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
- elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
- $author['owner_link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
-
- if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
- $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-
- foreach($base as $link) {
- if(!x($author, 'owner_photo') || ! $author['owner_photo']) {
- if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
- $author['owner_photo'] = unxmlify($link['attribs']['']['href']);
- }
- }
- }
-
- $rawgeo = $item->get_item_tags(NAMESPACE_GEORSS,'point');
- if($rawgeo)
- $res['coord'] = unxmlify($rawgeo[0]['data']);
-
-
- $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
-
- // select between supported verbs
-
- if($rawverb) {
- $res['verb'] = unxmlify($rawverb[0]['data']);
- }
-
- // translate OStatus unfollow to activity streams if it happened to get selected
-
- if((x($res,'verb')) && ($res['verb'] === 'http://ostatus.org/schema/1.0/unfollow'))
- $res['verb'] = ACTIVITY_UNFOLLOW;
-
- $cats = $item->get_categories();
- if($cats) {
- if(is_null($terms))
- $terms = array();
- foreach($cats as $cat) {
- $term = $cat->get_term();
- if(! $term)
- $term = $cat->get_label();
- $scheme = $cat->get_scheme();
- $termurl = '';
- if($scheme && $term && stristr($scheme,'X-DFRN:')) {
- $termtype = ((substr($scheme,7,1) === '#') ? TERM_HASHTAG : TERM_MENTION);
- $termurl = unxmlify(substr($scheme,9));
- }
- else {
- $termtype = TERM_CATEGORY;
- }
- $termterm = notags(trim(unxmlify($term)));
-
- if($termterm) {
- $terms[] = array(
- 'otype' => TERM_OBJ_POST,
- 'type' => $termtype,
- 'url' => $termurl,
- 'term' => $termterm,
- );
- }
- }
- }
-
- if(! is_null($terms))
- $res['term'] = $terms;
-
- $attach = $item->get_enclosures();
- if($attach) {
- $res['attach'] = array();
- foreach($attach as $att) {
- $len = intval($att->get_length());
- $link = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_link()))));
- $title = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_title()))));
- $type = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_type()))));
- if(strpos($type,';'))
- $type = substr($type,0,strpos($type,';'));
- if((! $link) || (strpos($link,'http') !== 0))
- continue;
-
- if(! $title)
- $title = ' ';
- if(! $type)
- $type = 'application/octet-stream';
-
- $res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title );
- }
- }
-
- $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
-
- if($rawobj) {
- $obj = array();
-
- $child = $rawobj[0]['child'];
- if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) {
- $res['obj_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
- $obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
- }
- if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
- $res['obj_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
- $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
- }
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
- $obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
- $obj['link'] = encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']);
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
- $obj['title'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'];
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
- $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
- if(! $body)
- $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
- // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
- $obj['orig'] = xmlify($body);
- if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
- $body = purify_html($body);
- $body = html2bbcode($body);
- }
-
- $obj['content'] = $body;
- }
-
- $res['object'] = $obj;
- }
-
- $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'target');
-
- if($rawobj) {
- $obj = array();
-
- $child = $rawobj[0]['child'];
- if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) {
- $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
- $obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data'];
- }
- if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
- $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
- $obj['type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
- }
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
- $obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'];
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
- $obj['link'] = encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']);
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
- $obj['title'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'];
- if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
- $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
- if(! $body)
- $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
-
- // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
- $obj['orig'] = xmlify($body);
- if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
- $body = purify_html($body);
- $body = html2bbcode($body);
- }
-
- $obj['content'] = $body;
- }
-
- $res['target'] = $obj;
- }
-
- $arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
-
- call_hooks('parse_atom', $arr);
- logger('get_atom_elements: author: ' . print_r($author,true),LOGGER_DATA);
-
- logger('get_atom_elements: ' . print_r($res,true),LOGGER_DATA);
-
- return $res;
-}
-
-function encode_rel_links($links) {
- $o = array();
- if(! ((is_array($links)) && (count($links))))
- return $o;
-
- foreach($links as $link) {
- $l = array();
- if($link['attribs']['']['rel'])
- $l['rel'] = $link['attribs']['']['rel'];
- if($link['attribs']['']['type'])
- $l['type'] = $link['attribs']['']['type'];
- if($link['attribs']['']['href'])
- $l['href'] = $link['attribs']['']['href'];
- if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['width'])
- $l['width'] = $link['attribs'][NAMESPACE_MEDIA]['width'];
- if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['height'])
- $l['height'] = $link['attribs'][NAMESPACE_MEDIA]['height'];
-
- if($l)
- $o[] = $l;
- }
- return $o;
-}
/**
* @brief
@@ -2223,7 +1537,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
dbesc($arr['layout_mid']),
intval($arr['uid'])
);
- if((! $l) || (! ($l[0]['item_type'] != ITEM_TYPE_PDL)))
+ if((! $l) || ($l[0]['item_type'] != ITEM_TYPE_PDL))
unset($arr['layout_mid']);
}
@@ -2286,9 +1600,9 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
}
}
- if((x($arr,'object')) && is_array($arr['object'])) {
- activity_sanitise($arr['object']);
- $arr['object'] = json_encode($arr['object']);
+ if((x($arr,'obj')) && is_array($arr['obj'])) {
+ activity_sanitise($arr['obj']);
+ $arr['obj'] = json_encode($arr['obj']);
}
if((x($arr,'target')) && is_array($arr['target'])) {
@@ -2319,7 +1633,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$arr['thr_parent'] = ((x($arr,'thr_parent')) ? notags(trim($arr['thr_parent'])) : $arr['parent_mid']);
$arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : ACTIVITY_POST);
$arr['obj_type'] = ((x($arr,'obj_type')) ? notags(trim($arr['obj_type'])) : ACTIVITY_OBJ_NOTE);
- $arr['object'] = ((x($arr,'object')) ? trim($arr['object']) : '');
+ $arr['obj'] = ((x($arr,'obj')) ? trim($arr['obj']) : '');
$arr['tgt_type'] = ((x($arr,'tgt_type')) ? notags(trim($arr['tgt_type'])) : '');
$arr['target'] = ((x($arr,'target')) ? trim($arr['target']) : '');
$arr['plink'] = ((x($arr,'plink')) ? notags(trim($arr['plink'])) : '');
@@ -2388,7 +1702,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
return $ret;
}
- if(($arr['obj_type'] == ACTIVITY_OBJ_NOTE) && (! $arr['object']))
+ if(($arr['obj_type'] == ACTIVITY_OBJ_NOTE) && (! $arr['obj']))
$arr['obj_type'] = ACTIVITY_OBJ_COMMENT;
// is the new message multi-level threaded?
@@ -2548,12 +1862,12 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
if(($terms) && (is_array($terms))) {
foreach($terms as $t) {
- q("insert into term (uid,oid,otype,type,term,url)
+ q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
intval($arr['uid']),
intval($current_post),
intval(TERM_OBJ_POST),
- intval($t['type']),
+ intval($t['ttype']),
dbesc($t['term']),
dbesc($t['url'])
);
@@ -2570,6 +1884,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
}
+ $ret['item'] = $arr;
call_hooks('post_remote_end',$arr);
@@ -2682,9 +1997,9 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
}
}
- if((x($arr,'object')) && is_array($arr['object'])) {
- activity_sanitise($arr['object']);
- $arr['object'] = json_encode($arr['object']);
+ if((x($arr,'obj')) && is_array($arr['obj'])) {
+ activity_sanitise($arr['obj']);
+ $arr['obj'] = json_encode($arr['obj']);
}
if((x($arr,'target')) && is_array($arr['target'])) {
@@ -2726,7 +2041,7 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : $orig[0]['coord']);
$arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : $orig[0]['verb']);
$arr['obj_type'] = ((x($arr,'obj_type')) ? notags(trim($arr['obj_type'])) : $orig[0]['obj_type']);
- $arr['object'] = ((x($arr,'object')) ? trim($arr['object']) : $orig[0]['object']);
+ $arr['obj'] = ((x($arr,'obj')) ? trim($arr['obj']) : $orig[0]['obj']);
$arr['tgt_type'] = ((x($arr,'tgt_type')) ? notags(trim($arr['tgt_type'])) : $orig[0]['tgt_type']);
$arr['target'] = ((x($arr,'target')) ? trim($arr['target']) : $orig[0]['target']);
$arr['plink'] = ((x($arr,'plink')) ? notags(trim($arr['plink'])) : $orig[0]['plink']);
@@ -2820,6 +2135,15 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
return $ret;
}
+ // fetch an unescaped complete copy of the stored item
+
+ $r = q("select * from item where id = %d",
+ intval($orig_post_id)
+ );
+ if($r)
+ $arr = $r[0];
+
+
$r = q("delete from term where oid = %d and otype = %d",
intval($orig_post_id),
intval(TERM_OBJ_POST)
@@ -2827,12 +2151,12 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
if(is_array($terms)) {
foreach($terms as $t) {
- q("insert into term (uid,oid,otype,type,term,url)
+ q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
intval($uid),
intval($orig_post_id),
intval(TERM_OBJ_POST),
- intval($t['type']),
+ intval($t['ttype']),
dbesc($t['term']),
dbesc($t['url'])
);
@@ -2851,6 +2175,8 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$arr['iconfig'] = $meta;
}
+ $ret['item'] = $arr;
+
call_hooks('post_remote_update_end',$arr);
if($deliver) {
@@ -2979,8 +2305,8 @@ function send_status_notifications($post_id,$item) {
if(! $notify)
return;
- require_once('include/enotify.php');
- notification(array(
+
+ Zlib\Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'from_xchan' => $item['author_xchan'],
'to_xchan' => $r[0]['channel_hash'],
@@ -3060,10 +2386,10 @@ function tag_deliver($uid, $item_id) {
if (stristr($item['verb'],ACTIVITY_POKE)) {
$poke_notify = true;
- if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['object']))
+ if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['obj']))
$poke_notify = false;
- $obj = json_decode_plus($item['object']);
+ $obj = json_decode($item['obj'],true);
if($obj) {
if($obj['id'] !== $u[0]['channel_hash'])
$poke_notify = false;
@@ -3073,8 +2399,7 @@ function tag_deliver($uid, $item_id) {
$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
if($poke_notify) {
- require_once('include/enotify.php');
- notification(array(
+ Zlib\Enotify::submit(array(
'to_xchan' => $u[0]['channel_hash'],
'from_xchan' => $item['author_xchan'],
'type' => NOTIFY_POKE,
@@ -3101,14 +2426,14 @@ function tag_deliver($uid, $item_id) {
if(($item['owner_xchan'] === $u[0]['channel_hash']) && (! get_pconfig($u[0]['channel_id'],'system','blocktags'))) {
logger('tag_deliver: community tag recipient: ' . $u[0]['channel_name']);
- $j_tgt = json_decode_plus($item['target']);
+ $j_tgt = json_decode($item['target'],true);
if($j_tgt && $j_tgt['id']) {
$p = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($j_tgt['id']),
intval($u[0]['channel_id'])
);
if($p) {
- $j_obj = json_decode_plus($item['object']);
+ $j_obj = json_decode($item['obj'],true);
logger('tag_deliver: tag object: ' . print_r($j_obj,true), LOGGER_DATA);
if($j_obj && $j_obj['id'] && $j_obj['title']) {
if(is_array($j_obj['link']))
@@ -3122,7 +2447,7 @@ function tag_deliver($uid, $item_id) {
dbesc($j_tgt['id']),
intval($u[0]['channel_id'])
);
- proc_run('php','include/notifier.php','edit_post',$p[0]['id']);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','edit_post',$p[0]['id']));
}
}
}
@@ -3193,7 +2518,7 @@ function tag_deliver($uid, $item_id) {
if(intval($item['item_obscured'])) {
$key = get_config('system','prvkey');
if($item['body'])
- $body = crypto_unencapsulate(json_decode_plus($item['body']),$key);
+ $body = crypto_unencapsulate(json_decode($item['body'],true),$key);
}
else
$body = $item['body'];
@@ -3239,8 +2564,7 @@ function tag_deliver($uid, $item_id) {
* Kill two birds with one stone. As long as we're here, send a mention notification.
*/
- require_once('include/enotify.php');
- notification(array(
+ Zlib\Enotify::submit(array(
'to_xchan' => $u[0]['channel_hash'],
'from_xchan' => $item['author_xchan'],
'type' => NOTIFY_TAGSELF,
@@ -3400,13 +2724,44 @@ function tgroup_check($uid,$item) {
*/
function start_delivery_chain($channel, $item, $item_id, $parent) {
+ $sourced = check_item_source($channel['channel_id'],$item);
+
+ if($sourced) {
+ $r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' or src_xchan = '*' ) limit 1",
+ intval($channel['channel_id']),
+ dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan'])
+ );
+ if($r) {
+ $t = trim($r[0]['src_tag']);
+ if($t) {
+ $tags = explode(',',$t);
+ if($tags) {
+ foreach($tags as $tt) {
+ $tt = trim($tt);
+ if($tt) {
+ q("insert into term (uid,oid,otype,ttype,term,url)
+ values(%d,%d,%d,%d,'%s','%s') ",
+ intval($channel['channel_id']),
+ intval($item_id),
+ intval(TERM_OBJ_POST),
+ intval(TERM_CATEGORY),
+ dbesc($tt),
+ dbesc(z_root() . '/channel/' . $channel['channel_address'] . '?f=&cat=' . urlencode($tt))
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+
// Change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
$private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
- $new_public_policy = map_scope($channel['channel_r_stream'],true);
+ $new_public_policy = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true);
if((! $private) && $new_public_policy)
$private = 1;
@@ -3451,7 +2806,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
dbesc($channel['channel_deny_gid']),
intval($private),
dbesc($new_public_policy),
- dbesc(map_scope($channel['channel_w_comment'])),
+ dbesc(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'))),
dbesc($title),
dbesc($body),
intval($item_wall),
@@ -3459,8 +2814,11 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
intval($item_id)
);
+
+
+
if($r)
- proc_run('php','include/notifier.php','tgroup',$item_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','tgroup',$item_id));
else {
logger('start_delivery_chain: failed to update item');
// reset the source xchan to prevent loops
@@ -3497,7 +2855,7 @@ function check_item_source($uid, $item) {
if(! $x)
return false;
- if(! ($x[0]['abook_their_perms'] & PERMS_A_REPUBLISH))
+ if(! get_abconfig($uid,$item['owner_xchan'],'their_perms','republish'))
return false;
if($item['item_private'] && (! intval($x[0]['abook_feed'])))
@@ -3524,7 +2882,7 @@ function check_item_source($uid, $item) {
foreach($words as $word) {
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
- if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
return true;
}
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
@@ -3577,7 +2935,7 @@ function post_is_importable($item,$abook) {
continue;
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
- if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
return false;
}
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
@@ -3598,7 +2956,7 @@ function post_is_importable($item,$abook) {
continue;
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
- if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
return true;
}
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
@@ -3707,7 +3065,6 @@ function mail_store($arr) {
);
}
else {
- require_once('include/enotify.php');
$notif_params = array(
'from_xchan' => $arr['from_xchan'],
@@ -3718,584 +3075,13 @@ function mail_store($arr) {
'otype' => 'mail'
);
- notification($notif_params);
+ Zlib\Enotify::submit($notif_params);
}
call_hooks('post_mail_end',$arr);
return $current_post;
}
-/**
- * @brief Process atom feed and update anything/everything we might need to update.
- *
- * @param array $xml
- * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
- * @param $importer
- * The contact_record (joined to user_record) of the local user who owns this
- * relationship. It is this person's stuff that is going to be updated.
- * @param $contact
- * The person who is sending us stuff. If not set, we MAY be processing a "follow" activity
- * from an external network and MAY create an appropriate contact record. Otherwise, we MUST
- * have a contact record.
- * @param int $pass by default ($pass = 0) we cannot guarantee that a parent item has been
- * imported prior to its children being seen in the stream unless we are certain
- * of how the feed is arranged/ordered.
- * * With $pass = 1, we only pull parent items out of the stream.
- * * With $pass = 2, we only pull children (comments/likes).
- *
- * So running this twice, first with pass 1 and then with pass 2 will do the right
- * thing regardless of feed ordering. This won't be adequate in a fully-threaded
- * model where comments can have sub-threads. That would require some massive sorting
- * to get all the feed items into a mostly linear ordering, and might still require
- * recursion.
- */
-function consume_feed($xml, $importer, &$contact, $pass = 0) {
-
- require_once('library/simplepie/simplepie.inc');
-
- if(! strlen($xml)) {
- logger('consume_feed: empty input');
- return;
- }
-
- $sys_expire = intval(get_config('system','default_expire_days'));
- $chn_expire = intval($importer['channel_expire_days']);
-
- $expire_days = $sys_expire;
-
- if(($chn_expire != 0) && ($chn_expire < $sys_expire))
- $expire_days = $chn_expire;
-
- // logger('expire_days: ' . $expire_days);
-
- $feed = new SimplePie();
- $feed->set_raw_data($xml);
- $feed->init();
-
- if($feed->error())
- logger('consume_feed: Error parsing XML: ' . $feed->error());
-
- $permalink = $feed->get_permalink();
-
- // Check at the feed level for updated contact name and/or photo
-
- // process any deleted entries
-
- $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry');
- if(is_array($del_entries) && count($del_entries) && $pass != 2) {
- foreach($del_entries as $dentry) {
- $deleted = false;
- if(isset($dentry['attribs']['']['ref'])) {
- $mid = $dentry['attribs']['']['ref'];
- $deleted = true;
- if(isset($dentry['attribs']['']['when'])) {
- $when = $dentry['attribs']['']['when'];
- $when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
- }
- else
- $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
- }
-
- if($deleted && is_array($contact)) {
- $r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1",
- dbesc(base64url_encode($mid)),
- dbesc($contact['xchan_hash']),
- intval($importer['channel_id'])
- );
-
- if($r) {
- $item = $r[0];
-
- if(! intval($item['item_deleted'])) {
- logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG);
- drop_item($item['id'],false);
- }
- }
- }
- }
- }
-
- // Now process the feed
-
- if($feed->get_item_quantity()) {
-
- logger('consume_feed: feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
-
- $items = $feed->get_items();
-
- foreach($items as $item) {
-
- $is_reply = false;
- $item_id = base64url_encode($item->get_id());
-
- logger('consume_feed: processing ' . $item_id, LOGGER_DEBUG);
-
- $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
- if(isset($rawthread[0]['attribs']['']['ref'])) {
- $is_reply = true;
- $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
- }
-
- if($is_reply) {
-
- if($pass == 1)
- continue;
-
- // Have we seen it? If not, import it.
-
- $item_id = base64url_encode($item->get_id());
- $author = array();
- $datarray = get_atom_elements($feed,$item,$author);
-
- if($contact['xchan_network'] === 'rss') {
- $datarray['public_policy'] = 'specific';
- $datarray['comment_policy'] = 'none';
- }
-
- if((! x($author,'author_name')) || ($author['author_is_feed']))
- $author['author_name'] = $contact['xchan_name'];
- if((! x($author,'author_link')) || ($author['author_is_feed']))
- $author['author_link'] = $contact['xchan_url'];
- if((! x($author,'author_photo'))|| ($author['author_is_feed']))
- $author['author_photo'] = $contact['xchan_photo_m'];
-
- $datarray['author_xchan'] = '';
-
- if($author['author_link'] != $contact['xchan_url']) {
- $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo'])));
- if($x)
- $datarray['author_xchan'] = $x;
- }
- if(! $datarray['author_xchan'])
- $datarray['author_xchan'] = $contact['xchan_hash'];
-
- $datarray['owner_xchan'] = $contact['xchan_hash'];
-
- $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
- dbesc($item_id),
- intval($importer['channel_id'])
- );
-
-
- // Update content if 'updated' changes
-
- if($r) {
- if((x($datarray,'edited') !== false)
- && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {
-
- // do not accept (ignore) an earlier edit than one we currently have.
- if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
- continue;
-
- update_feed_item($importer['channel_id'],$datarray);
- }
- continue;
- }
-
- $datarray['parent_mid'] = $parent_mid;
- $datarray['aid'] = $importer['channel_account_id'];
- $datarray['uid'] = $importer['channel_id'];
-
- logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);
-
- $xx = item_store($datarray);
- $r = $xx['item_id'];
- continue;
- }
- else {
-
- // Head post of a conversation. Have we seen it? If not, import it.
-
- $item_id = base64url_encode($item->get_id());
- $author = array();
- $datarray = get_atom_elements($feed,$item,$author);
-
- if($contact['xchan_network'] === 'rss') {
- $datarray['public_policy'] = 'specific';
- $datarray['comment_policy'] = 'none';
- }
-
-
- if(is_array($contact)) {
- if((! x($author,'author_name')) || ($author['author_is_feed']))
- $author['author_name'] = $contact['xchan_name'];
- if((! x($author,'author_link')) || ($author['author_is_feed']))
- $author['author_link'] = $contact['xchan_url'];
- if((! x($author,'author_photo'))|| ($author['author_is_feed']))
- $author['author_photo'] = $contact['xchan_photo_m'];
- }
-
- if((! x($author,'author_name')) || (! x($author,'author_link'))) {
- logger('consume_feed: no author information! ' . print_r($author,true));
- continue;
- }
-
- $datarray['author_xchan'] = '';
-
- if(activity_match($datarray['verb'],ACTIVITY_FOLLOW) && $datarray['obj_type'] === ACTIVITY_OBJ_PERSON) {
- $cb = array('item' => $datarray,'channel' => $importer, 'xchan' => null, 'author' => $author, 'caught' => false);
- call_hooks('follow_from_feed',$cb);
- if($cb['caught']) {
- if($cb['return_code'])
- http_status_exit($cb['return_code']);
- continue;
- }
- }
-
- if($author['author_link'] != $contact['xchan_url']) {
- $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo'])));
- if($x)
- $datarray['author_xchan'] = $x;
- }
- if(! $datarray['author_xchan'])
- $datarray['author_xchan'] = $contact['xchan_hash'];
-
- $datarray['owner_xchan'] = $contact['xchan_hash'];
-
- if(array_key_exists('created',$datarray) && $datarray['created'] != NULL_DATE && $expire_days) {
- $t1 = $datarray['created'];
- $t2 = datetime_convert('UTC','UTC','now - ' . $expire_days . 'days');
- if($t1 < $t2) {
- logger('feed content older than expiration. Ignoring.', LOGGER_DEBUG, LOG_INFO);
- continue;
- }
- }
-
-
-
- $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
- dbesc($item_id),
- intval($importer['channel_id'])
- );
-
- // Update content if 'updated' changes
-
- if($r) {
- if((x($datarray,'edited') !== false)
- && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) {
-
- // do not accept (ignore) an earlier edit than one we currently have.
- if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
- continue;
-
- update_feed_item($importer['channel_id'],$datarray);
- }
-
- continue;
- }
-
- $datarray['parent_mid'] = $item_id;
- $datarray['uid'] = $importer['channel_id'];
- $datarray['aid'] = $importer['channel_account_id'];
-
- if(! link_compare($author['owner_link'],$contact['xchan_url'])) {
- logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
- $author['owner_name'] = $contact['name'];
- $author['owner_link'] = $contact['url'];
- $author['owner_avatar'] = $contact['thumb'];
- }
-
- if(! post_is_importable($datarray,$contact))
- continue;
-
- logger('consume_feed: author ' . print_r($author,true),LOGGER_DEBUG);
-
- logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);
-
- $xx = item_store($datarray);
- $r = $xx['item_id'];
- continue;
- }
- }
- }
-}
-
-
-/**
- * @brief Process atom feed and return the first post and structure
- *
- * @param array $xml
- * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
- * @param $importer
- * The contact_record (joined to user_record) of the local user who owns this
- * relationship. It is this person's stuff that is going to be updated.
- */
-
-function process_salmon_feed($xml, $importer) {
-
- $ret = array();
-
- require_once('library/simplepie/simplepie.inc');
-
- if(! strlen($xml)) {
- logger('process_feed: empty input');
- return;
- }
-
- $feed = new SimplePie();
- $feed->set_raw_data($xml);
- $feed->init();
-
- if($feed->error())
- logger('Error parsing XML: ' . $feed->error());
-
- $permalink = $feed->get_permalink();
-
- if($feed->get_item_quantity()) {
-
- // this should be exactly one
-
- logger('feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
-
- $items = $feed->get_items();
-
- foreach($items as $item) {
-
- $item_id = base64url_encode($item->get_id());
-
- logger('processing ' . $item_id, LOGGER_DEBUG);
-
- $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
- if(isset($rawthread[0]['attribs']['']['ref'])) {
- $is_reply = true;
- $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
- }
-
- if($is_reply)
- $ret['parent_mid'] = $parent_mid;
-
- $ret['author'] = array();
-
- $datarray = get_atom_elements($feed,$item,$ret['author']);
-
- // reset policies which are restricted by default for RSS connections
- // This item is likely coming from GNU-social via salmon and allows public interaction
- $datarray['public_policy'] = '';
- $datarray['comment_policy'] = '';
-
- $ret['item'] = $datarray;
- }
- }
-
- return $ret;
-}
-
-/*
- * Given an xml (atom) feed, find author and hub links
- */
-
-
-function feed_meta($xml) {
- require_once('library/simplepie/simplepie.inc');
-
- $ret = array();
-
- if(! strlen($xml)) {
- logger('empty input');
- return $ret;
- }
-
- $feed = new SimplePie();
- $feed->set_raw_data($xml);
- $feed->init();
-
- if($feed->error()) {
- logger('Error parsing XML: ' . $feed->error());
- return $ret;
- }
-
- $ret['hubs'] = $feed->get_links('hub');
-
-// logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA);
-
- $author = array();
-
- $found_author = $feed->get_author();
- if($found_author) {
- $author['author_name'] = unxmlify($found_author->get_name());
- $author['author_link'] = unxmlify($found_author->get_link());
-
- $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
- logger('rawauthor: ' . print_r($rawauthor,true));
-
- if($rawauthor) {
- if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
- $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
- foreach($base as $link) {
- if(!x($author, 'author_photo') || ! $author['author_photo']) {
- if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') {
- $author['author_photo'] = unxmlify($link['attribs']['']['href']);
- break;
- }
- }
- }
- }
- if($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data'])
- $author['full_name'] = unxmlify($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data']);
- if($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
- $author['author_uri'] = unxmlify($rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
-
- }
- }
-
- if(substr($author['author_link'],-1,1) == '/')
- $author['author_link'] = substr($author['author_link'],0,-1);
-
- $ret['author'] = $author;
-
- return $ret;
-}
-
-
-
-function update_feed_item($uid,$datarray) {
- logger('update_feed_item: not implemented! ' . $uid . ' ' . print_r($datarray,true), LOGGER_DATA);
-}
-
-
-function handle_feed($uid,$abook_id,$url) {
-
- require_once('include/Contact.php');
- $channel = channelx_by_n($uid);
- if(! $channel)
- return;
-
- $x = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d limit 1",
- dbesc($abook_id),
- intval($uid)
- );
-
- $recurse = 0;
- $z = z_fetch_url($url,false,$recurse,array('novalidate' => true));
-
-//logger('handle_feed:' . print_r($z,true));
-
- if($z['success']) {
- consume_feed($z['body'],$channel,$x[0],1);
- consume_feed($z['body'],$channel,$x[0],2);
- }
-}
-
-
-function atom_author($tag,$name,$uri,$h,$w,$type,$photo) {
- $o = '';
- if(! $tag)
- return $o;
-
- $name = xmlify($name);
- $uri = xmlify($uri);
- $h = intval($h);
- $w = intval($w);
- $photo = xmlify($photo);
-
- $o .= "<$tag>\r\n";
- $o .= "<name>$name</name>\r\n";
- $o .= "<uri>$uri</uri>\r\n";
- $o .= '<link rel="photo" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
- $o .= '<link rel="avatar" type="' . $type . '" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
-
- call_hooks('atom_author', $o);
-
- $o .= "</$tag>\r\n";
-
- return $o;
-}
-
-function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
-
- if(! $item['parent'])
- return;
-
- if($item['deleted'])
- return '<at:deleted-entry ref="' . xmlify($item['mid']) . '" when="' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '" />' . "\r\n";
-
-
- create_export_photo_body($item);
-
- if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid'])
- $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid);
- else
- $body = $item['body'];
-
- $o = "\r\n\r\n<entry>\r\n";
-
- if(is_array($author))
- $o .= atom_author('author',$author['xchan_name'],$author['xchan_url'],80,80,$author['xchan_photo_mimetype'],$author['xchan_photo_m']);
- else
- $o .= atom_author('author',$item['author']['xchan_name'],$item['author']['xchan_url'],80,80,$item['author']['xchan_photo_mimetype'], $item['author']['xchan_photo_m']);
-
- $o .= atom_author('zot:owner',$item['owner']['xchan_name'],$item['owner']['xchan_url'],80,80,$item['owner']['xchan_photo_mimetype'],$item['owner']['xchan_photo_m']);
-
- if(($item['parent'] != $item['id']) || ($item['parent_mid'] !== $item['mid']) || (($item['thr_parent'] !== '') && ($item['thr_parent'] !== $item['mid']))) {
- $parent_item = (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']);
- $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
- }
-
- if(activity_match($item['obj_type'],ACTIVITY_OBJ_EVENT) && activity_match($item['verb'],ACTIVITY_POST)) {
- $obj = ((is_array($item['obj'])) ? $item['object'] : json_decode($item['object'],true));
-
- $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
- $o .= '<summary>' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
- $o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['start'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtstart>' . "\r\n";
- $o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['finish'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtend>' . "\r\n";
- $o .= '<location>' . bbcode($obj['location']) . '</location>' . "\r\n";
- $o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n";
- }
- else {
- $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
- $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
- }
-
- $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n";
- $o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n";
- $o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n";
-
- $o .= '<link rel="alternate" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
-
- if($item['location']) {
- $o .= '<zot:location>' . xmlify($item['location']) . '</zot:location>' . "\r\n";
- $o .= '<poco:address><poco:formatted>' . xmlify($item['location']) . '</poco:formatted></poco:address>' . "\r\n";
- }
-
- if($item['coord'])
- $o .= '<georss:point>' . xmlify($item['coord']) . '</georss:point>' . "\r\n";
-
- if(($item['item_private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
- $o .= '<zot:private>' . (($item['item_private']) ? $item['item_private'] : 1) . '</zot:private>' . "\r\n";
-
- if($item['app'])
- $o .= '<statusnet:notice_info local_id="' . $item['id'] . '" source="' . xmlify($item['app']) . '" ></statusnet:notice_info>' . "\r\n";
-
- $verb = construct_verb($item);
- $o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n";
- $actobj = construct_activity_object($item);
- if(strlen($actobj))
- $o .= $actobj;
- $actarg = construct_activity_target($item);
- if(strlen($actarg))
- $o .= $actarg;
-
- // FIXME
-// $tags = item_getfeedtags($item);
-// if(count($tags)) {
-// foreach($tags as $t) {
-// $o .= '<category scheme="X-DFRN:' . xmlify($t[0]) . ':' . xmlify($t[1]) . '" term="' . xmlify($t[2]) . '" />' . "\r\n";
-// }
-// }
-
-// FIXME
-// $o .= item_getfeedattach($item);
-
-// $mentioned = get_mentions($item,$tags);
-// if($mentioned)
-// $o .= $mentioned;
-
- call_hooks('atom_entry', $o);
-
- $o .= '</entry>' . "\r\n";
-
- return $o;
-}
function fix_private_photos($s, $uid, $item = null, $cid = 0) {
@@ -4324,7 +3110,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) {
if($x) {
$res = substr($i,$x+1);
$i = substr($i,0,$x);
- $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `scale` = %d AND `uid` = %d",
+ $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `imgscale` = %d AND `uid` = %d",
dbesc($i),
intval($res),
intval($uid)
@@ -4447,7 +3233,7 @@ function item_getfeedtags($item) {
if(count($terms)) {
foreach($terms as $term) {
- if(($term['type'] == TERM_HASHTAG) || ($term['type'] == TERM_COMMUNITYTAG))
+ if(($term['ttype'] == TERM_HASHTAG) || ($term['ttype'] == TERM_COMMUNITYTAG))
$ret[] = array('#',$term['url'],$term['term']);
else
$ret[] = array('@',$term['url'],$term['term']);
@@ -4499,15 +3285,17 @@ function item_expire($uid,$days) {
$item_normal = item_normal();
- $r = q("SELECT * FROM `item`
- WHERE `uid` = %d
- AND `created` < %s - INTERVAL %s
- AND `id` = `parent`
- $sql_extra
+ $r = q("SELECT id FROM item
+ WHERE uid = %d
+ AND created < %s - INTERVAL %s
AND item_retained = 0
- $item_normal LIMIT $expire_limit ",
+ AND item_thread_top = 1
+ AND resource_type = ''
+ AND item_starred = 0
+ $sql_extra $item_normal LIMIT $expire_limit ",
intval($uid),
- db_utcnow(), db_quoteinterval(intval($days).' DAY')
+ db_utcnow(),
+ db_quoteinterval(intval($days).' DAY')
);
if(! $r)
@@ -4525,21 +3313,10 @@ function item_expire($uid,$days) {
continue;
}
- // Only expire posts, not photos and photo comments
-
- if($item['resource_type'] === 'photo') {
- retain_item($item['id']);
- continue;
- }
- if(intval($item['item_starred'])) {
- retain_item($item['id']);
- continue;
- }
-
drop_item($item['id'],false);
}
-// proc_run('php',"include/notifier.php","expire","$uid");
+// Zotlabs\Daemon\Master::Summon(array('Notifier','expire',$uid));
}
function retain_item($id) {
@@ -4565,7 +3342,7 @@ function drop_items($items) {
// multiple threads may have been deleted, send an expire notification
if($uid)
- proc_run('php',"include/notifier.php","expire","$uid");
+ Zotlabs\Daemon\Master::Summon(array('Notifier','expire',$uid));
}
@@ -4661,7 +3438,7 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
// set if we know we're going to send delete notifications out to others.
if((intval($item['item_wall']) && ($stage != DROPITEM_PHASE2)) || ($stage == DROPITEM_PHASE1))
- proc_run('php','include/notifier.php','drop',$notify_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$notify_id));
goaway(z_root() . '/' . $_SESSION['return_url']);
}
@@ -4770,9 +3547,8 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
intval($item['id'])
);
- q("delete from item_id where iid = %d and uid = %d",
- intval($item['id']),
- intval($item['uid'])
+ q("delete from iconfig where iid = %d",
+ intval($item['id'])
);
q("delete from term where oid = %d and otype = %d",
@@ -4918,7 +3694,7 @@ function fetch_post_tags($items,$link = false) {
for($x = 0; $x < count($items); $x ++) {
if($tags) {
foreach($tags as $t) {
- if(($link) && ($t['type'] == TERM_MENTION))
+ if(($link) && ($t['ttype'] == TERM_MENTION))
$t['url'] = chanlink_url($t['url']);
if(array_key_exists('item_id',$items[$x])) {
if($t['oid'] == $items[$x]['item_id']) {
@@ -5128,8 +3904,8 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
$contact_str = '';
- /** @FIXME $group is undefined */
- $contacts = group_get_members($group);
+
+ $contacts = group_get_members($r[0]['id']);
if ($contacts) {
foreach($contacts as $c) {
if($contact_str)
@@ -5146,7 +3922,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent $item_normal ) ";
$x = group_rec_byhash($uid,$r[0]['hash']);
- $result['headline'] = sprintf( t('Privacy group: %s'),$x['name']);
+ $result['headline'] = sprintf( t('Privacy group: %s'),$x['gname']);
}
elseif($arr['cid'] && $uid) {
@@ -5338,6 +4114,23 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
return $items;
}
+function webpage_to_namespace($webpage) {
+
+ if($webpage == ITEM_TYPE_WEBPAGE)
+ $page_type = 'WEBPAGE';
+ elseif($webpage == ITEM_TYPE_BLOCK)
+ $page_type = 'BUILDBLOCK';
+ elseif($webpage == ITEM_TYPE_PDL)
+ $page_type = 'PDL';
+ elseif($webpage == ITEM_TYPE_DOC)
+ $page_type = 'docfile';
+ else
+ $page_type = 'unknown';
+ return $page_type;
+
+}
+
+
function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) {
@@ -5360,32 +4153,19 @@ function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remo
}
if($page_type) {
-
// store page info as an alternate message_id so we can access it via
// https://sitename/page/$channelname/$pagetitle
// if no pagetitle was given or it couldn't be transliterated into a url, use the first
// sixteen bytes of the mid - which makes the link portable and not quite as daunting
// as the entire mid. If it were the post_id the link would be less portable.
- $r = q("select * from item_id where iid = %d and uid = %d and service = '%s' limit 1",
+ \Zotlabs\Lib\IConfig::Set(
intval($post_id),
- intval($channel['channel_id']),
- dbesc($page_type)
+ 'system',
+ $page_type,
+ ($pagetitle) ? $pagetitle : substr($mid,0,16),
+ false
);
- if($r) {
- q("update item_id set sid = '%s' where id = %d",
- dbesc(($pagetitle) ? $pagetitle : substr($mid,0,16)),
- intval($r[0]['id'])
- );
- }
- else {
- q("insert into item_id ( iid, uid, sid, service ) values ( %d, %d, '%s','%s' )",
- intval($post_id),
- intval($channel['channel_id']),
- dbesc(($pagetitle) ? $pagetitle : substr($mid,0,16)),
- dbesc($page_type)
- );
- }
}
}
@@ -5478,90 +4258,6 @@ function comment_local_origin($item) {
}
-function gen_asld($items) {
- $ret = array();
- if(! $items)
- return $ret;
- foreach($items as $item) {
- $ret[] = i2asld($item);
- }
- return $ret;
-}
-
-
-function i2asld($i) {
-
- if(! $i)
- return array();
-
- $ret = array();
-
- $ret['@context'] = array( 'http://www.w3.org/ns/activitystreams', 'zot' => 'http://purl.org/zot/protocol');
-
- if($i['verb']) {
- if(strpos(dirname($i['verb'],'activitystrea.ms/schema/1.0'))) {
- $ret['@type'] = ucfirst(basename($i['verb']));
- }
- elseif(strpos(dirname($i['verb'],'purl.org/zot'))) {
- $ret['@type'] = 'zot:' . ucfirst(basename($i['verb']));
- }
- }
- $ret['@id'] = $i['plink'];
-
- $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
-
- // we need to pass the parent into this
-// if($i['id'] != $i['parent'] && $i['obj_type'] === ACTIVITY_OBJ_NOTE) {
-// $ret['inReplyTo'] = asencode_note
-// }
-
- if($i['obj_type'] === ACTIVITY_OBJ_NOTE)
- $ret['object'] = asencode_note($i);
-
-
- $ret['actor'] = asencode_person($i['author']);
-
-
- return $ret;
-
-}
-
-function asencode_note($i) {
-
- $ret = array();
-
- $ret['@type'] = 'Note';
- $ret['@id'] = $i['plink'];
- if($i['title'])
- $ret['title'] = bbcode($i['title']);
- $ret['content'] = bbcode($i['body']);
- $ret['zot:owner'] = asencode_person($i['owner']);
- $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
- if($i['created'] !== $i['edited'])
- $ret['updated'] = datetime_convert('UTC','UTC',$i['edited'],ATOM_TIME);
-
- return $ret;
-}
-
-
-function asencode_person($p) {
- $ret = array();
- $ret['@type'] = 'Person';
- $ret['@id'] = 'acct:' . $p['xchan_addr'];
- $ret['displayName'] = $p['xchan_name'];
- $ret['icon'] = array(
- '@type' => 'Link',
- 'mediaType' => $p['xchan_photo_mimetype'],
- 'href' => $p['xchan_photo_m']
- );
- $ret['url'] = array(
- '@type' => 'Link',
- 'mediaType' => 'text/html',
- 'href' => $p['xchan_url']
- );
-
- return $ret;
-}
function send_profile_photo_activity($channel,$photo,$profile) {
@@ -5578,7 +4274,7 @@ function send_profile_photo_activity($channel,$photo,$profile) {
$arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
$arr['verb'] = ACTIVITY_UPDATE;
- $arr['object'] = json_encode(array(
+ $arr['obj'] = json_encode(array(
'type' => $arr['obj_type'],
'id' => z_root() . '/photo/profile/l/' . $channel['channel_id'],
'link' => array('rel' => 'photo', 'type' => $photo['type'], 'href' => z_root() . '/photo/profile/l/' . $channel['channel_id'])
@@ -5617,157 +4313,17 @@ function send_profile_photo_activity($channel,$photo,$profile) {
}
+function sync_an_item($channel_id,$item_id) {
-
-
-function get_iconfig(&$item, $family, $key) {
-
- $is_item = false;
- if(is_array($item)) {
- $is_item = true;
- if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
- $item['iconfig'] = array();
-
- if(array_key_exists('item_id',$item))
- $iid = $item['item_id'];
- else
- $iid = $item['id'];
- }
- elseif(intval($item))
- $iid = $item;
-
- if(! $iid)
- return false;
-
- if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
- foreach($item['iconfig'] as $c) {
- if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
- return $c['v'];
- }
- }
-
- $r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
- intval($iid),
- dbesc($family),
- dbesc($key)
+ $r = q("select * from item where id = %d",
+ intval($item_id)
);
if($r) {
- $r[0]['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
- if($is_item)
- $item['iconfig'][] = $r[0];
- return $r[0]['v'];
- }
- return false;
-
-}
-
-/**
- * set_iconfig(&$item, $family, $key, $value, $sharing = false);
- *
- * $item - item array or item id. If passed an array the iconfig meta information is
- * added to the item structure (which will need to be saved with item_store eventually).
- * If passed an id, the DB is updated, but may not be federated and/or cloned.
- * $family - namespace of meta variable
- * $key - key of meta variable
- * $value - value of meta variable
- * $sharing - boolean (default false); if true the meta information is propagated with the item
- * to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
- * If the meta information is added after delivery and you wish it to be shared, it may be necessary to
- * alter the item edited timestamp and invoke the delivery process on the updated item. The edited
- * timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
- */
-
-
-function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
-
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- $is_item = false;
- $idx = null;
-
- if(is_array($item)) {
- $is_item = true;
- if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
- $item['iconfig'] = array();
- elseif($item['iconfig']) {
- for($x = 0; $x < count($item['iconfig']); $x ++) {
- if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
- $idx = $x;
- }
- }
- }
- $entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
-
- if(is_null($idx))
- $item['iconfig'][] = $entry;
- else
- $item['iconfig'][$idx] = $entry;
- return $value;
- }
-
- if(intval($item))
- $iid = intval($item);
-
- if(! $iid)
- return false;
-
- if(get_iconfig($item, $family, $key) === false) {
- $r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
- intval($iid),
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue),
- intval($sharing)
- );
- }
- else {
- $r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
- dbesc($dbvalue),
- intval($sharing),
- intval($iid),
- dbesc($family),
- dbesc($key)
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ $rid = q("select * from item_id where iid = %d",
+ intval($item_id)
);
+ build_sync_packet($channel_d,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
}
-
- if(! $r)
- return false;
-
- return $value;
-}
-
-
-
-function del_iconfig(&$item, $family, $key) {
-
-
- $is_item = false;
- $idx = null;
-
- if(is_array($item)) {
- $is_item = true;
- if(is_array($item['iconfig'])) {
- for($x = 0; $x < count($item['iconfig']); $x ++) {
- if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
- unset($item['iconfig'][$x]);
- }
- }
- }
- return true;
- }
-
- if(intval($item))
- $iid = intval($item);
-
- if(! $iid)
- return false;
-
- return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
- intval($iid),
- dbesc($family),
- dbesc($key)
- );
-
}
-
diff --git a/include/js_strings.php b/include/js_strings.php
index b1817f373..1b4668061 100644
--- a/include/js_strings.php
+++ b/include/js_strings.php
@@ -4,10 +4,10 @@ function js_strings() {
return replace_macros(get_markup_template('js_strings.tpl'), array(
'$delitem' => t('Delete this item?'),
'$comment' => t('Comment'),
- '$showmore' => t('[+] show all'),
- '$showfewer' => t('[-] show less'),
- '$divgrowmore' => t('[+] expand'),
- '$divgrowless' => t('[-] collapse'),
+ '$showmore' => sprintf( t('%s show all'), '<i class=\'fa fa-chevron-down\'></i>'),
+ '$showfewer' => sprintf( t('%s show less'), '<i class=\'fa fa-chevron-up\'></i>'),
+ '$divgrowmore' => sprintf( t('%s expand'), '<i class=\'fa fa-chevron-down\'></i>'),
+ '$divgrowless' => sprintf( t('%s collapse'),'<i class=\'fa fa-chevron-up\'></i>'),
'$pwshort' => t("Password too short"),
'$pwnomatch' => t("Passwords do not match"),
'$everybody' => t('everybody'),
diff --git a/include/language.php b/include/language.php
index d6b7606ca..96d3e48a9 100644
--- a/include/language.php
+++ b/include/language.php
@@ -82,13 +82,11 @@ function get_best_language() {
if($arr['preferred'] !== 'unset')
return $arr['preferred'];
- $a = get_app();
return ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en');
}
function push_lang($language) {
- global $a;
App::$langsave = App::$language;
@@ -104,7 +102,6 @@ function push_lang($language) {
}
function pop_lang() {
- global $a;
if(App::$language === App::$langsave)
return;
@@ -124,7 +121,6 @@ function pop_lang() {
* @param boolean $install (optional) default false
*/
function load_translation_table($lang, $install = false) {
- global $a;
App::$strings = array();
@@ -136,10 +132,10 @@ function load_translation_table($lang, $install = false) {
}
if(! $install) {
- $plugins = q("SELECT name FROM addon WHERE installed=1;");
+ $plugins = q("SELECT aname FROM addon WHERE installed=1;");
if ($plugins !== false) {
foreach($plugins as $p) {
- $name = $p['name'];
+ $name = $p['aname'];
if(file_exists("addon/$name/lang/$lang/hstrings.php")) {
include("addon/$name/lang/$lang/hstrings.php");
}
@@ -170,7 +166,6 @@ function load_translation_table($lang, $install = false) {
*
*/
function t($s, $ctx = '') {
- global $a;
$cs = $ctx ? '__ctx:' . $ctx . '__ ' . $s : $s;
if (x(App::$strings, $cs)) {
@@ -189,7 +184,7 @@ function t($s, $ctx = '') {
function translate_projectname($s) {
- return str_replace(array('$projectname','$Projectname'),array(Zotlabs\Project\System::get_platform_name(),ucfirst(Zotlabs\Project\System::get_platform_name())),$s);
+ return str_replace(array('$projectname','$Projectname'),array(Zotlabs\Lib\System::get_platform_name(),ucfirst(Zotlabs\Lib\System::get_platform_name())),$s);
}
@@ -205,7 +200,6 @@ function translate_projectname($s) {
* @return string
*/
function tt($singular, $plural, $count, $ctx = ''){
- $a = get_app();
$cs = $ctx ? "__ctx:" . $ctx . "__ " . $singular : $singular;
if (x(App::$strings,$cs)) {
diff --git a/include/message.php b/include/message.php
index a7883d50e..d3d8181ae 100644
--- a/include/message.php
+++ b/include/message.php
@@ -257,7 +257,7 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
}
}
- proc_run('php','include/notifier.php','mail',$post_id);
+ Zotlabs\Daemon\Master::Summon(array('Notifier','mail',$post_id));
$ret['success'] = true;
$ret['message_item'] = intval($post_id);
diff --git a/include/nav.php b/include/nav.php
index 541ab3aed..1fb0e98dc 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -104,6 +104,8 @@ EOT;
if(feature_enabled($channel['channel_id'],'webpages') && (! UNO))
$nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'),'webpages_nav_btn');
+ if(feature_enabled($channel['channel_id'],'wiki') && (! UNO))
+ $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wiki'),"",t('Your wiki'),'wiki_nav_btn');
}
else {
if(! get_account_id()) {
@@ -126,7 +128,7 @@ EOT;
$nav['lock'] = array('logout','','lock',
sprintf( t('%s - click to logout'), $observer['xchan_addr']));
}
- else {
+ elseif(! $_SESSION['authenticated']) {
$nav['loginmenu'][] = Array('rmagic',t('Remote authentication'),'',t('Click to authenticate to your home hub'),'rmagic_nav_btn');
}
@@ -143,16 +145,20 @@ EOT;
if((App::$module != 'home') && (! (local_channel())))
$nav['home'] = array($homelink, t('Home'), "", t('Home Page'),'home_nav_btn');
-
- if((App::$config['system']['register_policy'] == REGISTER_OPEN) && (! local_channel()) && (! remote_channel()))
+ if((App::$config['system']['register_policy'] == REGISTER_OPEN) && (! $_SESSION['authenticated']))
$nav['register'] = array('register',t('Register'), "", t('Create an account'),'register_nav_btn');
- $help_url = z_root() . '/help?f=&cmd=' . App::$cmd;
-
if(! get_config('system','hide_help')) {
- require_once('mod/help.php');
- $context_help = load_context_help();
- $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'),'help_nav_btn',$context_help);
+ $help_url = z_root() . '/help?f=&cmd=' . App::$cmd;
+ $context_help = '';
+ $enable_context_help = ((intval(get_config('system','enable_context_help')) === 1 || get_config('system','enable_context_help') === false) ? true : false);
+ if($enable_context_help === true) {
+ require_once('include/help.php');
+ $context_help = load_context_help();
+ //point directly to /help if $context_help is empty - this can be removed once we have context help for all modules
+ $enable_context_help = (($context_help) ? true : false);
+ }
+ $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'), 'help_nav_btn', $context_help, $enable_context_help);
}
if(! UNO)
@@ -160,7 +166,6 @@ EOT;
$nav['search'] = array('search', t('Search'), "", t('Search site @name, #tag, ?docs, content'));
-
$nav['directory'] = array('directory', t('Directory'), "", t('Channel Directory'),'directory_nav_btn');
@@ -237,7 +242,7 @@ $powered_by = '';
$tpl = get_markup_template('nav.tpl');
App::$page['nav'] .= replace_macros($tpl, array(
- '$baseurl' => z_root(),
+ '$baseurl' => z_root(),
'$sitelocation' => $sitelocation,
'$nav' => $x['nav'],
'$banner' => $banner,
@@ -250,6 +255,19 @@ $powered_by = '';
'$pleasewait' => t('Please wait...')
));
+
+ if(x($_SESSION, 'reload_avatar') && $observer) {
+ // The avatar has been changed on the server but the browser doesn't know that,
+ // force the browser to reload the image from the server instead of its cache.
+ $tpl = get_markup_template('force_image_reload.tpl');
+
+ App::$page['nav'] .= replace_macros($tpl, array(
+ '$imgUrl' => $observer['xchan_photo_m']
+ ));
+ unset($_SESSION['reload_avatar']);
+ }
+
+
call_hooks('page_header', App::$page['nav']);
}
diff --git a/include/network.php b/include/network.php
index ec255581d..47863b680 100644
--- a/include/network.php
+++ b/include/network.php
@@ -21,15 +21,18 @@ function get_capath() {
* TRUE if asked to return binary results (file download)
* @param int $redirects default 0
* internal use, recursion counter
- * @param array $opts (optional parameters) assoziative array with:
+ * @param array $opts (optional parameters) associative array with:
* * \b accept_content => supply Accept: header with 'accept_content' as the value
* * \b timeout => int seconds, default system config value or 60 seconds
* * \b http_auth => username:password
* * \b novalidate => do not validate SSL certs, default is to validate using our CA list
* * \b nobody => only return the header
* * \b filep => stream resource to write body to. header and body are not returned when using this option.
+ * * \b custom => custom request method: e.g. 'PUT', 'DELETE'
+ * * \b cookiejar => cookie file (write)
+ * * \B cookiefile => cookie file (read)
*
- * @return array an assoziative array with:
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -59,12 +62,27 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_HEADER, $false);
}
+ if(x($opts,'upload'))
+ @curl_setopt($ch, CURLOPT_UPLOAD, $opts['upload']);
+
+ if(x($opts,'infile'))
+ @curl_setopt($ch, CURLOPT_INFILE, $opts['infile']);
+
+ if(x($opts,'infilesize'))
+ @curl_setopt($ch, CURLOPT_INFILESIZE, $opts['infilesize']);
+
+ if(x($opts,'readfunc'))
+ @curl_setopt($ch, CURLOPT_READFUNCTION, $opts['readfunc']);
+
if(x($opts,'headers'))
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom'))
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -78,6 +96,14 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
+ if(x($opts,'cookiejar'))
+ @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
+ if(x($opts,'cookiefile'))
+ @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
+
+ if(x($opts,'cookie'))
+ @curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']);
+
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
@@ -165,7 +191,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'filep' => stream resource to write body to. header and body are not returned when using this option.
- * @return array an assoziative array with:
+ * 'custom' => custom request method: e.g. 'PUT', 'DELETE'
+ *
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -174,6 +202,10 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
*/
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
+// logger('url: ' . $url);
+// logger('params: ' . print_r($params,true));
+// logger('opts: ' . print_r($opts,true));
+
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
$ch = curl_init($url);
@@ -199,12 +231,17 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if(x($opts,'headers')) {
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
-logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
}
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom')) {
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+ @curl_setopt($ch, CURLOPT_POST,0);
+ }
+
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -218,6 +255,16 @@ logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
+
+ if(x($opts,'cookiejar'))
+ @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
+ if(x($opts,'cookiefile'))
+ @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
+
+
+ if(x($opts,'cookie'))
+ @curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']);
+
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
@@ -595,8 +642,6 @@ function parse_xml_string($s,$strict = true) {
function scale_external_images($s, $include_link = true, $scale_replace = false) {
- $a = get_app();
-
// Picture addresses can contain special characters
$s = htmlspecialchars_decode($s, ENT_COMPAT);
@@ -1168,6 +1213,10 @@ function discover_by_webbie($webbie) {
if(! $x)
$probe_old = true;
+
+ if((! $dfrn) && (! $has_salmon))
+ $probe_old = true;
+
if($probe_old) {
$y = old_webfinger($webbie);
if($y) {
@@ -1294,8 +1343,20 @@ function discover_by_webbie($webbie) {
$fullname = $vcard['fn'];
if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0))
$vcard['photo'] = $diaspora_base . '/' . $vcard['photo'];
+ if(($vcard['key']) && (! $pubkey))
+ $pubkey = $vcard['key'];
if(! $avatar)
$avatar = $vcard['photo'];
+ if($diaspora) {
+ if(($vcard['guid']) && (! $diaspora_guid))
+ $diaspora_guid = $vcard['guid'];
+ if(($vcard['url']) && (! $diaspora_base))
+ $diaspora_base = $vcard['url'];
+
+
+
+
+ }
}
}
@@ -1614,8 +1675,6 @@ function fetch_xrd_links($url) {
function scrape_vcard($url) {
- $a = get_app();
-
$ret = array();
logger('scrape_vcard: url=' . $url);
@@ -1695,8 +1754,6 @@ function scrape_vcard($url) {
function scrape_feed($url) {
- $a = get_app();
-
$ret = array();
$level = 0;
$x = z_fetch_url($url,false,$level,array('novalidate' => true));
@@ -1815,8 +1872,6 @@ function service_plink($contact, $guid) {
function format_and_send_email($sender,$xchan,$item) {
- require_once('include/enotify.php');
-
$title = $item['title'];
$body = $item['body'];
@@ -1835,7 +1890,7 @@ function format_and_send_email($sender,$xchan,$item) {
$tpl = get_markup_template('email_notify_html.tpl');
$email_html_body = replace_macros($tpl,array(
'$banner' => $banner,
- '$notify_icon' => Zotlabs\Project\System::get_notify_icon(),
+ '$notify_icon' => Zotlabs\Lib\System::get_notify_icon(),
'$product' => $product,
'$preamble' => '',
'$sitename' => $sitename,
@@ -1881,7 +1936,7 @@ function format_and_send_email($sender,$xchan,$item) {
// use the EmailNotification library to send the message
- enotify::send(array(
+ Zotlabs\Lib\Enotify::send(array(
'fromName' => $product,
'fromEmail' => $sender_email,
'replyTo' => $sender_email,
@@ -1912,10 +1967,13 @@ function do_delivery($deliveries) {
$deliver = array();
foreach($deliveries as $d) {
+ if(! $d)
+ continue;
+
$deliver[] = $d;
if(count($deliver) >= $deliveries_per_process) {
- proc_run('php','include/deliver.php',$deliver);
+ Zotlabs\Daemon\Master::Summon(array('Deliver',$deliver));
$deliver = array();
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
@@ -1925,7 +1983,7 @@ function do_delivery($deliveries) {
// catch any stragglers
if($deliver)
- proc_run('php','include/deliver.php',$deliver);
+ Zotlabs\Daemon\Master::Summon(array('Deliver',$deliver));
}
@@ -1933,9 +1991,6 @@ function do_delivery($deliveries) {
function get_site_info() {
- global $db;
- global $a;
-
$register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN');
$directory_mode = Array('DIRECTORY_MODE_NORMAL', 'DIRECTORY_MODE_PRIMARY', 'DIRECTORY_MODE_SECONDARY', 256 => 'DIRECTORY_MODE_STANDALONE');
@@ -1966,14 +2021,7 @@ function get_site_info() {
else
$service_class = false;
- $visible_plugins = array();
- if(is_array(App::$plugins) && count(App::$plugins)) {
- $r = q("select * from addon where hidden = 0");
- if(count($r))
- foreach($r as $rr)
- $visible_plugins[] = $rr['name'];
- }
- sort($visible_plugins);
+ $visible_plugins = visible_plugin_list();
if(@is_dir('.git') && function_exists('shell_exec'))
$commit = trim(@shell_exec('git log -1 --format="%h"'));
@@ -1983,8 +2031,8 @@ function get_site_info() {
$site_info = get_config('system','info');
$site_name = get_config('system','sitename');
if(! get_config('system','hidden_version_siteinfo')) {
- $version = Zotlabs\Project\System::get_project_version();
- $tag = Zotlabs\Project\System::get_std_version();
+ $version = Zotlabs\Lib\System::get_project_version();
+ $tag = Zotlabs\Lib\System::get_std_version();
if(@is_dir('.git') && function_exists('shell_exec')) {
$commit = trim( @shell_exec('git log -1 --format="%h"'));
@@ -2020,7 +2068,7 @@ function get_site_info() {
$data = Array(
'version' => $version,
'version_tag' => $tag,
- 'server_role' => Zotlabs\Project\System::get_server_role(),
+ 'server_role' => Zotlabs\Lib\System::get_server_role(),
'commit' => $commit,
'url' => z_root(),
'plugins' => $visible_plugins,
@@ -2034,8 +2082,8 @@ function get_site_info() {
'locked_features' => $locked_features,
'admin' => $admin,
'site_name' => (($site_name) ? $site_name : ''),
- 'platform' => Zotlabs\Project\System::get_platform_name(),
- 'dbdriver' => $db->getdriver(),
+ 'platform' => Zotlabs\Lib\System::get_platform_name(),
+ 'dbdriver' => DBA::$dba->getdriver(),
'lastpoll' => get_config('system','lastpoll'),
'info' => (($site_info) ? $site_info : ''),
'channels_total' => $channels_total_stat,
@@ -2114,8 +2162,9 @@ function check_channelallowed($hash) {
return $retvalue;
}
-function deliverable_singleton($xchan) {
- $r = q("select abook_instance from abook where abook_xchan = '%s' limit 1",
+function deliverable_singleton($channel_id,$xchan) {
+ $r = q("select abook_instance from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
+ intval($channel_id),
dbesc($xchan['xchan_hash'])
);
if($r) {
@@ -2127,3 +2176,44 @@ function deliverable_singleton($xchan) {
return false;
}
+
+
+function get_repository_version($branch = 'master') {
+
+ $path = "https://raw.githubusercontent.com/redmatrix/hubzilla/$branch/boot.php";
+
+ $x = z_fetch_url($path);
+ if($x['success']) {
+ $y = preg_match('/define(.*?)STD_VERSION(.*?)([0-9.].*)\'/',$x['body'],$matches);
+ if($y)
+ return $matches[3];
+ }
+ return '?.?';
+
+}
+
+function network_to_name($s) {
+
+ $nets = array(
+ NETWORK_DFRN => t('Friendica'),
+ NETWORK_FRND => t('Friendica'),
+ NETWORK_OSTATUS => t('OStatus'),
+ NETWORK_GNUSOCIAL => t('GNU-Social'),
+ NETWORK_FEED => t('RSS/Atom'),
+ NETWORK_MAIL => t('Email'),
+ NETWORK_DIASPORA => t('Diaspora'),
+ NETWORK_FACEBOOK => t('Facebook'),
+ NETWORK_ZOT => t('Zot'),
+ NETWORK_LINKEDIN => t('LinkedIn'),
+ NETWORK_XMPP => t('XMPP/IM'),
+ NETWORK_MYSPACE => t('MySpace'),
+ );
+
+ call_hooks('network_to_name', $nets);
+
+ $search = array_keys($nets);
+ $replace = array_values($nets);
+
+ return str_replace($search,$replace,$s);
+
+}
diff --git a/include/notifier.php b/include/notifier.php
deleted file mode 100644
index 628847d54..000000000
--- a/include/notifier.php
+++ /dev/null
@@ -1,646 +0,0 @@
-<?php /** @file */
-
-require_once("boot.php");
-require_once('include/queue_fn.php');
-require_once('include/html2plain.php');
-
-/*
- * This file was at one time responsible for doing all deliveries, but this caused
- * big problems on shared hosting systems, where the process might get killed by the
- * hosting provider and nothing would get delivered.
- * It now only delivers one message under certain cases, and invokes a queued
- * delivery mechanism (include/deliver.php) to deliver individual contacts at
- * controlled intervals.
- * This has a much better chance of surviving random processes getting killed
- * by the hosting provider.
- *
- * The basic flow is:
- * Identify the type of message
- * Collect any information that needs to be sent
- * Convert it into a suitable generic format for sending
- * Figure out who the recipients are and if we need to relay
- * through a conversation owner
- * Once we know what recipients are involved, collect a list of
- * destination sites
- * Build and store a queue item for each unique site and invoke
- * a delivery process for each site or a small number of sites (1-3)
- * and add a slight delay between each delivery invocation if desired (usually)
- *
- */
-
-/*
- * The notifier is typically called with:
- *
- * proc_run('php', "include/notifier.php", COMMAND, ITEM_ID);
- *
- * where COMMAND is one of the following:
- *
- * activity (in diaspora.php, dfrn_confirm.php, profiles.php)
- * comment-import (in diaspora.php, items.php)
- * comment-new (in item.php)
- * drop (in diaspora.php, items.php, photos.php)
- * edit_post (in item.php)
- * event (in events.php)
- * expire (in items.php)
- * like (in like.php, poke.php)
- * mail (in message.php)
- * tag (in photos.php, poke.php, tagger.php)
- * tgroup (in items.php)
- * wall-new (in photos.php, item.php)
- *
- * and ITEM_ID is the id of the item in the database that needs to be sent to others.
- *
- * ZOT
- * permission_create abook_id
- * permission_update abook_id
- * refresh_all channel_id
- * purge_all channel_id
- * expire channel_id
- * relay item_id (item was relayed to owner, we will deliver it as owner)
- * single_activity item_id (deliver to a singleton network from the appropriate clone)
- * single_mail mail_id (deliver to a singleton network from the appropriate clone)
- * location channel_id
- * request channel_id xchan_hash message_id
- * rating xlink_id
- *
- */
-
-require_once('include/cli_startup.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/identity.php');
-require_once('include/Contact.php');
-
-function notifier_run($argv, $argc){
-
- cli_startup();
-
- $a = get_app();
-
-
- if($argc < 3)
- return;
-
- logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
-
- $cmd = $argv[1];
-
- $item_id = $argv[2];
-
- $extra = (($argc > 3) ? $argv[3] : null);
-
- if(! $item_id)
- return;
-
- $sys = get_sys_channel();
-
- $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;
- $location = false;
- $recipients = array();
- $url_recipients = array();
- $normal_mode = true;
- $packet_type = 'undefined';
-
- if($cmd === 'mail') {
- $normal_mode = false;
- $mail = true;
- $private = true;
- $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
- intval($item_id)
- );
- if(! $message) {
- return;
- }
- xchan_mail_query($message[0]);
- $uid = $message[0]['channel_id'];
- $recipients[] = $message[0]['from_xchan']; // include clones
- $recipients[] = $message[0]['to_xchan'];
- $item = $message[0];
-
- $encoded_item = encode_mail($item);
-
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($item['channel_id'])
- );
- if($s)
- $channel = $s[0];
-
- }
- elseif($cmd === 'request') {
- $channel_id = $item_id;
- $xchan = $argv[3];
- $request_message_id = $argv[4];
-
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($channel_id)
- );
- if($s)
- $channel = $s[0];
-
- $private = true;
- $recipients[] = $xchan;
- $packet_type = 'request';
- $normal_mode = false;
- }
- elseif($cmd == 'permission_update' || $cmd == 'permission_create') {
- // Get the (single) recipient
- $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
- intval($item_id)
- );
- if($r) {
- $uid = $r[0]['abook_channel'];
- // Get the sender
- $channel = channelx_by_n($uid);
- if($channel) {
- $perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
-
- if($cmd == 'permission_create')
- call_hooks('permissions_create',$perm_update);
- else
- call_hooks('permissions_update',$perm_update);
-
- if($perm_update['success']) {
- if($perm_update['deliveries']) {
- $deliveries[] = $perm_update['deliveries'];
- do_delivery($deliveries);
- }
- return;
- }
- else {
- $recipients[] = $r[0]['abook_xchan'];
- $private = false;
- $packet_type = 'refresh';
- $packet_recips = array(array('guid' => $r[0]['xchan_guid'],'guid_sig' => $r[0]['xchan_guid_sig'],'hash' => $r[0]['xchan_hash']));
- }
- }
- }
- }
- elseif($cmd === 'refresh_all') {
- logger('notifier: refresh_all: ' . $item_id);
- $uid = $item_id;
- $channel = channelx_by_n($item_id);
- $r = q("select abook_xchan from abook where abook_channel = %d",
- intval($item_id)
- );
- if($r) {
- foreach($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
- }
- }
- $private = false;
- $packet_type = 'refresh';
- }
- elseif($cmd === 'location') {
- logger('notifier: location: ' . $item_id);
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($item_id)
- );
- if($s)
- $channel = $s[0];
- $uid = $item_id;
- $recipients = array();
- $r = q("select abook_xchan from abook where abook_channel = %d",
- intval($item_id)
- );
- if($r) {
- foreach($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
- }
- }
-
- $encoded_item = array('locations' => zot_encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
- $target_item = array('aid' => $channel['channel_account_id'],'uid' => $channel['channel_id']);
- $private = false;
- $packet_type = 'location';
- $location = true;
- }
- elseif($cmd === 'purge_all') {
- logger('notifier: purge_all: ' . $item_id);
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($item_id)
- );
- if($s)
- $channel = $s[0];
- $uid = $item_id;
- $recipients = array();
- $r = q("select abook_xchan from abook where abook_channel = %d",
- intval($item_id)
- );
- if($r) {
- foreach($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
- }
- }
- $private = false;
- $packet_type = 'purge';
- }
- else {
-
- // Normal items
-
- // Fetch the target item
-
- $r = q("SELECT * FROM item WHERE id = %d and parent != 0 LIMIT 1",
- intval($item_id)
- );
-
- if(! $r)
- return;
-
- xchan_query($r);
-
- $r = fetch_post_tags($r);
-
- $target_item = $r[0];
- $deleted_item = false;
-
- if(intval($target_item['item_deleted'])) {
- logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
- $deleted_item = true;
- }
-
- if(intval($target_item['item_type']) != ITEM_TYPE_POST) {
- logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
- return;
- }
- if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed'])) {
- logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
- return;
- }
-
- if(strpos($target_item['postopts'],'nodeliver') !== false) {
- logger('notifier: target item is undeliverable', LOGGER_DEBUG);
- return;
- }
-
- $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
- intval($target_item['uid'])
- );
- if($s)
- $channel = $s[0];
-
- if($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
- logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
- return;
- }
-
-
- if($target_item['id'] == $target_item['parent']) {
- $parent_item = $target_item;
- $top_level_post = true;
- }
- else {
- // fetch the parent item
- $r = q("SELECT * from item where id = %d order by id asc",
- intval($target_item['parent'])
- );
-
- if(! $r)
- return;
-
- if(strpos($r[0]['postopts'],'nodeliver') !== false) {
- logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE);
- return;
- }
-
- xchan_query($r);
- $r = fetch_post_tags($r);
-
- $parent_item = $r[0];
- $top_level_post = false;
- }
-
- // avoid looping of discover items 12/4/2014
-
- if($sys && $parent_item['uid'] == $sys['channel_id'])
- return;
-
- $encoded_item = encode_item($target_item);
-
- // Send comments to the owner to re-deliver to everybody in the conversation
- // We only do this if the item in question originated on this site. This prevents looping.
- // To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
- // Relaying should never be initiated on a post that arrived from elsewhere.
-
- // We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this
- // flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
- // the hostname in the message_id and provides a second (fallback) opinion.
-
- $relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
-
-
-
- $uplink = false;
-
- // $cmd === 'relay' indicates the owner is sending it to the original recipients
- // don't allow the item in the relay command to relay to owner under any circumstances, it will loop
-
- logger('notifier: relay_to_owner: ' . (($relay_to_owner) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG);
- logger('notifier: top_level_post: ' . (($top_level_post) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG);
-
- // tag_deliver'd post which needs to be sent back to the original author
-
- if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
- logger('notifier: uplink');
- $uplink = true;
- }
-
- if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
- logger('notifier: followup relay', LOGGER_DEBUG);
- $recipients = array(($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
- $private = true;
- if(! $encoded_item['flags'])
- $encoded_item['flags'] = array();
- $encoded_item['flags'][] = 'relay';
- }
- else {
- logger('notifier: normal distribution', LOGGER_DEBUG);
- if($cmd === 'relay')
- logger('notifier: owner relay');
-
- // if our parent is a tag_delivery recipient, uplink to the original author causing
- // a delivery fork.
-
- if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) {
- // don't uplink a relayed post to the relay owner
- if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
- logger('notifier: uplinking this item');
- proc_run('php','include/notifier.php','uplink',$item_id);
- }
- }
-
- $private = false;
- $recipients = collect_recipients($parent_item,$private);
-
- // FIXME add any additional recipients such as mentions, etc.
-
- // don't send deletions onward for other people's stuff
- // TODO verify this is needed - copied logic from same place in old code
-
- if(intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) {
- logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
- return;
- }
- }
-
- }
-
- $walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
-
- // Generic delivery section, we have an encoded item and recipients
- // Now start the delivery process
-
- $x = $encoded_item;
- $x['title'] = 'private';
- $x['body'] = 'private';
- logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
-
- stringify_array_elms($recipients);
- if(! $recipients)
- return;
-
-// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
-
- $env_recips = (($private) ? array() : null);
-
- $details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . implode(',',$recipients) . ")");
-
-
- $recip_list = array();
-
- if($details) {
- foreach($details as $d) {
-
- $recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
- if($private)
- $env_recips[] = array('guid' => $d['xchan_guid'],'guid_sig' => $d['xchan_guid_sig'],'hash' => $d['xchan_hash']);
-
- if($d['xchan_network'] === 'mail' && $normal_mode) {
- $delivery_options = get_xconfig($d['xchan_hash'],'system','delivery_mode');
- if(! $delivery_options)
- format_and_send_email($channel,$d,$target_item);
- }
- }
- }
-
-
- $narr = array(
- 'channel' => $channel,
- 'env_recips' => $env_recips,
- 'packet_recips' => $packet_recips,
- 'recipients' => $recipients,
- 'item' => $item,
- 'target_item' => $target_item,
- 'top_level_post' => $top_level_post,
- 'private' => $private,
- 'followup' => $followup,
- 'relay_to_owner' => $relay_to_owner,
- 'uplink' => $uplink,
- 'cmd' => $cmd,
- 'mail' => $mail,
- 'location' => $location,
- 'request' => $request,
- 'normal_mode' => $normal_mode,
- 'packet_type' => $packet_type,
- 'walltowall' => $walltowall,
- 'queued' => array()
- );
-
- call_hooks('notifier_process', $narr);
- if($narr['queued']) {
- foreach($narr['queued'] as $pq)
- $deliveries[] = $pq;
- }
-
-
- if(($private) && (! $env_recips)) {
- // shouldn't happen
- logger('notifier: private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE);
- }
-
- logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
-
-
- // Now we have collected recipients (except for external mentions, FIXME)
- // Let's reduce this to a set of hubs.
-
- $r = q("select * from hubloc where hubloc_hash in (" . implode(',',$recipients) . ")
- and hubloc_error = 0 and hubloc_deleted = 0"
- );
-
-
- if(! $r) {
- logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
- return;
- }
-
- $hubs = $r;
-
-
-
- /**
- * 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
-
-
- 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($hub['hubloc_network'] == 'zot') {
- if(! in_array($hub['hubloc_sitekey'],$keys)) {
- $hublist[] = $hub['hubloc_host'];
- $dhubs[] = $hub;
- $keys[] = $hub['hubloc_sitekey'];
- }
- }
- else {
- if(! in_array($hub['hubloc_url'],$urls)) {
- $hublist[] = $hub['hubloc_host'];
- $dhubs[] = $hub;
- $urls[] = $hub['hubloc_url'];
- }
- }
- }
-
- logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG);
-
-
- foreach($dhubs as $hub) {
-
- if($hub['hubloc_network'] !== 'zot') {
-
- $narr = array(
- 'channel' => $channel,
- 'env_recips' => $env_recips,
- 'packet_recips' => $packet_recips,
- 'recipients' => $recipients,
- 'item' => $item,
- 'target_item' => $target_item,
- 'hub' => $hub,
- 'top_level_post' => $top_level_post,
- 'private' => $private,
- 'followup' => $followup,
- 'relay_to_owner' => $relay_to_owner,
- 'uplink' => $uplink,
- 'cmd' => $cmd,
- 'mail' => $mail,
- 'location' => $location,
- 'request' => $request,
- 'normal_mode' => $normal_mode,
- 'packet_type' => $packet_type,
- 'walltowall' => $walltowall,
- 'queued' => array()
- );
-
-
- call_hooks('notifier_hub',$narr);
- if($narr['queued']) {
- foreach($narr['queued'] as $pq)
- $deliveries[] = $pq;
- }
- continue;
-
- }
-
- // default: zot protocol
-
- $hash = random_string();
- $packet = null;
-
- if($packet_type === 'refresh' || $packet_type === 'purge') {
- $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'],$hash,
- array('message_id' => $request_message_id)
- );
- }
-
- if($packet) {
- queue_insert(array(
- 'hash' => $hash,
- 'account_id' => $channel['channel_account_id'],
- 'channel_id' => $channel['channel_id'],
- 'posturl' => $hub['hubloc_callback'],
- 'notify' => $packet
- ));
- }
- else {
- $packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash);
- queue_insert(array(
- 'hash' => $hash,
- 'account_id' => $target_item['aid'],
- 'channel_id' => $target_item['uid'],
- 'posturl' => $hub['hubloc_callback'],
- 'notify' => $packet,
- 'msg' => json_encode($encoded_item)
- ));
-
- // only create delivery reports for normal undeleted items
- if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
- q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ",
- dbesc($target_item['mid']),
- dbesc($hub['hubloc_host']),
- dbesc($hub['hubloc_host']),
- dbesc('queued'),
- dbesc(datetime_convert()),
- dbesc($channel['channel_hash']),
- dbesc($hash)
- );
- }
- }
-
- $deliveries[] = $hash;
- }
-
- if($normal_mode) {
- $x = q("select * from hook where hook = 'notifier_normal'");
- if($x)
- proc_run('php','include/deliver_hooks.php', $target_item['id']);
- }
-
- if($deliveries)
- do_delivery($deliveries);
-
- logger('notifier: basic loop complete.', LOGGER_DEBUG);
-
- call_hooks('notifier_end',$target_item);
-
- logger('notifer: complete.');
- return;
-
-}
-
-
-if (array_search(__file__,get_included_files())===0){
- notifier_run($argv,$argc);
- killme();
-}
diff --git a/include/notify.php b/include/notify.php
deleted file mode 100644
index 2b032b56b..000000000
--- a/include/notify.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php /** @file */
-
-
-function format_notification($item) {
-
- $ret = '';
-
- require_once('include/conversation.php');
-
- // Call localize_item with the "brief" flag to get a one line status for activities.
- // This should set $item['localized'] to indicate we have a brief summary.
-
- localize_item($item);
-
- if($item_localize) {
- $itemem_text = $item['localize'];
- }
- else {
- $itemem_text = (($item['item_thread_top'])
- ? t('created a new post')
- : sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
- }
-
- // convert this logic into a json array just like the system notifications
-
- return array(
- 'notify_link' => $item['llink'],
- 'name' => $item['author']['xchan_name'],
- 'url' => $item['author']['xchan_url'],
- 'photo' => $item['author']['xchan_photo_s'],
- 'when' => relative_date($item['created']),
- 'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
- 'message' => strip_tags(bbcode($itemem_text))
- );
-
-}
-
diff --git a/include/oauth.php b/include/oauth.php
index ec41a5dd2..a3c52bf27 100644
--- a/include/oauth.php
+++ b/include/oauth.php
@@ -37,7 +37,7 @@ class ZotOAuth1DataStore extends OAuth1DataStore {
logger(__function__.":".$consumer.", ". $token_type.", ".$token, LOGGER_DEBUG);
- $r = q("SELECT id, secret, scope, expires, uid FROM tokens WHERE client_id = '%s' AND scope = '%s' AND id = '%s'",
+ $r = q("SELECT id, secret, auth_scope, expires, uid FROM tokens WHERE client_id = '%s' AND auth_scope = '%s' AND id = '%s'",
dbesc($consumer->key),
dbesc($token_type),
dbesc($token)
@@ -45,7 +45,7 @@ class ZotOAuth1DataStore extends OAuth1DataStore {
if (count($r)){
$ot=new OAuth1Token($r[0]['id'],$r[0]['secret']);
- $ot->scope=$r[0]['scope'];
+ $ot->scope=$r[0]['auth_scope'];
$ot->expires = $r[0]['expires'];
$ot->uid = $r[0]['uid'];
return $ot;
@@ -79,7 +79,7 @@ class ZotOAuth1DataStore extends OAuth1DataStore {
$k = $consumer;
}
- $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires) VALUES ('%s','%s','%s','%s', %d)",
+ $r = q("INSERT INTO tokens (id, secret, client_id, auth_scope, expires) VALUES ('%s','%s','%s','%s', %d)",
dbesc($key),
dbesc($sec),
dbesc($k),
@@ -110,7 +110,7 @@ class ZotOAuth1DataStore extends OAuth1DataStore {
$key = $this->gen_token();
$sec = $this->gen_token();
- $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires, uid) VALUES ('%s','%s','%s','%s', %d, %d)",
+ $r = q("INSERT INTO tokens (id, secret, client_id, auth_scope, expires, uid) VALUES ('%s','%s','%s','%s', %d, %d)",
dbesc($key),
dbesc($sec),
dbesc($consumer->key),
@@ -170,7 +170,7 @@ class ZotOAuth1 extends OAuth1Server {
);
if($x) {
require_once('include/security.php');
- authenticate_success($x[0],true,false,true,true);
+ authenticate_success($x[0],null,true,false,true,true);
$_SESSION['allow_api'] = true;
}
}
@@ -249,7 +249,7 @@ class FKOAuth2 extends OAuth2 {
protected function getAuthCode($code) {
- $r = q("SELECT id, client_id, redirect_uri, expires, scope FROM auth_codes WHERE id = '%s'",
+ $r = q("SELECT id, client_id, redirect_uri, expires, auth_scope FROM auth_codes WHERE id = '%s'",
dbesc($code));
if (count($r))
@@ -259,7 +259,7 @@ class FKOAuth2 extends OAuth2 {
protected function setAuthCode($code, $client_id, $redirect_uri, $expires, $scope = NULL) {
$r = q("INSERT INTO auth_codes
- (id, client_id, redirect_uri, expires, scope) VALUES
+ (id, client_id, redirect_uri, expires, auth_scope) VALUES
('%s', '%s', '%s', %d, '%s')",
dbesc($code),
dbesc($client_id),
diff --git a/include/oembed.php b/include/oembed.php
index 3994af0fb..fe3a3c33c 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -1,69 +1,102 @@
<?php /** @file */
+
+
+use Zotlabs\Lib as Zlib;
+
function oembed_replacecb($matches){
$embedurl=$matches[1];
+ $result = oembed_action($embedurl);
+ if($result['action'] === 'block') {
+ return '<a href="' . $result['url'] . '">' . $result['url'] . '</a>';
+ }
+
+ $j = oembed_fetch_url($result['url']);
+ $s = oembed_format_object($j);
+ return $s;
+}
+
+
+function oembed_action($embedurl) {
+
+ $host = '';
+ $action = 'filter';
+
+ $embedurl = trim(str_replace('&amp;','&', $embedurl));
+
+ logger('oembed_action: ' . $embedurl, LOGGER_DEBUG, LOG_INFO);
+
+ if(strpos($embedurl,'http://') === 0) {
+ if(intval(get_config('system','embed_sslonly'))) {
+ $action = 'block';
+ }
+ }
// site white/black list
if(($x = get_config('system','embed_deny'))) {
- $l = explode("\n",$x);
- if($l) {
- foreach($l as $ll) {
- if(trim($ll) && strpos($embedurl,trim($ll)) !== false)
- return '<a href="' . $embedurl . '">' . $embedurl . '</a>';
+ if(($x) && (! is_array($x)))
+ $x = explode("\n",$x);
+ if($x) {
+ foreach($x as $ll) {
+ $t = trim($ll);
+ if(($t) && (strpos($embedurl,$t) !== false)) {
+ $action = 'block';
+ break;
+ }
}
}
}
+
+ $found = false;
+
if(($x = get_config('system','embed_allow'))) {
- $found = false;
- $l = explode("\n",$x);
- if($l) {
- foreach($l as $ll) {
- if(trim($ll) && strpos($embedurl,trim($ll)) !== false) {
+ if(($x) && (! is_array($x)))
+ $x = explode("\n",$x);
+ if($x) {
+ foreach($x as $ll) {
+ $t = trim($ll);
+ if(($t) && (strpos($embedurl,$t) !== false) && ($action !== 'block')) {
$found = true;
+ $action = 'allow';
break;
}
}
}
- if(! $found) {
- return '<a href="' . $embedurl . '">' . $embedurl . '</a>';
+ if((! $found) && ($action !== 'block')) {
+ $action = 'filter';
}
}
- // implements a personal embed white/black list for logged in members
+ // allow individual members to block something that wasn't blocked already.
+ // They cannot over-ride the site to allow or change the filtering on an
+ // embed that is not allowed by the site admin.
+
if(local_channel()) {
if(($x = get_pconfig(local_channel(),'system','embed_deny'))) {
- $l = explode("\n",$x);
- if($l) {
- foreach($l as $ll) {
- if(trim($ll) && strpos($embedurl,trim($ll)) !== false)
- return '<a href="' . $embedurl . '">' . $embedurl . '</a>';
- }
- }
- }
- if(($x = get_pconfig(local_channel(),'system','embed_allow'))) {
- $found = false;
- $l = explode("\n",$x);
- if($l) {
- foreach($l as $ll) {
- if(trim($ll) && strpos($embedurl,trim($ll)) !== false) {
- $found = true;
+ if(($x) && (! is_array($x)))
+ $x = explode("\n",$x);
+ if($x) {
+ foreach($x as $ll) {
+ $t = trim($ll);
+ if(($t) && (strpos($embedurl,$t) !== false)) {
+ $action = 'block';
break;
}
}
}
- if(! $found) {
- return '<a href="' . $embedurl . '">' . $embedurl . '</a>';
- }
}
}
- $j = oembed_fetch_url($embedurl);
- $s = oembed_format_object($j);
- return $s;
-}
+ $arr = array('url' => $embedurl, 'action' => $action);
+ call_hooks('oembed_action',$arr);
+
+ logger('action: ' . $arr['action'] . ' url: ' . $arr['url'], LOGGER_DEBUG,LOG_DEBUG);
+ return $arr;
+
+}
// if the url is embeddable with oembed, return the bbcode link.
@@ -79,42 +112,54 @@ function oembed_process($url) {
function oembed_fetch_url($embedurl){
- $a = get_app();
+ // These media files should now be caught in bbcode.php
+ // left here as a fallback in case this is called from another source
- $embedurl = str_replace('&amp;','&', $embedurl);
+ $noexts = array(".mp3",".mp4",".ogg",".ogv",".oga",".ogm",".webm",".opus");
-// logger('fetch: ' . $embedurl);
+ $result = oembed_action($embedurl);
- $txt = Cache::get(App::$videowidth . $embedurl);
+ $embedurl = $result['url'];
+ $action = $result['action'];
- if(strstr($txt,'youtu') && strstr(z_root(),'https:')) {
- $txt = str_replace('http:','https:',$txt);
+ foreach($noexts as $ext) {
+ if(strpos(strtolower($embedurl),$ext) !== false) {
+ $action = 'block';
+ }
}
- // These media files should now be caught in bbcode.php
- // left here as a fallback in case this is called from another source
+ $txt = null;
- $noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm","opus");
- $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION);
-
-
- if(is_null($txt)){
- $txt = "";
+ if($action !== 'block') {
+ $txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $embedurl);
+
+ if(strstr($txt,'youtu') && strstr(z_root(),'https:')) {
+ $txt = str_replace('http:','https:',$txt);
+ }
+ }
- if (in_array($ext, $noexts)) {
+ if(is_null($txt)) {
+
+ $txt = "";
+ $furl = $embedurl;
+ $zrl = false;
+
+ if(local_channel()) {
require_once('include/hubloc.php');
- $zrl = is_matrix_url($embedurl);
+ $zrl = is_matrix_url($furl);
if($zrl)
- $embedurl = zid($embedurl);
+ $furl = zid($furl);
}
- else {
+
+
+ if ($action !== 'block') {
// try oembed autodiscovery
$redirects = 0;
- $result = z_fetch_url($embedurl, false, $redirects, array('timeout' => 15, 'accept_content' => "text/*", 'novalidate' => true ));
+ $result = z_fetch_url($furl, false, $redirects, array('timeout' => 15, 'accept_content' => "text/*", 'novalidate' => true ));
if($result['success'])
$html_text = $result['body'];
- if($html_text){
+ if($html_text) {
$dom = @DOMDocument::loadHTML($html_text);
if ($dom){
$xpath = new DOMXPath($dom);
@@ -149,17 +194,41 @@ function oembed_fetch_url($embedurl){
}
$txt=trim($txt);
+
if ($txt[0]!="{") $txt='{"type":"error"}';
//save in cache
if(! get_config('system','oembed_cache_disable'))
- Cache::set(App::$videowidth . $embedurl,$txt);
+ Zlib\Cache::set('[' . App::$videowidth . '] ' . $embedurl,$txt);
}
$j = json_decode($txt);
+
+ if($action === 'filter') {
+ if($j->html) {
+ $orig = $j->html;
+ $allow_position = (($zrl) ? true : false);
+ $j->html = purify_html($j->html,$allow_position);
+ if($j->html != $orig) {
+ logger('oembed html was purified. original: ' . $orig . ' purified: ' . $j->html, LOGGER_DEBUG, LOG_INFO);
+ }
+
+ $orig_len = trim(mb_strlen($orig));
+ $new_len = trim(mb_strlen($j->html));
+ if(! $new_len)
+ $j->type = 'error';
+ elseif($orig_len) {
+ $ratio = $new_len / $orig_len;
+ if($ratio < 0.8)
+ $j->type = 'error';
+ }
+
+ }
+ }
+
$j->embedurl = $embedurl;
// logger('fetch return: ' . print_r($j,true));
@@ -170,7 +239,7 @@ function oembed_fetch_url($embedurl){
}
function oembed_format_object($j){
- $a = get_app();
+
$embedurl = $j->embedurl;
// logger('format: ' . print_r($j,true));
diff --git a/include/onedirsync.php b/include/onedirsync.php
deleted file mode 100644
index ce516da9d..000000000
--- a/include/onedirsync.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/dir_fns.php');
-
-
-function onedirsync_run($argv, $argc){
-
-
- cli_startup();
- $a = get_app();
-
- logger('onedirsync: start ' . intval($argv[1]));
-
- if(($argc > 1) && (intval($argv[1])))
- $update_id = intval($argv[1]);
-
- if(! $update_id) {
- logger('onedirsync: no update');
- return;
- }
-
- $r = q("select * from updates where ud_id = %d limit 1",
- intval($update_id)
- );
-
- if(! $r)
- return;
- if(($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (! $r[0]['ud_addr']))
- return;
-
- // Have we probed this channel more recently than the other directory server
- // (where we received this update from) ?
- // If we have, we don't need to do anything except mark any older entries updated
-
- $x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
- dbesc($r[0]['ud_addr']),
- dbesc($r[0]['ud_date']),
- intval(UPDATE_FLAGS_UPDATED)
- );
- if($x) {
- $y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($r[0]['ud_addr']),
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($x[0]['ud_date'])
- );
- return;
- }
-
- // ignore doing an update if this ud_addr refers to a known dead hubloc
-
- $h = q("select * from hubloc where hubloc_addr = '%s' limit 1",
- dbesc($r[0]['ud_addr'])
- );
- if(($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
- $y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($r[0]['ud_addr']),
- intval(UPDATE_FLAGS_UPDATED)
- );
-
- return;
- }
-
- // we might have to pull this out some day, but for now update_directory_entry()
- // runs zot_finger() and is kind of zot specific
-
- if($h && $h[0]['hubloc_network'] !== 'zot')
- return;
-
- update_directory_entry($r[0]);
-
- return;
-}
-
-if (array_search(__file__,get_included_files())===0){
- onedirsync_run($argv,$argc);
- killme();
-}
diff --git a/include/onepoll.php b/include/onepoll.php
deleted file mode 100644
index fedeb1e95..000000000
--- a/include/onepoll.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php /** @file */
-
-require_once('boot.php');
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/socgraph.php');
-require_once('include/Contact.php');
-
-
-function onepoll_run($argv, $argc){
-
-
- cli_startup();
- $a = get_app();
-
- logger('onepoll: start');
-
- if(($argc > 1) && (intval($argv[1])))
- $contact_id = intval($argv[1]);
-
- if(! $contact_id) {
- logger('onepoll: no contact');
- return;
- }
-
- $d = datetime_convert();
-
- $contacts = q("SELECT abook.*, xchan.*, account.*
- FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
- where abook_id = %d
- and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
- AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
- intval($contact_id),
- intval(ACCOUNT_OK),
- intval(ACCOUNT_UNVERIFIED)
- );
-
- if(! $contacts) {
- logger('onepoll: abook_id not found: ' . $contact_id);
- return;
- }
-
- $contact = $contacts[0];
-
- $t = $contact['abook_updated'];
-
- $importer_uid = $contact['abook_channel'];
-
- $r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
- intval($importer_uid)
- );
-
- if(! $r)
- return;
-
- $importer = $r[0];
-
- logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
-
- $last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] === NULL_DATE))
- ? datetime_convert('UTC','UTC','now - 7 days')
- : datetime_convert('UTC','UTC',$contact['abook_updated'] . ' - 2 days')
- );
-
- if($contact['xchan_network'] === 'rss') {
- logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
- handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
- q("update abook set abook_connected = '%s' where abook_id = %d",
- dbesc(datetime_convert()),
- intval($contact['abook_id'])
- );
- return;
- }
-
- if($contact['xchan_network'] !== 'zot')
- return;
-
- // update permissions
-
- $x = zot_refresh($contact,$importer);
-
- $responded = false;
- $updated = datetime_convert();
- $connected = datetime_convert();
- if(! $x) {
- // mark for death by not updating abook_connected, this is caught in include/poller.php
- q("update abook set abook_updated = '%s' where abook_id = %d",
- dbesc($updated),
- intval($contact['abook_id'])
- );
- }
- else {
- q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
- dbesc($updated),
- dbesc($connected),
- intval($contact['abook_id'])
- );
- $responded = true;
- }
-
- if(! $responded)
- return;
-
- if($contact['xchan_connurl']) {
- $fetch_feed = true;
- $x = null;
-
- if(! ($contact['abook_their_perms'] & PERMS_R_STREAM ))
- $fetch_feed = false;
-
- if($fetch_feed) {
-
- $feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
- $feedurl .= '?f=&mindate=' . urlencode($last_update);
-
- $x = z_fetch_url($feedurl);
-
- logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
-
- }
-
- if(($x) && ($x['success'])) {
- $total = 0;
- logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
-
- $j = json_decode($x['body'],true);
- if($j['success'] && $j['messages']) {
- foreach($j['messages'] as $message) {
- $results = process_delivery(array('hash' => $contact['xchan_hash']), get_item_elements($message),
- array(array('hash' => $importer['xchan_hash'])), false);
- logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
- $total ++;
- }
- logger("onepoll: $total messages processed");
- }
- }
- }
-
-
- // update the poco details for this connection
-
- if($contact['xchan_connurl']) {
- $r = q("SELECT xlink_id from xlink
- where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
- intval($contact['xchan_hash']),
- db_utcnow(), db_quoteinterval('1 DAY')
- );
- if(! $r) {
- poco_load($contact['xchan_hash'],$contact['xchan_connurl']);
- }
- }
-
- return;
-}
-
-if (array_search(__file__,get_included_files())===0){
- onepoll_run($argv,$argc);
- killme();
-}
diff --git a/include/page_widgets.php b/include/page_widgets.php
index 49d1439be..3270de4a3 100644
--- a/include/page_widgets.php
+++ b/include/page_widgets.php
@@ -1,7 +1,8 @@
<?php
// A basic toolbar for observers with write_pages permissions
-function writepages_widget ($who,$which){
+
+function writepages_widget ($who,$which) {
return replace_macros(get_markup_template('write_pages.tpl'), array(
'$new' => t('New Page'),
'$newurl' => "webpages/$who",
@@ -13,9 +14,11 @@ function writepages_widget ($who,$which){
// Chan is channel_id, $which is channel_address - we'll need to pass observer later too.
-function pagelist_widget ($owner,$which){
- $r = q("select * from item_id left join item on item_id.iid = item.id where item_id.uid = %d and service = 'WEBPAGE' order by item.created desc",
+function pagelist_widget ($owner,$which) {
+
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id where item_id.uid = %d
+ and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' order by item.created desc",
intval($owner)
);
@@ -24,7 +27,7 @@ function pagelist_widget ($owner,$which){
if($r) {
$pages = array();
foreach($r as $rr) {
- $pages[$rr['iid']][] = array('url' => $rr['iid'],'pagetitle' => $rr['sid'],'title' => $rr['title'],'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']));
+ $pages[$rr['iid']][] = array('url' => $rr['iid'],'pagetitle' => $rr['v'],'title' => $rr['title'],'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']));
}
}
diff --git a/include/perm_upgrade.php b/include/perm_upgrade.php
new file mode 100644
index 000000000..5be1ffbb2
--- /dev/null
+++ b/include/perm_upgrade.php
@@ -0,0 +1,236 @@
+<?php
+
+function perm_limits_upgrade($channel) {
+ set_pconfig($channel['channel_id'],'perm_limits','view_stream',$channel['channel_r_stream']);
+ set_pconfig($channel['channel_id'],'perm_limits','view_profile',$channel['channel_r_profile']);
+ set_pconfig($channel['channel_id'],'perm_limits','view_contacts',$channel['channel_r_abook']);
+ set_pconfig($channel['channel_id'],'perm_limits','view_storage',$channel['channel_r_storage']);
+ set_pconfig($channel['channel_id'],'perm_limits','view_pages',$channel['channel_r_pages']);
+ set_pconfig($channel['channel_id'],'perm_limits','send_stream',$channel['channel_w_stream']);
+ set_pconfig($channel['channel_id'],'perm_limits','post_wall',$channel['channel_w_wall']);
+ set_pconfig($channel['channel_id'],'perm_limits','post_comments',$channel['channel_w_comment']);
+ set_pconfig($channel['channel_id'],'perm_limits','post_mail',$channel['channel_w_mail']);
+ set_pconfig($channel['channel_id'],'perm_limits','post_like',$channel['channel_w_like']);
+ set_pconfig($channel['channel_id'],'perm_limits','tag_deliver',$channel['channel_w_tagwall']);
+ set_pconfig($channel['channel_id'],'perm_limits','chat',$channel['channel_w_chat']);
+ set_pconfig($channel['channel_id'],'perm_limits','write_storage',$channel['channel_w_storage']);
+ set_pconfig($channel['channel_id'],'perm_limits','write_pages',$channel['channel_w_pages']);
+ set_pconfig($channel['channel_id'],'perm_limits','republish',$channel['channel_a_republish']);
+ set_pconfig($channel['channel_id'],'perm_limits','delegate',$channel['channel_a_delegate']);
+}
+
+function perms_int_to_array($p) {
+
+ $ret = [];
+
+ $ret['view_stream'] = (($p & PERMS_R_STREAM) ? 1 : 0);
+ $ret['view_profile'] = (($p & PERMS_R_PROFILE) ? 1 : 0);
+ $ret['view_contacts'] = (($p & PERMS_R_ABOOK) ? 1 : 0);
+ $ret['view_storage'] = (($p & PERMS_R_STORAGE) ? 1 : 0);
+ $ret['view_pages'] = (($p & PERMS_R_PAGES) ? 1 : 0);
+ $ret['send_stream'] = (($p & PERMS_W_STREAM) ? 1 : 0);
+ $ret['post_wall'] = (($p & PERMS_W_WALL) ? 1 : 0);
+ $ret['post_comments'] = (($p & PERMS_W_COMMENT) ? 1 : 0);
+ $ret['post_mail'] = (($p & PERMS_W_MAIL) ? 1 : 0);
+ $ret['post_like'] = (($p & PERMS_W_LIKE) ? 1 : 0);
+ $ret['tag_deliver'] = (($p & PERMS_W_TAGWALL) ? 1 : 0);
+ $ret['chat'] = (($p & PERMS_W_CHAT) ? 1 : 0);
+ $ret['write_storage'] = (($p & PERMS_W_STORAGE) ? 1 : 0);
+ $ret['write_pages'] = (($p & PERMS_W_PAGES) ? 1 : 0);
+ $ret['republish'] = (($p & PERMS_A_REPUBLISH) ? 1 : 0);
+ $ret['delegate'] = (($p & PERMS_A_DELEGATE) ? 1 : 0);
+
+ return $ret;
+}
+
+function autoperms_upgrade($channel) {
+ $x = get_pconfig($channel['channel_id'],'system','autoperms');
+ if(intval($x)) {
+ $y = perms_int_to_array($x);
+ if($y) {
+ foreach($y as $k => $v) {
+ set_pconfig($channel['channel_id'],'autoperms',$k,$v);
+ }
+ }
+ }
+}
+
+
+function perm_abook_upgrade($abook) {
+
+ $x = perms_int_to_array($abook['abook_their_perms']);
+ if($x) {
+ foreach($x as $k => $v) {
+ set_abconfig($abook['abook_channel'],$abook['abook_xchan'],'their_perms',$k, $v);
+ }
+ }
+
+ $x = perms_int_to_array($abook['abook_my_perms']);
+ if($x) {
+ foreach($x as $k => $v) {
+ set_abconfig($abook['abook_channel'],$abook['abook_xchan'],'my_perms',$k, $v);
+ }
+ }
+}
+
+function translate_channel_perms_outbound(&$channel) {
+ $r = q("select * from pconfig where uid = %d and cat = 'perm_limits' ",
+ intval($channel['channel_id'])
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ if($rr['k'] === 'view_stream')
+ $channel['channel_r_stream'] = $rr['v'];
+ if($rr['k'] === 'view_profile')
+ $channel['channel_r_profile'] = $rr['v'];
+ if($rr['k'] === 'view_contacts')
+ $channel['channel_r_abook'] = $rr['v'];
+ if($rr['k'] === 'view_storage')
+ $channel['channel_r_storage'] = $rr['v'];
+ if($rr['k'] === 'view_pages')
+ $channel['channel_r_pages'] = $rr['v'];
+ if($rr['k'] === 'send_stream')
+ $channel['channel_w_stream'] = $rr['v'];
+ if($rr['k'] === 'post_wall')
+ $channel['channel_w_wall'] = $rr['v'];
+ if($rr['k'] === 'post_comments')
+ $channel['channel_w_comment'] = $rr['v'];
+ if($rr['k'] === 'post_mail')
+ $channel['channel_w_mail'] = $rr['v'];
+ if($rr['k'] === 'post_like')
+ $channel['channel_w_like'] = $rr['v'];
+ if($rr['k'] === 'tag_deliver')
+ $channel['channel_w_tagwall'] = $rr['v'];
+ if($rr['k'] === 'chat')
+ $channel['channel_w_chat'] = $rr['v'];
+ if($rr['k'] === 'write_storage')
+ $channel['channel_w_storage'] = $rr['v'];
+ if($rr['k'] === 'write_pages')
+ $channel['channel_w_pages'] = $rr['v'];
+ if($rr['k'] === 'republish')
+ $channel['channel_a_republish'] = $rr['v'];
+ if($rr['k'] === 'delegate')
+ $channel['channel_a_delegate'] = $rr['v'];
+
+ }
+ $channel['perm_limits'] = $r;
+ }
+}
+
+function translate_channel_perms_inbound($channel) {
+
+ if($channel['perm_limits']) {
+ foreach($channel['perm_limits'] as $p) {
+ set_pconfig($channel['channel_id'],'perm_limits',$p['k'],$p['v']);
+ }
+ }
+ else {
+ perm_limits_upgrade($channel);
+ }
+
+}
+
+function translate_abook_perms_outbound(&$abook) {
+ $my_perms = 0;
+ $their_perms = 0;
+
+ if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && $abook['abconfig']) {
+ foreach($abook['abconfig'] as $p) {
+ if($p['cat'] === 'their_perms') {
+ if($p['k'] === 'view_stream' && intval($p['v']))
+ $their_perms += PERMS_R_STREAM;
+ if($p['k'] === 'view_profile' && intval($p['v']))
+ $their_perms += PERMS_R_PROFILE;
+ if($p['k'] === 'view_contacts' && intval($p['v']))
+ $their_perms += PERMS_R_ABOOK;
+ if($p['k'] === 'view_storage' && intval($p['v']))
+ $their_perms += PERMS_R_STORAGE;
+ if($p['k'] === 'view_pages' && intval($p['v']))
+ $their_perms += PERMS_R_PAGES;
+ if($p['k'] === 'send_stream' && intval($p['v']))
+ $their_perms += PERMS_W_STREAM;
+ if($p['k'] === 'post_wall' && intval($p['v']))
+ $their_perms += PERMS_W_WALL;
+ if($p['k'] === 'post_comments' && intval($p['v']))
+ $their_perms += PERMS_W_COMMENT;
+ if($p['k'] === 'post_mail' && intval($p['v']))
+ $their_perms += PERMS_W_MAIL;
+ if($p['k'] === 'post_like' && intval($p['v']))
+ $their_perms += PERMS_W_LIKE;
+ if($p['k'] === 'tag_deliver' && intval($p['v']))
+ $their_perms += PERMS_W_TAGWALL;
+ if($p['k'] === 'chat' && intval($p['v']))
+ $their_perms += PERMS_W_CHAT;
+ if($p['k'] === 'write_storage' && intval($p['v']))
+ $their_perms += PERMS_W_STORAGE;
+ if($p['k'] === 'write_pages' && intval($p['v']))
+ $their_perms += PERMS_W_PAGES;
+ if($p['k'] === 'republish' && intval($p['v']))
+ $their_perms += PERMS_A_REPUBLISH;
+ if($p['k'] === 'delegate' && intval($p['v']))
+ $their_perms += PERMS_A_DELEGATE;
+ }
+ if($p['cat'] === 'my_perms') {
+ if($p['k'] === 'view_stream' && intval($p['v']))
+ $my_perms += PERMS_R_STREAM;
+ if($p['k'] === 'view_profile' && intval($p['v']))
+ $my_perms += PERMS_R_PROFILE;
+ if($p['k'] === 'view_contacts' && intval($p['v']))
+ $my_perms += PERMS_R_ABOOK;
+ if($p['k'] === 'view_storage' && intval($p['v']))
+ $my_perms += PERMS_R_STORAGE;
+ if($p['k'] === 'view_pages' && intval($p['v']))
+ $my_perms += PERMS_R_PAGES;
+ if($p['k'] === 'send_stream' && intval($p['v']))
+ $my_perms += PERMS_W_STREAM;
+ if($p['k'] === 'post_wall' && intval($p['v']))
+ $my_perms += PERMS_W_WALL;
+ if($p['k'] === 'post_comments' && intval($p['v']))
+ $my_perms += PERMS_W_COMMENT;
+ if($p['k'] === 'post_mail' && intval($p['v']))
+ $my_perms += PERMS_W_MAIL;
+ if($p['k'] === 'post_like' && intval($p['v']))
+ $my_perms += PERMS_W_LIKE;
+ if($p['k'] === 'tag_deliver' && intval($p['v']))
+ $my_perms += PERMS_W_TAGWALL;
+ if($p['k'] === 'chat' && intval($p['v']))
+ $my_perms += PERMS_W_CHAT;
+ if($p['k'] === 'write_storage' && intval($p['v']))
+ $my_perms += PERMS_W_STORAGE;
+ if($p['k'] === 'write_pages' && intval($p['v']))
+ $my_perms += PERMS_W_PAGES;
+ if($p['k'] === 'republish' && intval($p['v']))
+ $my_perms += PERMS_A_REPUBLISH;
+ if($p['k'] === 'delegate' && intval($p['v']))
+ $my_perms += PERMS_A_DELEGATE;
+ }
+ }
+
+ $abook['abook_their_perms'] = $their_perms;
+ $abook['abook_my_perms'] = $my_perms;
+ }
+}
+
+function translate_abook_perms_inbound($channel,$abook) {
+
+ $new_perms = false;
+ $abook['abook_channel'] = $channel['channel_id'];
+
+ if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && $abook['abconfig']) {
+ foreach($abook['abconfig'] as $p) {
+ if($p['cat'] == 'their_perms' || $p['cat'] == 'my_perms') {
+ $new_perms = true;
+ break;
+ }
+ }
+ }
+
+ if($new_perms == false) {
+ perm_abook_upgrade($abook);
+ }
+
+}
+
+
+
diff --git a/include/permissions.php b/include/permissions.php
index 19242d29f..638bedb24 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -67,7 +67,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
if($api)
return get_all_api_perms($uid,$api);
- $global_perms = get_perms();
+ $global_perms = \Zotlabs\Access\Permissions::Perms();
// Save lots of individual lookups
@@ -81,11 +81,13 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
$ret = array();
+ $abperms = (($uid && $observer_xchan) ? load_abconfig($uid,$observer_xchan,'my_perms') : array());
+
foreach($global_perms as $perm_name => $permission) {
// First find out what the channel owner declared permissions to be.
- $channel_perm = $permission[0];
+ $channel_perm = \Zotlabs\Access\PermissionLimits::Get($uid,$perm_name);
if(! $channel_checked) {
$r = q("select * from channel where channel_id = %d limit 1",
@@ -105,7 +107,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// These take priority over all other settings.
if($observer_xchan) {
- if($r[0][$channel_perm] & PERMS_AUTHED) {
+ if($channel_perm & PERMS_AUTHED) {
$ret[$perm_name] = true;
continue;
}
@@ -136,7 +138,10 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// Check if this is a write permission and they are being ignored
// This flag is only visible internally.
- if(($x) && ($internal_use) && (! $global_perms[$perm_name][2]) && intval($x[0]['abook_ignored'])) {
+ $blocked_anon_perms = \Zotlabs\Access\Permissions::BlockedAnonPerms();
+
+
+ if(($x) && ($internal_use) && in_array($perm_name,$blocked_anon_perms) && intval($x[0]['abook_ignored'])) {
$ret[$perm_name] = false;
continue;
}
@@ -154,7 +159,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// if you've moved elsewhere, you will only have read only access
if(($observer_xchan) && ($r[0]['channel_hash'] === $observer_xchan)) {
- if($r[0]['channel_moved'] && (! $permission[2]))
+ if($r[0]['channel_moved'] && (in_array($perm_name,$blocked_anon_perms)))
$ret[$perm_name] = false;
else
$ret[$perm_name] = true;
@@ -163,7 +168,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// Anybody at all (that wasn't blocked or ignored). They have permission.
- if($r[0][$channel_perm] & PERMS_PUBLIC) {
+ if($channel_perm & PERMS_PUBLIC) {
$ret[$perm_name] = true;
continue;
}
@@ -178,7 +183,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// If we're still here, we have an observer, check the network.
- if($r[0][$channel_perm] & PERMS_NETWORK) {
+ if($channel_perm & PERMS_NETWORK) {
if(($x && $x[0]['xchan_network'] === 'zot') || ($y && $y[0]['xchan_network'] === 'zot')) {
$ret[$perm_name] = true;
continue;
@@ -187,7 +192,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// If PERMS_SITE is specified, find out if they've got an account on this hub
- if($r[0][$channel_perm] & PERMS_SITE) {
+ if($channel_perm & PERMS_SITE) {
if(! $onsite_checked) {
$c = q("select channel_hash from channel where channel_hash = '%s' limit 1",
dbesc($observer_xchan)
@@ -214,7 +219,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// They are in your address book, but haven't been approved
- if($r[0][$channel_perm] & PERMS_PENDING) {
+ if($channel_perm & PERMS_PENDING) {
$ret[$perm_name] = true;
continue;
}
@@ -226,16 +231,21 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// They're a contact, so they have permission
- if($r[0][$channel_perm] & PERMS_CONTACTS) {
+ if($channel_perm & PERMS_CONTACTS) {
$ret[$perm_name] = true;
continue;
}
// Permission granted to certain channels. Let's see if the observer is one of them
- if($r[0][$channel_perm] & PERMS_SPECIFIC) {
- if(($x[0]['abook_my_perms'] & $global_perms[$perm_name][1])) {
- $ret[$perm_name] = true;
+ if($channel_perm & PERMS_SPECIFIC) {
+ if($abperms) {
+ foreach($abperms as $ab) {
+ if(($ab['cat'] == 'my_perms') && ($ab['k'] == $perm_name)) {
+ $ret[$perm_name] = (intval($ab['v']) ? true : false);
+ break;
+ }
+ }
continue;
}
}
@@ -284,21 +294,23 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
if($arr['result'])
return true;
- $global_perms = get_perms();
+ $global_perms = \Zotlabs\Access\Permissions::Perms();
// First find out what the channel owner declared permissions to be.
- $channel_perm = $global_perms[$permission][0];
+ $channel_perm = \Zotlabs\Access\PermissionLimits::Get($uid,$permission);
- $r = q("select %s, channel_pageflags, channel_moved, channel_hash from channel where channel_id = %d limit 1",
- dbesc($channel_perm),
+ $r = q("select channel_pageflags, channel_moved, channel_hash from channel where channel_id = %d limit 1",
intval($uid)
);
if(! $r)
return false;
+
+ $blocked_anon_perms = \Zotlabs\Access\Permissions::BlockedAnonPerms();
+
if($observer_xchan) {
- if($r[0][$channel_perm] & PERMS_AUTHED)
+ if($channel_perm & PERMS_AUTHED)
return true;
$x = q("select abook_my_perms, abook_blocked, abook_ignored, abook_pending, xchan_network from abook left join xchan on abook_xchan = xchan_hash
@@ -312,7 +324,7 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
if(($x) && intval($x[0]['abook_blocked']))
return false;
- if(($x) && (! $global_perms[$permission][2]) && intval($x[0]['abook_ignored']))
+ if(($x) && in_array($permission,$blocked_anon_perms) && intval($x[0]['abook_ignored']))
return false;
if(! $x) {
@@ -321,7 +333,9 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
dbesc($observer_xchan)
);
}
+ $abperms = load_abconfig($uid,$observer_xchan,'my_perms');
}
+
// system is blocked to anybody who is not authenticated
@@ -333,13 +347,13 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
// in which case you will have read_only access
if($r[0]['channel_hash'] === $observer_xchan) {
- if($r[0]['channel_moved'] && (! $global_perms[$permission][2]))
+ if($r[0]['channel_moved'] && (in_array($permission,$blocked_anon_perms)))
return false;
else
return true;
}
- if($r[0][$channel_perm] & PERMS_PUBLIC)
+ if($channel_perm & PERMS_PUBLIC)
return true;
// If it's an unauthenticated observer, we only need to see if PERMS_PUBLIC is set
@@ -350,14 +364,14 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
// If we're still here, we have an observer, check the network.
- if($r[0][$channel_perm] & PERMS_NETWORK) {
+ if($channel_perm & PERMS_NETWORK) {
if (($x && $x[0]['xchan_network'] === 'zot') || ($y && $y[0]['xchan_network'] === 'zot'))
return true;
}
// If PERMS_SITE is specified, find out if they've got an account on this hub
- if($r[0][$channel_perm] & PERMS_SITE) {
+ if($channel_perm & PERMS_SITE) {
$c = q("select channel_hash from channel where channel_hash = '%s' limit 1",
dbesc($observer_xchan)
);
@@ -376,7 +390,7 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
// They are in your address book, but haven't been approved
- if($r[0][$channel_perm] & PERMS_PENDING) {
+ if($channel_perm & PERMS_PENDING) {
return true;
}
@@ -386,15 +400,20 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
// They're a contact, so they have permission
- if($r[0][$channel_perm] & PERMS_CONTACTS) {
+ if($channel_perm & PERMS_CONTACTS) {
return true;
}
// Permission granted to certain channels. Let's see if the observer is one of them
- if(($r) && $r[0][$channel_perm] & PERMS_SPECIFIC) {
- if($x[0]['abook_my_perms'] & $global_perms[$permission][1])
- return true;
+ if(($r) && ($channel_perm & PERMS_SPECIFIC)) {
+ if($abperms) {
+ foreach($abperms as $ab) {
+ if($ab['cat'] == 'my_perms' && $ab['k'] == $permission) {
+ return ((intval($ab['v'])) ? true : false);
+ }
+ }
+ }
}
// No permissions allowed.
@@ -560,28 +579,28 @@ function get_role_perms($role) {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = true;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_NETWORK;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'send_stream', 'post_wall', 'post_comments',
+ 'post_mail', 'chat', 'post_like', 'republish' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -590,28 +609,29 @@ function get_role_perms($role) {
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = true;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_SPECIFIC;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'send_stream', 'post_wall', 'post_comments',
+ 'post_mail', 'chat', 'post_like' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
+
break;
@@ -620,28 +640,28 @@ function get_role_perms($role) {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_SPECIFIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_SPECIFIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_SPECIFIC;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'send_stream', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_SPECIFIC,
+ 'view_storage' => PERMS_SPECIFIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -650,28 +670,28 @@ function get_role_perms($role) {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_NETWORK;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'post_wall', 'post_comments', 'tag_deliver',
+ 'post_mail', 'post_like' , 'republish', 'chat' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -680,28 +700,28 @@ function get_role_perms($role) {
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_SPECIFIC;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'post_wall', 'post_comments', 'tag_deliver',
+ 'post_mail', 'post_like' , 'chat' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -710,28 +730,29 @@ function get_role_perms($role) {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILEPERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_SPECIFIC;
- $ret['channel_r_abook'] = PERMS_SPECIFIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_SPECIFIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_SPECIFIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_SPECIFIC;
+
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like' , 'chat' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_SPECIFIC,
+ 'view_contacts' => PERMS_SPECIFIC,
+ 'view_storage' => PERMS_SPECIFIC,
+ 'view_pages' => PERMS_SPECIFIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -740,28 +761,29 @@ function get_role_perms($role) {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_NETWORK;
- $ret['channel_w_like'] = PERMS_NETWORK;
+
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'send_stream', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like' , 'republish' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -770,28 +792,28 @@ function get_role_perms($role) {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_NETWORK;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'send_stream', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like' , 'republish' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -800,26 +822,29 @@ function get_role_perms($role) {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_NETWORK;
+
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'post_like' , 'republish' ];
+
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
break;
@@ -828,28 +853,30 @@ function get_role_perms($role) {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
- $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_W_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_ABOOK
- |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
- |PERMS_R_STORAGE|PERMS_W_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
- $ret['channel_r_stream'] = PERMS_PUBLIC;
- $ret['channel_r_profile'] = PERMS_PUBLIC;
- $ret['channel_r_abook'] = PERMS_PUBLIC;
- $ret['channel_w_stream'] = PERMS_SPECIFIC;
- $ret['channel_w_wall'] = PERMS_SPECIFIC;
- $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
- $ret['channel_w_comment'] = PERMS_SPECIFIC;
- $ret['channel_w_mail'] = PERMS_SPECIFIC;
- $ret['channel_w_chat'] = PERMS_SPECIFIC;
- $ret['channel_a_delegate'] = PERMS_SPECIFIC;
- $ret['channel_r_storage'] = PERMS_PUBLIC;
- $ret['channel_w_storage'] = PERMS_SPECIFIC;
- $ret['channel_r_pages'] = PERMS_PUBLIC;
- $ret['channel_w_pages'] = PERMS_SPECIFIC;
- $ret['channel_a_republish'] = PERMS_SPECIFIC;
- $ret['channel_w_like'] = PERMS_NETWORK;
+
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'write_storage', 'write_pages', 'post_wall', 'post_comments', 'tag_deliver',
+ 'post_mail', 'post_like' , 'republish', 'chat' ];
+ $ret['limits'] = [
+ 'view_stream' => PERMS_PUBLIC,
+ 'view_profile' => PERMS_PUBLIC,
+ 'view_contacts' => PERMS_PUBLIC,
+ 'view_storage' => PERMS_PUBLIC,
+ 'view_pages' => PERMS_PUBLIC,
+ 'send_stream' => PERMS_SPECIFIC,
+ 'post_wall' => PERMS_SPECIFIC,
+ 'post_comments' => PERMS_SPECIFIC,
+ 'post_mail' => PERMS_SPECIFIC,
+ 'post_like' => PERMS_SPECIFIC,
+ 'tag_deliver' => PERMS_SPECIFIC,
+ 'chat' => PERMS_SPECIFIC,
+ 'write_storage' => PERMS_SPECIFIC,
+ 'write_pages' => PERMS_SPECIFIC,
+ 'republish' => PERMS_SPECIFIC,
+ 'delegate' => PERMS_SPECIFIC
+ ];
+
break;
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 3bea54fd4..6de75d497 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -316,7 +316,7 @@ abstract class photo_driver {
$p['resource_id'] = (($arr['resource_id']) ? $arr['resource_id'] : '');
$p['filename'] = (($arr['filename']) ? $arr['filename'] : '');
$p['album'] = (($arr['album']) ? $arr['album'] : '');
- $p['scale'] = ((intval($arr['scale'])) ? intval($arr['scale']) : 0);
+ $p['imgscale'] = ((intval($arr['imgscale'])) ? intval($arr['imgscale']) : 0);
$p['allow_cid'] = (($arr['allow_cid']) ? $arr['allow_cid'] : '');
$p['allow_gid'] = (($arr['allow_gid']) ? $arr['allow_gid'] : '');
$p['deny_cid'] = (($arr['deny_cid']) ? $arr['deny_cid'] : '');
@@ -329,14 +329,14 @@ abstract class photo_driver {
$p['os_storage'] = intval($arr['os_storage']);
$p['os_path'] = $arr['os_path'];
- if(! intval($p['scale']))
- logger('save: ' . print_r($arr,true));
+ if(! intval($p['imgscale']))
+ logger('save: ' . print_r($arr,true), LOGGER_DATA);
- $x = q("select id from photo where resource_id = '%s' and uid = %d and xchan = '%s' and `scale` = %d limit 1",
+ $x = q("select id from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
dbesc($p['resource_id']),
intval($p['uid']),
dbesc($p['xchan']),
- intval($p['scale'])
+ intval($p['imgscale'])
);
if($x) {
$r = q("UPDATE `photo` set
@@ -347,14 +347,14 @@ abstract class photo_driver {
`created` = '%s',
`edited` = '%s',
`filename` = '%s',
- `type` = '%s',
+ `mimetype` = '%s',
`album` = '%s',
`height` = %d,
`width` = %d,
- `data` = '%s',
+ `content` = '%s',
`os_storage` = %d,
- `size` = %d,
- `scale` = %d,
+ `filesize` = %d,
+ `imgscale` = %d,
`photo_usage` = %d,
`title` = '%s',
`description` = '%s',
@@ -378,7 +378,7 @@ abstract class photo_driver {
(intval($p['os_storage']) ? dbesc($p['os_path']) : dbescbin($this->imageString())),
intval($p['os_storage']),
intval(strlen($this->imageString())),
- intval($p['scale']),
+ intval($p['imgscale']),
intval($p['photo_usage']),
dbesc($p['title']),
dbesc($p['description']),
@@ -391,7 +391,7 @@ abstract class photo_driver {
}
else {
$r = q("INSERT INTO `photo`
- ( `aid`, `uid`, `xchan`, `resource_id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `data`, `os_storage`, `size`, `scale`, `photo_usage`, `title`, `description`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )
+ ( `aid`, `uid`, `xchan`, `resource_id`, `created`, `edited`, `filename`, mimetype, `album`, `height`, `width`, `content`, `os_storage`, `filesize`, `imgscale`, `photo_usage`, `title`, `description`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
intval($p['aid']),
intval($p['uid']),
@@ -407,7 +407,7 @@ abstract class photo_driver {
(intval($p['os_storage']) ? dbesc($p['os_path']) : dbescbin($this->imageString())),
intval($p['os_storage']),
intval(strlen($this->imageString())),
- intval($p['scale']),
+ intval($p['imgscale']),
intval($p['photo_usage']),
dbesc($p['title']),
dbesc($p['description']),
@@ -422,7 +422,7 @@ abstract class photo_driver {
public function store($aid, $uid, $xchan, $rid, $filename, $album, $scale, $usage = PHOTO_NORMAL, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '') {
- $x = q("select id from photo where `resource_id` = '%s' and uid = %d and `xchan` = '%s' and `scale` = %d limit 1",
+ $x = q("select id from photo where `resource_id` = '%s' and uid = %d and `xchan` = '%s' and `imgscale` = %d limit 1",
dbesc($rid),
intval($uid),
dbesc($xchan),
@@ -437,13 +437,13 @@ abstract class photo_driver {
`created` = '%s',
`edited` = '%s',
`filename` = '%s',
- `type` = '%s',
+ `mimetype` = '%s',
`album` = '%s',
`height` = %d,
`width` = %d,
- `data` = '%s',
- `size` = %d,
- `scale` = %d,
+ `content` = '%s',
+ `filesize` = %d,
+ `imgscale` = %d,
`photo_usage` = %d,
`allow_cid` = '%s',
`allow_gid` = '%s',
@@ -475,7 +475,7 @@ abstract class photo_driver {
}
else {
$r = q("INSERT INTO `photo`
- ( `aid`, `uid`, `xchan`, `resource_id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `data`, `size`, `scale`, `photo_usage`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )
+ ( `aid`, `uid`, `xchan`, `resource_id`, `created`, `edited`, `filename`, mimetype, `album`, `height`, `width`, `content`, `filesize`, `imgscale`, `photo_usage`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s' )",
intval($aid),
intval($uid),
@@ -521,7 +521,7 @@ function guess_image_type($filename, $headers = '') {
logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG);
$type = null;
if ($headers) {
- $a = get_app();
+
$hdrs=array();
$h = explode("\n",$headers);
foreach ($h as $l) {
@@ -580,8 +580,6 @@ function guess_image_type($filename, $headers = '') {
function import_xchan_photo($photo,$xchan,$thing = false) {
- $a = get_app();
-
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
$album = (($thing) ? 'Things' : 'Contact Photos');
@@ -590,7 +588,7 @@ function import_xchan_photo($photo,$xchan,$thing = false) {
if($thing)
$hash = photo_new_resource();
else {
- $r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and scale = 4 limit 1",
+ $r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
dbesc($xchan),
intval(PHOTO_XCHAN)
);
@@ -656,7 +654,7 @@ function import_xchan_photo($photo,$xchan,$thing = false) {
else
$photo_failure = true;
- $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'scale' => 4);
+ $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4);
$r = $img->save($p);
@@ -664,7 +662,7 @@ function import_xchan_photo($photo,$xchan,$thing = false) {
$photo_failure = true;
$img->scaleImage(80);
- $p['scale'] = 5;
+ $p['imgscale'] = 5;
$r = $img->save($p);
@@ -672,7 +670,7 @@ function import_xchan_photo($photo,$xchan,$thing = false) {
$photo_failure = true;
$img->scaleImage(48);
- $p['scale'] = 6;
+ $p['imgscale'] = 6;
$r = $img->save($p);
@@ -703,8 +701,6 @@ function import_xchan_photo($photo,$xchan,$thing = false) {
function import_channel_photo($photo,$type,$aid,$uid) {
- $a = get_app();
-
logger('import_channel_photo: importing channel photo for ' . $uid, LOGGER_DEBUG);
$hash = photo_new_resource();
@@ -719,7 +715,7 @@ function import_channel_photo($photo,$type,$aid,$uid) {
$img->scaleImageSquare(300);
- $p = array('aid' => $aid, 'uid' => $uid, 'resource_id' => $hash, 'filename' => $filename, 'album' => t('Profile Photos'), 'photo_usage' => PHOTO_PROFILE, 'scale' => 4);
+ $p = array('aid' => $aid, 'uid' => $uid, 'resource_id' => $hash, 'filename' => $filename, 'album' => t('Profile Photos'), 'photo_usage' => PHOTO_PROFILE, 'imgscale' => 4);
$r = $img->save($p);
@@ -727,7 +723,7 @@ function import_channel_photo($photo,$type,$aid,$uid) {
$photo_failure = true;
$img->scaleImage(80);
- $p['scale'] = 5;
+ $p['imgscale'] = 5;
$r = $img->save($p);
@@ -735,7 +731,7 @@ function import_channel_photo($photo,$type,$aid,$uid) {
$photo_failure = true;
$img->scaleImage(48);
- $p['scale'] = 6;
+ $p['imgscale'] = 6;
$r = $img->save($p);
diff --git a/include/photos.php b/include/photos.php
index 943d7d503..d14c12d84 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -19,8 +19,6 @@ require_once('include/text.php');
*/
function photo_upload($channel, $observer, $args) {
- $a = get_app();
-
$ret = array('success' => false);
$channel_id = $channel['channel_id'];
$account_id = $channel['channel_account_id'];
@@ -43,6 +41,10 @@ function photo_upload($channel, $observer, $args) {
else
$visible = 0;
+ $deliver = true;
+ if(array_key_exists('deliver',$args))
+ $deliver = intval($args['deliver']);
+
// Set to default channel permissions. If the parent directory (album) has permissions set,
// use those instead. If we have specific permissions supplied, they take precedence over
// all other settings. 'allow_cid' being passed from an external source takes priority over channel settings.
@@ -73,17 +75,17 @@ function photo_upload($channel, $observer, $args) {
$type = $args['getimagesize']['mime'];
$os_storage = 1;
}
- elseif ($args['data']) {
+ elseif ($args['data'] || $args['content']) {
// allow an import from a binary string representing the image.
// This bypasses the upload step and max size limit checking
- $imagedata = $args['data'];
+ $imagedata = (($args['content']) ? $args['content'] : $args['data']);
$filename = $args['filename'];
$filesize = strlen($imagedata);
// this is going to be deleted if it exists
$src = '/tmp/deletemenow';
- $type = $args['type'];
+ $type = (($args['mimetype']) ? $args['mimetype'] : $args['type']);
} else {
$f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
@@ -127,11 +129,11 @@ function photo_upload($channel, $observer, $args) {
$imagedata = @file_get_contents($src);
}
- $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
+ $r = q("select sum(filesize) as total from photo where aid = %d and imgscale = 0 ",
intval($account_id)
);
- $limit = service_class_fetch($channel_id,'photo_upload_limit');
+ $limit = engr_units_to_bytes(service_class_fetch($channel_id,'photo_upload_limit'));
if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
$ret['message'] = upgrade_message();
@@ -174,7 +176,7 @@ function photo_upload($channel, $observer, $args) {
$errors = false;
$p = array('aid' => $account_id, 'uid' => $channel_id, 'xchan' => $visitor, 'resource_id' => $photo_hash,
- 'filename' => $filename, 'album' => $album, 'scale' => 0, 'photo_usage' => PHOTO_NORMAL,
+ 'filename' => $filename, 'album' => $album, 'imgscale' => 0, 'photo_usage' => PHOTO_NORMAL,
'allow_cid' => $ac['allow_cid'], 'allow_gid' => $ac['allow_gid'],
'deny_cid' => $ac['deny_cid'], 'deny_gid' => $ac['deny_gid'],
'os_storage' => $os_storage, 'os_path' => $args['os_path']
@@ -207,7 +209,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 1024 || $height > 1024) && (! $errors))
$ph->scaleImage(1024);
- $p['scale'] = 1;
+ $p['imgscale'] = 1;
$r1 = $ph->save($p);
$link[1] = array(
'rel' => 'alternate',
@@ -222,7 +224,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 640 || $height > 640) && (! $errors))
$ph->scaleImage(640);
- $p['scale'] = 2;
+ $p['imgscale'] = 2;
$r2 = $ph->save($p);
$link[2] = array(
'rel' => 'alternate',
@@ -237,7 +239,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 320 || $height > 320) && (! $errors))
$ph->scaleImage(320);
- $p['scale'] = 3;
+ $p['imgscale'] = 3;
$r3 = $ph->save($p);
$link[3] = array(
'rel' => 'alternate',
@@ -296,7 +298,7 @@ function photo_upload($channel, $observer, $args) {
$photo_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]';
- $album_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) . ']' . $album . '[/zrl]';
+ $album_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) . ']' . ((strlen($album)) ? $album : '/') . '[/zrl]';
$activity_format = sprintf(t('%1$s posted %2$s to %3$s','photo_upload'), $author_link, $photo_link, $album_link);
@@ -332,9 +334,9 @@ function photo_upload($channel, $observer, $args) {
if($item['mid'] === $item['parent_mid']) {
- $item['body'] = $args['body'];
+ $item['body'] = $summary;
$item['obj_type'] = ACTIVITY_OBJ_PHOTO;
- $item['object'] = json_encode($object);
+ $item['obj'] = json_encode($object);
$item['tgt_type'] = ACTIVITY_OBJ_ALBUM;
$item['target'] = json_encode($target);
@@ -357,14 +359,14 @@ function photo_upload($channel, $observer, $args) {
if(($item['edited'] > $r[0]['edited']) || $force) {
$item['id'] = $r[0]['id'];
$item['uid'] = $channel['channel_id'];
- item_store_update($item);
+ item_store_update($item,false,$deliver);
continue;
}
}
else {
$item['aid'] = $channel['channel_account_id'];
$item['uid'] = $channel['channel_id'];
- $item_result = item_store($item);
+ $item_result = item_store($item,false,$deliver);
}
}
}
@@ -391,8 +393,8 @@ function photo_upload($channel, $observer, $args) {
$arr['deny_cid'] = $ac['deny_cid'];
$arr['deny_gid'] = $ac['deny_gid'];
$arr['verb'] = ACTIVITY_POST;
- $arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
- $arr['object'] = json_encode($object);
+ $arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
+ $arr['obj'] = json_encode($object);
$arr['tgt_type'] = ACTIVITY_OBJ_ALBUM;
$arr['target'] = json_encode($target);
$arr['item_wall'] = 1;
@@ -410,17 +412,17 @@ function photo_upload($channel, $observer, $args) {
// in the photos pages - using the photos permissions instead. We need the public policy to keep the photo
// linked item from leaking into the feed when somebody has a channel with read_stream restrictions.
- $arr['public_policy'] = map_scope($channel['channel_r_stream'],true);
+ $arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true);
if($arr['public_policy'])
$arr['item_private'] = 1;
- $result = item_store($arr);
+ $result = item_store($arr,false,$deliver);
$item_id = $result['item_id'];
- if($visible)
- proc_run('php', "include/notifier.php", 'wall-new', $item_id);
+ if($visible && $deliver)
+ Zotlabs\Daemon\Master::Summon(array('Notifier', 'wall-new', $item_id));
}
$ret['success'] = true;
@@ -445,7 +447,7 @@ function photo_upload($channel, $observer, $args) {
* * success (bool)
* * albums (array)
*/
-function photos_albums_list($channel, $observer) {
+function photos_albums_list($channel, $observer, $sort_key = 'album', $direction = 'asc') {
$channel_id = $channel['channel_id'];
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
@@ -453,11 +455,15 @@ function photos_albums_list($channel, $observer) {
if(! perm_is_allowed($channel_id, $observer_xchan, 'view_storage'))
return false;
- /** @FIXME create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status */
- $sql_extra = permissions_sql($channel_id);
+ $sql_extra = permissions_sql($channel_id,$observer_xchan);
+
+ $sort_key = dbesc($sort_key);
+ $direction = dbesc($direction);
- $albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and photo_usage IN ( %d, %d ) $sql_extra group by album order by max(created) desc",
+
+
+ $albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and photo_usage IN ( %d, %d ) $sql_extra group by album order by $sort_key $direction",
intval($channel_id),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
@@ -485,20 +491,14 @@ function photos_albums_list($channel, $observer) {
return $ret;
}
-function photos_album_widget($channelx,$observer,$albums = null) {
+function photos_album_widget($channelx,$observer,$sortkey = 'album',$direction = 'asc') {
$o = '';
- // If we weren't passed an album list, see if the photos module
- // dropped one for us to find in App::$data['albums'].
- // If all else fails, load it.
-
- if(! $albums) {
- if(array_key_exists('albums', App::$data))
- $albums = App::$data['albums'];
- else
- $albums = photos_albums_list($channelx,$observer);
- }
+ if(array_key_exists('albums', App::$data))
+ $albums = App::$data['albums'];
+ else
+ $albums = photos_albums_list($channelx,$observer,$sortkey,$direction);
if($albums['success']) {
$o = replace_macros(get_markup_template('photo_albums.tpl'),array(
@@ -537,7 +537,7 @@ function photos_list_photos($channel, $observer, $album = '') {
$ret = array('success' => false);
- $r = q("select resource_id, created, edited, title, description, album, filename, type, height, width, size, scale, photo_usage, allow_cid, allow_gid, deny_cid, deny_gid from photo where uid = %d and photo_usage in ( %d, %d ) $sql_extra ",
+ $r = q("select resource_id, created, edited, title, description, album, filename, mimetype, height, width, filesize, imgscale, photo_usage, allow_cid, allow_gid, deny_cid, deny_gid from photo where uid = %d and photo_usage in ( %d, %d ) $sql_extra ",
intval($channel_id),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
@@ -545,7 +545,7 @@ function photos_list_photos($channel, $observer, $album = '') {
if($r) {
for($x = 0; $x < count($r); $x ++) {
- $r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['scale'];
+ $r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['imgscale'];
}
$ret['success'] = true;
$ret['photos'] = $r;
@@ -663,7 +663,7 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']'
- . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['scale'] . '[/zmg]'
+ . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['imgscale'] . '[/zmg]'
. '[/zrl]';
$result = item_store($arr);
@@ -706,3 +706,68 @@ function gps2Num($coordPart) {
return floatval($parts[0]) / floatval($parts[1]);
}
+
+function profile_photo_set_profile_perms($uid, $profileid = 0) {
+
+ $allowcid = '';
+ if($profileid) {
+ $r = q("SELECT photo, profile_guid, id, is_default, uid
+ FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
+ intval($profileid),
+ dbesc($profileid)
+ );
+ }
+ else {
+ logger('Resetting permissions on default-profile-photo for user'.local_channel());
+
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile
+ WHERE profile.uid = %d AND is_default = 1 LIMIT 1",
+ intval($uid)
+ ); //If no profile is given, we update the default profile
+ }
+ if(! $r)
+ return;
+
+ $profile = $r[0];
+
+ if($profile['id'] && $profile['photo']) {
+ preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
+ $resource_id = $resource_id[0];
+
+ if (! intval($profile['is_default'])) {
+ $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1",
+ intval($uid)
+ );
+ //Should not be needed in future. Catches old int-profile-ids.
+ $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ",
+ intval($profile['id'])
+ );
+ $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'",
+ dbesc($profile['profile_guid'])
+ );
+ $allowcid = "<" . $r0[0]['channel_hash'] . ">";
+ foreach ($r1 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+ foreach ($r2 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+
+ q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",
+ dbesc($allowcid),
+ dbesc($resource_id),
+ intval($uid)
+ );
+
+ }
+ else {
+ //Reset permissions on default profile picture to public
+ q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d",
+ intval(PHOTO_PROFILE),
+ intval($uid)
+ );
+ }
+ }
+
+ return;
+ }
diff --git a/include/plugin.php b/include/plugin.php
index 8dceb8fb1..cb206d944 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -5,8 +5,6 @@
* @brief Some functions to handle addons and themes.
*/
-require_once("include/smarty.php");
-
/**
* @brief unloads an addon.
@@ -43,7 +41,7 @@ function uninstall_plugin($plugin) {
$func();
}
- q("DELETE FROM `addon` WHERE `name` = '%s' ",
+ q("DELETE FROM `addon` WHERE `aname` = '%s' ",
dbesc($plugin)
);
}
@@ -68,7 +66,7 @@ function install_plugin($plugin) {
$plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0);
- q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ",
+ q("INSERT INTO `addon` (`aname`, `installed`, `tstamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ",
dbesc($plugin),
intval($t),
$plugin_admin
@@ -113,7 +111,7 @@ function load_plugin($plugin) {
}
function plugin_is_installed($name) {
- $r = q("select name from addon where name = '%s' and installed = 1 limit 1",
+ $r = q("select aname from addon where aname = '%s' and installed = 1 limit 1",
dbesc($name)
);
if($r)
@@ -145,8 +143,8 @@ function reload_plugins() {
if(file_exists($fname)) {
$t = @filemtime($fname);
foreach($installed as $i) {
- if(($i['name'] == $pl) && ($i['timestamp'] != $t)) {
- logger('Reloading plugin: ' . $i['name']);
+ if(($i['aname'] == $pl) && ($i['tstamp'] != $t)) {
+ logger('Reloading plugin: ' . $i['aname']);
@include_once($fname);
if(function_exists($pl . '_unload')) {
@@ -157,7 +155,7 @@ function reload_plugins() {
$func = $pl . '_load';
$func();
}
- q("UPDATE `addon` SET `timestamp` = %d WHERE `id` = %d",
+ q("UPDATE `addon` SET `tstamp` = %d WHERE `id` = %d",
intval($t),
intval($i['id'])
);
@@ -169,6 +167,12 @@ function reload_plugins() {
}
}
+function visible_plugin_list() {
+ $r = q("select * from addon where hidden = 0 order by aname asc");
+ return(($r) ? ids_to_array($r,'aname') : array());
+}
+
+
/**
* @brief registers a hook.
@@ -180,15 +184,15 @@ function reload_plugins() {
* @return mixed|bool
*/
function register_hook($hook, $file, $function, $priority = 0) {
- $r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' LIMIT 1",
+ $r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `fn` = '%s' LIMIT 1",
dbesc($hook),
dbesc($file),
dbesc($function)
);
- if(count($r))
+ if($r)
return true;
- $r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )",
+ $r = q("INSERT INTO `hook` (`hook`, `file`, `fn`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )",
dbesc($hook),
dbesc($file),
dbesc($function),
@@ -208,7 +212,7 @@ function register_hook($hook, $file, $function, $priority = 0) {
* @return array
*/
function unregister_hook($hook, $file, $function) {
- $r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `function` = '%s'",
+ $r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `fn` = '%s'",
dbesc($hook),
dbesc($file),
dbesc($function)
@@ -226,9 +230,8 @@ function unregister_hook($hook, $file, $function) {
function load_hooks() {
- $a = get_app();
-// if(! is_array(App::$hooks))
- App::$hooks = array();
+
+ App::$hooks = array();
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
@@ -236,10 +239,10 @@ function load_hooks() {
if(! array_key_exists($rr['hook'],App::$hooks))
App::$hooks[$rr['hook']] = array();
- App::$hooks[$rr['hook']][] = array($rr['file'],$rr['function']);
+ App::$hooks[$rr['hook']][] = array($rr['file'],$rr['fn'],$rr['priority'],$rr['hook_version']);
}
}
-//logger('hooks: ' . print_r(App::$hooks,true));
+ //logger('hooks: ' . print_r(App::$hooks,true));
}
/**
@@ -259,15 +262,15 @@ function load_hooks() {
* @param string $fn
* function name of callback handler
*/
-function insert_hook($hook, $fn) {
- $a = get_app();
+function insert_hook($hook, $fn, $version = 0, $priority = 0) {
+
if(! is_array(App::$hooks))
App::$hooks = array();
if(! array_key_exists($hook, App::$hooks))
App::$hooks[$hook] = array();
- App::$hooks[$hook][] = array('', $fn);
+ App::$hooks[$hook][] = array('', $fn, $priority, $version);
}
/**
@@ -280,23 +283,41 @@ function insert_hook($hook, $fn) {
* @param string|array &$data to transmit to the callback handler
*/
function call_hooks($name, &$data = null) {
- $a = get_app();
-
+ $a = 0;
if((is_array(App::$hooks)) && (array_key_exists($name, App::$hooks))) {
foreach(App::$hooks[$name] as $hook) {
+ $origfn = $hook[1];
if($hook[0])
@include_once($hook[0]);
+ if(preg_match('|^a:[0-9]+:{.*}$|s', $hook[1])) {
+ $hook[1] = unserialize($hook[1]);
+ }
+ elseif(strpos($hook[1],'::')) {
+ // We shouldn't need to do this, but it appears that PHP
+ // isn't able to directly execute a string variable with a class
+ // method in the manner we are attempting it, so we'll
+ // turn it into an array.
+ $hook[1] = explode('::',$hook[1]);
+ }
- if(function_exists($hook[1])) {
+ if(is_callable($hook[1])) {
$func = $hook[1];
- $func($a, $data);
- } else {
-
- q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND function = '%s'",
- dbesc($name),
- dbesc($hook[0]),
- dbesc($hook[1])
- );
+ if($hook[3])
+ $func($data);
+ else
+ $func($a, $data);
+ }
+ else {
+
+ // Don't do any DB write calls if we're currently logging a possibly failed DB call.
+ if(! DBA::$logging) {
+ // The hook should be removed so we don't process it.
+ q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND fn = '%s'",
+ dbesc($name),
+ dbesc($hook[0]),
+ dbesc($origfn)
+ );
+ }
}
}
}
@@ -491,7 +512,7 @@ function get_theme_info($theme){
* @return string
*/
function get_theme_screenshot($theme) {
- $a = get_app();
+
$exts = array('.png', '.jpg');
foreach($exts as $ext) {
if(file_exists('view/theme/' . $theme . '/img/screenshot' . $ext))
@@ -512,7 +533,7 @@ function head_add_css($src, $media = 'screen') {
}
function head_remove_css($src, $media = 'screen') {
- $a = get_app();
+
$index = array_search(array($src, $media), App::$css_sources);
if ($index !== false)
unset(App::$css_sources[$index]);
@@ -530,13 +551,22 @@ function head_get_css() {
}
function format_css_if_exists($source) {
- if (strpos($source[0], '/') !== false)
+ $path_prefix = script_path() . '/';
+
+ if (strpos($source[0], '/') !== false) {
+ // The source is a URL
$path = $source[0];
- else
+ // If the url starts with // then it's an absolute URL
+ if($source[0][0] === '/' && $source[0][1] === '/') $path_prefix = '';
+ } else {
+ // It's a file from the theme
$path = theme_include($source[0]);
+ }
- if($path)
- return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ if($path) {
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<link rel="stylesheet" href="' . $path_prefix . $path . $qstring . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ }
}
/*
@@ -575,26 +605,38 @@ function script_path() {
return $scheme . '://' . $hostname;
}
-function head_add_js($src) {
- App::$js_sources[] = $src;
+function head_add_js($src, $priority = 0) {
+ if(! is_array(App::$js_sources[$priority]))
+ App::$js_sources[$priority] = array();
+ App::$js_sources[$priority][] = $src;
}
-function head_remove_js($src) {
- $a = get_app();
- $index = array_search($src, App::$js_sources);
+function head_remove_js($src, $priority = 0) {
+
+ $index = array_search($src, App::$js_sources[$priority]);
if($index !== false)
- unset(App::$js_sources[$index]);
+ unset(App::$js_sources[$priority][$index]);
}
+// We should probably try to register main.js with a high priority, but currently we handle it
+// separately and put it at the end of the html head block in case any other javascript is
+// added outside the head_add_js construct.
+
function head_get_js() {
+
$str = '';
- $sources = App::$js_sources;
- if(count($sources))
- foreach($sources as $source) {
- if($source === 'main.js')
- continue;
- $str .= format_js_if_exists($source);
+ if(App::$js_sources) {
+ ksort(App::$js_sources,SORT_NUMERIC);
+ foreach(App::$js_sources as $sources) {
+ if(count($sources)) {
+ foreach($sources as $source) {
+ if($src === 'main.js')
+ continue;
+ $str .= format_js_if_exists($source);
+ }
+ }
}
+ }
return $str;
}
@@ -608,17 +650,25 @@ function head_get_main_js() {
}
function format_js_if_exists($source) {
- if(strpos($source,'/') !== false)
+ $path_prefix = script_path() . '/';
+
+ if(strpos($source,'/') !== false) {
+ // The source is a URL
$path = $source;
- else
+ // If the url starts with // then it's an absolute URL
+ if($source[0] === '/' && $source[1] === '/') $path_prefix = '';
+ } else {
+ // It's a file from the theme
$path = theme_include($source);
- if($path)
- return '<script src="' . script_path() . '/' . $path . '" ></script>' . "\r\n" ;
+ }
+ if($path) {
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<script src="' . $path_prefix . $path . $qstring . '" ></script>' . "\r\n" ;
+ }
}
function theme_include($file, $root = '') {
- $a = get_app();
// Make sure $root ends with a slash / if it's not blank
if($root !== '' && $root[strlen($root)-1] !== '/')
@@ -631,12 +681,13 @@ function theme_include($file, $root = '') {
else
$parent = 'NOPATH';
- $theme = current_theme();
+ $theme = Zotlabs\Render\Theme::current();
+ $thname = $theme[0];
$ext = substr($file,strrpos($file,'.')+1);
$paths = array(
- "{$root}view/theme/$theme/$ext/$file",
+ "{$root}view/theme/$thname/$ext/$file",
"{$root}view/theme/$parent/$ext/$file",
"{$root}view/site/$ext/$file",
"{$root}view/$ext/$file",
@@ -655,7 +706,7 @@ function theme_include($file, $root = '') {
function get_intltext_template($s, $root = '') {
- $a = get_app();
+
$t = App::template_engine();
$template = $t->get_intltext_template($s, $root);
@@ -664,7 +715,7 @@ function get_intltext_template($s, $root = '') {
function get_markup_template($s, $root = '') {
- $a = get_app();
+
$t = App::template_engine();
$template = $t->get_markup_template($s, $root);
return $template;
@@ -678,4 +729,4 @@ function folder_exists($folder)
// If it exist, check if it's a directory
return (($path !== false) && is_dir($path)) ? $path : false;
-} \ No newline at end of file
+}
diff --git a/include/poller.php b/include/poller.php
index 808b54ee5..e72121a8a 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -1,445 +1,15 @@
<?php /** @file */
-require_once('boot.php');
require_once('include/cli_startup.php');
-
-function poller_run($argv, $argc){
+function poller_run($argc,$argv){
cli_startup();
+ \Zotlabs\Daemon\Master::Summon(array('Cron'));
- $a = get_app();
-
- $maxsysload = intval(get_config('system','maxloadavg'));
- if($maxsysload < 1)
- $maxsysload = 50;
- if(function_exists('sys_getloadavg')) {
- $load = sys_getloadavg();
- if(intval($load[0]) > $maxsysload) {
- logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
- return;
- }
- }
-
- $interval = intval(get_config('system','poll_interval'));
- if(! $interval)
- $interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
-
- // Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
- $lockfile = 'store/[data]/poller';
- if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
- && (! get_config('system','override_poll_lockfile'))) {
- logger("poller: Already running");
- return;
- }
-
- // Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
- file_put_contents($lockfile, $x);
-
- logger('poller: start');
-
- // run queue delivery process in the background
-
- proc_run('php',"include/queue.php");
-
-
- // maintenance for mod sharedwithme - check for updated items and remove them
-
- require_once('include/sharedwithme.php');
- apply_updates();
-
-
- // expire any expired mail
-
- q("delete from mail where expires != '%s' and expires < %s ",
- dbesc(NULL_DATE),
- db_utcnow()
- );
-
- // expire any expired items
-
- $r = q("select id from item where expires != '%s' and expires < %s
- and item_deleted = 0 ",
- dbesc(NULL_DATE),
- db_utcnow()
- );
- if($r) {
- require_once('include/items.php');
- foreach($r as $rr)
- drop_item($rr['id'],false);
- }
-
-
- // Ensure that every channel pings a directory server once a month. This way we can discover
- // channels and sites that quietly vanished and prevent the directory from accumulating stale
- // or dead entries.
-
- $r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s",
- db_utcnow(),
- db_quoteinterval('30 DAY')
- );
- if($r) {
- foreach($r as $rr) {
- proc_run('php','include/directory.php',$rr['channel_id'],'force');
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
- }
- }
-
- // publish any applicable items that were set to be published in the future
- // (time travel posts). Restrict to items that have come of age in the last
- // couple of days to limit the query to something reasonable.
-
- $r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
- db_utcnow(),
- dbesc(datetime_convert('UTC','UTC','now - 2 days'))
- );
- if($r) {
- foreach($r as $rr) {
- $x = q("update item set item_delayed = 0 where id = %d",
- intval($rr['id'])
- );
- if($x) {
- proc_run('php','include/notifier.php','wall-new',$rr['id']);
- }
- }
- }
-
- $abandon_days = intval(get_config('system','account_abandon_days'));
- if($abandon_days < 1)
- $abandon_days = 0;
-
-
- // once daily run birthday_updates and then expire in background
-
- // FIXME: add birthday updates, both locally and for xprof for use
- // by directory servers
-
- $d1 = intval(get_config('system','last_expire_day'));
- $d2 = intval(datetime_convert('UTC','UTC','now','d'));
-
- // Allow somebody to staggger daily activities if they have more than one site on their server,
- // or if it happens at an inconvenient (busy) hour.
-
- $h1 = intval(get_config('system','cron_hour'));
- $h2 = intval(datetime_convert('UTC','UTC','now','G'));
-
- $dirmode = get_config('system','directory_mode');
-
- /**
- * Cron Daily
- *
- * Actions in the following block are executed once per day, not on every poller run
- *
- */
-
- if(($d2 != $d1) && ($h1 == $h2)) {
-
- require_once('include/dir_fns.php');
- check_upstream_directory();
-
- call_hooks('cron_daily',datetime_convert());
-
-
- $d3 = intval(datetime_convert('UTC','UTC','now','N'));
- if($d3 == 7) {
-
- /**
- * Cron Weekly
- *
- * Actions in the following block are executed once per day only on Sunday (once per week).
- *
- */
-
-
- call_hooks('cron_weekly',datetime_convert());
-
-
- z_check_cert();
-
- require_once('include/hubloc.php');
- prune_hub_reinstalls();
-
- require_once('include/Contact.php');
- mark_orphan_hubsxchans();
-
-
- // get rid of really old poco records
-
- q("delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ",
- db_utcnow(), db_quoteinterval('14 DAY')
- );
-
- $dirmode = intval(get_config('system','directory_mode'));
- if($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
- logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true));
- }
-
- // Check for dead sites
- proc_run('php', 'include/checksites.php');
-
- // update searchable doc indexes
- proc_run('php', 'include/importdoc.php');
-
- /**
- * End Cron Weekly
- */
- }
-
- update_birthdays();
-
- //update statistics in config
- require_once('include/statistics_fns.php');
- update_channels_total_stat();
- update_channels_active_halfyear_stat();
- update_channels_active_monthly_stat();
- update_local_posts_stat();
-
- // expire any read notifications over a month old
-
- q("delete from notify where seen = 1 and date < %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('30 DAY')
- );
-
- // expire old delivery reports
-
- $keep_reports = intval(get_config('system','expire_delivery_reports'));
- if($keep_reports === 0)
- $keep_reports = 10;
-
- q("delete from dreport where dreport_time < %s - INTERVAL %s",
- db_utcnow(),
- db_quoteinterval($keep_reports . ' DAY')
- );
-
- // expire any expired accounts
- downgrade_accounts();
-
- // If this is a directory server, request a sync with an upstream
- // directory at least once a day, up to once every poll interval.
- // Pull remote changes and push local changes.
- // potential issue: how do we keep from creating an endless update loop?
-
- if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
- require_once('include/dir_fns.php');
- sync_directories($dirmode);
- }
-
- set_config('system','last_expire_day',$d2);
-
- proc_run('php','include/expire.php');
- proc_run('php','include/cli_suggest.php');
-
- require_once('include/hubloc.php');
- remove_obsolete_hublocs();
-
- /**
- * End Cron Daily
- */
- }
-
- // update any photos which didn't get imported properly
- // This should be rare
-
- $r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
- and xchan_photo_date < %s - INTERVAL %s",
- db_utcnow(),
- db_quoteinterval('1 DAY')
- );
- if($r) {
- require_once('include/photo/photo_driver.php');
- foreach($r as $rr) {
- $photos = import_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']);
- $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
- where xchan_hash = '%s'",
- dbesc($photos[0]),
- dbesc($photos[1]),
- dbesc($photos[2]),
- dbesc($photos[3]),
- dbesc($rr['xchan_hash'])
- );
- }
- }
-
-
- // pull in some public posts
-
- if(! get_config('system','disable_discover_tab'))
- proc_run('php','include/externals.php');
-
-
- $manual_id = 0;
- $generation = 0;
-
- $force = false;
- $restart = false;
-
- if(($argc > 1) && ($argv[1] == 'force'))
- $force = true;
-
- if(($argc > 1) && ($argv[1] == 'restart')) {
- $restart = true;
- $generation = intval($argv[2]);
- if(! $generation)
- killme();
- }
-
- if(($argc > 1) && intval($argv[1])) {
- $manual_id = intval($argv[1]);
- $force = true;
- }
-
-
- $sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
-
- reload_plugins();
-
- $d = datetime_convert();
-
- // TODO check to see if there are any cronhooks before wasting a process
-
- if(! $restart)
- proc_run('php','include/cronhooks.php');
-
- // Only poll from those with suitable relationships
-
- $abandon_sql = (($abandon_days)
- ? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days).' DAY'))
- : ''
- );
-
- $randfunc = db_getfunc('RAND');
-
- $contacts = q("SELECT * FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
- LEFT JOIN account on abook_account = account_id
- where abook_self = 0
- $sql_extra
- AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
- intval(ACCOUNT_OK),
- intval(ACCOUNT_UNVERIFIED) // FIXME
-
- );
-
- if($contacts) {
-
- foreach($contacts as $contact) {
-
- $update = false;
-
- $t = $contact['abook_updated'];
- $c = $contact['abook_connected'];
-
- if(intval($contact['abook_feed'])) {
- $min = service_class_fetch($contact['abook_channel'],'minimum_feedcheck_minutes');
- if(! $min)
- $min = intval(get_config('system','minimum_feedcheck_minutes'));
- if(! $min)
- $min = 60;
- $x = datetime_convert('UTC','UTC',"now - $min minutes");
- if($c < $x) {
- proc_run('php','include/onepoll.php',$contact['abook_id']);
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
- }
- continue;
- }
-
-
- if($contact['xchan_network'] !== 'zot')
- continue;
-
- if($c == $t) {
- if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
- $update = true;
- }
- else {
-
- // if we've never connected with them, start the mark for death countdown from now
-
- if($c == NULL_DATE) {
- $r = q("update abook set abook_connected = '%s' where abook_id = %d",
- dbesc(datetime_convert()),
- intval($contact['abook_id'])
- );
- $c = datetime_convert();
- $update = true;
- }
-
- // He's dead, Jim
-
- if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 30 day")) > 0) {
- $r = q("update abook set abook_archived = 1 where abook_id = %d",
- intval($contact['abook_id'])
- );
- $update = false;
- continue;
- }
-
- if(intval($contact['abook_archived'])) {
- $update = false;
- continue;
- }
-
- // might be dead, so maybe don't poll quite so often
-
- // recently deceased, so keep up the regular schedule for 3 days
-
- if((strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 3 day")) > 0)
- && (strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 1 day")) > 0))
- $update = true;
-
- // After that back off and put them on a morphine drip
-
- if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 2 day")) > 0) {
- $update = true;
- }
-
- }
-
- if(intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked']))
- continue;
-
- if((! $update) && (! $force))
- continue;
-
- proc_run('php','include/onepoll.php',$contact['abook_id']);
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
-
- }
- }
-
- if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
- $r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last = '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
- intval(UPDATE_FLAGS_UPDATED),
- dbesc(NULL_DATE),
- db_utcnow(), db_quoteinterval('7 DAY')
- );
- if($r) {
- foreach($r as $rr) {
-
- // If they didn't respond when we attempted before, back off to once a day
- // After 7 days we won't bother anymore
-
- if($rr['ud_last'] != NULL_DATE)
- if($rr['ud_last'] > datetime_convert('UTC','UTC', 'now - 1 day'))
- continue;
- proc_run('php','include/onedirsync.php',$rr['ud_id']);
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
- }
- }
- }
-
- set_config('system','lastpoll',datetime_convert());
-
- //All done - clear the lockfile
- @unlink($lockfile);
-
- return;
}
if (array_search(__file__,get_included_files())===0){
- poller_run($argv,$argc);
+ poller_run($argc,$argv);
killme();
}
diff --git a/include/queue.php b/include/queue.php
deleted file mode 100644
index 8a3b2aa58..000000000
--- a/include/queue.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php /** @file */
-require_once("boot.php");
-require_once('include/cli_startup.php');
-require_once('include/queue_fn.php');
-require_once('include/zot.php');
-
-function queue_run($argv, $argc){
-
- cli_startup();
-
- global $a;
-
- require_once('include/items.php');
- require_once('include/bbcode.php');
-
- if(argc() > 1)
- $queue_id = argv(1);
- else
- $queue_id = 0;
-
- logger('queue: start');
-
- // delete all queue items more than 3 days old
- // but first mark these sites dead if we haven't heard from them in a month
-
- $r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('3 DAY')
- );
- if($r) {
- foreach($r as $rr) {
- $site_url = '';
- $h = parse_url($rr['outq_posturl']);
- $desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
- q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
- dbesc($desturl),
- db_utcnow(), db_quoteinterval('1 MONTH')
- );
- }
- }
-
- $r = q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
- db_utcnow(), db_quoteinterval('3 DAY')
- );
-
- if($queue_id) {
- $r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
- dbesc($queue_id)
- );
- }
- else {
-
- // For the first 12 hours we'll try to deliver every 15 minutes
- // After that, we'll only attempt delivery once per hour.
- // This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
- // so that we don't start off a thousand deliveries for a couple of dead hubs.
- // The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
- // Other drivers will have to do something different here and may need their own query.
-
- // Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
- // "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
- // or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
- // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
- // or twice a day.
-
- // FIXME: can we sort postgres on outq_priority and maintain the 'distinct' ?
- // The order by max(outq_priority) might be a dodgy query because of the group by.
- // The desired result is to return a sequence in the order most likely to be delivered in this run.
- // If a hub has already been sitting in the queue for a few days, they should be delivered last;
- // hence every failure should drop them further down the priority list.
-
- if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
- $prefix = 'DISTINCT ON (outq_posturl)';
- $suffix = 'ORDER BY outq_posturl';
- } else {
- $prefix = '';
- $suffix = 'GROUP BY outq_posturl ORDER BY max(outq_priority)';
- }
- $r = q("SELECT $prefix * FROM outq WHERE outq_delivered = 0 and (( outq_created > %s - INTERVAL %s and outq_updated < %s - INTERVAL %s ) OR ( outq_updated < %s - INTERVAL %s )) $suffix",
- db_utcnow(), db_quoteinterval('12 HOUR'),
- db_utcnow(), db_quoteinterval('15 MINUTE'),
- db_utcnow(), db_quoteinterval('1 HOUR')
- );
- }
- if(! $r)
- return;
-
- foreach($r as $rr) {
- queue_deliver($rr);
- }
-}
-
-if (array_search(__file__,get_included_files())===0){
- queue_run($argv,$argc);
- killme();
-}
diff --git a/include/ratenotif.php b/include/ratenotif.php
deleted file mode 100644
index 2c636c710..000000000
--- a/include/ratenotif.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-
-require_once('include/cli_startup.php');
-require_once('include/zot.php');
-require_once('include/queue_fn.php');
-
-
-function ratenotif_run($argv, $argc){
-
- cli_startup();
-
- $a = get_app();
-
- require_once("datetime.php");
- require_once('include/items.php');
- require_once('include/Contact.php');
-
- if($argc < 3)
- return;
-
-
- logger('ratenotif: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
-
- $cmd = $argv[1];
-
- $item_id = $argv[2];
-
-
- if($cmd === 'rating') {
- $r = q("select * from xlink where xlink_id = %d and xlink_static = 1 limit 1",
- intval($item_id)
- );
- if(! $r) {
- logger('rating not found');
- return;
- }
-
- $encoded_item = array(
- 'type' => 'rating',
- 'encoding' => 'zot',
- 'target' => $r[0]['xlink_link'],
- 'rating' => intval($r[0]['xlink_rating']),
- 'rating_text' => $r[0]['xlink_rating_text'],
- 'signature' => $r[0]['xlink_sig'],
- 'edited' => $r[0]['xlink_updated']
- );
- }
-
- $channel = channelx_by_hash($r[0]['xlink_xchan']);
- if(! $channel) {
- logger('no channel');
- return;
- }
-
-
- $primary = get_directory_primary();
-
- if(! $primary)
- return;
-
-
- $interval = ((get_config('system','delivery_interval') !== false)
- ? intval(get_config('system','delivery_interval')) : 2 );
-
- $deliveries_per_process = intval(get_config('system','delivery_batch_count'));
-
- if($deliveries_per_process <= 0)
- $deliveries_per_process = 1;
-
- $deliver = array();
-
- $x = z_fetch_url($primary . '/regdir');
- if($x['success']) {
- $j = json_decode($x['body'],true);
- if($j && $j['success'] && is_array($j['directories'])) {
-
- foreach($j['directories'] as $h) {
- if($h == z_root())
- continue;
-
- $hash = random_string();
- $n = zot_build_packet($channel,'notify',null,null,$hash);
-
- queue_insert(array(
- 'hash' => $hash,
- 'account_id' => $channel['channel_account_id'],
- 'channel_id' => $channel['channel_id'],
- 'posturl' => $h . '/post',
- 'notify' => $n,
- 'msg' => json_encode($encoded_item)
- ));
-
- $deliver[] = $hash;
-
- if(count($deliver) >= $deliveries_per_process) {
- proc_run('php','include/deliver.php',$deliver);
- $deliver = array();
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
- }
- }
-
- // catch any stragglers
-
- if(count($deliver)) {
- proc_run('php','include/deliver.php',$deliver);
- }
- }
- }
-
- logger('ratenotif: complete.');
- return;
-
-}
-
-if (array_search(__file__,get_included_files())===0){
- ratenotif_run($argv,$argc);
- killme();
-}
diff --git a/include/reddav.php b/include/reddav.php
deleted file mode 100644
index abf21b86d..000000000
--- a/include/reddav.php
+++ /dev/null
@@ -1,299 +0,0 @@
-<?php
-/**
- * @file include/reddav.php
- * @brief some DAV related functions for Hubzilla.
- *
- * This file contains some functions which did not fit into one of the RedDAV
- * classes.
- *
- * The extended SabreDAV classes you will find in the RedDAV namespace under
- * @ref includes/RedDAV/.
- * The original SabreDAV classes you can find under @ref vendor/sabre/dav/.
- * We need to use SabreDAV 1.8.x for PHP5.3 compatibility. SabreDAV >= 2.0
- * requires PHP >= 5.4.
- *
- * @todo split up the classes into own files.
- *
- * @link http://github.com/friendica/red
- * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
- */
-
-use Sabre\DAV;
-use Zotlabs\Storage;
-
-require_once('vendor/autoload.php');
-require_once('include/attach.php');
-
-/**
- * @brief Returns an array with viewable channels.
- *
- * Get a list of RedDirectory objects with all the channels where the visitor
- * has <b>view_storage</b> perms.
- *
- * @todo Is there any reason why this is not inside RedDirectory class?
- * @fixme function name looks like a class name, should we rename it?
- *
- * @param RedBasicAuth &$auth
- * @return array RedDirectory[]
- */
-function RedChannelList(&$auth) {
- $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",
- intval(PAGE_HIDDEN)
- );
-
- if ($r) {
- foreach ($r as $rr) {
- if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) {
- logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
- // @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory
- $ret[] = new Zotlabs\Storage\Directory('/cloud/' . $rr['channel_address'], $auth);
- }
- }
- }
- return $ret;
-}
-
-
-/**
- * @brief TODO what exactly does this function?
- *
- * Array with all RedDirectory and RedFile DAV\Node items for the given path.
- *
- * @todo Is there any reason why this is not inside RedDirectory class? Seems
- * only to be used there and we could simplify it a bit there.
- * @fixme function name looks like a class name, should we rename it?
- *
- * @param string $file path to a directory
- * @param RedBasicAuth &$auth
- * @returns null|array \Sabre\DAV\INode[]
- * @throw \Sabre\DAV\Exception\Forbidden
- * @throw \Sabre\DAV\Exception\NotFound
- */
-function RedCollectionData($file, &$auth) {
- $ret = array();
-
- $x = strpos($file, '/cloud');
- if ($x === 0) {
- $file = substr($file, 6);
- }
-
- // return a list of channel if we are not inside a channel
- if ((! $file) || ($file === '/')) {
- return RedChannelList($auth);
- }
-
- $file = trim($file, '/');
- $path_arr = explode('/', $file);
-
- if (! $path_arr)
- return null;
-
- $channel_name = $path_arr[0];
-
- $r = q("SELECT channel_id FROM channel WHERE channel_address = '%s' LIMIT 1",
- dbesc($channel_name)
- );
-
- if (! $r)
- return null;
-
- $channel_id = $r[0]['channel_id'];
- $perms = permissions_sql($channel_id);
-
- $auth->owner_id = $channel_id;
-
- $path = '/' . $channel_name;
-
- $folder = '';
- $errors = false;
- $permission_error = false;
-
- for ($x = 1; $x < count($path_arr); $x++) {
- $r = q("SELECT id, hash, filename, flags, is_dir FROM attach WHERE folder = '%s' AND filename = '%s' AND uid = %d AND is_dir != 0 $perms LIMIT 1",
- dbesc($folder),
- dbesc($path_arr[$x]),
- intval($channel_id)
- );
- if (! $r) {
- // path wasn't found. Try without permissions to see if it was the result of permissions.
- $errors = true;
- $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 limit 1",
- dbesc($folder),
- basename($path_arr[$x]),
- intval($channel_id)
- );
- if ($r) {
- $permission_error = true;
- }
- break;
- }
-
- if ($r && intval($r[0]['is_dir'])) {
- $folder = $r[0]['hash'];
- $path = $path . '/' . $r[0]['filename'];
- }
- }
-
- if ($errors) {
- if ($permission_error) {
- throw new DAV\Exception\Forbidden('Permission denied.');
- } else {
- throw new DAV\Exception\NotFound('A component of the request file path could not be found.');
- }
- }
-
- // This should no longer be needed since we just returned errors for paths not found
- if ($path !== '/' . $file) {
- 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';
- }
- $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) {
- //logger('filename: ' . $rr['filename'], LOGGER_DEBUG);
- if (intval($rr['is_dir'])) {
- $ret[] = new Zotlabs\Storage\Directory($path . '/' . $rr['filename'], $auth);
- } else {
- $ret[] = new Zotlabs\Storage\File($path . '/' . $rr['filename'], $rr, $auth);
- }
- }
-
- return $ret;
-}
-
-
-/**
- * @brief TODO What exactly is this function for?
- *
- * @fixme function name looks like a class name, should we rename it?
- *
- * @param string $file
- * path to file or directory
- * @param RedBasicAuth &$auth
- * @param boolean $test (optional) enable test mode
- * @return RedFile|RedDirectory|boolean|null
- * @throw \Sabre\DAV\Exception\Forbidden
- */
-function RedFileData($file, &$auth, $test = false) {
- logger($file . (($test) ? ' (test mode) ' : ''), LOGGER_DATA);
-
- $x = strpos($file, '/cloud');
- if ($x === 0) {
- $file = substr($file, 6);
- }
- else {
- $x = strpos($file,'/dav');
- if($x === 0)
- $file = substr($file,4);
- }
-
-
- if ((! $file) || ($file === '/')) {
- return new Zotlabs\Storage\Directory('/', $auth);
- }
-
- $file = trim($file, '/');
-
- $path_arr = explode('/', $file);
-
- if (! $path_arr)
- return null;
-
- $channel_name = $path_arr[0];
-
- $r = q("select channel_id from channel where channel_address = '%s' limit 1",
- dbesc($channel_name)
- );
-
- if (! $r)
- return null;
-
- $channel_id = $r[0]['channel_id'];
-
- $path = '/' . $channel_name;
-
- $auth->owner_id = $channel_id;
-
- $permission_error = false;
-
- $folder = '';
-
- require_once('include/security.php');
- $perms = permissions_sql($channel_id);
-
- $errors = false;
-
- for ($x = 1; $x < count($path_arr); $x++) {
- $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 $perms",
- dbesc($folder),
- dbesc($path_arr[$x]),
- intval($channel_id)
- );
-
- if ($r && intval($r[0]['is_dir'])) {
- $folder = $r[0]['hash'];
- $path = $path . '/' . $r[0]['filename'];
- }
- if (! $r) {
- $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach
- where folder = '%s' and filename = '%s' and uid = %d $perms order by filename limit 1",
- dbesc($folder),
- dbesc(basename($file)),
- intval($channel_id)
- );
- }
- if (! $r) {
- $errors = true;
- $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach
- where folder = '%s' and filename = '%s' and uid = %d order by filename limit 1",
- dbesc($folder),
- dbesc(basename($file)),
- intval($channel_id)
- );
- if ($r)
- $permission_error = true;
- }
- }
-
- if ($path === '/' . $file) {
- if ($test)
- return true;
- // final component was a directory.
- return new Zotlabs\Storage\Directory($file, $auth);
- }
-
- if ($errors) {
- logger('not found ' . $file);
- if ($test)
- return false;
- if ($permission_error) {
- logger('permission error ' . $file);
- throw new DAV\Exception\Forbidden('Permission denied.');
- }
- return;
- }
-
- if ($r) {
- if ($test)
- return true;
-
- if (intval($r[0]['is_dir'])) {
- return new Zotlabs\Storage\Directory($path . '/' . $r[0]['filename'], $auth);
- } else {
- return new Zotlabs\Storage\File($path . '/' . $r[0]['filename'], $r[0], $auth);
- }
- }
- return false;
-} \ No newline at end of file
diff --git a/include/security.php b/include/security.php
index 38045c8a9..c67a1b400 100644
--- a/include/security.php
+++ b/include/security.php
@@ -12,7 +12,7 @@
* @param bool $return
* @param bool $update_lastlog
*/
-function authenticate_success($user_record, $login_initial = false, $interactive = false, $return = false, $update_lastlog = false) {
+function authenticate_success($user_record, $channel = null, $login_initial = false, $interactive = false, $return = false, $update_lastlog = false) {
$_SESSION['addr'] = $_SERVER['REMOTE_ADDR'];
@@ -23,11 +23,15 @@ function authenticate_success($user_record, $login_initial = false, $interactive
$_SESSION['account_id'] = $user_record['account_id'];
$_SESSION['authenticated'] = 1;
+ if($channel)
+ $uid_to_load = $channel['channel_id'];
- $uid_to_load = (((x($_SESSION,'uid')) && (intval($_SESSION['uid'])))
- ? intval($_SESSION['uid'])
- : intval(App::$account['account_default_channel'])
- );
+ if(! $uid_to_load) {
+ $uid_to_load = (((x($_SESSION,'uid')) && (intval($_SESSION['uid'])))
+ ? intval($_SESSION['uid'])
+ : intval(App::$account['account_default_channel'])
+ );
+ }
if($uid_to_load) {
change_channel($uid_to_load);
@@ -82,6 +86,41 @@ function authenticate_success($user_record, $login_initial = false, $interactive
/* else just return */
}
+function atoken_login($atoken) {
+ if(! $atoken)
+ return false;
+ $_SESSION['authenticated'] = 1;
+ $_SESSION['visitor_id'] = $atoken['xchan_hash'];
+ $_SESSION['atoken'] = $atoken['atoken_id'];
+
+ \App::set_observer($atoken);
+ return true;
+}
+
+
+function atoken_xchan($atoken) {
+
+ $c = channelx_by_n($atoken['atoken_uid']);
+ if($c) {
+ return [
+ 'atoken_id' => $atoken['atoken_id'],
+ 'xchan_hash' => substr($c['channel_hash'],0,16) . '.' . $atoken['atoken_name'],
+ 'xchan_name' => $atoken['atoken_name'],
+ 'xchan_addr' => t('guest:') . $atoken['atoken_name'] . '@' . \App::get_hostname(),
+ 'xchan_network' => 'unknown',
+ 'xchan_hidden' => 1,
+ 'xchan_photo_mimetype' => 'image/jpeg',
+ 'xchan_photo_l' => get_default_profile_photo(300),
+ 'xchan_photo_m' => get_default_profile_photo(80),
+ 'xchan_photo_s' => get_default_profile_photo(48)
+
+ ];
+ }
+ return null;
+}
+
+
+
/**
* @brief Change to another channel with current logged-in account.
*
@@ -89,6 +128,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive
*
* @return bool|array false or channel record of the new channel
*/
+
function change_channel($change_channel) {
$ret = false;
@@ -125,13 +165,17 @@ function change_channel($change_channel) {
);
if($x) {
$_SESSION['my_url'] = $x[0]['xchan_url'];
- $_SESSION['my_address'] = $r[0]['channel_address'] . '@' . substr(z_root(), strpos(z_root(), '://') + 3);
+ $_SESSION['my_address'] = $r[0]['channel_address'] . '@' . App::get_hostname();
App::set_observer($x[0]);
App::set_perms(get_all_perms(local_channel(), $hash));
}
if(! is_dir('store/' . $r[0]['channel_address']))
@os_mkdir('store/' . $r[0]['channel_address'], STORAGE_DEFAULT_PERMISSIONS,true);
+
+ $arr = [ 'channel_id' => $change_channel, 'chanx' => $ret ];
+ call_hooks('change_channel', $arr);
+
}
return $ret;
@@ -434,14 +478,19 @@ function stream_perms_api_uids($perms = NULL, $limit = 0, $rand = 0 ) {
$random_sql = (($rand) ? " ORDER BY " . db_getfunc('RAND') . " " : '');
if(local_channel())
$ret[] = local_channel();
- $r = q("select channel_id from channel where channel_r_stream > 0 and ( channel_r_stream & %d )>0 and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 $random_sql $limit_sql ",
- intval($perms),
- intval(PAGE_ADULT|PAGE_CENSORED)
+ $x = q("select uid from pconfig where cat = 'perm_limits' and k = 'view_stream' and ( v & %d ) > 0 ",
+ intval($perms)
);
- if($r) {
- foreach($r as $rr)
- if(! in_array($rr['channel_id'], $ret))
- $ret[] = $rr['channel_id'];
+ if($x) {
+ $ids = ids_to_querystr($x,'uid');
+ $r = q("select channel_id from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 $random_sql $limit_sql ",
+ intval(PAGE_ADULT|PAGE_CENSORED)
+ );
+ if($r) {
+ foreach($r as $rr)
+ if(! in_array($rr['channel_id'], $ret))
+ $ret[] = $rr['channel_id'];
+ }
}
$str = '';
@@ -467,16 +516,21 @@ function stream_perms_xchans($perms = NULL ) {
if(local_channel())
$ret[] = get_observer_hash();
- $r = q("select channel_hash from channel where channel_r_stream > 0 and (channel_r_stream & %d)>0 and not (channel_pageflags & %d)>0 and channel_system = 0 and channel_removed = 0 ",
- intval($perms),
- intval(PAGE_ADULT|PAGE_CENSORED)
+ $x = q("select uid from pconfig where cat = 'perm_limits' and k = 'view_stream' and ( v & %d ) > 0 ",
+ intval($perms)
);
- if($r) {
- foreach($r as $rr)
- if(! in_array($rr['channel_hash'], $ret))
- $ret[] = $rr['channel_hash'];
- }
+ if($x) {
+ $ids = ids_to_querystr($x,'uid');
+ $r = q("select channel_hash from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 ",
+ intval(PAGE_ADULT|PAGE_CENSORED)
+ );
+ if($r) {
+ foreach($r as $rr)
+ if(! in_array($rr['channel_hash'], $ret))
+ $ret[] = $rr['channel_hash'];
+ }
+ }
$str = '';
if($ret) {
foreach($ret as $rr) {
diff --git a/include/profile_selectors.php b/include/selectors.php
index 9f993f803..d7d070d31 100644
--- a/include/profile_selectors.php
+++ b/include/selectors.php
@@ -1,6 +1,49 @@
<?php /** @file */
+function contact_profile_assign($current) {
+
+ $o = '';
+
+ $o .= "<select id=\"contact-profile-selector\" name=\"profile_assign\" class=\"form-control\"/>\r\n";
+
+ $r = q("SELECT profile_guid, profile_name FROM `profile` WHERE `uid` = %d",
+ intval($_SESSION['uid']));
+
+ if($r) {
+ foreach($r as $rr) {
+ $selected = (($rr['profile_guid'] == $current) ? " selected=\"selected\" " : "");
+ $o .= "<option value=\"{$rr['profile_guid']}\" $selected >{$rr['profile_name']}</option>\r\n";
+ }
+ }
+ $o .= "</select>\r\n";
+ return $o;
+}
+
+function contact_poll_interval($current, $disabled = false) {
+
+ $dis = (($disabled) ? ' disabled="disabled" ' : '');
+ $o = '';
+ $o .= "<select id=\"contact-poll-interval\" name=\"poll\" $dis />" . "\r\n";
+
+ $rep = array(
+ 0 => t('Frequently'),
+ 1 => t('Hourly'),
+ 2 => t('Twice daily'),
+ 3 => t('Daily'),
+ 4 => t('Weekly'),
+ 5 => t('Monthly')
+ );
+
+ foreach($rep as $k => $v) {
+ $selected = (($k == $current) ? " selected=\"selected\" " : "");
+ $o .= "<option value=\"$k\" $selected >$v</option>\r\n";
+ }
+ $o .= "</select>\r\n";
+ return $o;
+}
+
+
function gender_selector($current="",$suffix="") {
$o = '';
$select = array('', t('Male'), t('Female'), t('Currently Male'), t('Currently Female'), t('Mostly Male'), t('Mostly Female'), t('Transgender'), t('Intersex'), t('Transsexual'), t('Hermaphrodite'), t('Neuter'), t('Non-specific'), t('Other'), t('Undecided'));
@@ -108,3 +151,4 @@ function marital_selector_min($current="",$suffix="") {
$o .= '</select>';
return $o;
}
+
diff --git a/include/sharedwithme.php b/include/sharedwithme.php
index b01764ad3..b342f51d5 100644
--- a/include/sharedwithme.php
+++ b/include/sharedwithme.php
@@ -3,7 +3,7 @@
function apply_updates() {
//check for updated items and remove them
- $x = q("SELECT mid, max(object) AS object FROM item WHERE verb = '%s' AND obj_type = '%s' GROUP BY mid",
+ $x = q("SELECT mid, max(obj) AS obj FROM item WHERE verb = '%s' AND obj_type = '%s' GROUP BY mid",
dbesc(ACTIVITY_UPDATE),
dbesc(ACTIVITY_OBJ_FILE)
);
@@ -12,7 +12,7 @@ function apply_updates() {
foreach($x as $xx) {
- $object = json_decode($xx['object'],true);
+ $object = json_decode($xx['obj'],true);
$d_mid = $object['d_mid'];
$u_mid = $xx['mid'];
diff --git a/include/smarty.php b/include/smarty.php
deleted file mode 100755
index 3812c6021..000000000
--- a/include/smarty.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php /** @file */
-require_once 'include/ITemplateEngine.php';
-require_once("library/Smarty/libs/Smarty.class.php");
-
-
-class FriendicaSmarty extends Smarty {
-
- public $filename;
-
- function __construct() {
- parent::__construct();
-
- $a = get_app();
- $theme = current_theme();
-
- // setTemplateDir can be set to an array, which Smarty will parse in order.
- // The order is thus very important here
- $template_dirs = array('theme' => "view/theme/$theme/tpl/");
- if( x(App::$theme_info,"extends") )
- $template_dirs = $template_dirs + array('extends' => "view/theme/".App::$theme_info["extends"]."/tpl/");
- $template_dirs = $template_dirs + array('base' => 'view/tpl/');
- $this->setTemplateDir($template_dirs);
-
- $basecompiledir = App::$config['system']['smarty3_folder'];
-
- $this->setCompileDir($basecompiledir.'/compiled/');
- $this->setConfigDir($basecompiledir.'/config/');
- $this->setCacheDir($basecompiledir.'/cache/');
-
- $this->left_delimiter = App::get_template_ldelim('smarty3');
- $this->right_delimiter = App::get_template_rdelim('smarty3');
-
- // Don't report errors so verbosely
- $this->error_reporting = E_ALL & ~E_NOTICE;
- }
-
- function parsed($template = '') {
- if($template) {
- return $this->fetch('string:' . $template);
- }
- return $this->fetch('file:' . $this->filename);
- }
-}
-
-
-
-class FriendicaSmartyEngine implements ITemplateEngine {
- static $name ="smarty3";
-
- public function __construct(){
- $a = get_app();
-
- // Cannot use get_config() here because it is called during installation when there is no DB.
- // FIXME: this may leak private information such as system pathnames.
-
- $basecompiledir = ((array_key_exists('smarty3_folder',App::$config['system'])) ? App::$config['system']['smarty3_folder'] : '');
- if (!$basecompiledir) $basecompiledir = dirname(__dir__) . "/" . TEMPLATE_BUILD_PATH;
- if (!is_dir($basecompiledir)) {
- echo "<b>ERROR:</b> folder <tt>$basecompiledir</tt> does not exist."; killme();
- }
- if(!is_writable($basecompiledir)){
- echo "<b>ERROR:</b> folder <tt>$basecompiledir</tt> must be writable by webserver."; killme();
- }
- App::$config['system']['smarty3_folder'] = $basecompiledir;
- }
-
- // ITemplateEngine interface
- public function replace_macros($s, $r) {
- $template = '';
- if(gettype($s) === 'string') {
- $template = $s;
- $s = new FriendicaSmarty();
- }
- foreach($r as $key=>$value) {
- if($key[0] === '$') {
- $key = substr($key, 1);
- }
- $s->assign($key, $value);
- }
- return $s->parsed($template);
- }
-
- public function get_markup_template($file, $root=''){
- $template_file = theme_include($file, $root);
- if($template_file) {
- $template = new FriendicaSmarty();
- $template->filename = $template_file;
-
- return $template;
- }
- return "";
- }
-
- public function get_intltext_template($file, $root='') {
- $a = get_app();
-
- if(file_exists("view/{App::$language}/$file"))
- $template_file = "view/{App::$language}/$file";
- elseif(file_exists("view/en/$file"))
- $template_file = "view/en/$file";
- else
- $template_file = theme_include($file,$root);
- if($template_file) {
- $template = new FriendicaSmarty();
- $template->filename = $template_file;
-
- return $template;
- }
- return "";
- }
-
-
-
-}
diff --git a/include/socgraph.php b/include/socgraph.php
index 1b1bccf20..4cb5600ec 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -152,11 +152,9 @@ function poco_load($xchan = '', $url = null) {
if(($x !== false) && (! count($x))) {
if($address) {
if($network === 'zot') {
- $z = zot_finger($address,null);
- if($z['success']) {
- $j = json_decode($z['body'],true);
- if($j)
- import_xchan($j);
+ $j = Zotlabs\Zot\Finger::run($address,null);
+ if($j['success']) {
+ import_xchan($j);
}
$x = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($hash)
@@ -404,7 +402,7 @@ function poco($a,$extended = false) {
$system_mode = false;
- if(intval(get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
+ if(observer_prohibited()) {
logger('mod_poco: block_public');
http_status_exit(401);
}
diff --git a/include/spam.php b/include/spam.php
deleted file mode 100644
index 8b158b7ae..000000000
--- a/include/spam.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php /** @file */
-
-
-function string_splitter($s) {
-
- if(! $s)
- return array();
-
- $s = preg_replace('/\pP+/','',$s);
-
- $x = mb_split("\[|\]|\s",$s);
-
- $ret = array();
- if($x) {
- foreach($x as $y) {
- if(mb_strlen($y) > 2)
- $ret[] = substr($y,0,64);
- }
- }
- return $ret;
-}
-
-
-
-function get_words($uid,$list) {
-
- stringify($list,true);
-
- $r = q("select * from spam where term in ( " . $list . ") and uid = %d",
- intval($uid)
- );
-
- return $r;
-}
-
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 71ed6e91d..067bd3246 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -20,7 +20,7 @@ function file_tag_file_query($table,$s,$type = 'file') {
else
$termtype = TERM_CATEGORY;
- return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
+ return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.ttype = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
intval($termtype),
protect_sprintf(dbesc($s))
);
@@ -29,14 +29,14 @@ function file_tag_file_query($table,$s,$type = 'file') {
function term_query($table,$s,$type = TERM_UNKNOWN, $type2 = '') {
if($type2) {
- return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type in (%d, %d) and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
+ return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.ttype in (%d, %d) and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
intval($type),
intval($type2),
protect_sprintf(dbesc($s))
);
}
else {
- return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
+ return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.ttype = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ",
intval($type),
protect_sprintf(dbesc($s))
);
@@ -49,7 +49,7 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') {
return false;
$r = q("select * from term
- where uid = %d and oid = %d and otype = %d and type = %d
+ where uid = %d and oid = %d and otype = %d and ttype = %d
and term = '%s' and url = '%s' ",
intval($uid),
intval($iid),
@@ -61,7 +61,7 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') {
if($r)
return false;
- $r = q("insert into term (uid, oid, otype, type, term, url)
+ $r = q("insert into term (uid, oid, otype, ttype, term, url)
values( %d, %d, %d, %d, '%s', '%s') ",
intval($uid),
intval($iid),
@@ -85,7 +85,7 @@ function get_terms_oftype($arr,$type) {
foreach($type as $t)
foreach($arr as $x)
- if($x['type'] == $t)
+ if($x['ttype'] == $t)
$ret[] = $x;
return $ret;
@@ -93,9 +93,9 @@ function get_terms_oftype($arr,$type) {
function format_term_for_display($term) {
$s = '';
- if(($term['type'] == TERM_HASHTAG) || ($term['type'] == TERM_COMMUNITYTAG))
+ if(($term['ttype'] == TERM_HASHTAG) || ($term['ttype'] == TERM_COMMUNITYTAG))
$s .= '#';
- elseif($term['type'] == TERM_MENTION)
+ elseif($term['ttype'] == TERM_MENTION)
$s .= '@';
else
return $s;
@@ -142,7 +142,7 @@ function tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0, $re
// Fetch tags
$r = q("select term, count(term) as total from term left join item on term.oid = item.id
- where term.uid = %d and term.type = %d
+ where term.uid = %d and term.ttype = %d
and otype = %d and item_type = %d and item_private = 0
$sql_options $item_normal
group by term order by total desc %s",
@@ -156,78 +156,66 @@ function tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0, $re
if(! $r)
return array();
- // Find minimum and maximum log-count.
- $tags = array();
- $min = 1e9;
- $max = -1e9;
-
- $x = 0;
- foreach($r as $rr) {
- $tags[$x][0] = $rr['term'];
- $tags[$x][1] = log($rr['total']);
- $tags[$x][2] = 0;
- $min = min($min,$tags[$x][1]);
- $max = max($max,$tags[$x][1]);
- $x ++;
- }
+ return Zotlabs\Text\Tagadelic::calc($r);
- usort($tags,'tags_sort');
+}
- $range = max(.01, $max - $min) * 1.0001;
+function dir_tagadelic($count = 0) {
- for($x = 0; $x < count($tags); $x ++) {
- $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range);
- }
+ $count = intval($count);
+
+ // Fetch tags
+ $r = q("select xtag_term as term, count(xtag_term) as total from xtag where xtag_flags = 0
+ group by xtag_term order by total desc %s",
+ ((intval($count)) ? "limit $count" : '')
+ );
+
+ if(! $r)
+ return array();
+
+
+ return Zotlabs\Text\Tagadelic::calc($r);
- return $tags;
}
-function tags_sort($a,$b) {
- if(strtolower($a[0]) == strtolower($b[0]))
- return 0;
+function app_tagblock($link,$count = 0) {
+ $o = '';
+
+ $r = app_tagadelic($count);
- return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1);
+ if($r) {
+ $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
+ foreach($r as $rr) {
+ $o .= '<a href="'.$link .'/' . '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
+ }
+ $o .= '</div></div>';
+ }
+
+ return $o;
}
+function app_tagadelic($count = 0) {
-function dir_tagadelic($count = 0) {
+ if(! local_channel())
+ return '';
$count = intval($count);
+
// Fetch tags
- $r = q("select xtag_term, count(xtag_term) as total from xtag where xtag_flags = 0
- group by xtag_term order by total desc %s",
+ $r = q("select term, count(term) as total from term left join app on term.uid = app_channel where term.uid = %d
+ and term.otype = %d group by term order by total desc %s",
+ intval(local_channel()),
+ intval(TERM_OBJ_APP),
((intval($count)) ? "limit $count" : '')
);
if(! $r)
return array();
- // Find minimum and maximum log-count.
- $tags = array();
- $min = 1e9;
- $max = -1e9;
-
- $x = 0;
- foreach($r as $rr) {
- $tags[$x][0] = $rr['xtag_term'];
- $tags[$x][1] = log($rr['total']);
- $tags[$x][2] = 0;
- $min = min($min,$tags[$x][1]);
- $max = max($max,$tags[$x][1]);
- $x ++;
- }
-
- usort($tags,'tags_sort');
-
- $range = max(.01, $max - $min) * 1.0001;
-
- for($x = 0; $x < count($tags); $x ++) {
- $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range);
- }
+ return Zotlabs\Text\Tagadelic::calc($r);
- return $tags;
}
@@ -412,7 +400,7 @@ function get_things($profile_hash,$uid) {
if(! $things[$rr['obj_verb']])
$things[$rr['obj_verb']] = array();
- $things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
+ $things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'editurl' => z_root() . '/thing/' . $rr['obj_obj'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
}
$sorted_things = array();
if($things) {
diff --git a/include/template_processor.php b/include/template_processor.php
deleted file mode 100755
index d2bf283e3..000000000
--- a/include/template_processor.php
+++ /dev/null
@@ -1,307 +0,0 @@
-<?php
-require_once 'include/ITemplateEngine.php';
-
-define ("KEY_NOT_EXISTS", '^R_key_not_Exists^');
-
-class Template implements ITemplateEngine {
- static $name ="internal";
-
- var $r;
- var $search;
- var $replace;
- var $stack = array();
- var $nodes = array();
- var $done = false;
- var $d = false;
- var $lang = null;
- var $debug=false;
-
- private function _preg_error() {
- switch(preg_last_error()) {
- case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break;
- case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break;
- case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break;
- case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break;
-// This is only valid for php > 5.3, not certain how to code around it for unit tests
-// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break;
- default:
- //die("Unknown preg error.");
- return;
- }
- echo "<hr><pre>";
- debug_print_backtrace();
- die();
- }
-
- private function _push_stack() {
- $this->stack[] = array($this->r, $this->nodes);
- }
-
- private function _pop_stack(){
- list($this->r, $this->nodes) = array_pop($this->stack);
- }
-
- private function _get_var($name, $retNoKey=false) {
- $keys = array_map('trim',explode(".",$name));
- if ($retNoKey && !array_key_exists($keys[0], $this->r))
- return KEY_NOT_EXISTS;
-
- $val = $this->r;
- foreach($keys as $k) {
- $val = (isset($val[$k]) ? $val[$k] : null);
- }
-
- return template_escape($val);
- }
-
- /**
- * IF node
- * \code
- * {{ if <$var> }}...[{{ else }} ...] {{ endif }}
- * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }}
- * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }}
- * \endcode
- */
- private function _replcb_if($args) {
- if (strpos($args[2],"==")>0){
- list($a,$b) = array_map("trim",explode("==",$args[2]));
- $a = $this->_get_var($a);
- if ($b[0]=="$") $b = $this->_get_var($b);
- $val = ($a == $b);
- } else if (strpos($args[2],"!=")>0){
- list($a,$b) = array_map("trim", explode("!=",$args[2]));
- $a = $this->_get_var($a);
- if ($b[0]=="$") $b = $this->_get_var($b);
- $val = ($a != $b);
- } else {
- $val = $this->_get_var($args[2]);
- }
- $x = preg_split("|{{ *else *}}|", $args[3]);
-
- return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : ""));
- }
-
- /**
- * FOR node
- * \code
- * {{ for <$var> as $name }}...{{ endfor }}
- * {{ for <$var> as $key=>$name }}...{{ endfor }}
- * \endcode
- */
- private function _replcb_for($args) {
- $m = array_map('trim', explode(" as ", $args[2]));
- $x = explode("=>",$m[1]);
- if (count($x) == 1) {
- $varname = $x[0];
- $keyname = "";
- } else {
- list($keyname, $varname) = $x;
- }
- if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ;
- //$vals = $this->r[$m[0]];
- $vals = $this->_get_var($m[0]);
- $ret="";
- if (!is_array($vals)) return $ret;
-
- foreach ($vals as $k=>$v){
- $this->_push_stack();
- $r = $this->r;
- $r[$varname] = $v;
- if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k);
- $ret .= $this->replace($args[3], $r);
- $this->_pop_stack();
- }
-
- return $ret;
- }
-
- /**
- * INC node
- * \code
- * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }}
- * \endcode
- */
- private function _replcb_inc($args) {
- if (strpos($args[2],"with")) {
- list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
- } else {
- $tplfile = trim($args[2]);
- $newctx = null;
- }
-
- if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile);
-
- $this->_push_stack();
- $r = $this->r;
- if (!is_null($newctx)) {
- list($a,$b) = array_map('trim', explode("=",$newctx));
- $r[$a] = $this->_get_var($b);
- }
- $this->nodes = Array();
- $tpl = get_markup_template($tplfile);
- $ret = $this->replace($tpl, $r);
- $this->_pop_stack();
-
- return $ret;
- }
-
- /**
- * DEBUG node
- * \code
- * {{ debug $var [$var [$var [...]]] }}{{ enddebug }}
- * \endcode
- * replace node with <pre>var_dump($var, $var, ...);</pre>
- */
- private function _replcb_debug($args) {
- $vars = array_map('trim', explode(" ",$args[2]));
- $vars[] = $args[1];
-
- $ret = "<pre>";
- foreach ($vars as $var){
- $ret .= htmlspecialchars(var_export( $this->_get_var($var), true ));
- $ret .= "\n";
- }
- $ret .= "</pre>";
-
- return $ret;
- }
-
- private function _replcb_node($m) {
- $node = $this->nodes[$m[1]];
- if (method_exists($this, "_replcb_".$node[1])){
- $s = call_user_func(array($this, "_replcb_".$node[1]), $node);
- } else {
- $s = "";
- }
- $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
-
- return $s;
- }
-
- private function _replcb($m) {
- //var_dump(array_map('htmlspecialchars', $m));
- $this->done = false;
- $this->nodes[] = (array) $m;
-
- return "||". (count($this->nodes)-1) ."||";
- }
-
- private function _build_nodes($s) {
- $this->done = false;
- while (!$this->done) {
- $this->done=true;
- $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s);
- if ($s==Null) $this->_preg_error();
- }
- //({{ *else *}}[^{]*)?
- krsort($this->nodes);
-
- return $s;
- }
-
- private function var_replace($s) {
- $m = array();
- /** regexp:
- * \$ literal $
- * (\[)? optional open square bracket
- * ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional
- * dot, repeated at least 1 time
- * (?(1)\]) if there was opened square bracket
- * (subgrup 1), match close bracket
- */
- if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)) {
- foreach ($m[0] as $var) {
- $exp = str_replace(array("[", "]"), array("", ""), $var);
- $exptks = explode("|", $exp);
-
- $varn = $exptks[0];
- unset($exptks[0]);
- $val = $this->_get_var($varn, true);
- if ($val != KEY_NOT_EXISTS) {
- /* run filters */
- /*
- * Filter are in form of:
- * filtername:arg:arg:arg
- *
- * "filtername" is function name
- * "arg"s are optional, var value is appended to the end
- * if one "arg"==='x' , is replaced with var value
- *
- * examples:
- * $item.body|htmlspecialchars // escape html chars
- * $item.body|htmlspecialchars|strtoupper // escape html and uppercase result
- * $item.created|date:%Y %M %j // format date (created is a timestamp)
- * $item.body|str_replace:cat:dog // replace all "cat" with "dog"
- * $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog"
- */
- foreach ($exptks as $filterstr) {
- $filter = explode(":", $filterstr);
- $filtername = $filter[0];
- unset($filter[0]);
- $valkey = array_search("x", $filter);
- if ($valkey === false) {
- $filter[] = $val;
- } else {
- $filter[$valkey] = $val;
- }
- if (function_exists($filtername)) {
- $val = call_user_func_array($filtername, $filter);
- }
- }
- $s = str_replace($var, $val, $s);
- }
- }
- }
-
- return $s;
- }
-
- private function replace($s, $r) {
- $this->replace_macros($s, $r);
- }
-
- // TemplateEngine interface
- public function replace_macros($s, $r) {
- $this->r = $r;
-
- $s = $this->_build_nodes($s);
-
- $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
- if ($s == Null)
- $this->_preg_error();
-
- // remove comments block
- $s = preg_replace('/{#[^#]*#}/', "" , $s);
-
- //$t2 = dba_timer();
-
- // replace strings recursively (limit to 10 loops)
- $os = "";
- $count=0;
- while (($os !== $s) && $count<10) {
- $os=$s;
- $count++;
- $s = $this->var_replace($s);
- }
-
- return $s;
- }
-
- public function get_markup_template($file, $root='') {
- $template_file = theme_include($file, $root);
- if ($template_file) {
- $content = file_get_contents($template_file);
- }
-
- return $content;
- }
-}
-
-
-function template_escape($s) {
- return str_replace(array('$','{{'),array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),$s);
-}
-
-function template_unescape($s) {
- return str_replace(array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),array('$','{{'),$s);
-}
diff --git a/include/text.php b/include/text.php
index 0a7f84b01..dd7d9eaa8 100644
--- a/include/text.php
+++ b/include/text.php
@@ -3,8 +3,6 @@
* @file include/text.php
*/
-require_once("include/template_processor.php");
-require_once("include/smarty.php");
require_once("include/bbcode.php");
// random string, there are 86 characters max in text mode, 128 for hex
@@ -16,13 +14,12 @@ define('RANDOM_STRING_TEXT', 0x01 );
/**
* @brief This is our template processor.
*
- * @param string|FriendicaSmarty $s the string requiring macro substitution,
- * or an instance of FriendicaSmarty
+ * @param string|SmartyEngine $s the string requiring macro substitution,
+ * or an instance of SmartyEngine
* @param array $r key value pairs (search => replace)
* @return string substituted string
*/
function replace_macros($s, $r) {
- $a = get_app();
$arr = array('template' => $s, 'params' => $r);
call_hooks('replace_macros', $arr);
@@ -98,7 +95,6 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') {
if($type == 'application/x-pdl')
return escape_tags($s);
- $a = get_app();
if(App::$is_sys) {
return $s;
}
@@ -122,7 +118,7 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') {
-function purify_html($s) {
+function purify_html($s, $allow_position = false) {
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
@@ -202,6 +198,35 @@ function purify_html($s) {
$def->addElement('header', 'Block', 'Flow', 'Common');
$def->addElement('footer', 'Block', 'Flow', 'Common');
+
+ if($allow_position) {
+ $cssDefinition = $config->getCSSDefinition();
+
+ $cssDefinition->info['position'] = new HTMLPurifier_AttrDef_Enum(array('absolute', 'fixed', 'relative', 'static', 'inherit'), false);
+
+ $cssDefinition->info['left'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
+ new HTMLPurifier_AttrDef_CSS_Length(),
+ new HTMLPurifier_AttrDef_CSS_Percentage()
+ ));
+
+ $cssDefinition->info['right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
+ new HTMLPurifier_AttrDef_CSS_Length(),
+ new HTMLPurifier_AttrDef_CSS_Percentage()
+ ));
+
+ $cssDefinition->info['top'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
+ new HTMLPurifier_AttrDef_CSS_Length(),
+ new HTMLPurifier_AttrDef_CSS_Percentage()
+ ));
+
+ $cssDefinition->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
+ new HTMLPurifier_AttrDef_CSS_Length(),
+ new HTMLPurifier_AttrDef_CSS_Percentage()
+ ));
+
+ }
+
+
$purifier = new HTMLPurifier($config);
return $purifier->purify($s);
@@ -297,6 +322,15 @@ function autoname($len) {
function xmlify($str) {
$buffer = '';
+ if(is_array($str)) {
+
+ // allow to fall through so we ge a PHP error, as the log statement will
+ // probably get lost in the noise unless we're specifically looking for it.
+
+ btlogger('xmlify called with array: ' . print_r($str,true), LOGGER_NORMAL, LOG_WARNING);
+ }
+
+
$len = mb_strlen($str);
for($x = 0; $x < $len; $x ++) {
$char = mb_substr($str,$x,1);
@@ -342,30 +376,6 @@ function unxmlify($s) {
return $ret;
}
-/**
- * Convenience wrapper, reverse the operation "bin2hex"
- * This is a built-in function in php >= 5.4
- *
- * @FIXME We already have php >= 5.4 requirements, so can we remove this?
- */
-if(! function_exists('hex2bin')) {
-function hex2bin($s) {
- if(! (is_string($s) && strlen($s)))
- return '';
-
- if(strlen($s) & 1) {
- logger('hex2bin: illegal hex string: ' . $s);
- return $s;
- }
-
- if(! ctype_xdigit($s)) {
- return($s);
- }
-
- return(pack("H*",$s));
-}}
-
-
// Automatic pagination.
// To use, get the count of total items.
// Then call App::set_pager_total($number_items);
@@ -540,21 +550,25 @@ function attribute_contains($attr, $s) {
*/
function logger($msg, $level = LOGGER_NORMAL, $priority = LOG_INFO) {
- // turn off logger in install mode
- global $a;
- global $db;
- if((App::$module == 'install') || (! ($db && $db->connected)))
- return;
-
- $debugging = get_config('system', 'debugging');
- $loglevel = intval(get_config('system', 'loglevel'));
- $logfile = get_config('system', 'logfile');
+ if(App::$module == 'setup' && is_writable('install.log')) {
+ $debugging = true;
+ $logfile = 'install.log';
+ $loglevel = LOGGER_ALL;
+ }
+ else {
+ $debugging = get_config('system', 'debugging');
+ $loglevel = intval(get_config('system', 'loglevel'));
+ $logfile = get_config('system', 'logfile');
+ }
if((! $debugging) || (! $logfile) || ($level > $loglevel))
return;
$where = '';
+
+ // We require > 5.4 but leave the version check so that install issues (including version) can be logged
+
if(version_compare(PHP_VERSION, '5.4.0') >= 0) {
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$where = basename($stack[0]['file']) . ':' . $stack[0]['line'] . ':' . $stack[1]['function'] . ': ';
@@ -563,7 +577,8 @@ function logger($msg, $level = LOGGER_NORMAL, $priority = LOG_INFO) {
$s = datetime_convert() . ':' . log_priority_str($priority) . ':' . session_id() . ':' . $where . $msg . PHP_EOL;
$pluginfo = array('filename' => $logfile, 'loglevel' => $level, 'message' => $s,'priority' => $priority, 'logged' => false);
- call_hooks('logger',$pluginfo);
+ if(! (App::$module == 'setup'))
+ call_hooks('logger',$pluginfo);
if(! $pluginfo['logged'])
@file_put_contents($pluginfo['filename'], $pluginfo['message'], FILE_APPEND);
@@ -621,11 +636,10 @@ function log_priority_str($priority) {
* @param int $level A log level.
*/
function dlogger($msg, $level = 0) {
+
// turn off logger in install mode
- global $a;
- global $db;
- if((App::$module == 'install') || (! ($db && $db->connected)))
+ if(App::$module == 'setup')
return;
$debugging = get_config('system','debugging');
@@ -673,7 +687,7 @@ function get_tags($s) {
// ignore anything in a code block
- $s = preg_replace('/\[code\](.*?)\[\/code\]/sm','',$s);
+ $s = preg_replace('/\[code(.*?)\](.*?)\[\/code\]/sm','',$s);
// ignore anything in [style= ]
$s = preg_replace('/\[style=(.*?)\]/sm','',$s);
@@ -696,6 +710,10 @@ function get_tags($s) {
// '=' needs to be avoided because when the replacement is made (in handle_tag()) it has to be ignored there
// Feel free to allow '=' if the issue with '=' is solved in handle_tag()
// added / ? and [ to avoid issues with hashchars in url paths
+
+ // added ; to single word tags to allow emojis and other unicode character constructs in bbcode
+ // (this would actually be &#xnnnnn; but the ampersand will have been escaped to &amp; by the time we see it.)
+
if(preg_match_all('/(?<![a-zA-Z0-9=\/\?])(@[^ \x0D\x0A,:?\[]+ [^ \x0D\x0A@,:?\[]+)/',$s,$match)) {
foreach($match[1] as $mtch) {
if(substr($mtch,-1,1) === '.')
@@ -708,7 +726,7 @@ function get_tags($s) {
// Otherwise pull out single word tags. These can be @nickname, @first_last
// and #hash tags.
- if(preg_match_all('/(?<![a-zA-Z0-9=\/\?])([@#][^ \x0D\x0A,;:?\[]+)/',$s,$match)) {
+ if(preg_match_all('/(?<![a-zA-Z0-9=\/\?\;])([@#][^ \x0D\x0A,;:?\[]+)/',$s,$match)) {
foreach($match[1] as $mtch) {
if(substr($mtch,-1,1) === '.')
$mtch = substr($mtch,0,-1);
@@ -756,6 +774,10 @@ function strip_zids($s) {
return preg_replace('/[\?&]zid=(.*?)(&|$)/ism','$2',$s);
}
+function strip_zats($s) {
+ return preg_replace('/[\?&]zat=(.*?)(&|$)/ism','$2',$s);
+}
+
// quick and dirty quoted_printable encoding
@@ -772,7 +794,7 @@ function get_mentions($item,$tags) {
return $o;
foreach($tags as $x) {
- if($x['type'] == TERM_MENTION) {
+ if($x['ttype'] == TERM_MENTION) {
$o .= "\t\t" . '<link rel="mentioned" href="' . $x['url'] . '" />' . "\r\n";
$o .= "\t\t" . '<link rel="ostatus:attention" href="' . $x['url'] . '" />' . "\r\n";
}
@@ -783,7 +805,6 @@ function get_mentions($item,$tags) {
function contact_block() {
$o = '';
- $a = get_app();
if(! App::$profile['uid'])
return;
@@ -896,7 +917,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
function search($s,$id='search-box',$url='/search',$save = false) {
- $a = get_app();
+
return replace_macros(get_markup_template('searchbox.tpl'),array(
'$s' => $s,
'$id' => $id,
@@ -1041,7 +1062,7 @@ function get_mood_verbs() {
// Function to list all smilies, both internal and from addons
// Returns array with keys 'texts' and 'icons'
function list_smilies() {
- $a = get_app();
+
$texts = array(
'&lt;3',
'&lt;/3',
@@ -1075,9 +1096,7 @@ function list_smilies() {
':facepalm',
':like',
':dislike',
- 'red#matrix',
- 'red#',
- 'r#'
+ ':hubzilla'
);
$icons = array(
@@ -1113,12 +1132,24 @@ function list_smilies() {
'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" />',
'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" />',
'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" />',
- '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . z_root() . '/images/rm-32.png" alt="' . urlencode('red#matrix') . '" />matrix</strong></a>',
- '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . z_root() . '/images/rm-32.png" alt="' . urlencode('red#') . '" />matrix</strong></a>',
- '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . z_root() . '/images/rm-32.png" alt="r#" />matrix</strong></a>'
+ '<img class="smiley" src="' . z_root() . '/images/hz-16.png" alt=":hubzilla" />',
);
+ $x = get_config('feature','emoji');
+ if($x === false)
+ $x = 1;
+ if($x) {
+ if(! App::$emojitab)
+ App::$emojitab = json_decode(file_get_contents('library/emoji.json'),true);
+ foreach(App::$emojitab as $e) {
+ if(strpos($e['shortname'],':tone') === 0)
+ continue;
+ $texts[] = $e['shortname'];
+ $icons[] = '<img class="smiley emoji" height="16" width="16" src="images/emoji/' . $e['unicode'] . '.png' . '" alt="' . $e['name'] . '" />';
+ }
+ }
+
$params = array('texts' => $texts, 'icons' => $icons);
call_hooks('smilie', $params);
@@ -1186,7 +1217,7 @@ function smile_unshield($m) {
* @param array $x
*/
function preg_heart($x) {
- $a = get_app();
+
if (strlen($x[1]) == 1)
return $x[0];
@@ -1232,7 +1263,7 @@ function normalise_link($url) {
* is https and the other isn't, or if one is www.something and the other
* isn't - and also ignore case differences.
*
- * @see normalis_link()
+ * @see normalise_link()
*
* @param string $a
* @param string $b
@@ -1253,9 +1284,9 @@ function unobscure(&$item) {
if(array_key_exists('item_obscured',$item) && intval($item['item_obscured'])) {
$key = get_config('system','prvkey');
if($item['title'])
- $item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key);
+ $item['title'] = crypto_unencapsulate(json_decode($item['title'],true),$key);
if($item['body'])
- $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key);
+ $item['body'] = crypto_unencapsulate(json_decode($item['body'],true),$key);
if(get_config('system','item_cache')) {
q("update item set title = '%s', body = '%s', item_obscured = 0 where id = %d",
dbesc($item['title']),
@@ -1278,7 +1309,7 @@ function unobscure_mail(&$item) {
function theme_attachments(&$item) {
- $arr = json_decode_plus($item['attach']);
+ $arr = json_decode($item['attach'],true);
if(is_array($arr) && count($arr)) {
$attaches = array();
foreach($arr as $r) {
@@ -1292,7 +1323,7 @@ function theme_attachments(&$item) {
$title = t('Size') . ' ' . (($r['length']) ? userReadableSize($r['length']) : t('unknown'));
- require_once('include/identity.php');
+ require_once('include/channel.php');
if(is_foreigner($item['author_xchan']))
$url = $r['href'];
else
@@ -1426,40 +1457,8 @@ function generate_named_map($location) {
return (($arr['html']) ? $arr['html'] : $location);
}
-function format_event($jobject) {
- $event = array();
-
- $object = json_decode($jobject,true);
-
- //ensure compatibility with older items - this check can be removed at a later point
- if(array_key_exists('description', $object)) {
-
- $bd_format = t('l F d, Y \@ g:i A'); // Friday January 18, 2011 @ 8:01 AM
-
- $event['header'] = replace_macros(get_markup_template('event_item_header.tpl'),array(
- '$title' => bbcode($object['title']),
- '$dtstart_label' => t('Starts:'),
- '$dtstart_title' => datetime_convert('UTC', 'UTC', $object['start'], (($object['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )),
- '$dtstart_dt' => (($object['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $object['start'] , $bd_format )) : day_translate(datetime_convert('UTC', 'UTC', $object['start'] , $bd_format))),
- '$finish' => (($object['nofinish']) ? false : true),
- '$dtend_label' => t('Finishes:'),
- '$dtend_title' => datetime_convert('UTC','UTC',$object['finish'], (($object['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )),
- '$dtend_dt' => (($object['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $object['finish'] , $bd_format )) : day_translate(datetime_convert('UTC', 'UTC', $object['finish'] , $bd_format )))
- ));
-
- $event['content'] = replace_macros(get_markup_template('event_item_content.tpl'),array(
- '$description' => bbcode($object['description']),
- '$location_label' => t('Location:'),
- '$location' => bbcode($object['location'])
- ));
-
- }
-
- return $event;
-}
function prepare_body(&$item,$attach = false) {
- require_once('include/identity.php');
call_hooks('prepare_body_init', $item);
@@ -1469,7 +1468,7 @@ function prepare_body(&$item,$attach = false) {
if($is_photo) {
- $object = json_decode($item['object'],true);
+ $object = json_decode($item['obj'],true);
// if original photo width is <= 640px prepend it to item body
if($object['link'][0]['width'] && $object['link'][0]['width'] <= 640) {
@@ -1485,7 +1484,7 @@ function prepare_body(&$item,$attach = false) {
$s .= prepare_text($item['body'],$item['mimetype'], false);
- $event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event($item['object']) : false);
+ $event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event_obj($item['obj']) : false);
$prep_arr = array(
'item' => $item,
@@ -1532,35 +1531,6 @@ function prepare_body(&$item,$attach = false) {
$s = sslify($s);
- // Look for spoiler
- $spoilersearch = '<blockquote class="spoiler">';
-
- // Remove line breaks before the spoiler
- while ((strpos($s, "\n".$spoilersearch) !== false))
- $s = str_replace("\n".$spoilersearch, $spoilersearch, $s);
- while ((strpos($s, "<br />".$spoilersearch) !== false))
- $s = str_replace("<br />".$spoilersearch, $spoilersearch, $s);
-
- while ((strpos($s, $spoilersearch) !== false)) {
-
- $pos = strpos($s, $spoilersearch);
- $rnd = random_string(8);
- $spoilerreplace = '<br /> <span id="spoiler-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'spoiler-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
- '<blockquote class="spoiler" id="spoiler-'.$rnd.'" style="display: none;">';
- $s = substr($s, 0, $pos).$spoilerreplace.substr($s, $pos+strlen($spoilersearch));
- }
-
- // Look for quote with author
- $authorsearch = '<blockquote class="author">';
-
- while ((strpos($s, $authorsearch) !== false)) {
- $pos = strpos($s, $authorsearch);
- $rnd = random_string(8);
- $authorreplace = '<br /> <span id="author-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'author-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
- '<blockquote class="author" id="author-'.$rnd.'" style="display: block;">';
- $s = substr($s, 0, $pos).$authorreplace.substr($s, $pos+strlen($authorsearch));
- }
-
$prep_arr = array(
'item' => $item,
'photo' => $photo,
@@ -1645,7 +1615,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) {
function create_export_photo_body(&$item) {
if(($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) {
- $j = json_decode($item['object'],true);
+ $j = json_decode($item['obj'],true);
if($j) {
$item['body'] .= "\n\n" . (($j['body']) ? $j['body'] : $j['bbcode']);
$item['sig'] = '';
@@ -1718,7 +1688,6 @@ function feed_hublinks() {
/* return atom link elements for salmon endpoints */
function feed_salmonlinks($nick) {
- $a = get_app();
$salmon = '<link rel="salmon" href="' . xmlify(z_root() . '/salmon/' . $nick) . '" />' . "\n" ;
@@ -1754,7 +1723,8 @@ function unamp($s) {
}
function layout_select($channel_id, $current = '') {
- $r = q("select mid,sid from item left join item_id on iid = item.id where service = 'PDL' and item.uid = item_id.uid and item_id.uid = %d and item_type = %d ",
+ $r = q("select mid, v from item left join iconfig on iconfig.iid = item.id
+ where iconfig.cat = 'system' and iconfig.k = 'PDL' and item.uid = %d and item_type = %d ",
intval($channel_id),
intval(ITEM_TYPE_PDL)
);
@@ -1764,7 +1734,7 @@ function layout_select($channel_id, $current = '') {
$options .= '<option value="" ' . $empty_selected . '>' . t('default') . '</option>';
foreach($r as $rr) {
$selected = (($rr['mid'] == $current) ? ' selected="selected" ' : '');
- $options .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['sid'] . '</option>';
+ $options .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['v'] . '</option>';
}
}
@@ -1786,7 +1756,7 @@ function mimetype_select($channel_id, $current = 'text/bbcode') {
'application/x-pdl'
);
- $a = get_app();
+
if(App::$is_sys) {
$x[] = 'application/x-php';
}
@@ -1819,7 +1789,6 @@ function mimetype_select($channel_id, $current = 'text/bbcode') {
function lang_selector() {
- global $a;
$langs = glob('view/*/hstrings.php');
@@ -1854,8 +1823,10 @@ function lang_selector() {
}
-function return_bytes ($size_str) {
- switch (substr ($size_str, -1)) {
+function engr_units_to_bytes ($size_str) {
+ if(! $size_str)
+ return $size_str;
+ switch (substr(trim($size_str), -1)) {
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
@@ -1893,32 +1864,15 @@ function cleardiv() {
function bb_translate_video($s) {
-
- $matches = null;
- $r = preg_match_all("/\[video\](.*?)\[\/video\]/ism",$s,$matches,PREG_SET_ORDER);
- if($r) {
- foreach($matches as $mtch) {
- if((stristr($mtch[1],'youtube')) || (stristr($mtch[1],'youtu.be')))
- $s = str_replace($mtch[0],'[youtube]' . $mtch[1] . '[/youtube]',$s);
- elseif(stristr($mtch[1],'vimeo'))
- $s = str_replace($mtch[0],'[vimeo]' . $mtch[1] . '[/vimeo]',$s);
- }
- }
- return $s;
+ $arr = array('string' => $s);
+ call_hooks('bb_translate_video',$arr);
+ return $arr['string'];
}
function html2bb_video($s) {
-
- $s = preg_replace('#<object[^>]+>(.*?)https?://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+)(.*?)</object>#ism',
- '[youtube]$2[/youtube]', $s);
-
- $s = preg_replace('#<iframe[^>](.*?)https?://www.youtube.com/embed/([A-Za-z0-9\-_=]+)(.*?)</iframe>#ism',
- '[youtube]$2[/youtube]', $s);
-
- $s = preg_replace('#<iframe[^>](.*?)https?://player.vimeo.com/video/([0-9]+)(.*?)</iframe>#ism',
- '[vimeo]$2[/vimeo]', $s);
-
- return $s;
+ $arr = array('string' => $s);
+ call_hooks('html2bb_video',$arr);
+ return $arr['string'];
}
/**
@@ -2040,7 +1994,7 @@ function check_webbie($arr) {
if(strlen($reservechan))
$taken = explode(',', $reservechan);
else
- $taken = array();
+ $taken = array('principals','addressbooks','calendars');
$str = '';
if(count($arr)) {
@@ -2072,6 +2026,20 @@ function check_webbie($arr) {
return '';
}
+function ids_to_array($arr,$idx = 'id') {
+ $t = array();
+ if($arr) {
+ foreach($arr as $x) {
+ if(array_key_exists($idx,$x) && strlen($x[$idx]) && (! in_array($x[$idx],$t))) {
+ $t[] = $x[$idx];
+ }
+ }
+ }
+ return($t);
+}
+
+
+
function ids_to_querystr($arr,$idx = 'id') {
$t = array();
@@ -2101,9 +2069,9 @@ function xchan_query(&$items,$abook = true,$effective_uid = 0) {
}
foreach($items as $item) {
- if($item['owner_xchan'] && (! in_array($item['owner_xchan'],$arr)))
+ if($item['owner_xchan'] && (! in_array("'" . dbesc($item['owner_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['owner_xchan']) . "'";
- if($item['author_xchan'] && (! in_array($item['author_xchan'],$arr)))
+ if($item['author_xchan'] && (! in_array("'" . dbesc($item['author_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['author_xchan']) . "'";
}
}
@@ -2136,9 +2104,9 @@ function xchan_mail_query(&$item) {
$arr = array();
$chans = null;
if($item) {
- if($item['from_xchan'] && (! in_array($item['from_xchan'],$arr)))
+ if($item['from_xchan'] && (! in_array("'" . dbesc($item['from_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['from_xchan']) . "'";
- if($item['to_xchan'] && (! in_array($item['to_xchan'],$arr)))
+ if($item['to_xchan'] && (! in_array("'" . dbesc($item['to_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['to_xchan']) . "'";
}
@@ -2244,27 +2212,19 @@ function jindent($json) {
return $result;
}
-
-function json_decode_plus($s) {
- $x = json_decode($s,true);
- if(! $x)
- $x = json_decode(str_replace(array('\\"','\\\\'),array('"','\\'),$s),true);
-
- return $x;
-}
-
/**
* @brief Creates navigation menu for webpage, layout, blocks, menu sites.
*
* @return string
*/
+
function design_tools() {
$channel = App::get_channel();
$sys = false;
if(App::$is_sys && is_site_admin()) {
- require_once('include/identity.php');
+ require_once('include/channel.php');
$channel = get_sys_channel();
$sys = true;
}
@@ -2390,7 +2350,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
$str_tags .= $newtag;
}
- return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $basetag, 'url' => $url, 'contact' => $r[0]);
+ return [
+ 'replaced' => $replaced,
+ 'termtype' => $termtype,
+ 'term' => $basetag,
+ 'url' => $url,
+ 'contact' => $r[0]
+ ];
}
//is it a person tag?
@@ -2581,7 +2547,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
}
}
- return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $newname, 'url' => $url, 'contact' => $r[0]);
+ return [
+ 'replaced' => $replaced,
+ 'termtype' => $termtype,
+ 'term' => $newname,
+ 'url' => $url,
+ 'contact' => $r[0]
+ ];
}
function linkify_tags($a, &$body, $uid, $diaspora = false) {
@@ -2630,41 +2602,41 @@ function linkify_tags($a, &$body, $uid, $diaspora = false) {
function getIconFromType($type) {
$iconMap = array(
//Folder
- t('Collection') => 'icon-folder-close',
- 'multipart/mixed' => 'icon-folder-close', //dirs in attach use this mime type
+ t('Collection') => 'fa-folder',
+ 'multipart/mixed' => 'fa-folder', //dirs in attach use this mime type
//Common file
- 'application/octet-stream' => 'icon-file-alt',
+ 'application/octet-stream' => 'fa-file-o',
//Text
- 'text/plain' => 'icon-file-text-alt',
- 'application/msword' => 'icon-file-text-alt',
- 'application/pdf' => 'icon-file-text-alt',
- 'application/vnd.oasis.opendocument.text' => 'icon-file-text-alt',
- 'application/epub+zip' => 'icon-book',
+ 'text/plain' => 'fa-file-text-o',
+ 'application/msword' => 'fa-file-text-o',
+ 'application/pdf' => 'fa-file-text-o',
+ 'application/vnd.oasis.opendocument.text' => 'fa-file-text-o',
+ 'application/epub+zip' => 'fa-book',
//Spreadsheet
- 'application/vnd.oasis.opendocument.spreadsheet' => 'icon-table',
- 'application/vnd.ms-excel' => 'icon-table',
+ 'application/vnd.oasis.opendocument.spreadsheet' => 'fa-table',
+ 'application/vnd.ms-excel' => 'fa-table',
//Image
- 'image/jpeg' => 'icon-picture',
- 'image/png' => 'icon-picture',
- 'image/gif' => 'icon-picture',
- 'image/svg+xml' => 'icon-picture',
+ 'image/jpeg' => 'fa-picture-o',
+ 'image/png' => 'fa-picture-o',
+ 'image/gif' => 'fa-picture-o',
+ 'image/svg+xml' => 'fa-picture-o',
//Archive
- 'application/zip' => 'icon-archive',
- 'application/x-rar-compressed' => 'icon-archive',
+ 'application/zip' => 'fa-archive',
+ 'application/x-rar-compressed' => 'fa-archive',
//Audio
- 'audio/mpeg' => 'icon-music',
- 'audio/wav' => 'icon-music',
- 'application/ogg' => 'icon-music',
- 'audio/ogg' => 'icon-music',
- 'audio/webm' => 'icon-music',
- 'audio/mp4' => 'icon-music',
+ 'audio/mpeg' => 'fa-music',
+ 'audio/wav' => 'fa-music',
+ 'application/ogg' => 'fa-music',
+ 'audio/ogg' => 'fa-music',
+ 'audio/webm' => 'fa-music',
+ 'audio/mp4' => 'fa-music',
//Video
- 'video/quicktime' => 'icon-film',
- 'video/webm' => 'icon-film',
- 'video/mp4' => 'icon-film'
+ 'video/quicktime' => 'fa-film',
+ 'video/webm' => 'fa-film',
+ 'video/mp4' => 'fa-film'
);
- $iconFromType = 'icon-file-alt';
+ $iconFromType = 'fa-file-o';
if (array_key_exists($type, $iconMap)) {
$iconFromType = $iconMap[$type];
@@ -2822,3 +2794,125 @@ function expand_acl($s) {
return $ret;
}
+
+
+// When editing a webpage - a dropdown is needed to select a page layout
+// On submit, the pdl_select value (which is the mid of an item with item_type = ITEM_TYPE_PDL) is stored in
+// the webpage's resource_id, with resource_type 'pdl'.
+
+// Then when displaying a webpage, we can see if it has a pdl attached. If not we'll
+// use the default site/page layout.
+
+// If it has a pdl we'll load it as we know the mid and pass the body through comanche_parser() which will generate the
+// page layout from the given description
+
+// @FIXME - there is apparently a very similar function called layout_select; this one should probably take precedence
+// and the other should be checked for compatibility and removed
+
+function pdl_selector($uid, $current="") {
+ $o = '';
+
+ $sql_extra = item_permissions_sql($uid);
+
+ $r = q("select iconfig.*, mid from item_id left join item on iconfig.iid = item.id
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' $sql_extra order by v asc",
+ intval($uid)
+ );
+
+ $arr = array('channel_id' => $uid, 'current' => $current, 'entries' => $r);
+ call_hooks('pdl_selector',$arr);
+
+ $entries = $arr['entries'];
+ $current = $arr['current'];
+
+ $o .= '<select name="pdl_select" id="pdl_select" size="1">';
+ $entries[] = array('title' => t('Default'), 'mid' => '');
+ foreach($entries as $selection) {
+ $selected = (($selection == $current) ? ' selected="selected" ' : '');
+ $o .= "<option value=\"{$selection['mid']}\" $selected >{$selection['v']}</option>";
+ }
+
+ $o .= '</select>';
+ return $o;
+}
+
+/*
+ * array flatten_array_recursive(array);
+ * returns a one-dimensional array from a multi-dimensional array
+ * empty values are discarded
+ * example: print_r(flatten_array_recursive(array('foo','bar',array('baz','blip',array('zob','glob')),'','grip')));
+ *
+ * Array ( [0] => foo [1] => bar [2] => baz [3] => blip [4] => zob [5] => glob [6] => grip )
+ *
+ */
+
+function flatten_array_recursive($arr) {
+ $ret = array();
+
+ if(! $arr)
+ return $ret;
+
+ foreach($arr as $a) {
+ if(is_array($a)) {
+ $tmp = flatten_array_recursive($a);
+ if($tmp) {
+ $ret = array_merge($ret,$tmp);
+ }
+ }
+ elseif($a) {
+ $ret[] = $a;
+ }
+ }
+ return($ret);
+}
+
+function text_highlight($s,$lang) {
+
+ if($lang === 'js')
+ $lang = 'javascript';
+
+ if($lang === 'json') {
+ $lang = 'javascript';
+ if(! strpos(trim($s),"\n"))
+ $s = jindent($s);
+ }
+
+ if(! strpos('Text_Highlighter',get_include_path())) {
+ set_include_path(get_include_path() . PATH_SEPARATOR . 'library/Text_Highlighter');
+ }
+ require_once('library/Text_Highlighter/Text/Highlighter.php');
+ require_once('library/Text_Highlighter/Text/Highlighter/Renderer/Html.php');
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 4,
+ );
+ $tag_added = false;
+ $s = trim(html_entity_decode($s,ENT_COMPAT));
+ $s = str_replace(" ","\t",$s);
+
+ // The highlighter library insists on an opening php tag for php code blocks. If
+ // it isn't present, nothing is highlighted. So we're going to see if it's present.
+ // If not, we'll add it, and then quietly remove it after we get the processed output back.
+
+ if($lang === 'php') {
+ if(strpos('<?php',$s) !== 0) {
+ $s = '<?php' . "\n" . $s;
+ $tag_added = true;
+ }
+
+ }
+ $renderer = new Text_Highlighter_Renderer_HTML($options);
+ $hl = Text_Highlighter::factory($lang);
+ $hl->setRenderer($renderer);
+ $o = $hl->highlight($s);
+ $o = str_replace([" ","\n"],["&nbsp;&nbsp;&nbsp;&nbsp;",''],$o);
+
+ if($tag_added) {
+ $b = substr($o,0,strpos($o,'<li>'));
+ $e = substr($o,strpos($o,'</li>'));
+ $o = $b . $e;
+ }
+
+ return('<code>' . $o . '</code>');
+}
+
diff --git a/include/widgets.php b/include/widgets.php
index 0355ebd8c..3516e82da 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -8,17 +8,17 @@
require_once('include/dir_fns.php');
require_once('include/contact_widgets.php');
require_once('include/attach.php');
-require_once('include/Contact.php');
+
function widget_profile($args) {
- $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
+ $block = observer_prohibited();
return profile_sidebar(App::$profile, $block, true);
}
function widget_zcard($args) {
- $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
+ $block = observer_prohibited();
$channel = channelx_by_n(App::$profile_uid);
return get_zcard($channel,get_observer_hash(),array('width' => 875));
}
@@ -103,8 +103,8 @@ function widget_appselect($arr) {
'$system' => t('System'),
'$authed' => ((local_channel()) ? true : false),
'$personal' => t('Personal'),
- '$new' => t('Create Personal App'),
- '$edit' => t('Edit Personal App')
+ '$new' => t('New App'),
+ '$edit' => t('Edit App')
));
}
@@ -212,13 +212,13 @@ function widget_savedsearch($arr) {
$search = ((x($_GET,'search')) ? $_GET['search'] : '');
if(x($_GET,'searchsave') && $search) {
- $r = q("select * from `term` where `uid` = %d and `type` = %d and `term` = '%s' limit 1",
+ $r = q("select * from `term` where `uid` = %d and `ttype` = %d and `term` = '%s' limit 1",
intval(local_channel()),
intval(TERM_SAVEDSEARCH),
dbesc($search)
);
if(! $r) {
- q("insert into `term` ( `uid`,`type`,`term` ) values ( %d, %d, '%s') ",
+ q("insert into `term` ( `uid`,`ttype`,`term` ) values ( %d, %d, '%s') ",
intval(local_channel()),
intval(TERM_SAVEDSEARCH),
dbesc($search)
@@ -227,7 +227,7 @@ function widget_savedsearch($arr) {
}
if(x($_GET,'searchremove') && $search) {
- q("delete from `term` where `uid` = %d and `type` = %d and `term` = '%s'",
+ q("delete from `term` where `uid` = %d and `ttype` = %d and `term` = '%s'",
intval(local_channel()),
intval(TERM_SAVEDSEARCH),
dbesc($search)
@@ -254,7 +254,7 @@ function widget_savedsearch($arr) {
$o = '';
- $r = q("select `tid`,`term` from `term` WHERE `uid` = %d and `type` = %d ",
+ $r = q("select `tid`,`term` from `term` WHERE `uid` = %d and `ttype` = %d ",
intval(local_channel()),
intval(TERM_SAVEDSEARCH)
);
@@ -296,7 +296,7 @@ function widget_filer($arr) {
$selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : '');
$terms = array();
- $r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
+ $r = q("select distinct term from term where uid = %d and ttype = %d order by term asc",
intval(local_channel()),
intval(TERM_FILE)
);
@@ -369,7 +369,7 @@ function widget_fullprofile($arr) {
if(! App::$profile['profile_uid'])
return;
- $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
+ $block = observer_prohibited();
return profile_sidebar(App::$profile, $block);
}
@@ -379,7 +379,7 @@ function widget_shortprofile($arr) {
if(! App::$profile['profile_uid'])
return;
- $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
+ $block = observer_prohibited();
return profile_sidebar(App::$profile, $block, true, true);
}
@@ -400,6 +400,55 @@ function widget_categories($arr) {
}
+function widget_appcategories($arr) {
+
+ if(! local_channel())
+ 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);
+
+ $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
+ 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,
+
+ ));
+ }
+
+
+
+}
+
+
+
+function widget_appcloud($arr) {
+ if(! local_channel())
+ return '';
+ return app_tagblock(z_root() . '/apps');
+}
+
+
function widget_tagcloud_wall($arr) {
@@ -560,6 +609,15 @@ function widget_settings_menu($arr) {
'selected' => ((argv(1) === 'oauth') ? 'active' : ''),
);
+ if(! UNO) {
+ $tabs[] = array(
+ 'label' => t('Guest Access Tokens'),
+ 'url' => z_root() . '/settings/tokens',
+ 'selected' => ((argv(1) === 'tokens') ? 'active' : ''),
+ );
+ }
+
+
if($role === false || $role === 'custom') {
$tabs[] = array(
'label' => t('Connection Default Permissions'),
@@ -694,21 +752,6 @@ function widget_conversations($arr) {
return $o;
}
-function widget_eventsmenu($arr) {
- if (! local_channel())
- return;
-
- return replace_macros(get_markup_template('events_menu_side.tpl'), array(
- '$title' => t('Events Menu'),
- '$day' => t('Day View'),
- '$week' => t('Week View'),
- '$month' => t('Month View'),
- '$export' => t('Export'),
- '$upload' => t('Import'),
- '$submit' => t('Submit')
- ));
-}
-
function widget_eventstools($arr) {
if (! local_channel())
return;
@@ -722,7 +765,6 @@ function widget_eventstools($arr) {
}
function widget_design_tools($arr) {
- $a = get_app();
// mod menu doesn't load a profile. For any modules which load a profile, check it.
// otherwise local_channel() is sufficient for permissions.
@@ -751,13 +793,14 @@ function widget_photo_albums($arr) {
if((! $channelx) || (! perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_storage')))
return '';
require_once('include/photos.php');
+ $sortkey = ((array_key_exists('sortkey',$arr)) ? $arr['sortkey'] : 'album');
+ $direction = ((array_key_exists('direction',$arr)) ? $arr['direction'] : 'asc');
- return photos_album_widget($channelx, App::get_observer());
+ return photos_album_widget($channelx, App::get_observer(),$sortkey,$direction);
}
function widget_vcard($arr) {
- require_once ('include/Contact.php');
return vcard_from_xchan('', App::get_observer());
}
@@ -786,8 +829,7 @@ function widget_menu_preview($arr) {
function widget_chatroom_list($arr) {
- require_once("include/chat.php");
- $r = chatroom_list(App::$profile['profile_uid']);
+ $r = Zotlabs\Lib\Chatroom::roomlist(App::$profile['profile_uid']);
if($r) {
return replace_macros(get_markup_template('chatroomlist.tpl'), array(
@@ -808,6 +850,78 @@ function widget_chatroom_members() {
return $o;
}
+function widget_wiki_list($arr) {
+
+ require_once("include/wiki.php");
+ $channel = null;
+ if (argc() < 2 && local_channel()) {
+ // This should not occur because /wiki should redirect to /wiki/channel ...
+ $channel = \App::get_channel();
+ } else {
+ $channel = get_channel_by_nick(argv(1)); // Channel being viewed by observer
+ }
+ if (!$channel) {
+ return '';
+ }
+ $wikis = wiki_list($channel, get_observer_hash());
+ if ($wikis) {
+ return replace_macros(get_markup_template('wikilist.tpl'), array(
+ '$header' => t('Wiki List'),
+ '$channel' => $channel['channel_address'],
+ '$wikis' => $wikis['wikis'],
+ // If the observer is the local channel owner, show the wiki controls
+ '$showControls' => ((local_channel() === intval($channel['channel_id'])) ? true : false)
+ ));
+ }
+ return '';
+}
+
+function widget_wiki_pages($arr) {
+
+ require_once("include/wiki.php");
+ $channelname = ((array_key_exists('channel',$arr)) ? $arr['channel'] : '');
+ $wikiname = '';
+ if (array_key_exists('refresh', $arr)) {
+ $not_refresh = (($arr['refresh']=== true) ? false : true);
+ } else {
+ $not_refresh = true;
+ }
+ $pages = array();
+ if (!array_key_exists('resource_id', $arr)) {
+ $hide = true;
+ } else {
+ $p = wiki_page_list($arr['resource_id']);
+ if ($p['pages']) {
+ $pages = $p['pages'];
+ $w = $p['wiki'];
+ // Wiki item record is $w['wiki']
+ $wikiname = $w['urlName'];
+ if (!$wikiname) {
+ $wikiname = '';
+ }
+ }
+ }
+ return replace_macros(get_markup_template('wiki_page_list.tpl'), array(
+ '$hide' => $hide,
+ '$not_refresh' => $not_refresh,
+ '$header' => t('Wiki Pages'),
+ '$channel' => $channelname,
+ '$wikiname' => $wikiname,
+ '$pages' => $pages
+ ));
+}
+
+function widget_wiki_page_history($arr) {
+ require_once("include/wiki.php");
+ $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $pageHistory = wiki_page_history(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
+
+ return replace_macros(get_markup_template('wiki_page_history.tpl'), array(
+ '$pageHistory' => $pageHistory['history']
+ ));
+}
+
function widget_bookmarkedchats($arr) {
if(! feature_enabled(App::$profile['profile_uid'],'ajaxchat'))
@@ -874,8 +988,9 @@ function widget_item($arr) {
$sql_extra = item_permissions_sql($channel_id);
if($arr['title']) {
- $r = q("select item.* from item left join item_id on item.id = item_id.iid
- where item.uid = %d and sid = '%s' and service = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1",
+ $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)
@@ -1003,7 +1118,7 @@ function widget_photo($arr) {
function widget_cover_photo($arr) {
- require_once('include/identity.php');
+ require_once('include/channel.php');
$o = '';
if(App::$module == 'channel' && $_REQUEST['mid'])
@@ -1037,7 +1152,7 @@ function widget_cover_photo($arr) {
if(array_key_exists('subtitle', $arr) && isset($arr['subtitle']))
$subtitle = $arr['subtitle'];
else
- $subtitle = $channel['xchan_addr'];
+ $subtitle = str_replace('@','&#x40;',$channel['xchan_addr']);
$c = get_cover_photo($channel_id,'html');
@@ -1080,7 +1195,7 @@ function widget_photo_rand($arr) {
$filtered = array();
if($ret['success'] && $ret['photos'])
foreach($ret['photos'] as $p)
- if($p['scale'] == $scale)
+ if($p['imgscale'] == $scale)
$filtered[] = $p['src'];
if($filtered) {
@@ -1133,8 +1248,8 @@ function widget_random_block($arr) {
$randfunc = db_getfunc('RAND');
- $r = q("select item.* from item left join item_id on item.id = item_id.iid
- where item.uid = %d and sid like '%s' and service = 'BUILDBLOCK' and
+ $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 like '%s' and iconfig.k = 'BUILDBLOCK' and
item_type = %d $sql_options order by $randfunc limit 1",
intval($channel_id),
dbesc('%' . $contains . '%'),
@@ -1203,12 +1318,12 @@ function widget_rating($arr) {
if((($remote) || (local_channel())) && (! $self)) {
if($remote)
- $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="icon-pencil"></i> ' . t('Rate Me') . '</a>';
+ $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</a>';
else
- $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="icon-pencil"></i> ' . t('Rate Me') . '</div>';
+ $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</div>';
}
- $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="icon-eye-open"></i> ' . t('View Ratings') . '</a>';
+ $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="fa fa-eye"></i> ' . t('View Ratings') . '</a>';
$o .= '</div>';
return $o;
@@ -1241,9 +1356,14 @@ function widget_forums($arr) {
$perms_sql = item_permissions_sql(local_channel()) . item_normal();
- $r1 = q("select * from abook left join xchan on abook_xchan = xchan_hash where ( xchan_pubforum = 1 or ((abook_their_perms & %d ) != 0 and (abook_their_perms & %d ) = 0) ) and xchan_deleted = 0 and abook_channel = %d order by xchan_name $limit ",
- intval(PERMS_W_TAGWALL),
- intval(PERMS_W_STREAM),
+ /**
+ * We used to try and find public forums with custom permissions by checking to see if
+ * send_stream was false and tag_deliver was true. However with the newer extensible
+ * permissions infrastructure this makes for a very complicated query. Now we're only
+ * checking channels that report themselves specifically as pubforums
+ */
+
+ $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_pubforum = 1 and xchan_deleted = 0 and abook_channel = %d order by xchan_name $limit ",
intval(local_channel())
);
if(! $r1)
@@ -1255,12 +1375,34 @@ function widget_forums($arr) {
// 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 $perms_sql ",
+ $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) {
@@ -1332,7 +1474,7 @@ function widget_admin($arr) {
$aside = array(
'site' => array(z_root() . '/admin/site/', t('Site'), 'site'),
- 'users' => array(z_root() . '/admin/users/', t('Accounts'), 'users', 'pending-update', t('Member registrations waiting for confirmation')),
+ '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'),
@@ -1351,7 +1493,7 @@ function widget_admin($arr) {
$plugins = array();
if($r) {
foreach ($r as $h){
- $plugin = $h['name'];
+ $plugin = $h['aname'];
$plugins[] = array(z_root() . '/admin/plugins/' . $plugin, $plugin, 'plugin');
// temp plugins with admin
App::$plugins_admin[] = $plugin;
@@ -1413,9 +1555,9 @@ function widget_album($args) {
$order = 'DESC';
- $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN
- (SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
- ON (p.resource_id = ph.resource_id AND p.scale = ph.scale)
+ $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),
@@ -1436,7 +1578,7 @@ function widget_album($args) {
else
$twist = 'rotright';
- $ext = $phototypes[$rr['type']];
+ $ext = $phototypes[$rr['mimetype']];
$imgalt_e = $rr['filename'];
$desc_e = $rr['description'];
@@ -1449,7 +1591,7 @@ function widget_album($args) {
'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink,
'title' => t('View Photo'),
- 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext,
+ 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext,
'alt' => $imgalt_e,
'desc'=> $desc_e,
'ext' => $ext,
diff --git a/include/wiki.php b/include/wiki.php
new file mode 100644
index 000000000..424b2d9a0
--- /dev/null
+++ b/include/wiki.php
@@ -0,0 +1,571 @@
+<?php
+/**
+ * @file include/wiki.php
+ * @brief Wiki related functions.
+ */
+
+use \Zotlabs\Storage\GitRepo as GitRepo;
+define ( 'WIKI_ITEM_RESOURCE_TYPE', 'wiki' );
+
+function wiki_list($channel, $observer_hash) {
+ $sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
+ $wikis = q("SELECT * FROM item WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ intval($channel['channel_id'])
+ );
+ foreach($wikis as &$w) {
+ $w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
+ $w['htmlName'] = get_iconfig($w, 'wiki', 'htmlName');
+ $w['urlName'] = get_iconfig($w, 'wiki', 'urlName');
+ $w['path'] = get_iconfig($w, 'wiki', 'path');
+ }
+ // TODO: query db for wikis the observer can access. Return with two lists, for read and write access
+ return array('wikis' => $wikis);
+}
+
+function wiki_page_list($resource_id) {
+ // TODO: Create item table records for pages so that metadata like title can be applied
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('pages' => null, 'wiki' => null);
+ }
+ $pages = array();
+ if (is_dir($w['path']) === true) {
+ $files = array_diff(scandir($w['path']), array('.', '..', '.git'));
+ // TODO: Check that the files are all text files
+
+ foreach($files as $file) {
+ // strip the .md file extension and unwrap URL encoding to leave HTML encoded name
+ $pages[] = array('title' => urldecode(substr($file, 0, -3)), 'url' => urlencode(substr($file, 0, -3)));
+ }
+ }
+
+ return array('pages' => $pages, 'wiki' => $w);
+}
+
+function wiki_init_wiki($channel, $wiki) {
+ // Store the path as a relative path, but pass absolute path to mkdir
+ $path = 'store/[data]/git/'.$channel['channel_address'].'/wiki/'.$wiki['urlName'];
+ if (!os_mkdir(__DIR__ . '/../' . $path, 0770, true)) {
+ logger('Error creating wiki path: ' . $path);
+ return null;
+ }
+ // Create GitRepo object
+ $git = new GitRepo($channel['channel_address'], null, false, $wiki['urlName'], __DIR__ . '/../' . $path);
+ if(!$git->initRepo()) {
+ logger('Error creating new git repo in ' . $git->path);
+ return null;
+ }
+
+ return array('path' => $path);
+}
+
+function wiki_create_wiki($channel, $observer_hash, $wiki, $acl) {
+ $wikiinit = wiki_init_wiki($channel, $wiki);
+ if (!$wikiinit['path']) {
+ notice('Error creating wiki');
+ return array('item' => null, 'success' => false);
+ }
+ $path = $wikiinit['path'];
+ // Generate unique resource_id using the same method as item_message_id()
+ do {
+ $dups = false;
+ $resource_id = random_string();
+ $r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
+ dbesc($resource_id),
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ intval($channel['channel_id'])
+ );
+ if (count($r))
+ $dups = true;
+ } while ($dups == true);
+ $ac = $acl->get();
+ $mid = item_message_id();
+ $arr = array(); // Initialize the array of parameters for the post
+ $item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
+ $wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
+ $arr['aid'] = $channel['channel_account_id'];
+ $arr['uid'] = $channel['channel_id'];
+ $arr['mid'] = $mid;
+ $arr['parent_mid'] = $mid;
+ $arr['item_hidden'] = $item_hidden;
+ $arr['resource_type'] = WIKI_ITEM_RESOURCE_TYPE;
+ $arr['resource_id'] = $resource_id;
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['author_xchan'] = $observer_hash;
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['llink'] = $arr['plink'];
+ $arr['title'] = $wiki['htmlName']; // name of new wiki;
+ $arr['allow_cid'] = $ac['allow_cid'];
+ $arr['allow_gid'] = $ac['allow_gid'];
+ $arr['deny_cid'] = $ac['deny_cid'];
+ $arr['deny_gid'] = $ac['deny_gid'];
+ $arr['item_wall'] = 1;
+ $arr['item_origin'] = 1;
+ $arr['item_thread_top'] = 1;
+ $arr['item_private'] = intval($acl->is_private());
+ $arr['verb'] = ACTIVITY_CREATE;
+ $arr['obj_type'] = ACTIVITY_OBJ_WIKI;
+ $arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
+ // Save the path using iconfig. The file path should not be shared with other hubs
+ if (!set_iconfig($arr, 'wiki', 'path', $path, false)) {
+ return array('item' => null, 'success' => false);
+ }
+ // Save the wiki name information using iconfig. This is shareable.
+ if (!set_iconfig($arr, 'wiki', 'rawName', $wiki['rawName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ if (!set_iconfig($arr, 'wiki', 'htmlName', $wiki['htmlName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ if (!set_iconfig($arr, 'wiki', 'urlName', $wiki['urlName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ $post = item_store($arr);
+ $item_id = $post['item_id'];
+
+ if ($item_id) {
+ proc_run('php', "include/notifier.php", "activity", $item_id);
+ return array('item' => $arr, 'success' => true);
+ } else {
+ return array('item' => null, 'success' => false);
+ }
+}
+
+function wiki_delete_wiki($resource_id) {
+
+ $w = wiki_get_wiki($resource_id);
+ $item = $w['wiki'];
+ if (!$item || !$w['path']) {
+ return array('item' => null, 'success' => false);
+ } else {
+ $drop = drop_item($item['id'], false, DROPITEM_NORMAL, true);
+ $pathdel = rrmdir($w['path']);
+ if ($pathdel) {
+ info('Wiki files deleted successfully');
+ }
+ return array('item' => $item, 'success' => (($drop === 1 && $pathdel) ? true : false));
+ }
+}
+
+function wiki_get_wiki($resource_id) {
+ $item = q("SELECT * FROM item WHERE resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0 limit 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc($resource_id)
+ );
+ if (!$item) {
+ return array('wiki' => null, 'path' => null);
+ } else {
+ $w = $item[0]; // wiki item table record
+ // Get wiki metadata
+ $rawName = get_iconfig($w, 'wiki', 'rawName');
+ $htmlName = get_iconfig($w, 'wiki', 'htmlName');
+ $urlName = get_iconfig($w, 'wiki', 'urlName');
+ $path = get_iconfig($w, 'wiki', 'path');
+ if (!realpath(__DIR__ . '/../' . $path)) {
+ return array('wiki' => null, 'path' => null);
+ }
+ // Path to wiki exists
+ $abs_path = realpath(__DIR__ . '/../' . $path);
+ return array( 'wiki' => $w,
+ 'path' => $abs_path,
+ 'rawName' => $rawName,
+ 'htmlName' => $htmlName,
+ 'urlName' => $urlName
+ );
+ }
+}
+
+function wiki_exists_by_name($uid, $urlName) {
+ $item = q("SELECT id,resource_id FROM item WHERE resource_type = '%s' AND title = '%s' AND uid = '%s' AND item_deleted = 0 limit 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc(escape_tags(urldecode($urlName))),
+ dbesc($uid)
+ );
+ if (!$item) {
+ return array('id' => null, 'resource_id' => null);
+ } else {
+ return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
+ }
+}
+
+function wiki_get_permissions($resource_id, $owner_id, $observer_hash) {
+ // TODO: For now, only the owner can edit
+ $sql_extra = item_permissions_sql($owner_id, $observer_hash);
+ $r = q("SELECT * FROM item WHERE resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc($resource_id)
+ );
+
+ if (!$r) {
+ return array('read' => false, 'write' => false, 'success' => true);
+ } else {
+ $perms = get_all_perms($owner_id, $observer_hash);
+ // TODO: Create a new permission setting for wiki analogous to webpages. Until
+ // then, use webpage permissions
+ if (!$perms['write_pages']) {
+ $write = false;
+ } else {
+ $write = true;
+ }
+ return array('read' => true, 'write' => $write, 'success' => true);
+ }
+}
+
+function wiki_create_page($name, $resource_id) {
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Wiki not found.', 'success' => false);
+ }
+ $page = array('rawName' => $name, 'htmlName' => escape_tags($name), 'urlName' => urlencode(escape_tags($name)), 'fileName' => urlencode(escape_tags($name)).'.md');
+ $page_path = $w['path'] . '/' . $page['fileName'];
+ if (is_file($page_path)) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Page already exists.', 'success' => false);
+ }
+ // Create the page file in the wiki repo
+ if(!touch($page_path)) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Page file cannot be created.', 'success' => false);
+ } else {
+ return array('page' => $page, 'wiki' => $w, 'message' => '', 'success' => true);
+ }
+
+}
+
+function wiki_rename_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $pageNewName = ((array_key_exists('pageNewName',$arr)) ? $arr['pageNewName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Wiki not found.', 'success' => false);
+ }
+ $page_path_old = $w['path'].'/'.$pageUrlName.'.md';
+ if (!is_readable($page_path_old) === true) {
+ return array('message' => 'Cannot read wiki page: ' . $page_path_old, 'success' => false);
+ }
+ $page = array('rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), 'urlName' => urlencode(escape_tags($pageNewName)), 'fileName' => urlencode(escape_tags($pageNewName)).'.md');
+ $page_path_new = $w['path'] . '/' . $page['fileName'] ;
+ if (is_file($page_path_new)) {
+ return array('message' => 'Page already exists.', 'success' => false);
+ }
+ // Rename the page file in the wiki repo
+ if(!rename($page_path_old, $page_path_new)) {
+ return array('message' => 'Error renaming page file.', 'success' => false);
+ } else {
+ return array('page' => $page, 'message' => '', 'success' => true);
+ }
+
+}
+
+function wiki_get_page_content($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_readable($page_path) === true) {
+ if(filesize($page_path) === 0) {
+ $content = '';
+ } else {
+ $content = file_get_contents($page_path);
+ if(!$content) {
+ return array('content' => null, 'message' => 'Error reading page content', 'success' => false);
+ }
+ }
+ // TODO: Check that the files are all text files
+ return array('content' => json_encode($content), 'message' => '', 'success' => true);
+ }
+}
+
+function wiki_page_history($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (!is_readable($page_path) === true) {
+ return array('history' => null, 'message' => 'Cannot read wiki page: ' . $page_path, 'success' => false);
+ }
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? $w['wiki']['title'] : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo('', null, false, $w['wiki']['title'], $w['path']);
+ try {
+ $gitlog = $git->git->log('', $page_path , array('limit' => 500));
+ return array('history' => $gitlog, 'message' => '', 'success' => true);
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('history' => null, 'message' => 'GitRepo error thrown', 'success' => false);
+ }
+}
+
+function wiki_save_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $content = ((array_key_exists('content',$arr)) ? purify_html($arr['content']) : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+ if(!file_put_contents($page_path, $content)) {
+ return array('message' => 'Error writing to page file', 'success' => false);
+ }
+ return array('message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_delete_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+ if(!unlink($page_path)) {
+ return array('message' => 'Error deleting page file', 'success' => false);
+ }
+ return array('message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_revert_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
+ if (! $commitHash) {
+ return array('content' => $content, 'message' => 'No commit was provided', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('content' => $content, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo($observer['xchan_addr'], null, false, $w['wiki']['title'], $w['path']);
+ $content = null;
+ try {
+ $git->setIdentity($observer['xchan_name'], $observer['xchan_addr']);
+ foreach ($git->git->tree($commitHash) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $content = $git->git->cat->blob($object['hash']);
+ }
+ }
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('content' => $content, 'message' => 'GitRepo error thrown', 'success' => false);
+ }
+ return array('content' => $content, 'message' => '', 'success' => true);
+ } else {
+ return array('content' => $content, 'message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_compare_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : 'HEAD');
+ $compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : null);
+ if (! $compareCommit) {
+ return array('message' => 'No compare commit was provided', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_readable($page_path) === true) {
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo('', null, false, $w['wiki']['title'], $w['path']);
+ $compareContent = $currentContent = '';
+ try {
+ foreach ($git->git->tree($currentCommit) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $currentContent = $git->git->cat->blob($object['hash']);
+ }
+ }
+ foreach ($git->git->tree($compareCommit) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $compareContent = $git->git->cat->blob($object['hash']);
+ }
+ }
+ require_once('library/class.Diff.php');
+ $diff = Diff::toTable(Diff::compare($currentContent, $compareContent));
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('message' => 'GitRepo error thrown', 'success' => false);
+ }
+ return array('diff' => $diff, 'message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_git_commit($arr) {
+ $files = ((array_key_exists('files', $arr)) ? $arr['files'] : null);
+ $all = ((array_key_exists('all', $arr)) ? $arr['all'] : false);
+ $commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : 'Repo updated');
+ if(array_key_exists('resource_id', $arr)) {
+ $resource_id = $arr['resource_id'];
+ } else {
+ return array('message' => 'Wiki resource_id required for git commit', 'success' => false);
+ }
+ if(array_key_exists('observer', $arr)) {
+ $observer = $arr['observer'];
+ } else {
+ return array('message' => 'Observer required for git commit', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo($observer['xchan_addr'], null, false, $w['wiki']['title'], $w['path']);
+ try {
+ $git->setIdentity($observer['xchan_name'], $observer['xchan_addr']);
+ if ($files === null) {
+ $options = array('all' => true); // git commit option to include all changes
+ } else {
+ $options = array('all' => $all); // git commit options\
+ foreach ($files as $file) {
+ if (!$git->git->add($file)) { // add specified files to the git repo stage
+ if (!$git->git->reset->hard()) {
+ return array('message' => 'Error adding file to git stage: ' . $file . '. Error resetting git repo.', 'success' => false);
+ }
+ return array('message' => 'Error adding file to git stage: ' . $file, 'success' => false);
+ }
+ }
+ }
+ if ($git->commit($commit_msg, $options)) {
+ return array('message' => 'Wiki repo commit succeeded', 'success' => true);
+ } else {
+ return array('message' => 'Wiki repo commit failed', 'success' => false);
+ }
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('message' => 'GitRepo error thrown', 'success' => false);
+ }
+}
+
+function wiki_generate_page_filename($name) {
+ $file = urlencode(escape_tags($name));
+ if( $file === '') {
+ return null;
+ } else {
+ return $file . '.md';
+ }
+}
+
+function wiki_convert_links($s, $wikiURL) {
+
+ if (strpos($s,'[[') !== false) {
+ preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
+ $pages = $pageURLs = array();
+ foreach ($match[1] as $m) {
+ // TODO: Why do we need to double urlencode for this to work?
+ $pageURLs[] = urlencode(urlencode(escape_tags($m)));
+ $pages[] = $m;
+ }
+ $idx = 0;
+ while(strpos($s,'[[') !== false) {
+ $replace = '<a href="'.$wikiURL.'/'.$pageURLs[$idx].'">'.$pages[$idx].'</a>';
+ $s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
+ $idx++;
+ }
+ }
+ return $s;
+}
+
+function wiki_generate_toc($s) {
+
+ if (strpos($s,'[toc]') !== false) {
+ //$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
+ $toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
+ $s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
+ }
+ return $s;
+}
+
+// This function is derived from
+// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
+function wiki_toc($content) {
+ // ensure using only "\n" as line-break
+ $source = str_replace(["\r\n", "\r"], "\n", $content);
+
+ // look for markdown TOC items
+ preg_match_all(
+ '/^(?:=|-|#).*$/m',
+ $source,
+ $matches,
+ PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
+ );
+
+ // preprocess: iterate matched lines to create an array of items
+ // where each item is an array(level, text)
+ $file_size = strlen($source);
+ foreach ($matches[0] as $item) {
+ $found_mark = substr($item[0], 0, 1);
+ if ($found_mark == '#') {
+ // text is the found item
+ $item_text = $item[0];
+ $item_level = strrpos($item_text, '#') + 1;
+ $item_text = substr($item_text, $item_level);
+ } else {
+ // text is the previous line (empty if <hr>)
+ $item_offset = $item[1];
+ $prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
+ $item_text =
+ substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
+ $item_text = trim($item_text);
+ $item_level = $found_mark == '=' ? 1 : 2;
+ }
+ if (!trim($item_text) OR strpos($item_text, '|') !== FALSE) {
+ // item is an horizontal separator or a table header, don't mind
+ continue;
+ }
+ $raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
+ }
+ $o = '';
+ foreach($raw_toc as $t) {
+ $level = intval($t['level']);
+ $text = $t['text'];
+ switch ($level) {
+ case 1:
+ $li = '* ';
+ break;
+ case 2:
+ $li = ' * ';
+ break;
+ case 3:
+ $li = ' * ';
+ break;
+ case 4:
+ $li = ' * ';
+ break;
+ default:
+ $li = '* ';
+ break;
+ }
+ $o .= $li . $text . "\n";
+ }
+ return $o;
+}
diff --git a/include/zot.php b/include/zot.php
index 0cdf7fc87..73d9ef950 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -12,6 +12,7 @@ require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/hubloc.php');
require_once('include/queue_fn.php');
+require_once('include/perm_upgrade.php');
/**
@@ -329,8 +330,12 @@ function zot_refresh($them, $channel = null, $force = false) {
return false;
}
+ $token = random_string();
+
$postvars = array();
+ $postvars['token'] = $token;
+
if($channel) {
$postvars['target'] = $channel['channel_guid'];
$postvars['target_sig'] = $channel['channel_guid_sig'];
@@ -343,9 +348,9 @@ function zot_refresh($them, $channel = null, $force = false) {
$postvars['guid_hash'] = $them['xchan_hash'];
if (array_key_exists('xchan_guid',$them) && $them['xchan_guid']
&& array_key_exists('xchan_guid_sig',$them) && $them['xchan_guid_sig']) {
-
$postvars['guid'] = $them['xchan_guid'];
$postvars['guid_sig'] = $them['xchan_guid_sig'];
+
}
$rhs = '/.well-known/zot-info';
@@ -363,15 +368,28 @@ function zot_refresh($them, $channel = null, $force = false) {
return false;
}
+ $signed_token = ((is_array($j) && array_key_exists('signed_token',$j)) ? $j['signed_token'] : null);
+ if($signed_token) {
+ $valid = rsa_verify('token.' . $token,base64url_decode($signed_token),$j['key']);
+ if(! $valid) {
+ logger('invalid signed token: ' . $url . $rhs, LOGGER_NORMAL, LOG_ERR);
+ return false;
+ }
+ }
+ else {
+ logger('No signed token from ' . $url . $rhs, LOGGER_NORMAL, LOG_WARNING);
+ // after 2017-01-01 this will be a hard error unless you over-ride it.
+ if((time() > 1483228800) && (! get_config('system','allow_unsigned_zotfinger'))) {
+ return false;
+ }
+ }
+
$x = import_xchan($j, (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
if(! $x['success'])
return false;
- $their_perms = 0;
-
if($channel) {
- $global_perms = get_perms();
if($j['permissions']['data']) {
$permissions = crypto_unencapsulate(array(
'data' => $j['permissions']['data'],
@@ -388,15 +406,10 @@ function zot_refresh($them, $channel = null, $force = false) {
$connected_set = false;
if($permissions && is_array($permissions)) {
+ $old_read_stream_perm = get_abconfig($channel['channel_id'],$x['hash'],'their_perms','view_stream');
+
foreach($permissions as $k => $v) {
- // The connected permission means you are in their address book
- if($k === 'connected') {
- $connected_set = intval($v);
- continue;
- }
- if(($v) && (array_key_exists($k,$global_perms))) {
- $their_perms = $their_perms | intval($global_perms[$k][1]);
- }
+ set_abconfig($channel['channel_id'],$x['hash'],'their_perms',$k,$v);
}
}
@@ -423,52 +436,49 @@ function zot_refresh($them, $channel = null, $force = false) {
if(substr($r[0]['abook_dob'],5) == substr($next_birthday,5))
$next_birthday = $r[0]['abook_dob'];
- $current_abook_connected = (intval($r[0]['abook_unconnected']) ? 0 : 1);
-
- $y = q("update abook set abook_their_perms = %d, abook_dob = '%s'
+ $y = q("update abook set abook_dob = '%s'
where abook_xchan = '%s' and abook_channel = %d
and abook_self = 0 ",
- intval($their_perms),
dbescdate($next_birthday),
dbesc($x['hash']),
intval($channel['channel_id'])
);
-// if(($connected_set === 0 || $connected_set === 1) && ($connected_set !== $current_abook_unconnected)) {
-
- // if they are in your address book but you aren't in theirs, and/or this does not
- // match your current connected state setting, toggle it.
- /** @FIXME uncoverted to postgres */
- /** @FIXME when this was enabled, all contacts became unconnected. Currently disabled intentionally */
-// $y1 = q("update abook set abook_unconnected = 1
-// where abook_xchan = '%s' and abook_channel = %d
-// and abook_self = 0 limit 1",
-// dbesc($x['hash']),
-// intval($channel['channel_id'])
-// );
-// }
-
if(! $y)
logger('abook update failed');
else {
// if we were just granted read stream permission and didn't have it before, try to pull in some posts
- if((! ($r[0]['abook_their_perms'] & PERMS_R_STREAM)) && ($their_perms & PERMS_R_STREAM))
- proc_run('php','include/onepoll.php',$r[0]['abook_id']);
+ if((! $old_read_stream_perm) && (intval($permissions['view_stream'])))
+ Zotlabs\Daemon\Master::Summon(array('Onepoll',$r[0]['abook_id']));
}
}
else {
// new connection
+ $my_perms = null;
+
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
if($role) {
- $xx = get_role_perms($role);
- if($xx['perms_auto'])
- $default_perms = $xx['perms_accept'];
+ $xx = \Zotlabs\Access\PermissionRoles::role_perms($role);
+ if($xx['perms_auto']) {
+ $default_perms = $xx['perms_connect'];
+ $my_perms = \Zotlabs\Access\Permissions::FilledPerms($default_perms);
+ }
}
- if(! $default_perms)
- $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms'));
+ if(! $my_perms) {
+ $m = \Zotlabs\Access\Permissions::FilledAutoperms($channel['channel_id']);
+ if($m) {
+ $my_perms = $m;
+ }
+ }
+
+ if($my_perms) {
+ foreach($my_perms as $k => $v) {
+ set_abconfig($channel['channel_id'],$x['hash'],'my_perms',$k,$v);
+ }
+ }
// Keep original perms to check if we need to notify them
$previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
@@ -478,13 +488,11 @@ function zot_refresh($them, $channel = null, $force = false) {
if($closeness === false)
$closeness = 80;
- $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_dob, abook_pending ) values ( %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d )",
+ $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_created, abook_updated, abook_dob, abook_pending ) values ( %d, %d, %d, '%s', '%s', '%s', '%s', %d )",
intval($channel['channel_account_id']),
intval($channel['channel_id']),
intval($closeness),
dbesc($x['hash']),
- intval($their_perms),
- intval($default_perms),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($next_birthday),
@@ -503,27 +511,36 @@ function zot_refresh($them, $channel = null, $force = false) {
);
if($new_connection) {
- if($new_perms != $previous_perms)
- proc_run('php','include/notifier.php','permission_create',$new_connection[0]['abook_id']);
- require_once('include/enotify.php');
- notification(array(
+ if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
+ Zotlabs\Daemon\Master::Summon(array('Notifier','permission_create',$new_connection[0]['abook_id']));
+ Zotlabs\Lib\Enotify::submit(array(
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
));
- if($their_perms & PERMS_R_STREAM) {
- if(($channel['channel_w_stream'] & PERMS_PENDING)
- || (! intval($new_connection[0]['abook_pending'])) )
- proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']);
+ if(intval($permissions['view_stream'])) {
+ if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
+ || (! intval($new_connection[0]['abook_pending'])))
+ Zotlabs\Daemon\Master::Summon(array('Onepoll',$new_connection[0]['abook_id']));
+ }
+
+
+ /** If there is a default group for this channel, add this connection to it */
+ $default_group = $channel['channel_default_group'];
+ if($default_group) {
+ require_once('include/group.php');
+ $g = group_rec_byhash($channel['channel_id'],$default_group);
+ if($g)
+ group_add_member($channel['channel_id'],'',$x['hash'],$g['id']);
}
unset($new_connection[0]['abook_id']);
unset($new_connection[0]['abook_account']);
unset($new_connection[0]['abook_channel']);
- $abconfig = load_abconfig($channel['channel_hash'],$new_connection['abook_xchan']);
+ $abconfig = load_abconfig($channel['channel_id'],$new_connection['abook_xchan']);
if($abconfig)
$new_connection['abconfig'] = $abconfig;
@@ -1027,8 +1044,9 @@ function zot_process_response($hub, $arr, $outq) {
/**
* @brief
*
- * We received a notification packet (in mod/post.php) that a message is waiting for us, and we've verified the sender.
- * Now send back a pickup message, using our message tracking ID ($arr['secret']), which we will sign with our site private key.
+ * We received a notification packet (in mod_post) that a message is waiting for us, and we've verified the sender.
+ * Now send back a pickup message, using our message tracking ID ($arr['secret']), which we will sign with our site
+ * private key.
* The entire pickup message is encrypted with the remote site's public key.
* If everything checks out on the remote end, we will receive back a packet containing one or more messages,
* which will be processed and delivered before this function ultimately returns.
@@ -1102,6 +1120,7 @@ function zot_fetch($arr) {
* * [1] => \e string $delivery_status
* * [2] => \e string $address
*/
+
function zot_import($arr, $sender_url) {
$data = json_decode($arr['body'], true);
@@ -1332,7 +1351,7 @@ function zot_import($arr, $sender_url) {
*/
function public_recips($msg) {
- require_once('include/identity.php');
+ require_once('include/channel.php');
$check_mentions = false;
$include_sys = false;
@@ -1340,8 +1359,8 @@ function public_recips($msg) {
if($msg['message']['type'] === 'activity') {
if(! get_config('system','disable_discover_tab'))
$include_sys = true;
- $col = 'channel_w_stream';
- $field = PERMS_W_STREAM;
+ $perm = 'send_stream';
+
if(array_key_exists('flags',$msg['message']) && in_array('thread_parent', $msg['message']['flags'])) {
// check mention recipient permissions on top level posts only
$check_mentions = true;
@@ -1373,65 +1392,30 @@ function public_recips($msg) {
// contains the tag. we'll solve that further below.
if($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) {
- $col = 'channel_w_comment';
- $field = PERMS_W_COMMENT;
+ $perm = 'post_comments';
}
}
}
- elseif($msg['message']['type'] === 'mail') {
- $col = 'channel_w_mail';
- $field = PERMS_W_MAIL;
- }
+ elseif($msg['message']['type'] === 'mail')
+ $perm = 'post_mail';
- if(! $col)
- return NULL;
-
- $col = dbesc($col);
-
- // First find those channels who are accepting posts from anybody, or at least
- // something greater than just their connections.
-
- if($msg['notify']['sender']['url'] === z_root()) {
- $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0
- or ( " . $col . " & " . intval(PERMS_SITE) . " ) > 0
- or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0
- or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) ";
- } else {
- $sql = " where ( " . $col . " = " . intval(PERMS_NETWORK) . "
- or " . $col . " = " . intval(PERMS_PUBLIC) . "
- or " . $col . " = " . intval(PERMS_AUTHED) . " ) ";
+ $r = array();
+
+ $c = q("select channel_id, channel_hash from channel where channel_removed = 0");
+ if($c) {
+ foreach($c as $cc) {
+ if(perm_is_allowed($cc['channel_id'],$msg['notify']['sender']['hash'],$perm)) {
+ $r[] = [ 'hash' => $cc['channel_hash'] ];
+ }
+ }
}
- $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s'
- and channel_removed = 0 ",
- dbesc($msg['notify']['sender']['hash'])
- );
-
- if(! $r)
- $r = array();
-
- // Now we have to get a bit dirty. Find every channel that has the sender in their connections (abook)
- // and is allowing this sender at least at a high level.
-
- $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id
- where abook_xchan = '%s' and channel_removed = 0
- and (( " . $col . " = " . intval(PERMS_SPECIFIC) . " and ( abook_my_perms & " . intval($field) . " ) > 0 )
- OR " . $col . " = " . intval(PERMS_PENDING) . "
- OR ( " . $col . " = " . intval(PERMS_CONTACTS) . " and abook_pending = 0 )) ",
- dbesc($msg['notify']['sender']['hash'])
- );
-
- if(! $x)
- $x = array();
-
- $r = array_merge($r,$x);
-
- //logger('message: ' . print_r($msg['message'],true));
+ // logger('message: ' . print_r($msg['message'],true));
if($include_sys && array_key_exists('public_scope',$msg['message']) && $msg['message']['public_scope'] === 'public') {
$sys = get_sys_channel();
if($sys)
- $r[] = array('hash' => $sys['channel_hash']);
+ $r[] = [ 'hash' => $sys['channel_hash'] ];
}
// look for any public mentions on this site
@@ -1494,7 +1478,7 @@ function public_recips($msg) {
/**
* @brief
*
- * This is the second part of public_recipes().
+ * This is the second part of public_recips().
* We'll find all the channels willing to accept public posts from us, then
* match them against the sender privacy scope and see who in that list that
* the sender is allowing.
@@ -1703,7 +1687,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
if((! $relay) && (! $request) && (! $local_public)
&& perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) {
- proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']);
+ Zotlabs\Daemon\Master::Summon(array('Notifier', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']));
}
continue;
}
@@ -1775,7 +1759,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
if($relay && $item_id) {
logger('process_delivery: invoking relay');
- proc_run('php','include/notifier.php','relay',intval($item_id));
+ Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
$DR->update('relayed');
$result[] = $DR->get();
}
@@ -1858,7 +1842,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
if($relay && $item_id) {
logger('process_delivery: invoking relay');
- proc_run('php','include/notifier.php','relay',intval($item_id));
+ Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
$DR->addto_update('relayed');
$result[] = $DR->get();
}
@@ -1912,9 +1896,9 @@ function remove_community_tag($sender, $arr, $uid) {
$i = $r[0];
if($i['target'])
- $i['target'] = json_decode_plus($i['target']);
+ $i['target'] = json_decode($i['target'],true);
if($i['object'])
- $i['object'] = json_decode_plus($i['object']);
+ $i['object'] = json_decode($i['object'],true);
if(! ($i['target'] && $i['object'])) {
logger('remove_community_tag: no target/object');
@@ -1932,7 +1916,7 @@ function remove_community_tag($sender, $arr, $uid) {
return;
}
- q("delete from term where uid = %d and oid = %d and otype = %d and type in ( %d, %d ) and term = '%s' and url = '%s'",
+ q("delete from term where uid = %d and oid = %d and otype = %d and ttype in ( %d, %d ) and term = '%s' and url = '%s'",
intval($uid),
intval($r[0]['id']),
intval(TERM_OBJ_POST),
@@ -1953,6 +1937,16 @@ function remove_community_tag($sender, $arr, $uid) {
*/
function update_imported_item($sender, $item, $orig, $uid) {
+ // If this is a comment being updated, remove any privacy information
+ // so that item_store_update will set it from the original.
+
+ if($item['mid'] !== $item['parent_mid']) {
+ unset($item['allow_cid']);
+ unset($item['allow_gid']);
+ unset($item['deny_cid']);
+ unset($item['deny_gid']);
+ unset($item['item_private']);
+ }
$x = item_store_update($item);
@@ -2371,11 +2365,14 @@ function sync_locations($sender, $arr, $absolute = false) {
$current_site = false;
+ $t = datetime_convert('UTC','UTC','now - 15 minutes');
+
if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) {
- q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d",
+ q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_connected < '%s'",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
+ intval($r[0]['hubloc_id']),
+ dbesc($t)
);
$current_site = true;
}
@@ -2935,8 +2932,6 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if(UNO)
return;
- $a = get_app();
-
logger('build_sync_packet');
if($packet)
@@ -2956,6 +2951,14 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
$channel = $r[0];
+ translate_channel_perms_outbound($channel);
+ if($packet && array_key_exists('abook',$packet) && $packet['abook']) {
+ for($x = 0; $x < count($packet['abook']); $x ++) {
+ translate_abook_perms_outbound($packet['abook'][$x]);
+ }
+ }
+
+
if(intval($channel['channel_removed']))
return;
@@ -2972,7 +2975,12 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if($x['hubloc_host'] == App::get_hostname())
continue;
- $synchubs[] = $x;
+ $y = q("select site_dead from site where site_url = '%s' limit 1",
+ dbesc($x['hubloc_url'])
+ );
+
+ if((! $y) || ($y[0]['site_dead'] == 0))
+ $synchubs[] = $x;
}
if(! $synchubs)
@@ -2989,7 +2997,8 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
$info = (($packet) ? $packet : array());
$info['type'] = 'channel_sync';
- $info['encoding'] = 'red'; // note: not zot, this packet is very red specific
+ $info['encoding'] = 'red'; // note: not zot, this packet is very platform specific
+ $info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ];
if(array_key_exists($uid,App::$config) && array_key_exists('transient',App::$config[$uid])) {
$settings = App::$config[$uid]['transient'];
@@ -3019,7 +3028,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
}
if($groups_changed) {
- $r = q("select hash as collection, visible, deleted, name from groups where uid = %d",
+ $r = q("select hash as collection, visible, deleted, gname as name from groups where uid = %d",
intval($uid)
);
if($r)
@@ -3050,7 +3059,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
'msg' => json_encode($info)
));
- proc_run('php', 'include/deliver.php', $hash);
+ Zotlabs\Daemon\Master::Summon(array('Deliver', $hash));
$total = $total - 1;
if($interval && $total)
@@ -3073,7 +3082,8 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
require_once('include/import.php');
- /** @FIXME this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. */
+ /** @FIXME this will sync red structures (channel, pconfig and abook).
+ Eventually we need to make this application agnostic. */
$result = array();
@@ -3121,16 +3131,19 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
import_conv($channel,$arr['conv']);
if(array_key_exists('mail',$arr) && $arr['mail'])
- import_mail($channel,$arr['mail']);
+ sync_mail($channel,$arr['mail']);
if(array_key_exists('event',$arr) && $arr['event'])
sync_events($channel,$arr['event']);
if(array_key_exists('event_item',$arr) && $arr['event_item'])
- sync_items($channel,$arr['event_item']);
+ sync_items($channel,$arr['event_item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
if(array_key_exists('item',$arr) && $arr['item'])
- sync_items($channel,$arr['item']);
+ sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
+
+ // deprecated, maintaining for a few months for upward compatibility
+ // this should sync webpages, but the logic is a bit subtle
if(array_key_exists('item_id',$arr) && $arr['item_id'])
sync_items($channel,$arr['item_id']);
@@ -3143,6 +3156,8 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) {
+ translate_channel_perms_inbound($arr['channel']);
+
if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
// These flags cannot be sync'd.
// remove the bits from the incoming flags.
@@ -3156,7 +3171,15 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
- $disallowed = array('channel_id','channel_account_id','channel_primary','channel_prvkey', 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', 'channel_system');
+ $disallowed = [
+ 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
+ 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
+ 'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
+ 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
+ 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
+ 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
+ 'channel_a_delegate'
+ ];
$clean = array();
foreach($arr['channel'] as $k => $v) {
@@ -3192,6 +3215,8 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
foreach($arr['abook'] as $abook) {
+
+
$abconfig = null;
if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
@@ -3212,7 +3237,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
$clean = array();
if($abook['abook_xchan'] && $abook['entry_deleted']) {
logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']);
- require_once('include/Contact.php');
$r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc($abook['abook_xchan']),
@@ -3287,11 +3311,16 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
+ // This will set abconfig vars if the sender is using old-style fixed permissions
+ // using the raw abook record as passed to us. New-style permissions will fall through
+ // and be set using abconfig
+
+ translate_abook_perms_inbound($channel,$abook);
+
if($abconfig) {
// @fixme does not handle sync of del_abconfig
foreach($abconfig as $abc) {
- if($abc['chan'] === $channel['channel_hash'])
- set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
+ set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
}
}
}
@@ -3313,10 +3342,10 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
if($found) {
- if(($y['name'] != $cl['name'])
+ if(($y['gname'] != $cl['name'])
|| ($y['visible'] != $cl['visible'])
|| ($y['deleted'] != $cl['deleted'])) {
- q("update groups set name = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
+ q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
dbesc($cl['name']),
intval($cl['visible']),
intval($cl['deleted']),
@@ -3332,7 +3361,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
if(! $found) {
- $r = q("INSERT INTO `groups` ( hash, uid, visible, deleted, name )
+ $r = q("INSERT INTO `groups` ( hash, uid, visible, deleted, gname )
VALUES( '%s', %d, %d, %d, '%s' ) ",
dbesc($cl['collection']),
intval($channel['channel_id']),
@@ -3439,7 +3468,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('profile',$arr) && is_array($arr['profile']) && count($arr['profile'])) {
- $disallowed = array('id','aid','uid');
+ $disallowed = array('id','aid','uid','guid');
foreach($arr['profile'] as $profile) {
$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
@@ -3463,13 +3492,22 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
foreach($profile as $k => $v) {
if(in_array($k,$disallowed))
continue;
+
+ if($k === 'name')
+ $clean['fullname'] = $v;
+ elseif($k === 'with')
+ $clean['partner'] = $v;
+ elseif($k === 'work')
+ $clean['employment'] = $v;
+ elseif(array_key_exists($k,$x[0]))
+ $clean[$k] = $v;
- $clean[$k] = $v;
/**
- * @TODO check if these are allowed, otherwise we'll error
+ * @TODO
* We also need to import local photos if a custom photo is selected
*/
}
+
if(count($clean)) {
foreach($clean as $k => $v) {
$r = dbq("UPDATE profile set `" . dbesc($k) . "` = '" . dbesc($v)
@@ -3479,13 +3517,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
-
- if(array_key_exists('item',$arr) && $arr['item'])
- sync_items($channel,$arr['item']);
-
- if(array_key_exists('item_id',$arr) && $arr['item_id'])
- sync_items($channel,$arr['item_id']);
-
$addon = array('channel' => $channel,'data' => $arr);
call_hooks('process_channel_sync_delivery',$addon);
@@ -3642,7 +3673,7 @@ function zot_reply_message_request($data) {
* invoke delivery to send out the notify packet
*/
- proc_run('php', 'include/deliver.php', $hash);
+ Zotlabs\Daemon\Master::Summon(array('Deliver', $hash));
}
}
$ret['success'] = true;
@@ -3662,6 +3693,8 @@ function zotinfo($arr) {
$zsig = ((x($arr,'target_sig')) ? $arr['target_sig'] : '');
$zkey = ((x($arr,'key')) ? $arr['key'] : '');
$mindate = ((x($arr,'mindate')) ? $arr['mindate'] : '');
+ $token = ((x($arr,'token')) ? $arr['token'] : '');
+
$feed = ((x($arr,'feed')) ? intval($arr['feed']) : 0);
if($ztarget) {
@@ -3749,11 +3782,21 @@ function zotinfo($arr) {
}
else {
// check if it has characteristics of a public forum based on custom permissions.
- $t = q("select abook_my_perms from abook where abook_channel = %d and abook_self = 1 limit 1",
- intval($e['channel_id'])
+ $t = q("select * from abconfig where abconfig.cat = 'my_perms' and abconfig.chan = %d and abconfig.xchan = '%s' and abconfig.k in ('tag_deliver', 'send_stream') ",
+ intval($e['channel_id']),
+ intval($e['channel_hash'])
);
- if(($t) && (($t[0]['abook_my_perms'] & PERMS_W_TAGWALL) && (! ($t[0]['abook_my_perms'] & PERMS_W_STREAM))))
- $public_forum = true;
+ $ch = 0;
+ if($t) {
+ foreach($t as $tt) {
+ if($tt['k'] == 'tag_deliver' && $tt['v'] == 1)
+ $ch ++;
+ if($tt['k'] == 'send_stream' && $tt['v'] == 0)
+ $ch ++;
+ }
+ if($ch == 2)
+ $public_forum = true;
+ }
}
@@ -3806,6 +3849,10 @@ function zotinfo($arr) {
// Communication details
+ if($token)
+ $ret['signed_token'] = base64url_encode(rsa_sign('token.' . $token,$e['channel_prvkey']));
+
+
$ret['guid'] = $e['xchan_guid'];
$ret['guid_sig'] = $e['xchan_guid_sig'];
$ret['key'] = $e['xchan_pubkey'];
@@ -3910,16 +3957,14 @@ function zotinfo($arr) {
$ret['site']['accounts'] = account_total();
- require_once('include/identity.php');
+ require_once('include/channel.php');
$ret['site']['channels'] = channel_total();
- $ret['site']['version'] = Zotlabs\Project\System::get_platform_name() . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']';
+ $ret['site']['version'] = Zotlabs\Lib\System::get_platform_name() . ' ' . STD_VERSION . '[' . DB_UPDATE_VERSION . ']';
$ret['site']['admin'] = get_config('system','admin_email');
- $a = get_app();
-
$visible_plugins = array();
if(is_array(App::$plugins) && count(App::$plugins)) {
$r = q("select * from addon where hidden = 0");
@@ -3934,7 +3979,7 @@ function zotinfo($arr) {
$ret['site']['sellpage'] = get_config('system','sellpage');
$ret['site']['location'] = get_config('system','site_location');
$ret['site']['realm'] = get_directory_realm();
- $ret['site']['project'] = Zotlabs\Project\System::get_platform_name();
+ $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role();
}
@@ -4048,6 +4093,17 @@ function delivery_report_is_storable($dr) {
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
return false;
+ // If you have a private post with a recipient list, every single site is going to report
+ // back a failed delivery for anybody on that list that isn't local to them. We're only
+ // concerned about this if we have a local hubloc record which says we expected them to
+ // have a channel on that site.
+
+ $r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
+ dbesc($rxchan),
+ dbesc($dr['location'])
+ );
+ if((! $r) && ($dr['status'] === 'recipient_not_found'))
+ return false;
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($rxchan),
@@ -4082,7 +4138,7 @@ function update_hub_connected($hub,$sitekey = '') {
$sitekey = $hub['sitekey'];
}
- // $sender['sitekey'] is a new addition to the protcol to distinguish
+ // $sender['sitekey'] is a new addition to the protocol to distinguish
// hublocs coming from re-installed sites. Older sites will not provide
// this field and we have to still mark them valid, since we can't tell
// if this hubloc has the same sitekey as the packet we received.
@@ -4091,10 +4147,13 @@ function update_hub_connected($hub,$sitekey = '') {
// Update our DB to show when we last communicated successfully with this hub
// This will allow us to prune dead hubs from using up resources
- $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' ",
+ $t = datetime_convert('UTC','UTC','now - 15 minutes');
+
+ $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' and hubloc_connected < '%s' ",
dbesc(datetime_convert()),
intval($hub['hubloc_id']),
- dbesc($sitekey)
+ dbesc($sitekey),
+ dbesc($t)
);
// a dead hub came back to life - reset any tombstones we might have
@@ -4394,7 +4453,6 @@ function zot_reply_purge($sender,$recipients) {
$arr = $sender;
$sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
- require_once('include/Contact.php');
remove_all_xchan_resources($sender_hash);
$ret['success'] = true;