aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php69
-rw-r--r--include/ConversationObject.php27
-rw-r--r--include/ItemObject.php37
-rw-r--r--include/activities.php5
-rw-r--r--include/api.php33
-rw-r--r--include/attach.php2
-rw-r--r--include/auth.php1
-rw-r--r--include/bbcode.php55
-rw-r--r--include/comanche.php170
-rw-r--r--include/config.php9
-rw-r--r--include/contact_widgets.php36
-rw-r--r--include/conversation.php122
-rwxr-xr-xinclude/dba/dba_mysqli.php2
-rw-r--r--include/deliver.php2
-rw-r--r--include/dir_fns.php64
-rw-r--r--include/enotify.php13
-rw-r--r--include/event.php3
-rw-r--r--include/features.php4
-rw-r--r--include/follow.php7
-rwxr-xr-xinclude/friendica_smarty.php2
-rw-r--r--include/identity.php14
-rwxr-xr-xinclude/items.php641
-rw-r--r--include/menu.php12
-rw-r--r--include/nav.php16
-rw-r--r--include/network.php12
-rw-r--r--include/notifier.php48
-rw-r--r--include/oauth.php67
-rw-r--r--include/onedirsync.php42
-rw-r--r--include/onepoll.php9
-rw-r--r--include/page_widgets.php2
-rw-r--r--include/permissions.php1
-rw-r--r--include/photos.php8
-rwxr-xr-xinclude/plugin.php19
-rw-r--r--include/poller.php125
-rw-r--r--include/security.php49
-rw-r--r--include/taxonomy.php60
-rwxr-xr-xinclude/text.php134
-rw-r--r--include/zot.php361
38 files changed, 1732 insertions, 551 deletions
diff --git a/include/Contact.php b/include/Contact.php
index bf536ccd5..46c84aab6 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -15,13 +15,20 @@ function rconnect_url($channel_id,$xchan) {
if($r)
return '';
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($xchan)
+ );
+
+ if(($r) && ($r[0]['xchan_follow']))
+ return $r[0]['xchan_follow'];
+
$r = q("select hubloc_url from hubloc where hubloc_hash = '%s' and ( hubloc_flags & %d ) limit 1",
dbesc($xchan),
intval(HUBLOC_FLAGS_PRIMARY)
);
if($r)
- return $r[0]['hubloc_url'];
+ return $r[0]['hubloc_url'] . '/follow?f=&url=%s';
return '';
}
@@ -140,7 +147,9 @@ function user_remove($uid) {
}
-function account_remove($account_id) {
+function account_remove($account_id,$local = true) {
+
+ logger('account_remove: ' . $account_id);
if(! intval($account_id)) {
logger('account_remove: no account.');
@@ -172,7 +181,7 @@ function account_remove($account_id) {
);
if($x) {
foreach($x as $xx) {
- channel_remove($xx['channel_id']);
+ channel_remove($xx['channel_id'],$local);
}
}
@@ -184,7 +193,7 @@ function account_remove($account_id) {
}
-function channel_remove($channel_id) {
+function channel_remove($channel_id, $local = true) {
if(! $channel_id)
return;
@@ -192,13 +201,39 @@ function channel_remove($channel_id) {
logger('Removing channel: ' . $channel_id);
$r = q("select * from channel where channel_id = %d limit 1", intval($channel_id));
+ if(! $r) {
+ logger('channel_remove: channel not found: ' . $channel_id);
+ return;
+ }
+
+ $channel = $r[0];
call_hooks('channel_remove',$r[0]);
+ if(! $local) {
+
// FIXME notify the directory
// FIXME notify all contacts
+ $r = q("update channel set channel_pageflags = (channel_pageflags | %d), 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 limit 1",
+ intval(PAGE_REMOVED),
+ intval($channel_id)
+ );
+
+ $r = q("update hubloc set hubloc_flags = hubloc_flags | %d where hubloc_hash = '%s'",
+ intval(HUBLOC_FLAGS_DELETED),
+ dbesc($channel['channel_hash'])
+ );
+
+ proc_run('php','include/notifier.php','purge_all',$channel_id);
+
+
+ }
q("DELETE FROM `group` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `group_member` WHERE `uid` = %d", intval($channel_id));
@@ -271,18 +306,20 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) {
);
- $r = q("delete from xchan where xchan_hash = '%s' limit 1",
- dbesc($xchan)
- );
- $r = q("delete from hubloc where hubloc_hash = '%s'",
- dbesc($xchan)
- );
- $r = q("delete from abook where abook_xchan = '%s'",
- dbesc($xchan)
- );
- $r = q("delete from xtag where xtag_hash = '%s'",
- dbesc($xchan)
- );
+// This could get sticky with directories
+
+// $r = q("delete from xchan where xchan_hash = '%s' limit 1",
+// dbesc($xchan)
+// );
+// $r = q("delete from hubloc where hubloc_hash = '%s'",
+// dbesc($xchan)
+// );
+// $r = q("delete from abook where abook_xchan = '%s'",
+// dbesc($xchan)
+// );
+// $r = q("delete from xtag where xtag_hash = '%s'",
+// dbesc($xchan)
+// );
}
}
diff --git a/include/ConversationObject.php b/include/ConversationObject.php
index 30026e908..bb144d893 100644
--- a/include/ConversationObject.php
+++ b/include/ConversationObject.php
@@ -7,6 +7,7 @@ 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
@@ -138,22 +139,28 @@ class Conversation extends BaseObject {
return false;
}
- if(local_user() && $item->get_data_value('uid') == local_user())
- $this->commentable = true;
+// if(local_user() && $item->get_data_value('uid') == local_user())
+// $this->commentable = true;
- if($this->writable)
- $this->commentable = true;
+// if($this->writable)
+// $this->commentable = true;
+
+ $item->set_commentable(false);
+ $ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
+
+ if(($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash))
+ $item->set_commentable(true);
if($item->get_data_value('item_flags') & ITEM_NOCOMMENT) {
- $this->commentable = false;
+ $item->set_commentable(false);
}
- elseif(($this->observer) && (! $this->writable)) {
- $this->commentable = can_comment_on_post($this->observer['xchan_hash'],$item->data);
+ elseif(($this->observer) && (! $item->is_commentable())) {
+ if((array_key_exists('owner',$item->data)) && ($item->data['owner']['abook_flags'] & ABOOK_FLAG_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));
}
-
-
-
$item->set_conversation($this);
$this->threads[] = $item;
return end($this->threads);
diff --git a/include/ItemObject.php b/include/ItemObject.php
index 8c8c0ee2a..df9386232 100644
--- a/include/ItemObject.php
+++ b/include/ItemObject.php
@@ -14,6 +14,7 @@ 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;
@@ -39,10 +40,10 @@ class Item extends BaseObject {
foreach($data['children'] as $item) {
/*
- * Only add thos that will be displayed
+ * Only add those that will be displayed
*/
- if(! visible_activity($item)) {
+ if((! visible_activity($item)) || array_key_exists('author_blocked',$item)) {
continue;
}
@@ -74,7 +75,7 @@ class Item extends BaseObject {
$buttons = '';
$dropping = false;
$star = false;
- $isstarred = "unstarred";
+ $isstarred = "unstarred icon-star-empty";
$indent = '';
$osparkle = '';
$total_children = $this->count_descendants();
@@ -88,6 +89,8 @@ class Item extends BaseObject {
: false);
$shareable = ((($conv->get_profile_owner() == local_user()) && ($item['item_private'] != 1)) ? true : false);
+ $mode = $conv->get_mode();
+
if(local_user() && $observer['xchan_hash'] === $item['author_xchan'])
$edpost = array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit"));
else
@@ -144,7 +147,7 @@ class Item extends BaseObject {
'toggle' => t("toggle star status"),
'classdo' => (($item['item_flags'] & ITEM_STARRED) ? "hidden" : ""),
'classundo' => (($item['item_flags'] & ITEM_STARRED) ? "" : "hidden"),
- 'isstarred' => (($item['item_flags'] & ITEM_STARRED) ? "starred" : "unstarred"),
+ 'isstarred' => (($item['item_flags'] & ITEM_STARRED) ? "starred icon-star" : "unstarred icon-star-empty"),
'starred' => t('starred'),
);
@@ -153,6 +156,12 @@ class Item extends BaseObject {
$indent = 'comment';
}
+
+ $verified = (($item['item_flags'] & ITEM_VERIFIED) ? t('Message is verified') : '');
+ $unverified = '' ; // (($this->is_wall_to_wall() && (! ($item['item_flags'] & ITEM_VERIFIED))) ? t('Message cannot be verified') : '');
+
+
+
// FIXME - check this permission
if($conv->get_profile_owner() == local_user()) {
$tagger = array(
@@ -161,7 +170,7 @@ class Item extends BaseObject {
);
}
- if($conv->is_commentable()) {
+ 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)
@@ -183,7 +192,7 @@ class Item extends BaseObject {
$tmp_item = array(
'template' => $this->get_template(),
-
+ 'mode' => $mode,
'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'tags' => array(),
'body' => $body,
@@ -207,6 +216,8 @@ class Item extends BaseObject {
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
'lock' => $lock,
+ 'verified' => $verified,
+ 'unverified' => $unverified,
'location' => $location,
'indent' => $indent,
'owner_url' => $this->get_owner_url(),
@@ -293,6 +304,16 @@ class Item extends BaseObject {
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
*/
@@ -478,7 +499,9 @@ class Item extends BaseObject {
$comment_box = '';
$conv = $this->get_conversation();
- if(! $conv->is_commentable())
+// logger('Commentable conv: ' . $conv->is_commentable());
+
+ if(! $this->is_commentable())
return;
$template = get_markup_template($this->get_comment_box_template());
diff --git a/include/activities.php b/include/activities.php
index 10a01792f..73180eae0 100644
--- a/include/activities.php
+++ b/include/activities.php
@@ -45,6 +45,8 @@ function profile_activity($changed, $value) {
$prof = '[url=' . z_root() . '/profile/' . $self['channel_address'] . ']' . t('public profile') . '[/url]';
if($t == 1 && strlen($value)) {
+ // if it's a url, the HTML quotes will mess it up, so link it and don't try and zidify it because we don't know what it points to.
+ $value = linkify($value);
$message = sprintf( t('%1$s changed %2$s to “%3$s”'), $A, $changes, $value);
$message .= "\n\n" . sprintf( t('Visit %1$s\'s %2$s'), $A, $prof);
}
@@ -73,7 +75,8 @@ function profile_activity($changed, $value) {
$arr['deny_cid'] = $self['channel_deny_cid'];
$arr['deny_gid'] = $self['channel_deny_gid'];
- $i = item_store($arr);
+ $res = item_store($arr);
+ $i = $res['item_id'];
if($i) {
// FIXME - limit delivery in notifier.php to those specificed in the perms argument
diff --git a/include/api.php b/include/api.php
index a49258d18..2760914e9 100644
--- a/include/api.php
+++ b/include/api.php
@@ -730,9 +730,10 @@ require_once('include/photos.php');
$in_reply_to_user_id = $user_info['id'];
$in_reply_to_screen_name = $user_info['screen_name'];
}
- }
+ }
+ unobscure($lastwall);
$status_info = array(
- 'text' => html2plain(bbcode($lastwall['body']), 0),
+ 'text' => html2plain(prepare_text($lastwall['body'],$lastwall['mimetype']), 0),
'truncated' => false,
'created_at' => api_date($lastwall['created']),
'in_reply_to_status_id' => $in_reply_to_status_id,
@@ -803,8 +804,9 @@ require_once('include/photos.php');
$in_reply_to_screen_name = $user_info['screen_name'];
}
}
+ unobscure($lastwall);
$user_info['status'] = array(
- 'text' => html2plain(bbcode($lastwall['body']), 0),
+ 'text' => html2plain(prepare_text($lastwall['body'],$lastwall['mimetype']), 0),
'truncated' => false,
'created_at' => api_date($lastwall['created']),
'in_reply_to_status_id' => $in_reply_to_status_id,
@@ -1369,19 +1371,19 @@ require_once('include/photos.php');
'recipient_screen_name' => $recipient['screen_name'],
'recipient' => $recipient,
);
-
+ unobscure($item);
//don't send title to regular StatusNET requests to avoid confusing these apps
if (x($_GET, 'getText')) {
$ret['title'] = $item['title'] ;
if ($_GET["getText"] == "html") {
- $ret['text'] = bbcode($item['body']);
+ $ret['text'] = prepare_text($item['body'],$item['mimetype']);
}
elseif ($_GET["getText"] == "plain") {
- $ret['text'] = html2plain(bbcode($item['body']), 0);
+ $ret['text'] = html2plain(prepare_text($item['body'],$item['mimetype']), 0);
}
}
else {
- $ret['text'] = $item['title']."\n".html2plain(bbcode($item['body']), 0);
+ $ret['text'] = $item['title']."\n".html2plain(prepare_text($item['body'],$item['mimetype']), 0);
}
if (isset($_GET["getUserObjects"]) && $_GET["getUserObjects"] == "false") {
unset($ret['sender']);
@@ -1425,9 +1427,9 @@ require_once('include/photos.php');
$in_reply_to_user_id = 0;
$in_reply_to_status_id = 0;
}
-
+ unobscure($item);
// Workaround for ostatus messages where the title is identically to the body
- $statusbody = trim(html2plain(bbcode($item['body']), 0));
+ $statusbody = trim(html2plain(prepare_text($item['body'],$item['mimetype']), 0));
$statustitle = trim($item['title']);
if (($statustitle != '') and (strpos($statusbody, $statustitle) !== false))
@@ -1448,7 +1450,7 @@ require_once('include/photos.php');
'geo' => '',
'favorited' => (($item['item_flags'] & ITEM_STARRED) ? true : false),
'user' => $status_user ,
- 'statusnet_html' => trim(bbcode($item['body'])),
+ 'statusnet_html' => trim(prepare_text($item['body']),$item['mimetype']),
'statusnet_conversation_id' => $item['parent'],
);
@@ -1823,9 +1825,13 @@ require_once('include/photos.php');
function api_oauth_request_token(&$a, $type){
try{
$oauth = new FKOAuth1();
- $r = $oauth->fetch_request_token(OAuthRequest::from_request());
+ $req = OAuthRequest::from_request();
+logger('Req: ' . var_export($req,true));
+ $r = $oauth->fetch_request_token($req);
}catch(Exception $e){
- echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme();
+ logger('oauth_exception: ' . print_r($e->getMessage(),true));
+ echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage());
+ killme();
}
echo $r;
killme();
@@ -1833,7 +1839,8 @@ require_once('include/photos.php');
function api_oauth_access_token(&$a, $type){
try{
$oauth = new FKOAuth1();
- $r = $oauth->fetch_access_token(OAuthRequest::from_request());
+ $req = OAuthRequest::from_request();
+ $r = $oauth->fetch_access_token($req);
}catch(Exception $e){
echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme();
}
diff --git a/include/attach.php b/include/attach.php
index 46d406f4b..da08154c6 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -339,7 +339,7 @@ function attach_store($channel,$observer_hash,$options = '',$arr = null) {
intval($channel_id)
);
if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) {
- $ret['message'] = upgrade_message(true);
+ $ret['message'] = upgrade_message(true).sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."),$limit / 1024000);
@unlink($src);
return $ret;
}
diff --git a/include/auth.php b/include/auth.php
index 143a16de8..d04ebbe43 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -15,6 +15,7 @@ function nuke_session() {
unset($_SESSION['cid']);
unset($_SESSION['theme']);
unset($_SESSION['mobile_theme']);
+ unset($_SESSION['show_mobile']);
unset($_SESSION['page_flags']);
unset($_SESSION['submanage']);
unset($_SESSION['my_url']);
diff --git a/include/bbcode.php b/include/bbcode.php
index a0a53a310..756d73aba 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -106,52 +106,32 @@ function bb_ShareAttributes($match) {
$author = "";
preg_match("/author='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
- $author = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
-
- preg_match('/author="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "")
- $author = $matches[1];
+ $author = urldecode($matches[1]);
$link = "";
preg_match("/link='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$link = $matches[1];
- preg_match('/link="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "")
- $link = $matches[1];
-
$avatar = "";
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$avatar = $matches[1];
- preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "")
- $avatar = $matches[1];
-
$profile = "";
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$profile = $matches[1];
- preg_match('/profile="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "")
- $profile = $matches[1];
-
$posted = "";
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
- preg_match('/posted="(.*?)"/ism', $attributes, $matches);
- if ($matches[1] != "")
- $posted = $matches[1];
-
// FIXME - this should really be a wall-item-ago so it will get updated on the client
$reldate = (($posted) ? relative_date($posted) : '');
- $headline = '<div class="shared_header">';
+ $headline = '<div class="shared_container"> <div class="shared_header">';
if ($avatar != "")
$headline .= '<img src="' . $avatar . '" alt="' . $author . '" height="32" width="32" />';
@@ -166,7 +146,7 @@ function bb_ShareAttributes($match) {
$headline .= '<span>' . $fmt . '</span></div>';
- $text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div>';
+ $text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div></div>';
return($text);
}
@@ -237,6 +217,18 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$ev = bbtoevent($Text);
+ // process [observer] tags before we do anything else because we might
+ // be stripping away stuff that then doesn't need to be worked on anymore
+ $observer = $a->get_observer();
+ if (strpos($Text,'[/observer]') !== false) {
+ if ($observer) {
+ $Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text);
+ $Text = preg_replace("/\[observer\=0\].*?\[\/observer\]/ism", '', $Text);
+ } else {
+ $Text = preg_replace("/\[observer\=1\].*?\[\/observer\]/ism", '', $Text);
+ $Text = preg_replace("/\[observer\=0\](.*?)\[\/observer\]/ism", '$1', $Text);
+ }
+ }
// Replace any html brackets with HTML Entities to prevent executing HTML or script
// Don't use strip_tags here because it breaks [url] search by replacing & with amp
@@ -259,12 +251,29 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = str_replace(array("\n","\r"), array('',''),$Text);
+ $Text = str_replace(array("\t"," "),array("&nbsp;&nbsp;&nbsp;&nbsp;","&nbsp;&nbsp;"),$Text);
// Set up the parameters for a URL search string
$URLSearchString = "^\[\]";
// Set up the parameters for a MAIL search string
$MAILSearchString = $URLSearchString;
+ // replace [observer.baseurl]
+ if ($observer) {
+ $obsBaseURL = $observer['xchan_url'];
+ $obsBaseURL = preg_replace("/\/channel\/.*$/", '', $obsBaseURL);
+ $Text = str_replace('[observer.baseurl]', $obsBaseURL, $Text);
+ $Text = str_replace('[observer.url]',$observer['xchan_url'], $Text);
+ $Text = str_replace('[observer.name]',$observer['xchan_name'], $Text);
+ $Text = str_replace('[observer.address]',$observer['xchan_addr'], $Text);
+ $Text = str_replace('[observer.photo]','[zmg]'.$observer['xchan_photo_l'].'[/zmg]', $Text);
+ } else {
+ $Text = str_replace('[observer.baseurl]', '', $Text);
+ $Text = str_replace('[observer.url]','', $Text);
+ $Text = str_replace('[observer.name]','', $Text);
+ $Text = str_replace('[observer.address]','', $Text);
+ $Text = str_replace('[observer.photo]','', $Text);
+ }
// Perform URL Search
diff --git a/include/comanche.php b/include/comanche.php
new file mode 100644
index 000000000..f1dd0e521
--- /dev/null
+++ b/include/comanche.php
@@ -0,0 +1,170 @@
+<?php /** @file */
+
+require_once('include/security.php');
+require_once('include/menu.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_restrict = ITEM_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' order by sid asc",
+ intval($owner)
+ );
+
+ $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) {
+
+
+ $cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches);
+ if($cnt)
+ $a->page['template'] = trim($matches[1]);
+
+ $cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches);
+ if($cnt)
+ $a->layout['theme'] = trim($matches[1]);
+
+ $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER);
+ if($cnt) {
+ foreach($matches as $mtch) {
+ $a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
+ }
+ }
+
+ $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) {
+ $a->layout['webpage'] = comanche_webpage($a,$mtch[1]);
+ }
+ }
+
+}
+
+
+function comanche_menu($name) {
+ $a = get_app();
+ $m = menu_fetch($name,$a->profile['profile_uid'],get_observer_hash());
+ return menu_render($m);
+}
+
+function comanche_replace_region($match) {
+ $a = get_app();
+ if(array_key_exists($match[1],$a->page)) {
+ return $a->page[$match[1]];
+ }
+}
+
+function comanche_block($name) {
+
+ $o = '';
+ $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(get_app()->profile['profile_uid']),
+ dbesc($name)
+ );
+ if($r) {
+ $o = '<div class="widget bblock">';
+ if($r[0]['title'])
+ $o .= '<h3>' . $r[0]['title'] . '</h3>';
+ $o .= prepare_text($r[0]['body'],$r[0]['mimetype']);
+ $o .= '</div>';
+
+ }
+ return $o;
+}
+
+// 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();
+ $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
+
+
+function comanche_widget($name,$args = null) {
+ $a = get_app();
+ $func = 'widget_' . trim($name);
+ if(function_exists($func))
+ return $func($args);
+}
+
+
+function comanche_region(&$a,$s) {
+
+
+ $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);
+ }
+ }
+ $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);
+ }
+ }
+
+ // 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])),$s);
+ }
+ }
+
+ return $s;
+}
+
+
+function widget_profile($args) {
+ $a = get_app();
+ $block = (((get_config('system','block_public')) && (! local_user()) && (! remote_user())) ? true : false);
+ return profile_sidebar($a->profile, $block, true);
+}
diff --git a/include/config.php b/include/config.php
index 38840f5e4..bccf0737f 100644
--- a/include/config.php
+++ b/include/config.php
@@ -24,6 +24,15 @@ function load_config($family) {
if(! array_key_exists('config_loaded',$a->config[$family])) {
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
+
+ // This is often one of the earliest database calls in the life of the page.
+ // If the DB was successfully opened, but we can't read from it,
+ // we must assume catastrophic failure of the DB. Report the system down.
+
+// if($r === false) {
+// system_unavailable();
+// }
+
if($r !== false) {
if($r) {
foreach($r as $rr) {
diff --git a/include/contact_widgets.php b/include/contact_widgets.php
index ca212796f..af05f8c9f 100644
--- a/include/contact_widgets.php
+++ b/include/contact_widgets.php
@@ -1,12 +1,27 @@
<?php /** @file */
function follow_widget() {
-
+ $a = get_app();
+ $uid =$a->channel['channel_id'];
+ $r = q("select count(*) as total from abook where abook_channel = %d and not (abook_flags & %d) ",
+ intval($uid),
+ intval(ABOOK_FLAG_SELF)
+ );
+ if($r)
+ $total_channels = $r[0]['total'];
+ $limit = service_class_fetch($uid,'total_channels');
+ if($limit !== false) {
+ $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total_channels, $limit);
+ }
+ else {
+ $abook_usage_message = '';
+ }
return replace_macros(get_markup_template('follow.tpl'),array(
'$connect' => t('Add New Connection'),
'$desc' => t('Enter the channel address'),
'$hint' => t('Example: bob@example.com, http://example.com/barbara'),
- '$follow' => t('Connect')
+ '$follow' => t('Connect'),
+ '$abook_usage_message' => $abook_usage_message
));
}
@@ -32,7 +47,7 @@ function findpeople_widget() {
'$hint' => t('Examples: Robert Morgenstein, Fishing'),
'$findthem' => t('Find'),
'$suggest' => t('Channel Suggestions'),
- '$similar' => t('Similar Interests'),
+ '$similar' => '', // FIXME and uncomment when mod/match working // t('Similar Interests'),
'$random' => t('Random Profile'),
'$inv' => t('Invite Friends')
));
@@ -70,15 +85,22 @@ function fileas_widget($baseurl,$selected = '') {
function categories_widget($baseurl,$selected = '') {
+ $a = get_app();
+
if(! feature_enabled($a->profile['profile_uid'],'categories'))
return '';
- $a = get_app();
-
$terms = array();
- $r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
+ $r = q("select distinct(term.term)
+ from term join item on term.oid = item.id
+ where item.uid = %d
+ and term.uid = item.uid
+ and term.type = %d
+ and item.author_xchan = '%s'
+ order by term.term asc",
intval($a->profile['profile_uid']),
- intval(TERM_CATEGORY)
+ intval(TERM_CATEGORY),
+ dbesc($a->profile['channel_hash'])
);
if($r && count($r)) {
foreach($r as $rr)
diff --git a/include/conversation.php b/include/conversation.php
index aade06b8a..1820a8568 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -92,8 +92,14 @@ function item_redir_and_replace_images($body, $images, $cid) {
function localize_item(&$item){
if (activity_match($item['verb'],ACTIVITY_LIKE) || activity_match($item['verb'],ACTIVITY_DISLIKE)){
-
+
+ if(! $item['object'])
+ return;
+
$obj = json_decode_plus($item['object']);
+ if((! $obj) && ($item['object'])) {
+ logger('localize_item: failed to decode object: ' . print_r($item['object'],true));
+ }
if($obj['author'] && $obj['author']['link'])
$author_link = get_rel_link($obj['author']['link'],'alternate');
@@ -162,6 +168,9 @@ function localize_item(&$item){
$item['body'] .= "\n\n\n" . '[zrl=' . chanlink_url($author_link) . '][zmg=80x80]' . $Bphoto . '[/zmg][/zrl]';
}
+ else {
+ logger('localize_item like failed: link ' . $author_link . ' name ' . $author_name . ' url ' . $item_url);
+ }
}
@@ -391,6 +400,9 @@ function visible_activity($item) {
function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
$tstart = dba_timer();
+ $t0 = $t1 = $t2 = $t3 = $t4 = $t5 = $t6 = null;
+ $content_html = '';
+ $o = '';
require_once('bbcode.php');
@@ -488,10 +500,16 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
}
- else if($mode === 'search') {
+ elseif($mode === 'search') {
$live_update_div = '<div id="live-search"></div>' . "\r\n";
}
-
+ elseif($mode === 'photos') {
+ $profile_onwer = $a->profile['profile_uid'];
+ $page_writeable = ($profile_owner == local_user());
+ $live_update_div = '<div id="live-photos"></div>' . "\r\n";
+ // for photos we've already formatted the top-level item (the photo)
+ $content_html = $a->data['photo_html'];
+ }
$page_dropping = ((local_user() && local_user() == $profile_owner) ? true : false);
@@ -614,12 +632,17 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
);
$star = false;
- $isstarred = "unstarred";
+ $isstarred = "unstarred icon-star-empty";
$lock = false;
$likebuttons = false;
$shareable = false;
+ $verified = (($item['item_flags'] & ITEM_VERIFIED) ? t('Message is verified') : '');
+ $unverified = '';
+
+
+
$tags=array();
$terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN));
if(count($terms))
@@ -633,6 +656,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
$tmp_item = array(
'template' => $tpl,
'toplevel' => 'toplevel_item',
+ 'mode' => $mode,
'id' => (($preview) ? 'P0' : $item['item_id']),
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, $profile_url),
'profile_url' => $profile_link,
@@ -646,6 +670,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
'tags' => $tags,
'hashtags' => $hashtags,
'mentions' => $mentions,
+ 'verified' => $verified,
+ 'unverified' => $unverified,
'txt_cats' => t('Categories:'),
'txt_folders' => t('Filed under:'),
'has_cats' => ((count($categories)) ? 'true' : ''),
@@ -712,6 +738,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
$threads = array();
foreach($items as $item) {
+ // Check for any blocked authors
+
if($arr_blocked) {
$blocked = false;
foreach($arr_blocked as $b) {
@@ -724,6 +752,18 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
continue;
}
+ // Check all the kids too
+
+ if($arr_blocked && $item['children']) {
+ for($d = 0; $d < count($item['children']); $d ++) {
+ foreach($arr_blocked as $b) {
+ if(($b) && ($item['children'][$d]['author_xchan'] == $b))
+ $item['children'][$d]['author_blocked'] = true;
+ }
+ }
+ }
+
+
// Can we put this after the visibility check?
like_puller($a,$item,$alike,'like');
@@ -781,8 +821,9 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') {
// logger('nouveau: ' . print_r($threads,true));
- $o = replace_macros($page_template, array(
+ $o .= replace_macros($page_template, array(
'$baseurl' => $a->get_baseurl($ssl_state),
+ '$photo_item' => $content_html,
'$live_update' => $live_update_div,
'$remove' => t('remove'),
'$mode' => $mode,
@@ -843,6 +884,12 @@ function item_photo_menu($item){
$ssl_state = false;
+ $sub_link="";
+ $poke_link="";
+ $contact_url="";
+ $pm_url="";
+ $vsrc_link = "";
+
if(local_user()) {
$ssl_state = true;
if(! count($a->contacts))
@@ -851,14 +898,11 @@ function item_photo_menu($item){
$channel_hash = (($channel) ? $channel['channel_hash'] : '');
}
- $sub_link="";
- $poke_link="";
- $contact_url="";
- $pm_url="";
-
- if((local_user()) && local_user() == $item['uid'] && $item['parent'] == $item['id']
- && $channel && ($channel_hash != $item['author_xchan'])) {
- $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
+ if((local_user()) && local_user() == $item['uid']) {
+ $vsrc_link = $a->get_baseurl() . '/viewsrc/' . $item['id'];
+ if($item['parent'] == $item['id'] && $channel && ($channel_hash != $item['author_xchan'])) {
+ $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
+ }
}
$profile_link = z_root() . "/chanview/?f=&hash=" . $item['author_xchan'];
@@ -877,11 +921,12 @@ function item_photo_menu($item){
}
$menu = Array(
+ t("View Source") => $vsrc_link,
t("Follow Thread") => $sub_link,
t("View Status") => $status_link,
t("View Profile") => $profile_link,
t("View Photos") => $photos_link,
- t("Network Posts") => $posts_link,
+ t("Matrix Activity") => $posts_link,
t("Edit Contact") => $contact_url,
t("Send PM") => $pm_url,
t("Poke") => $poke_link
@@ -976,9 +1021,34 @@ function status_editor($a,$x,$popup=false) {
$geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
$plaintext = true;
+
if(feature_enabled(local_user(),'richtext'))
$plaintext = 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'] . '" />';
+ }
+
+ $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'] . '" />';
+ }
+
+
+
+ $webpage = ((x($x,'webpage')) ? $x['webpage'] : '');
+
$tpl = get_markup_template('jot-header.tpl');
$a->page['htmlhead'] .= replace_macros($tpl, array(
@@ -1009,7 +1079,7 @@ function status_editor($a,$x,$popup=false) {
'$return_path' => $a->query_string,
'$action' => $a->get_baseurl(true) . '/item',
'$share' => (x($x,'button') ? $x['button'] : t('Share')),
- '$webpage' => (x($x,'webpage') ? '1' : ''),
+ '$webpage' => $webpage,
'$placeholdpagetitle' => t('Page link title'),
'$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''),
'$upload' => t('Upload photo'),
@@ -1028,7 +1098,7 @@ function status_editor($a,$x,$popup=false) {
'$shortnoloc' => t('clear location'),
'$title' => "",
'$placeholdertitle' => t('Set title'),
- '$catsenabled' => ((feature_enabled($x['profile_uid'],'categories')) ? 'categories' : ''),
+ '$catsenabled' => ((feature_enabled($x['profile_uid'],'categories') && (! $webpage)) ? 'categories' : ''),
'$category' => "",
'$placeholdercategory' => t('Categories (comma-separated list)'),
'$wait' => t('Please wait'),
@@ -1046,6 +1116,8 @@ function status_editor($a,$x,$popup=false) {
'$emtitle' => t('Example: bob@example.com, mary@example.com'),
'$lockstate' => $x['lockstate'],
'$acl' => $x['acl'],
+ '$mimeselect' => $mimeselect,
+ '$layoutselect' => $layoutselect,
'$showacl' => ((array_key_exists('showacl',$x)) ? $x['showacl'] : 'yes'),
'$bang' => $x['bang'],
'$profile_uid' => $x['profile_uid'],
@@ -1125,6 +1197,7 @@ function conv_sort($arr,$order) {
elseif(stristr($order,'ascending'))
usort($parents,'sort_thr_created_rev');
+
if(count($parents))
foreach($parents as $i=>$_x)
$parents[$i]['children'] = get_item_children($arr, $_x);
@@ -1200,12 +1273,21 @@ function render_location_default($item) {
function prepare_page($item) {
+
+ $a = get_app();
+ $naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
+ if(array_key_exists('webpage',$a->layout) && array_key_exists('authored',$a->layout['webpage'])) {
+ if($a->layout['webpage']['authored'] === 'none')
+ $naked = 1;
+ // ... other possible options
+ }
+
return replace_macros(get_markup_template('page_display.tpl'),array(
- '$author' => $item['author']['xchan_name'],
- '$auth_url' => $item['author']['xchan_url'],
- '$date' => datetime_convert('UTC',date_default_timezone_get(),$item['created'],'Y-m-d H:i'),
+ '$author' => (($naked) ? '' : $item['author']['xchan_name']),
+ '$auth_url' => (($naked) ? '' : $item['author']['xchan_url']),
+ '$date' => (($naked) ? '' : datetime_convert('UTC',date_default_timezone_get(),$item['created'],'Y-m-d H:i')),
'$title' => smilies(bbcode($item['title'])),
- '$body' => smilies(bbcode($item['body']))
+ '$body' => prepare_text($item['body'],$item['mimetype'])
));
}
diff --git a/include/dba/dba_mysqli.php b/include/dba/dba_mysqli.php
index f1a50cc3f..19907705b 100755
--- a/include/dba/dba_mysqli.php
+++ b/include/dba/dba_mysqli.php
@@ -70,7 +70,7 @@ class dba_mysqli extends dba_driver {
function close() {
if($this->db)
$this->db->close();
- $this->connected = flase;
+ $this->connected = false;
}
} \ No newline at end of file
diff --git a/include/deliver.php b/include/deliver.php
index 547d009cc..b1314ce39 100644
--- a/include/deliver.php
+++ b/include/deliver.php
@@ -26,7 +26,7 @@ function deliver_run($argv, $argc) {
// If there is no outq_msg, this is a refresh_all message which does not require local handling
if($r[0]['outq_msg']) {
$msg = array('body' => json_encode(array('pickup' => array(array('notify' => json_decode($r[0]['outq_notify'],true),'message' => json_decode($r[0]['outq_msg'],true))))));
- zot_import($msg);
+ zot_import($msg,z_root());
$r = q("delete from outq where outq_hash = '%s' limit 1",
dbesc($argv[$x])
);
diff --git a/include/dir_fns.php b/include/dir_fns.php
index 0b678fd91..585121434 100644
--- a/include/dir_fns.php
+++ b/include/dir_fns.php
@@ -13,7 +13,7 @@ function sync_directories($dirmode) {
return;
$r = q("select * from site where (site_flags & %d) and site_url != '%s'",
- intval(DIRECTORY_MODE_PRIMARY),
+ intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root())
);
@@ -34,21 +34,79 @@ function sync_directories($dirmode) {
dbesc($r[0]['site_directory'])
);
+ $r = q("select * from site where (site_flags & %d) and site_url != '%s'",
+ intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
+ dbesc(z_root())
+ );
+
}
+ if(! $r)
+ return;
+ foreach($r as $rr) {
+ if(! $rr['site_directory'])
+ continue;
+ $x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($rr['site_sync']));
+ if(! $x['success'])
+ continue;
+ $j = json_decode($x['body'],true);
+ if((! $j['transactions']) || (! is_array($j['transactions'])))
+ continue;
+
+ q("update site set site_sync = '%s' where site_url = '%s' limit 1",
+ dbesc(datetime_convert()),
+ dbesc($rr['site_url'])
+ );
+ logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA);
+
+ if(count($j['transactions'])) {
+ foreach($j['transactions'] as $t) {
+ $r = q("select * from updates where ud_guid = '%s' limit 1",
+ dbesc($t['transaction_id'])
+ );
+ if($r)
+ continue;
+ $ud_flags = 0;
+ if(is_array($t['flags']) && in_array('deleted',$t['flags']))
+ $ud_flags |= UPDATE_FLAGS_DELETED;
+ $z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
+ values ( '%s', '%s', '%s', '%d, '%s' ) ",
+ dbesc($t['hash']),
+ dbesc($t['transaction_id']),
+ dbesc($t['timestamp']),
+ intval($ud_flags),
+ dbesc($t['address'])
+ );
+ }
+ }
+ }
+}
+function update_directory_entry($ud) {
+ logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
+ if($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
+ $x = zot_finger($ud['ud_addr'],'');
+ if($x['success']) {
+ $j = json_decode($x['body'],true);
+ $y = import_xchan($j,0);
+ }
+ else {
+ $r = q("update updates set ud_last = '%s' where ud_addr = '%s'",
+ dbesc(datetime_convert()),
+ dbesc($ud['ud_addr'])
+ );
+ }
+ }
}
-
-
function syncdirs($uid) {
logger('syncdirs', LOGGER_DEBUG);
diff --git a/include/enotify.php b/include/enotify.php
index a15e42b73..147023f41 100644
--- a/include/enotify.php
+++ b/include/enotify.php
@@ -51,9 +51,9 @@ function notification($params) {
$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'])) {
- require_once('include/conversation.php');
// localize_item() alters the original item so make a copy first
$i = $params['item'];
logger('calling localize');
@@ -89,6 +89,11 @@ function notification($params) {
if($params['type'] == NOTIFY_COMMENT) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
+ // 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_id = $params['parent'];
// Check to see if there was already a notify for this post.
@@ -379,11 +384,9 @@ function notification($params) {
logger('notification: sending notification email');
- $textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n"), "\n",
- $body))),ENT_QUOTES,'UTF-8'));
+ $textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8'));
- $htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r","\\n\\n" ,"\\n"),
- "<br />\n",$body))), ENT_QUOTES,'UTF-8');
+ $htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body))), ENT_QUOTES,'UTF-8');
// use $_SESSION['zid_override'] to force zid() to use
diff --git a/include/event.php b/include/event.php
index 29ada2e96..7873de1ef 100644
--- a/include/event.php
+++ b/include/event.php
@@ -360,7 +360,8 @@ function event_store($arr) {
}
- $item_id = item_store($item_arr);
+ $res = item_store($item_arr);
+ $item_id = $res['item_id'];
call_hooks("event_created", $event['id']);
diff --git a/include/features.php b/include/features.php
index 757f719df..9950039c0 100644
--- a/include/features.php
+++ b/include/features.php
@@ -27,8 +27,7 @@ function get_features() {
//FIXME - needs a description, but how the hell do we explain this to normals?
array('sendzid', t('Extended Identity Sharing'), t(' ')),
array('expert', t('Expert Mode'), t('Enable Expert Mode to provide advanced configuration options')),
-
-
+ array('premium_channel', t('Premium Channel'), t('Allows you to set restrictions and terms on those that connect with your channel')),
),
// Post composition
@@ -36,6 +35,7 @@ function get_features() {
t('Post Composition Features'),
array('richtext', t('Richtext Editor'), t('Enable richtext editor')),
array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them')),
+ array('channel_sources', t('Channel Sources'), t('Automatically import channel content from other channels or feeds')),
),
// Network Tools
diff --git a/include/follow.php b/include/follow.php
index ce550b07f..10bcddf2b 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -11,7 +11,7 @@
require_once('include/zot.php');
-function new_contact($uid,$url,$channel,$interactive = false) {
+function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) {
$result = array('success' => false,'message' => '');
@@ -60,6 +60,11 @@ function new_contact($uid,$url,$channel,$interactive = false) {
return $result;
}
+ // Premium channel, set confirm before callback to avoid recursion
+
+ if(array_key_exists('connect_url',$j) && (! $confirm))
+ goaway(zid($j['connect_url']));
+
// check service class limits
diff --git a/include/friendica_smarty.php b/include/friendica_smarty.php
index 1e8ef5406..12a789c9a 100755
--- a/include/friendica_smarty.php
+++ b/include/friendica_smarty.php
@@ -49,7 +49,7 @@ class FriendicaSmartyEngine implements ITemplateEngine {
public function __construct(){
$a = get_app();
- $basecompiledir = $a->config['system']['smarty3_folder'];
+ $basecompiledir = ((array_key_exists('smarty3_folder',$a->config['system'])) ? $a->config['system']['smarty3_folder'] : '');
if (!$basecompiledir) $basecompiledir = dirname(__dir__)."/view/tpl/smarty3";
if (!is_dir($basecompiledir)) {
echo "<b>ERROR:</b> folder <tt>$basecompiledir</tt> does not exist."; killme();
diff --git a/include/identity.php b/include/identity.php
index 5f210c456..d6b6735f6 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -7,7 +7,7 @@ require_once('include/crypto.php');
function identity_check_service_class($account_id) {
$ret = array('success' => false, $message => '');
- $r = q("select count(channel_id) as total from channel were channel_account_id = %d ",
+ $r = q("select count(channel_id) as total from channel where channel_account_id = %d ",
intval($account_id)
);
if(! ($r && count($r))) {
@@ -48,7 +48,7 @@ function validate_channelname($name) {
function create_dir_account() {
- create_account(array(
+ create_identity(array(
'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required
'nickname' => 'dir',
'name' => 'Directory',
@@ -80,8 +80,11 @@ function create_identity($arr) {
$ret['message'] = t('No account identifier');
return $ret;
}
-
- $nick = trim($arr['nickname']);
+ $ret=identity_check_service_class($arr['account_id']);
+ if (!$ret['success']) {
+ return $ret;
+ }
+ $nick = mb_strtolower(trim($arr['nickname']));
$name = escape_tags($arr['name']);
$pageflags = ((x($arr,'pageflags')) ? intval($arr['pageflags']) : PAGE_NORMAL);
@@ -182,7 +185,7 @@ function create_identity($arr) {
$newuid = $ret['channel']['channel_id'];
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
+ $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
dbesc($hash),
dbesc($guid),
dbesc($sig),
@@ -192,6 +195,7 @@ function create_identity($arr) {
dbesc($a->get_baseurl() . "/photo/profile/s/{$newuid}"),
dbesc($ret['channel']['channel_address'] . '@' . get_app()->get_hostname()),
dbesc(z_root() . '/channel/' . $ret['channel']['channel_address']),
+ dbesc(z_root() . '/follow?f=&url=%s'),
dbesc($ret['channel']['channel_name']),
dbesc('zot'),
dbesc(datetime_convert()),
diff --git a/include/items.php b/include/items.php
index 10bdcb38f..800684ae2 100755
--- a/include/items.php
+++ b/include/items.php
@@ -18,13 +18,37 @@ function collect_recipients($item,&$private) {
require_once('include/group.php');
+ if($item['item_private'])
+ $private = true;
+
if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) {
$allow_people = expand_acl($item['allow_cid']);
$allow_groups = expand_groups(expand_acl($item['allow_gid']));
+
+ $recipients = array_unique(array_merge($allow_people,$allow_groups));
+
+ // if you specifically deny somebody but haven't allowed anybody, we'll allow everybody in your
+ // address book minus the denied connections. The post is still private and can't be seen publicly
+ // as that would allow the denied person to see the post by logging out.
+
+ if((! $item['allow_cid']) && (! $item['allow_gid'])) {
+ $r = q("select * from abook where abook_channel = %d and not (abook_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d)",
+ intval($item['uid']),
+ intval(ABOOK_FLAG_SELF),
+ intval(ABOOK_FLAG_PENDING),
+ intval(ABOOK_FLAG_ARCHIVED)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ $recipients[] = $rr['abook_xchan'];
+ }
+ }
+ }
+
$deny_people = expand_acl($item['deny_cid']);
$deny_groups = expand_groups(expand_acl($item['deny_gid']));
- $recipients = array_unique(array_merge($allow_people,$allow_groups));
$deny = array_unique(array_merge($deny_people,$deny_groups));
$recipients = array_diff($recipients,$deny);
$private = true;
@@ -59,24 +83,44 @@ function collect_recipients($item,&$private) {
}
-
+/**
+ * @function can_comment_on_post($observer_xchan,$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.
+ * 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()
+ */
function can_comment_on_post($observer_xchan,$item) {
+
+// logger('can_comment_on_post: comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG);
+
if(! $observer_xchan)
return false;
if($item['comment_policy'] === 'none')
return false;
+ if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan'])
+ return true;
switch($item['comment_policy']) {
case 'self':
if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan'])
return true;
break;
case 'public':
+ // We don't allow public comments yet, until a policy
+ // for dealing with anonymous comments is in place with
+ // a means to moderate comments. Until that time, return
+ // false.
return false;
break;
case 'contacts':
case '':
- if(($item['owner']['abook_xchan']) && ($item['owner']['abook_their_perms'] & PERMS_W_COMMENT))
- return true;
+ if(array_key_exists('owner',$item)) {
+ if(($item['owner']['abook_xchan']) && ($item['owner']['abook_their_perms'] & PERMS_W_COMMENT))
+ return true;
+ }
break;
default:
break;
@@ -193,7 +237,9 @@ function post_activity_item($arr) {
}
- $post_id = item_store($arr);
+ $post = item_store($arr);
+ if($post['result'])
+ $post_id = $post['item_id'];
if($post_id) {
$arr['id'] = $post_id;
@@ -220,16 +266,18 @@ function get_public_feed($channel,$params) {
$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'] : '0000-00-00 00:00:00');
- $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['type'] = ((x($params,'type')) ? $params['type'] : 'xml');
+ $params['begin'] = ((x($params,'begin')) ? $params['begin'] : '0000-00-00 00:00:00');
+ $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);
switch($params['type']) {
case 'json':
@@ -250,9 +298,15 @@ function get_feed_for($channel, $observer_hash, $params) {
if(! channel)
http_status_exit(401);
- if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream'))
- http_status_exit(403);
+ 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['begin'],
@@ -260,6 +314,7 @@ function get_feed_for($channel, $observer_hash, $params) {
'start' => $params['start'], // FIXME
'records' => $params['records'], // FIXME
'direction' => $params['direction'], // FIXME
+ 'pages' => $params['pages'],
'order' => 'post'
), $channel, $observer_hash, CLIENT_MODE_NORMAL, get_app()->module);
@@ -491,6 +546,7 @@ function title_is_body($title, $body) {
function get_item_elements($x) {
+// logger('get_item_elements');
$arr = array();
$arr['body'] = (($x['body']) ? htmlentities($x['body'],ENT_COMPAT,'UTF-8',false) : '');
@@ -524,6 +580,9 @@ function get_item_elements($x) {
$arr['obj_type'] = (($x['object_type']) ? htmlentities($x['object_type'], ENT_COMPAT,'UTF-8',false) : '');
$arr['tgt_type'] = (($x['target_type']) ? htmlentities($x['target_type'], ENT_COMPAT,'UTF-8',false) : '');
$arr['comment_policy'] = (($x['comment_scope']) ? htmlentities($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts');
+
+ $arr['sig'] = (($x['signature']) ? htmlentities($x['signature'], ENT_COMPAT,'UTF-8',false) : '');
+
$arr['object'] = activity_sanitise($x['object']);
$arr['target'] = activity_sanitise($x['target']);
@@ -535,18 +594,6 @@ function get_item_elements($x) {
$arr['item_flags'] = 0;
- // if it's a private post, encrypt it in the DB.
- // We have to do that here because we need to cleanse the input and prevent bad stuff from getting in,
- // and we need plaintext to do that.
-
- if(intval($arr['item_private'])) {
- $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED;
- $key = get_config('system','pubkey');
- if($arr['title'])
- $arr['title'] = json_encode(aes_encapsulate($arr['title'],$key));
- if($arr['body'])
- $arr['body'] = json_encode(aes_encapsulate($arr['body'],$key));
- }
if(array_key_exists('flags',$x) && in_array('deleted',$x['flags']))
$arr['item_restrict'] = ITEM_DELETED;
@@ -573,6 +620,31 @@ function get_item_elements($x) {
}
+ if($arr['sig']) {
+ $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
+ dbesc($arr['author_xchan'])
+ );
+ if($r && rsa_verify($x['body'],base64url_decode($arr['sig']),$r[0]['xchan_pubkey']))
+ $arr['item_flags'] |= ITEM_VERIFIED;
+ else
+ logger('get_item_elements: message verification failed.');
+ }
+
+
+ // if it's a private post, encrypt it in the DB.
+ // We have to do that here because we need to cleanse the input and prevent bad stuff from getting in,
+ // and we need plaintext to do that.
+
+ if(intval($arr['item_private'])) {
+ $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED;
+ $key = get_config('system','pubkey');
+ if($arr['title'])
+ $arr['title'] = json_encode(aes_encapsulate($arr['title'],$key));
+ if($arr['body'])
+ $arr['body'] = json_encode(aes_encapsulate($arr['body'],$key));
+ }
+
+
return $arr;
}
@@ -601,7 +673,7 @@ function encode_item($item) {
$x = array();
$x['type'] = 'activity';
- logger('encode_item: ' . print_r($item,true));
+// logger('encode_item: ' . print_r($item,true));
$r = q("select channel_r_stream, channel_w_comment from channel where channel_id = %d limit 1",
intval($item['uid'])
@@ -652,6 +724,7 @@ function encode_item($item) {
$x['permalink'] = $item['plink'];
$x['location'] = $item['location'];
$x['longlat'] = $item['coord'];
+ $x['signature'] = $item['sig'];
$x['owner'] = encode_item_xchan($item['owner']);
$x['author'] = encode_item_xchan($item['author']);
@@ -675,6 +748,8 @@ function encode_item($item) {
if($item['term'])
$x['tags'] = encode_item_terms($item['term']);
+ logger('encode_item: ' . print_r($x,true));
+
return $x;
}
@@ -1246,14 +1321,9 @@ function get_atom_elements($feed,$item) {
$res['object'] .= '<orig>' . xmlify($body) . '</orig>' . "\n";
if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
- $body = html2bb_video($body);
-
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.DefinitionImpl', null);
-
- $purifier = new HTMLPurifier($config);
- $body = $purifier->purify($body);
+ $body = purify_html($body);
$body = html2bbcode($body);
+
}
$res['object'] .= '<content>' . $body . '</content>' . "\n";
@@ -1284,13 +1354,7 @@ function get_atom_elements($feed,$item) {
$res['target'] .= '<orig>' . xmlify($body) . '</orig>' . "\n";
if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
- $body = html2bb_video($body);
-
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.DefinitionImpl', null);
-
- $purifier = new HTMLPurifier($config);
- $body = $purifier->purify($body);
+ $body = purify_html($body);
$body = html2bbcode($body);
}
@@ -1329,6 +1393,7 @@ function get_atom_elements($feed,$item) {
$arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
call_hooks('parse_atom', $arr);
+ logger('get_atom_elements: ' . print_r($res,true));
return $res;
}
@@ -1356,9 +1421,23 @@ function encode_rel_links($links) {
function item_store($arr,$allow_exec = false) {
+ $ret = array('result' => false, 'item_id' => 0);
+
if(! $arr['uid']) {
logger('item_store: no uid');
- return 0;
+ $ret['message'] = 'No uid.';
+ return ret;
+ }
+
+ // If a page layout is provided, ensure it exists and belongs to us.
+
+ if(array_key_exists('layout_mid',$arr) && $arr['layout_mid']) {
+ $l = q("select item_restrict from item where mid = '%s' and uid = %d limit 1",
+ dbesc($arr['layout_mid']),
+ intval($arr['uid'])
+ );
+ if((! $l) || (! ($l[0]['item_restrict'] & ITEM_PDL)))
+ unset($arr['layout_mid']);
}
// Don't let anybody set these, either intentionally or accidentally
@@ -1372,7 +1451,8 @@ function item_store($arr,$allow_exec = false) {
if(($arr['mimetype'] == 'application/x-php') && (! $allow_exec)) {
logger('item_store: php mimetype but allow_exec is denied.');
- return 0;
+ $ret['message'] = 'exec denied.';
+ return $ret;
}
@@ -1385,21 +1465,27 @@ function item_store($arr,$allow_exec = false) {
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? trim($arr['deny_gid']) : '');
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 );
$arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 );
-
- // this is a bit messy - we really need an input filter chain that temporarily undoes obscuring
- if($arr['mimetype'] != 'text/html' && $arr['mimetype'] != 'application/x-php') {
- if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
- $arr['body'] = escape_tags($arr['body']);
- if((strpos($arr['title'],'<') !== false) || (strpos($arr['title'],'>') !== false))
- $arr['title'] = escape_tags($arr['title']);
- }
+ $arr['title'] = escape_tags($arr['title']);
+
// only detect language if we have text content, and if the post is private but not yet
// obscured, make it so.
if(! ($arr['item_flags'] & ITEM_OBSCURED)) {
+
$arr['lang'] = detect_language($arr['body']);
+ // apply the input filter here - if it is obscured it has been filtered already
+ $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']);
+
+
+ if(local_user() && (! $arr['sig'])) {
+ $channel = get_app()->get_channel();
+ if($channel['channel_hash'] === $arr['author_xchan']) {
+ $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
+ $arr['item_flags'] |= ITEM_VERIFIED;
+ }
+ }
$allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
@@ -1408,7 +1494,8 @@ function item_store($arr,$allow_exec = false) {
call_hooks('item_translate', $translate);
if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
- return;
+ $ret['message'] = 'language not accepted';
+ return $ret;
}
$arr = $translate['item'];
}
@@ -1423,15 +1510,10 @@ function item_store($arr,$allow_exec = false) {
}
- if($arr['object'])
- logger('item_store: input object: ' . print_r($arr['object'],true), LOGGER_DATA);
-
if((x($arr,'object')) && is_array($arr['object'])) {
activity_sanitise($arr['object']);
- logger('item_store: sanitised object: ' . print_r($arr['object'],true), LOGGER_DATA);
$arr['object'] = json_encode($arr['object']);
- logger('item_store: encoded object: ' . print_r($arr['object'],true), LOGGER_DATA);
}
if((x($arr,'target')) && is_array($arr['target'])) {
@@ -1554,7 +1636,8 @@ function item_store($arr,$allow_exec = false) {
}
else {
logger('item_store: item parent was not found - ignoring item');
- return 0;
+ $ret['message'] = 'parent not found.';
+ return $ret;
}
}
@@ -1567,15 +1650,17 @@ function item_store($arr,$allow_exec = false) {
intval($arr['uid'])
);
if($r) {
- logger('item-store: duplicate item ignored. ' . print_r($arr,true));
- return 0;
+ logger('item_store: duplicate item ignored. ' . print_r($arr,true));
+ $ret['message'] = 'duplicate post.';
+ return $ret;
}
call_hooks('post_remote',$arr);
if(x($arr,'cancel')) {
logger('item_store: post cancelled by plugin.');
- return 0;
+ $ret['message'] = 'cancelled.';
+ return $ret;
}
// pull out all the taxonomy stuff for separate storage
@@ -1598,18 +1683,21 @@ function item_store($arr,$allow_exec = false) {
// find the item we just created
- $r = q("SELECT `id` FROM `item` WHERE `mid` = '%s' AND `uid` = %d ORDER BY `id` ASC ",
+ $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d ORDER BY `id` ASC ",
$arr['mid'], // already dbesc'd
intval($arr['uid'])
);
+
if($r && count($r)) {
$current_post = $r[0]['id'];
+ $arr = $r[0]; // This will gives us a fresh copy of what's now in the DB and undo the db escaping, which really messes up the notifications
logger('item_store: created item ' . $current_post, LOGGER_DEBUG);
}
else {
- logger('item_store: could not locate created item');
- return 0;
+ logger('item_store: could not locate stored item');
+ $ret['message'] = 'unable to retrieve.';
+ return $ret;
}
if(count($r) > 1) {
logger('item_store: duplicated post occurred. Removing duplicates.');
@@ -1641,6 +1729,7 @@ function item_store($arr,$allow_exec = false) {
intval($current_post)
);
+ // These are probably redundant now that we've queried the just stored post
$arr['id'] = $current_post;
$arr['parent'] = $parent_id;
$arr['allow_cid'] = $allow_cid;
@@ -1681,82 +1770,113 @@ function item_store($arr,$allow_exec = false) {
send_status_notifications($current_post,$arr);
tag_deliver($arr['uid'],$current_post);
+ $ret['success'] = true;
+ $ret['item_id'] = $current_post;
- return $current_post;
+ return $ret;
}
function item_store_update($arr,$allow_exec = false) {
+ $ret = array('result' => false, 'item_id' => 0);
if(! intval($arr['uid'])) {
logger('item_store_update: no uid');
- return 0;
+ $ret['message'] = 'no uid.';
+ return $ret;
}
if(! intval($arr['id'])) {
logger('item_store_update: no id');
- return 0;
+ $ret['message'] = 'no id.';
+ return $ret;
}
$orig_post_id = $arr['id'];
- unset($arr['id']);
$uid = $arr['uid'];
- unset($arr['uid']);
-
- $arr['lang'] = detect_language($arr['body']);
+ $orig = q("select * from item where id = %d and uid = %d limit 1",
+ intval($orig_post_id),
+ intval($uid)
+ );
+ if(! $orig) {
+ logger('item_store_update: original post not found: ' . $orig_post_id);
+ $ret['message'] = 'no original';
+ return $ret;
+ }
+
+ if($orig[0]['item_flags'] & ITEM_VERIFIED)
+ $orig[0]['item_flags'] = $orig[0]['item_flags'] ^ ITEM_VERIFIED;
- $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
-
- if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
- $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
- call_hooks('item_translate', $translate);
- if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
- logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
- return;
- }
- $arr = $translate['item'];
- }
+ $arr['item_flags'] = intval($arr['item_flags']) | $orig[0]['item_flags'];
+ $arr['item_restrict'] = intval($arr['item_restrict']) | $orig[0]['item_restrict'];
+ unset($arr['id']);
+ unset($arr['uid']);
+ if(array_key_exists('edit',$arr))
+ unset($arr['edit']);
$arr['mimetype'] = ((x($arr,'mimetype')) ? notags(trim($arr['mimetype'])) : 'text/bbcode');
if(($arr['mimetype'] == 'application/x-php') && (! $allow_exec)) {
logger('item_store: php mimetype but allow_exec is denied.');
- return 0;
+ $ret['message'] = 'exec denied.';
+ return $ret;
}
+ if(! ($arr['item_flags'] & ITEM_OBSCURED)) {
- // Shouldn't happen but we want to make absolutely sure it doesn't leak from a plugin.
+ $arr['lang'] = detect_language($arr['body']);
+ // apply the input filter here - if it is obscured it has been filtered already
+ $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']);
+
+ if(local_user() && (! $arr['sig'])) {
+ $channel = get_app()->get_channel();
+ if($channel['channel_hash'] === $arr['author_xchan']) {
+ $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
+ $arr['item_flags'] |= ITEM_VERIFIED;
+ }
+ }
- if($arr['mimetype'] != 'text/html' && $arr['mimetype'] != 'application/x-php') {
+ $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
+
+ if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
+ $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
+ call_hooks('item_translate', $translate);
+ if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
+ logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
+ $ret['message'] = 'language not accepted';
+ return $ret;
+ }
+ $arr = $translate['item'];
+ }
+ if($arr['item_private']) {
+ $key = get_config('system','pubkey');
+ $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED;
+ if($arr['title'])
+ $arr['title'] = json_encode(aes_encapsulate($arr['title'],$key));
+ if($arr['body'])
+ $arr['body'] = json_encode(aes_encapsulate($arr['body'],$key));
+ }
- if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
- $arr['body'] = escape_tags($arr['body']);
+ }
- if((x($arr,'object')) && is_array($arr['object'])) {
- activity_sanitise($arr['object']);
- $arr['object'] = json_encode($arr['object']);
- }
- if((x($arr,'target')) && is_array($arr['target'])) {
- activity_sanitise($arr['target']);
- $arr['target'] = json_encode($arr['target']);
- }
+ if((x($arr,'object')) && is_array($arr['object'])) {
+ activity_sanitise($arr['object']);
+ $arr['object'] = json_encode($arr['object']);
+ }
- if((x($arr,'attach')) && is_array($arr['attach'])) {
- activity_sanitise($arr['attach']);
- $arr['attach'] = json_encode($arr['attach']);
- }
+ if((x($arr,'target')) && is_array($arr['target'])) {
+ activity_sanitise($arr['target']);
+ $arr['target'] = json_encode($arr['target']);
+ }
+
+ if((x($arr,'attach')) && is_array($arr['attach'])) {
+ activity_sanitise($arr['attach']);
+ $arr['attach'] = json_encode($arr['attach']);
}
- $orig = q("select * from item where id = %d and uid = %d limit 1",
- intval($orig_post_id),
- intval($uid)
- );
- if(! $orig) {
- logger('item_store_update: original post not found: ' . $orig_post_id);
- return 0;
- }
+
unset($arr['aid']);
unset($arr['mid']);
@@ -1774,13 +1894,13 @@ function item_store_update($arr,$allow_exec = false) {
$arr['received'] = datetime_convert();
$arr['changed'] = datetime_convert();
$arr['title'] = ((x($arr,'title')) ? notags(trim($arr['title'])) : '');
- $arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : '');
- $arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : '');
- $arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : '');
- $arr['obj_type'] = ((x($arr,'obj_type')) ? notags(trim($arr['obj_type'])) : '');
- $arr['object'] = ((x($arr,'object')) ? trim($arr['object']) : '');
- $arr['tgt_type'] = ((x($arr,'tgt_type')) ? notags(trim($arr['tgt_type'])) : '');
- $arr['target'] = ((x($arr,'target')) ? trim($arr['target']) : '');
+ $arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : $orig[0]['location']);
+ $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['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']);
$arr['allow_cid'] = ((x($arr,'allow_cid')) ? trim($arr['allow_cid']) : $orig[0]['allow_cid']);
$arr['allow_gid'] = ((x($arr,'allow_gid')) ? trim($arr['allow_gid']) : $orig[0]['allow_gid']);
@@ -1788,17 +1908,20 @@ function item_store_update($arr,$allow_exec = false) {
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? trim($arr['deny_gid']) : $orig[0]['deny_gid']);
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : $orig[0]['item_private']);
$arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : '');
- $arr['attach'] = ((x($arr,'attach')) ? notags(trim($arr['attach'])) : '');
- $arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : '');
- $arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict']) : $orig[0]['item_restrict'] );
- $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : $orig[0]['item_flags'] );
+ $arr['attach'] = ((x($arr,'attach')) ? notags(trim($arr['attach'])) : $orig[0]['attach']);
+ $arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : $orig[0]['app']);
+// $arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict']) : $orig[0]['item_restrict'] );
+// $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : $orig[0]['item_flags'] );
+ $arr['sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
+ $arr['layout_mid'] = ((x($arr,'layout_mid')) ? dbesc($arr['layout_mid']) : $orig[0]['layout_mid'] );
call_hooks('post_remote_update',$arr);
if(x($arr,'cancel')) {
logger('item_store_update: post cancelled by plugin.');
- return 0;
+ $ret['message'] = 'cancelled.';
+ return $ret;
}
// pull out all the taxonomy stuff for separate storage
@@ -1826,7 +1949,8 @@ function item_store_update($arr,$allow_exec = false) {
logger('item_store_update: updated item ' . $orig_post_id, LOGGER_DEBUG);
else {
logger('item_store_update: could not update item');
- return 0;
+ $ret['message'] = 'DB update failed.';
+ return $ret;
}
$r = q("delete from term where oid = %d and otype = %d",
@@ -1855,8 +1979,10 @@ function item_store_update($arr,$allow_exec = false) {
send_status_notifications($orig_post_id,$arr);
tag_deliver($uid,$orig_post_id);
+ $ret['success'] = true;
+ $ret['item_id'] = $orig_post_id;
- return $orig_post_id;
+ return $ret;
}
@@ -1993,6 +2119,12 @@ function tag_deliver($uid,$item_id) {
logger('tag_deliver: tag permission denied for ' . $u[0]['channel_address']);
}
+
+ $union = check_item_source($uid,$item);
+ if($union)
+ logger('check_item_source returns true');
+
+
// This might be a followup by the original post author to a tagged forum
// If so setup a second delivery chain
@@ -2003,8 +2135,13 @@ function tag_deliver($uid,$item_id) {
intval($item['parent']),
intval($uid)
);
- if(($x) && ($x[0]['item_flags'] & ITEM_UPLINK) && ($x[0]['author_xchan'] == $item['author_xchan'])) {
- logger('tag_deliver: creating second delivery chain for owner comment.');
+
+// issue #59
+// FIXME - check security on post and allowed senders, right now we just allow it. The author *may* be foreign and the original owner is lost on our copy of the post. So this could be very hard to verify. For instance what happens if the top-level post was a wall-to-wall?
+// if(($x) && ($x[0]['item_flags'] & ITEM_UPLINK) && ($x[0]['author_xchan'] == $item['author_xchan'])) {
+ if(($x) && ($x[0]['item_flags'] & ITEM_UPLINK)) {
+// logger('tag_deliver: creating second delivery chain for owner comment.');
+ logger('tag_deliver: creating second delivery chain for comment to tagged post.');
// now 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
@@ -2054,42 +2191,44 @@ function tag_deliver($uid,$item_id) {
intval(ITEM_MENTIONSME),
intval($item_id)
);
- }
- else
- return;
- // At this point we've determined that the person receiving this post was mentioned in it.
- // Now let's check if this mention was inside a reshare so we don't spam a forum
+ // At this point we've determined that the person receiving this post was mentioned in it or it is a union.
+ // Now let's check if this mention was inside a reshare so we don't spam a forum
- $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
+ $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
- $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
+ $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
- if(! preg_match($pattern,$body,$matches)) {
- logger('tag_deliver: mention was in a reshare - ignoring');
- return;
- }
+ if(! preg_match($pattern,$body,$matches)) {
+ logger('tag_deliver: mention was in a reshare - ignoring');
+ return;
+ }
- // All good.
- // Send a notification
+ // All good.
+ // Send a notification
- require_once('include/enotify.php');
- notification(array(
- 'to_xchan' => $u[0]['channel_hash'],
- 'from_xchan' => $item['author_xchan'],
- 'type' => NOTIFY_TAGSELF,
- 'item' => $item,
- 'link' => $i[0]['llink'],
- 'verb' => ACTIVITY_TAG,
- 'otype' => 'item'
- ));
+ require_once('include/enotify.php');
+ notification(array(
+ 'to_xchan' => $u[0]['channel_hash'],
+ 'from_xchan' => $item['author_xchan'],
+ 'type' => NOTIFY_TAGSELF,
+ 'item' => $item,
+ 'link' => $i[0]['llink'],
+ 'verb' => ACTIVITY_TAG,
+ 'otype' => 'item'
+ ));
+
+
+ if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) {
+ logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']);
+ return;
+ }
+ }
- if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) {
- logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']);
+ if((! $mention) && (! $union))
return;
- }
// tgroup delivery - setup a second delivery chain
@@ -2198,6 +2337,73 @@ function tgroup_check($uid,$item) {
}
+/**
+ * @function check_item_source($uid,$item)
+ * @param $uid
+ * @param $item
+ *
+ * @description
+ * Checks to see if this item owner is referenced as a source for this channel and if the post
+ * matches the rules for inclusion in this channel. Returns true if we should create a second delivery
+ * chain and false if none of the rules apply, or if the item is private.
+ */
+
+
+function check_item_source($uid,$item) {
+
+ if($item['item_private'])
+ return false;
+
+
+ $r = q("select * from source where src_channel_id = %d and src_xchan = '%s' limit 1",
+ intval($uid),
+ dbesc($item['owner_xchan'])
+ );
+
+ if(! $r)
+ return false;
+
+ $x = q("select abook_their_perms from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
+ intval($uid),
+ dbesc($item['owner_xchan'])
+ );
+
+ if(! $x)
+ return false;
+
+ if(! ($x[0]['abook_their_perms'] & PERMS_A_REPUBLISH))
+ return false;
+
+ if($r[0]['src_channel_xchan'] === $item['owner_xchan'])
+ return false;
+
+ if(! $r[0]['src_patt'])
+ return true;
+
+ require_once('include/html2plain.php');
+ $text = prepare_text($item['body'],$item['mimetype']);
+ $text = html2plain($text);
+
+ $tags = ((count($items['term'])) ? $items['term'] : false);
+
+ $words = explode("\n",$r[0]['src_patt']);
+ if($words) {
+ foreach($words as $word) {
+ if(substr($word,0,1) === '#' && $tags) {
+ foreach($tags as $t)
+ if($t['type'] == TERM_HASHTAG && substr($t,1) === $word)
+ return true;
+ }
+ if(stristr($text,$word) !== false)
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
function mail_store($arr) {
if(! $arr['channel_id']) {
@@ -2320,21 +2526,21 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
if(! $rino_enable)
$rino = 0;
- $ssl_val = intval(get_config('system','ssl_policy'));
- $ssl_policy = '';
-
- switch($ssl_val){
- case SSL_POLICY_FULL:
- $ssl_policy = 'full';
- break;
- case SSL_POLICY_SELFSIGN:
- $ssl_policy = 'self';
- break;
- case SSL_POLICY_NONE:
- default:
- $ssl_policy = 'none';
- break;
- }
+// $ssl_val = intval(get_config('system','ssl_policy'));
+// $ssl_policy = '';
+
+// switch($ssl_val){
+// case SSL_POLICY_FULL:
+// $ssl_policy = 'full';
+// break;
+// case SSL_POLICY_SELFSIGN:
+// $ssl_policy = 'self';
+// break;
+// case SSL_POLICY_NONE:
+// default:
+// $ssl_policy = 'none';
+// break;
+// }
$url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino=1' : '');
@@ -2423,7 +2629,7 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
$postvars['perm'] = 'r';
}
- $postvars['ssl_policy'] = $ssl_policy;
+// $postvars['ssl_policy'] = $ssl_policy;
if($page)
$postvars['page'] = $page;
@@ -2526,6 +2732,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
logger('consume_feed: empty input');
return;
}
+
+ // Want to see this work as a content source for the matrix?
+ // Read this: https://github.com/friendica/red/wiki/Service_Federation
$feed = new SimplePie();
$feed->set_raw_data($xml);
@@ -2542,12 +2751,6 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
// Check at the feed level for updated contact name and/or photo
- $name_updated = '';
- $new_name = '';
- $photo_timestamp = '';
- $photo_url = '';
- $birthday = '';
-
// process any deleted entries
@@ -2569,7 +2772,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
/* $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join `contact` on `item`.`contact-id` = `contact`.`id`
WHERE `mid` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
dbesc($mid),
- intval($importer['uid']),
+ intval($importer['channel_id']),
intval($contact['id'])
);
*/
@@ -2587,7 +2790,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
dbesc($when),
dbesc(datetime_convert()),
dbesc($item['mid']),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
}
else {
@@ -2598,7 +2801,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
dbesc($when),
dbesc(datetime_convert()),
dbesc($mid),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
}
}
@@ -2623,6 +2826,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$is_reply = false;
$item_id = $item->get_id();
+
+logger('consume_feed: processing ' . $item_id);
+
$rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
if(isset($rawthread[0]['attribs']['']['ref'])) {
$is_reply = true;
@@ -2634,11 +2840,6 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if($pass == 1)
continue;
- // not allowed to post
-// FIXME - check permissions
-// if($contact['rel'] == CONTACT_IS_FOLLOWER)
-// continue;
-
// Have we seen it? If not, import it.
@@ -2660,12 +2861,12 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$r = q("SELECT `uid`, `edited`, `body` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item_id),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
// Update content if 'updated' changes
- if(count($r)) {
+ 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.
@@ -2677,7 +2878,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
dbesc($datarray['body']),
dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
dbesc($item_id),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
}
@@ -2686,7 +2887,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$datarray['parent_mid'] = $parent_mid;
- $datarray['uid'] = $importer['uid'];
+ $datarray['uid'] = $importer['channel_id'];
$datarray['contact-id'] = $contact['id'];
if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) {
$datarray['type'] = 'activity';
@@ -2710,7 +2911,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if($xt->type == ACTIVITY_OBJ_NOTE) {
$r = q("select * from item where `mid` = '%s' AND `uid` = %d limit 1",
dbesc($xt->id),
- intval($importer['importer_uid'])
+ intval($importer['channel_id'])
);
if(! count($r))
continue;
@@ -2728,7 +2929,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
}
}
- $r = item_store($datarray);
+logger('consume_feed: ' . print_r($datarray,true));
+
+// $xx = item_store($datarray);
+ $r = $xx['item_id'];
continue;
}
@@ -2759,7 +2963,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if((x($datarray,'obj_type')) && ($datarray['obj_type'] === ACTIVITY_OBJ_EVENT)) {
$ev = bbtoevent($datarray['body']);
if(x($ev,'desc') && x($ev,'start')) {
- $ev['uid'] = $importer['uid'];
+ $ev['uid'] = $importer['channel_id'];
$ev['mid'] = $item_id;
$ev['edited'] = $datarray['edited'];
$ev['private'] = $datarray['private'];
@@ -2768,23 +2972,23 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$ev['cid'] = $contact['id'];
$r = q("SELECT * FROM `event` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item_id),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
if(count($r))
$ev['id'] = $r[0]['id'];
- $xyz = event_store($ev);
+// $xyz = event_store($ev);
continue;
}
}
$r = q("SELECT `uid`, `edited`, `body` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item_id),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
// Update content if 'updated' changes
- if(count($r)) {
+ 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.
@@ -2796,7 +3000,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
dbesc($datarray['body']),
dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
dbesc($item_id),
- intval($importer['uid'])
+ intval($importer['channel_id'])
);
}
@@ -2824,8 +3028,8 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
}
- if(! is_array($contact))
- return;
+// if(! is_array($contact))
+// return;
// This is my contact on another system, but it's really me.
@@ -2836,7 +3040,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
}
$datarray['parent_mid'] = $item_id;
- $datarray['uid'] = $importer['uid'];
+ $datarray['uid'] = $importer['channel_id'];
$datarray['contact-id'] = $contact['id'];
if(! link_compare($datarray['owner-link'],$contact['url'])) {
@@ -2854,16 +3058,20 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
// posting an @-tag delivery, which followers are allowed to do for certain
// page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it.
- if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['uid'],$datarray)))
+ if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['channel_id'],$datarray)))
continue;
+logger('consume_feed: ' . print_r($datarray,true));
- $r = item_store($datarray);
+// $xx = item_store($datarray);
+ $r = $xx['item_id'];
continue;
}
}
}
+
+
}
@@ -2926,9 +3134,8 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
$o .= '<title>' . xmlify($item['title']) . '</title>' . "\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 .= '<zot:env>' . base64url_encode($body, true) . '</zot:env>' . "\r\n";
- // FIXME for other content types
- $o .= '<content type="' . $type . '" >' . xmlify((($type === 'html') ? bbcode($body) : $body)) . '</content>' . "\r\n";
+
+ $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
$o .= '<link rel="alternate" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
if($item['location']) {
@@ -3599,23 +3806,29 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
return $result;
}
- $contacts = expand_groups(array($arr['group']));
- if((is_array($contacts)) && count($contacts)) {
- $contact_str = implode(',',$contacts);
+
+ $contact_str = '';
+ $contacts = group_get_members($group);
+ if($contacts) {
+ foreach($contacts as $c) {
+ if($contact_str)
+ $contact_str .= ',';
+ $contact_str .= "'" . $c['xchan'] . "'";
+ }
}
else {
- $contact_str = ' 0 ';
- $result['message'] = t('Collection has no members.');
+ $contact_str = ' 0 ';
+ info( t('Group is empty'));
}
- $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 item_restrict = 0 ) ";
+ $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 and item_restrict = 0 ) ";
}
elseif($arr['cid'] && $uid) {
- $r = q("SELECT * from abook where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ") limit 1",
+ $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ") limit 1",
intval($arr['cid']),
- intval($uid)
+ intval(local_user())
);
if($r) {
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval($arr['uid']) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) ";
@@ -3698,11 +3911,17 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
require_once('include/security.php');
$sql_extra .= item_permissions_sql($channel['channel_id']);
+ if($arr['pages'])
+ $item_restrict = " AND (item_restrict & " . ITEM_WEBPAGE . ") ";
+ else
+ $item_restrict = " AND item_restrict = 0 ";
+
+
if($arr['nouveau'] && ($client_mode & CLIENT_MODELOAD) && $channel) {
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT item.*, item.id AS item_id FROM item
- WHERE $item_uids AND item_restrict = 0
+ WHERE $item_uids $item_restrict
$simple_update
$sql_extra $sql_nets
ORDER BY item.received DESC $pager_sql "
@@ -3729,7 +3948,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$r = q("SELECT distinct item.id AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- WHERE $item_uids AND item.item_restrict = 0
+ WHERE $item_uids $item_restrict
AND item.parent = item.id
and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets
@@ -3742,7 +3961,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
// update
$r = q("SELECT item.parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- WHERE $item_uids AND item.item_restrict = 0 $simple_update
+ WHERE $item_uids $item_restrict $simple_update
and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets ",
intval(ABOOK_FLAG_BLOCKED)
@@ -3758,7 +3977,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$parents_str = ids_to_querystr($r,'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item
- WHERE $item_uids AND item.item_restrict = 0
+ WHERE $item_uids $item_restrict
AND item.parent IN ( %s )
$sql_extra ",
dbesc($parents_str)
@@ -3790,4 +4009,4 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
return $items;
-} \ No newline at end of file
+}
diff --git a/include/menu.php b/include/menu.php
index 8d4664385..900b48e65 100644
--- a/include/menu.php
+++ b/include/menu.php
@@ -40,6 +40,7 @@ function menu_render($menu) {
}
+
function menu_fetch_id($menu_id,$channel_id) {
$r = q("select * from menu where menu_id = %d and menu_channel_id = %d limit 1",
@@ -117,6 +118,8 @@ function menu_edit($arr) {
return false;
+ $menu_channel_id = intval($arr['menu_channel_id']);
+
$r = q("select menu_id from menu where menu_name = '%s' and menu_channel_id = %d limit 1",
dbesc($menu_name),
intval($menu_channel_id)
@@ -127,9 +130,6 @@ function menu_edit($arr) {
}
-
- $menu_channel_id = intval($arr['menu_channel_id']);
-
$r = q("select * from menu where menu_id = %d and menu_channel_id = %d limit 1",
intval($menu_id),
intval($menu_channel_id)
@@ -140,14 +140,16 @@ function menu_edit($arr) {
}
- $r = q("select * from menu where menu_name = '%s' and menu_channel_id = %d limit 1",
+ $r = q("select * from menu where menu_name = '%s' and menu_channel_id = %d and menu_desc = '%s' limit 1",
dbesc($menu_name),
- intval($menu_channel_id)
+ intval($menu_channel_id),
+ dbesc($menu_desc)
);
if($r)
return false;
+
return q("update menu set menu_name = '%s', menu_desc = '%s'
where menu_id = %d and menu_channel_id = %d limit 1",
dbesc($menu_name),
diff --git a/include/nav.php b/include/nav.php
index 626caf981..a16d8d078 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -95,12 +95,16 @@ EOT;
);
}
- if($observer)
+ if($observer) {
+ $nav['locked'] = true;
$nav['lock'] = array('logout','','lock',
sprintf( t('%s - click to logout'), $observer['xchan_addr']));
- else
+ }
+ else {
+ $nav['locked'] = false;
$nav['lock'] = array('rmagic','','unlock',
t('Click to authenticate to your home hub'));
+ }
/**
* "Home" should also take you home from an authenticated remote profile connection
@@ -141,11 +145,11 @@ EOT;
if(local_user()) {
- $nav['network'] = array('network', t('Matrix'), "", t('Conversations from your grid'));
+ $nav['network'] = array('network', t('Matrix'), "", t('Your matrix'));
$nav['network']['all']=array('notifications/network', t('See all matrix notifications'), "", "");
$nav['network']['mark'] = array('', t('Mark all matrix notifications seen'), '','');
- $nav['home'] = array('channel/' . $channel['channel_address'], t('Home'), "", t('Your posts and conversations'));
+ $nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'));
$nav['home']['all']=array('notifications/channel', t('See all channel notifications'), "", "");
$nav['home']['mark'] = array('', t('Mark all channel notifications seen'), '','');
@@ -200,7 +204,7 @@ EOT;
$a->page['nav'] .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
- '$langselector' => lang_selector(),
+ '$langselector' => ((get_config('system','select_language')) ? lang_selector() : ''),
'$sitelocation' => $sitelocation,
'$nav' => $nav,
'$banner' => $banner,
@@ -235,5 +239,5 @@ function nav_set_selected($item){
'manage' => null,
'register' => null,
);
- $a->nav_sel[$item] = 'selected';
+ $a->nav_sel[$item] = 'active';
}
diff --git a/include/network.php b/include/network.php
index 8b9a8a6a6..99a0a8e2b 100644
--- a/include/network.php
+++ b/include/network.php
@@ -312,8 +312,13 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
$rc = intval($http_code);
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
+ if(! $ret['success']) {
+ $ret['debug'] = $curl_info;
+ logger('z_fetch_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
+ }
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
+
@curl_close($ch);
return($ret);
}
@@ -407,6 +412,11 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$rc = intval($http_code);
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
+ if(! $ret['success']) {
+ $ret['debug'] = $curl_info;
+ logger('z_fetch_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
+ }
+
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
curl_close($ch);
@@ -1326,7 +1336,7 @@ function xml2array($contents, $namespaces = true, $get_attributes=1, $priority =
}
-function email_header_encode($in_str, $charset) {
+function email_header_encode($in_str, $charset = 'UTF-8') {
$out_str = $in_str;
$need_to_convert = false;
diff --git a/include/notifier.php b/include/notifier.php
index 2a0301357..0c7ac5264 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -54,6 +54,7 @@ require_once('include/html2plain.php');
* ZOT
* 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)
*
@@ -208,9 +209,8 @@ function notifier_run($argv, $argc){
$channel = $s[0];
$uid = $item_id;
$recipients = array();
- $r = q("select * from abook where abook_channel = %d and not (abook_flags & %d)",
- intval($item_id),
- intval(ABOOK_FLAG_SELF)
+ $r = q("select abook_xchan from abook where abook_channel = %d",
+ intval($item_id)
);
if($r) {
foreach($r as $rr) {
@@ -220,6 +220,26 @@ function notifier_run($argv, $argc){
$private = false;
$packet_type = 'refresh';
}
+ 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
@@ -257,6 +277,10 @@ function notifier_run($argv, $argc){
return;
}
+ if($target_item['item_restrict'] & ITEM_PDL) {
+ logger('notifier: target item ITEM_PDL', LOGGER_DEBUG);
+ return;
+ }
$s = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
@@ -369,6 +393,10 @@ function notifier_run($argv, $argc){
}
}
+ if(($private) && (! $env_recips)) {
+ // shouldn't happen
+ logger('notifier: private message with no envelope recipients.' . print_r($argv,true));
+ }
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
@@ -381,7 +409,7 @@ function notifier_run($argv, $argc){
$sql_extra = (($private) ? "" : " or hubloc_url = '" . z_root() . "' ");
- $r = q("select distinct hubloc_sitekey, hubloc_callback, hubloc_host from hubloc
+ $r = q("select distinct hubloc_sitekey, hubloc_flags, hubloc_callback, hubloc_host from hubloc
where hubloc_hash in (" . implode(',',$recipients) . ") $sql_extra group by hubloc_sitekey");
if(! $r) {
logger('notifier: no hubs');
@@ -390,8 +418,12 @@ function notifier_run($argv, $argc){
$hubs = $r;
$hublist = array();
- foreach($hubs as $hub)
- $hublist[] = $hub['hubloc_host'];
+ foreach($hubs as $hub) {
+ // don't try to deliver to deleted hublocs
+ if(! ($hub['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) {
+ $hublist[] = $hub['hubloc_host'];
+ }
+ }
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG);
@@ -407,8 +439,8 @@ function notifier_run($argv, $argc){
foreach($hubs as $hub) {
$hash = random_string();
- if($packet_type === 'refresh') {
- $n = zot_build_packet($channel,'refresh');
+ if($packet_type === 'refresh' || $packet_type === 'purge') {
+ $n = zot_build_packet($channel,$packet_type);
q("insert into outq ( outq_hash, outq_account, outq_channel, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($channel['channel_account']),
diff --git a/include/oauth.php b/include/oauth.php
index 6ec5285e4..b10802ecd 100644
--- a/include/oauth.php
+++ b/include/oauth.php
@@ -18,11 +18,12 @@ class FKOAuthDataStore extends OAuthDataStore {
function lookup_consumer($consumer_key) {
logger(__function__.":".$consumer_key);
- //echo "<pre>"; var_dump($consumer_key); killme();
-
+// echo "<pre>"; var_dump($consumer_key); killme();
+
$r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id='%s'",
dbesc($consumer_key)
);
+
if (count($r))
return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']);
return null;
@@ -30,11 +31,13 @@ class FKOAuthDataStore extends OAuthDataStore {
function lookup_token($consumer, $token_type, $token) {
logger(__function__.":".$consumer.", ". $token_type.", ".$token);
+
$r = q("SELECT id, secret,scope, expires, uid FROM tokens WHERE client_id='%s' AND scope='%s' AND id='%s'",
dbesc($consumer->key),
dbesc($token_type),
dbesc($token)
);
+
if (count($r)){
$ot=new OAuthToken($r[0]['id'],$r[0]['secret']);
$ot->scope=$r[0]['scope'];
@@ -46,12 +49,14 @@ class FKOAuthDataStore extends OAuthDataStore {
}
function lookup_nonce($consumer, $token, $nonce, $timestamp) {
- //echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme();
+// echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme();
+
$r = q("SELECT id, secret FROM tokens WHERE client_id='%s' AND id='%s' AND expires=%d",
dbesc($consumer->key),
dbesc($nonce),
intval($timestamp)
);
+
if (count($r))
return new OAuthToken($r[0]['id'],$r[0]['secret']);
return null;
@@ -67,13 +72,14 @@ class FKOAuthDataStore extends OAuthDataStore {
} else {
$k = $consumer;
}
-
+
$r = q("INSERT INTO tokens (id, secret, client_id, scope, expires) VALUES ('%s','%s','%s','%s', UNIX_TIMESTAMP()+%d)",
dbesc($key),
dbesc($sec),
dbesc($k),
'request',
intval(REQUEST_TOKEN_DURATION));
+
if (!$r) return null;
return new OAuthToken($key,$sec);
}
@@ -95,6 +101,7 @@ class FKOAuthDataStore extends OAuthDataStore {
$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', UNIX_TIMESTAMP()+%d, %d)",
dbesc($key),
dbesc($sec),
@@ -102,6 +109,7 @@ class FKOAuthDataStore extends OAuthDataStore {
'access',
intval(ACCESS_TOKEN_DURATION),
intval($uverifier));
+
if ($r)
$ret = new OAuthToken($key,$sec);
}
@@ -131,9 +139,9 @@ class FKOAuth1 extends OAuthServer {
}
function loginUser($uid){
- logger("FKOAuth1::loginUser $uid");
+ logger("RedOAuth1::loginUser $uid");
$a = get_app();
- $r = q("SELECT * FROM `user` WHERE uid=%d AND `blocked` = 0 AND `account_expired` = 0 AND `verified` = 1 LIMIT 1",
+ $r = q("SELECT * FROM channel WHERE channel_id = %d LIMIT 1",
intval($uid)
);
if(count($r)){
@@ -143,35 +151,36 @@ class FKOAuth1 extends OAuthServer {
header('HTTP/1.0 401 Unauthorized');
die('This api requires login');
}
- $_SESSION['uid'] = $record['uid'];
- $_SESSION['theme'] = $record['theme'];
- $_SESSION['mobile_theme'] = get_pconfig($record['uid'], 'system', 'mobile_theme');
+ $_SESSION['uid'] = $record['channel_id'];
+ $_SESSION['theme'] = $record['channel_theme'];
+ $_SESSION['account_id'] = $record['channel_account_id'];
+ $_SESSION['mobile_theme'] = get_pconfig($record['channel_id'], 'system', 'mobile_theme');
$_SESSION['authenticated'] = 1;
- $_SESSION['page_flags'] = $record['page-flags'];
- $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $record['nickname'];
+// $_SESSION['page_flags'] = $record['page-flags'];
+ $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $record['channel_address'];
$_SESSION['addr'] = $_SERVER['REMOTE_ADDR'];
+ $_SESSION['allow_api'] = true;
- //notice( t("Welcome back ") . $record['username'] . EOL);
- $a->user = $record;
+ $a->channel = $record;
- if(strlen($a->user['timezone'])) {
- date_default_timezone_set($a->user['timezone']);
- $a->timezone = $a->user['timezone'];
+ if(strlen($a->channel['channel_timezone'])) {
+ date_default_timezone_set($a->channel['channel_timezone']);
+// $a->timezone = $a->user['timezone'];
}
- $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
- intval($_SESSION['uid']));
- if(count($r)) {
- $a->contact = $r[0];
- $a->cid = $r[0]['id'];
- $_SESSION['cid'] = $a->cid;
- }
- q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1",
- dbesc(datetime_convert()),
- intval($_SESSION['uid'])
- );
-
- call_hooks('logged_in', $a->user);
+// $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
+// intval($_SESSION['uid']));
+// if(count($r)) {
+// $a->contact = $r[0];
+// $a->cid = $r[0]['id'];
+// $_SESSION['cid'] = $a->cid;
+// }
+// q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1",
+// dbesc(datetime_convert()),
+// intval($_SESSION['uid'])
+// );
+//
+// call_hooks('logged_in', $a->user);
}
}
diff --git a/include/onedirsync.php b/include/onedirsync.php
new file mode 100644
index 000000000..b9c17628a
--- /dev/null
+++ b/include/onedirsync.php
@@ -0,0 +1,42 @@
+<?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');
+
+ 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['ud_flags'] & UPDATE_FLAGS_UPDATED)
+ 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
index a225edfd8..50c2566be 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -69,7 +69,7 @@ function onepoll_run($argv, $argc){
$last_update = (($contact['abook_updated'] === '0000-00-00 00:00:00')
? datetime_convert('UTC','UTC','now - 7 days')
- : datetime_convert('UTC','UTC',$contact['abook_updated'])
+ : datetime_convert('UTC','UTC',$contact['abook_updated'] . ' - 2 days')
);
// update permissions
@@ -98,11 +98,12 @@ function onepoll_run($argv, $argc){
return;
if($contact['xchan_connurl']) {
- $feedurl = str_replace('/poco/','/zotfeed/',$channel['xchan_connurl']);
-
- $x = z_fetch_url($feedurl . '?f=$mindate=' . $last_update);
+ $feedurl = str_replace('/poco/','/zotfeed/',$channel['xchan_connurl']);
+ $x = z_fetch_url($feedurl . '?f=&mindate=' . $last_update);
if($x['success']) {
$total = 0;
+ logger('onepoll: feed update ' . $contact['xchan_name']);
+
$j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) {
foreach($j['messages'] as $message) {
diff --git a/include/page_widgets.php b/include/page_widgets.php
index 23d6d25ba..d70281afc 100644
--- a/include/page_widgets.php
+++ b/include/page_widgets.php
@@ -5,7 +5,7 @@ function writepages_widget ($who,$which){
return replace_macros(get_markup_template('write_pages.tpl'), array(
'$new' => t('New Page'),
'$newurl' => "webpages/$who",
- '$edit' => t('edit'),
+ '$edit' => t('Edit'),
'$editurl' => "editwebpage/$who/$which"
));
}
diff --git a/include/permissions.php b/include/permissions.php
index bf50ebdd1..45ea7c3eb 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -28,6 +28,7 @@ function get_perms() {
'write_storage' => array('channel_w_storage', intval(PERMS_W_STORAGE), false, t('Can write to my "public" file storage'), ''),
'write_pages' => array('channel_w_pages', intval(PERMS_W_PAGES), false, t('Can edit my "public" pages'), ''),
+ 'republish' => array('channel_a_republish', intval(PERMS_A_REPUBLISH), false, t('Can source my "public" posts in derived channels'), t('Somewhat advanced - very useful in open communities')),
'delegate' => array('channel_a_delegate', intval(PERMS_A_DELEGATE), false, t('Can administer my channel resources'), t('Extremely advanced. Leave this alone unless you know what you are doing')),
);
$ret = array('global_permissions' => $global_perms);
diff --git a/include/photos.php b/include/photos.php
index c670bd90c..ea4b494e0 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -216,13 +216,14 @@ function photo_upload($channel, $observer, $args) {
$arr['allow_gid'] = $str_group_allow;
$arr['deny_cid'] = $str_contact_deny;
$arr['deny_gid'] = $str_group_deny;
-
+ $arr['verb'] = ACTIVITY_POST;
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
. '[zmg]' . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
. '[/zrl]';
- $item_id = item_store($arr);
+ $result = item_store($arr);
+ $item_id = $result['item_id'];
if($visible)
proc_run('php', "include/notifier.php", 'wall-new', $item_id);
@@ -402,7 +403,8 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
. '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['scale'] . '[/zmg]'
. '[/zrl]';
- $item_id = item_store($arr);
+ $result = item_store($arr);
+ $item_id = $result['item_id'];
return $item_id;
} \ No newline at end of file
diff --git a/include/plugin.php b/include/plugin.php
index 01ee99786..ea88a61df 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -374,12 +374,14 @@ function get_theme_screenshot($theme) {
function service_class_allows($uid,$property,$usage = false) {
-
+ $a = get_app();
if($uid == local_user()) {
- $service_class = $a->user['service_class'];
+ $service_class = $a->account['account_service_class'];
}
else {
- $r = q("select service_class from user where uid = %d limit 1",
+ $r = q("select account_service_class as service_class
+ from channel c, account a
+ where c.channel_account_id=a.account_id and c.channel_id= %d limit 1",
intval($uid)
);
if($r !== false and count($r)) {
@@ -404,13 +406,15 @@ function service_class_allows($uid,$property,$usage = false) {
function service_class_fetch($uid,$property) {
-
+ $a = get_app();
if($uid == local_user()) {
- $service_class = $a->user['service_class'];
+ $service_class = $a->account['account_service_class'];
}
else {
- $r = q("select service_class from user where uid = %d limit 1",
- intval($uid)
+ $r = q("select account_service_class as service_class
+ from channel c, account a
+ where c.channel_account_id=a.account_id and c.channel_id= %d limit 1",
+ intval($uid)
);
if($r !== false and count($r)) {
$service_class = $r[0]['service_class'];
@@ -420,6 +424,7 @@ function service_class_fetch($uid,$property) {
return false; // everything is allowed
$arr = get_config('service_class',$service_class);
+
if(! is_array($arr) || (! count($arr)))
return false;
diff --git a/include/poller.php b/include/poller.php
index 7a6aaeb22..95eb810a0 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -69,6 +69,8 @@ function poller_run($argv, $argc){
$d1 = get_config('system','last_expire_day');
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
+ $dirmode = get_config('system','directory_mode');
+
if($d2 != intval($d1)) {
// If this is a directory server, request a sync with an upstream
@@ -76,7 +78,6 @@ function poller_run($argv, $argc){
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
- $dirmode = get_config('system','directory_mode');
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
require_once('include/dir_fns.php');
sync_directories($dirmode);
@@ -158,7 +159,7 @@ function poller_run($argv, $argc){
);
- $contacts = q("SELECT abook_id, abook_updated, abook_connected, abook_closeness, abook_channel
+ $contacts = q("SELECT abook_id, abook_flags, abook_updated, abook_connected, abook_closeness, abook_channel
FROM abook LEFT JOIN account on abook_account = account_id where 1
$sql_extra
AND (( abook_flags = %d ) OR ( abook_flags = %d ))
@@ -171,69 +172,95 @@ function poller_run($argv, $argc){
);
- if(! $contacts) {
- return;
- }
+ if($contacts) {
- foreach($contacts as $contact) {
+ foreach($contacts as $contact) {
- $update = false;
+ $update = false;
- $t = $contact['abook_updated'];
- $c = $contact['abook_connected'];
+ $t = $contact['abook_updated'];
+ $c = $contact['abook_connected'];
- 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 == '0000-00-00 00:00:00') {
- $r = q("update abook set abook_connected = '%s' where abook_id = %d limit 1",
- dbesc(datetime_convert()),
- intval($contact['abook_id'])
- );
- $c = datetime_convert();
- $update = true;
+ 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 == '0000-00-00 00:00:00') {
+ $r = q("update abook set abook_connected = '%s' where abook_id = %d limit 1",
+ 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_flags = (abook_flags | %d) where abook_id = %d limit 1",
+ intval(ABOOK_FLAG_ARCHIVED),
+ intval($contact['abook_id'])
+ );
+ $update = false;
+ continue;
+ }
+
+ if($contact['abook_flags'] & ABOOK_FLAG_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;
+ }
- // 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_flags = (abook_flags | %d) where abook_id = %d limit 1",
- intval(ABOOK_FLAG_ARCHIVED),
- intval($contact['abook_id'])
- );
- $update = false;
- continue;
}
- // might be dead, so maybe don't poll quite so often
+ if((! $update) && (! $force))
+ continue;
- // 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;
+ proc_run('php','include/onepoll.php',$contact['abook_id']);
+ if($interval)
+ @time_sleep_until(microtime(true) + (float) $interval);
- // 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($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
+ $r = q("select ud_id from updates where not ( ud_flags & %d ) and ( ud_last = '0000-00-00 00:00:00' OR ud_last > UTC_TIMESTAMP() - INTERVAL 7 DAY ) ",
+ intval(UPDATE_FLAGS_UPDATED)
+ );
+ 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'] != '0000-00-00 00:00:00')
+ 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);
}
}
-dbg(0);
- if((! $update) && (! $force))
- continue;
-
- proc_run('php','include/onepoll.php',$contact['abook_id']);
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
-
}
-
+
return;
}
diff --git a/include/security.php b/include/security.php
index 4738e473b..1181e6bf2 100644
--- a/include/security.php
+++ b/include/security.php
@@ -302,16 +302,19 @@ function public_permissions_sql($observer_hash) {
foreach($groups as $g)
$gs .= '|<' . $g . '>';
}
- $sql = sprintf(
- " OR (( NOT (deny_cid like '%s' OR deny_gid REGEXP '%s')
- AND ( allow_cid like '%s' OR allow_gid REGEXP '%s' OR ( allow_cid = '' AND allow_gid = '') )
- ))
- ",
- dbesc(protect_sprintf( '%<' . $observer_hash . '>%')),
- dbesc($gs),
- dbesc(protect_sprintf( '%<' . $observer_hash . '>%')),
- dbesc($gs)
- );
+ $sql = '';
+ if($observer_hash) {
+ $sql = sprintf(
+ " OR (( NOT (deny_cid like '%s' OR deny_gid REGEXP '%s')
+ AND ( allow_cid like '%s' OR allow_gid REGEXP '%s' OR ( allow_cid = '' AND allow_gid = '') )
+ ))
+ ",
+ dbesc(protect_sprintf( '%<' . $observer_hash . '>%')),
+ dbesc($gs),
+ dbesc(protect_sprintf( '%<' . $observer_hash . '>%')),
+ dbesc($gs)
+ );
+ }
return $sql;
}
@@ -409,7 +412,7 @@ function stream_perms_api_uids($perms_min = PERMS_SITE) {
$ret = array();
if(local_user())
$ret[] = local_user();
- $r = q("select channel_id from channel where channel_r_stream <= %d",
+ $r = q("select channel_id from channel where channel_r_stream > 0 and channel_r_stream <= %d",
intval($perms_min)
);
if($r)
@@ -424,6 +427,30 @@ function stream_perms_api_uids($perms_min = PERMS_SITE) {
$str .= ',';
$str .= intval($rr);
}
+logger('stream_perms_api_uids: ' . $str);
return $str;
}
+function stream_perms_xchans($perms_min = PERMS_SITE) {
+ $ret = array();
+ if(local_user())
+ $ret[] = get_observer_hash();
+
+ $r = q("select channel_hash from channel where channel_r_stream > 0 and channel_r_stream <= %d",
+ intval($perms_min)
+ );
+ if($r)
+ foreach($r as $rr)
+ if(! in_array($rr['channel_hash'],$ret))
+ $ret[] = $rr['channel_hash'];
+
+ $str = '';
+ if($ret)
+ foreach($ret as $rr) {
+ if($str)
+ $str .= ',';
+ $str .= "'" . dbesc($rr) . "'";
+ }
+logger('stream_perms_xchans: ' . $str);
+ return $str;
+}
diff --git a/include/taxonomy.php b/include/taxonomy.php
index b6803743a..85396a51d 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -99,6 +99,7 @@ function format_term_for_display($term) {
function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $type = TERM_HASHTAG) {
$sql_options = '';
+ $count = intval($count);
if($flags)
$sql_options .= " and ((item_flags & " . intval($flags) . ") = " . intval($flags) . ") ";
@@ -157,6 +158,47 @@ function tags_sort($a,$b) {
}
+function dir_tagadelic($count = 0) {
+
+ $sql_options = '';
+ $count = intval($count);
+
+ // Fetch tags
+ $r = q("select xtag_term, count(xtag_term) as total from xtag
+ group by xtag_term order by total desc %s",
+ ((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(5 * ($tags[$x][1] - $min) / $range);
+ }
+
+ return $tags;
+}
+
+
function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$type = TERM_HASHTAG) {
$o = '';
$tab = 0;
@@ -172,6 +214,24 @@ function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$type = TERM_HA
return $o;
}
+function dir_tagblock($link,$r) {
+ $o = '';
+ $tab = 0;
+
+ if($r) {
+ $o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">';
+ foreach($r as $rr) {
+ $o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n";
+ }
+ $o .= '</div></div>';
+ }
+ return $o;
+}
+
+
+
+
+
/**
* verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
diff --git a/include/text.php b/include/text.php
index 99d5c9d78..8f700458c 100755
--- a/include/text.php
+++ b/include/text.php
@@ -81,6 +81,34 @@ function escape_tags($string) {
}
+function z_input_filter($channel_id,$s,$type = 'text/bbcode') {
+
+ if($type === 'text/bbcode')
+ return escape_tags($s);
+ if($type === 'text/markdown')
+ return escape_tags($s);
+ if($type == 'text/plain')
+ return escape_tags($s);
+ $r = q("select account_id, account_roles from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
+ intval($channel_id)
+ );
+ if($r && ($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE)) {
+ if(local_user() && (get_account_id() == $r[0]['account_id'])) {
+ return $s;
+ }
+ }
+
+ if($type === 'text/html')
+ return purify_html($s);
+
+ return escape_tags($s);
+
+}
+
+
+
+
+
function purify_html($s) {
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
@@ -698,7 +726,7 @@ function search($s,$id='search-box',$url='/search',$save = false) {
$a = get_app();
$o = '<div id="' . $id . '">';
$o .= '<form action="' . $a->get_baseurl((stristr($url,'network')) ? true : false) . $url . '" method="get" >';
- $o .= '<input type="text" name="search" id="search-text" placeholder="' . t('Search') . '" value="' . $s .'" />';
+ $o .= '<input type="text" class="icon-search" name="search" id="search-text" placeholder="&#xf002;" value="' . $s .'" onclick="this.submit();" />';
$o .= '<input type="submit" name="submit" id="search-submit" value="' . t('Search') . '" />';
if($save)
$o .= '<input type="submit" name="save" id="search-save" value="' . t('Save') . '" />';
@@ -976,6 +1004,17 @@ function link_compare($a,$b) {
// If attach is true, also add icons for item attachments
+function unobscure(&$item) {
+ if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED)) {
+ $key = get_config('system','prvkey');
+ if($item['title'])
+ $item['title'] = aes_unencapsulate(json_decode_plus($item['title']),$key);
+ if($item['body'])
+ $item['body'] = aes_unencapsulate(json_decode_plus($item['body']),$key);
+ }
+
+}
+
function prepare_body(&$item,$attach = false) {
@@ -985,13 +1024,7 @@ function prepare_body(&$item,$attach = false) {
call_hooks('prepare_body_init', $item);
- if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED)) {
- $key = get_config('system','prvkey');
- if($item['title'])
- $item['title'] = aes_unencapsulate(json_decode_plus($item['title']),$key);
- if($item['body'])
- $item['body'] = aes_unencapsulate(json_decode_plus($item['body']),$key);
- }
+ unobscure($item);
$s = prepare_text($item['body'],$item['mimetype']);
@@ -1127,6 +1160,7 @@ function prepare_body(&$item,$attach = false) {
function prepare_text($text,$content_type = 'text/bbcode') {
+
switch($content_type) {
case 'text/plain':
@@ -1171,6 +1205,8 @@ function prepare_text($text,$content_type = 'text/bbcode') {
break;
}
+//logger('prepare_text: ' . $s);
+
return $s;
}
@@ -1276,7 +1312,7 @@ function get_plink($item) {
$a = get_app();
if (x($item,'plink') && ($item['item_private'] != 1)) {
return array(
- 'href' => $item['plink'],
+ 'href' => zid($item['plink']),
'title' => t('link to source'),
);
}
@@ -1290,9 +1326,64 @@ function unamp($s) {
return str_replace('&amp;', '&', $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_restrict & %d)",
+ intval($channel_id),
+ intval(ITEM_PDL)
+ );
+ if($r) {
+ $o = t('Select a page layout: ');
+ $o .= '<select name="layout_mid" id="select-layout_mid" >';
+ $empty_selected = (($current === '') ? ' selected="selected" ' : '');
+ $o .= '<option value="" ' . $empty_selected . '>' . t('default') . '</option>';
+ foreach($r as $rr) {
+ $selected = (($rr['mid'] == $current) ? ' selected="selected" ' : '');
+ $o .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['sid'] . '</option>';
+ }
+ $o .= '</select>';
+ }
+
+ return $o;
+}
+
+
+function mimetype_select($channel_id, $current = 'text/bbcode') {
+
+ $x = array(
+ 'text/bbcode',
+ 'text/html',
+ 'text/markdown',
+ 'text/plain'
+ );
+
+ $r = q("select account_id, account_roles from account left join channel on account_id = channel_account_id where
+ channel_id = %d limit 1",
+ intval($channel_id)
+ );
+
+ if($r) {
+ if($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) {
+ if(local_user() && get_account_id() == $r[0]['account_id'])
+ $x[] = 'application/x-php';
+ }
+ }
+
+ $o = t('Page content type: ');
+ $o .= '<select name="mimetype" id="mimetype-select">';
+ foreach($x as $y) {
+ $select = (($y == $current) ? ' selected="selected" ' : '');
+ $o .= '<option name="' . $y . '"' . $select . '>' . $y . '</option>';
+ }
+ $o .= '</select>';
+
+ return $o;
+
+}
+
+
function lang_selector() {
global $a;
@@ -1740,4 +1831,27 @@ function json_decode_plus($s) {
$x = json_decode(str_replace(array('\\"','\\\\'),array('"','\\'),$s),true);
return $x;
-} \ No newline at end of file
+}
+
+
+function design_tools() {
+$channel = get_app()->get_channel();
+$who = $channel['channel_address'];
+
+return replace_macros(get_markup_template('design_tools.tpl'), array(
+ '$title' => t('Design'),
+ '$who' => $who,
+ '$blocks' => t('Blocks'),
+ '$menus' => t('Menus'),
+ '$layout' => t('Layouts'),
+ '$pages' => t('Pages')
+ ));
+
+}
+
+/* case insensitive in_array() */
+
+function in_arrayi($needle, $haystack) {
+ return in_array(strtolower($needle), array_map('strtolower', $haystack));
+}
+
diff --git a/include/zot.php b/include/zot.php
index bddbc9bee..b250557e6 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -111,12 +111,14 @@ function zot_zot($url,$data) {
* does not have to be host qualified e.g. 'foo' is treated as 'foo@thishub'
* @param: array $channel
* (optional), if supplied permissions will be enumerated specifically for $channel
+ * @param: boolean $autofallback
+ * fallback/failover to http if https connection cannot be established. Default is true.
*
* @returns: array => see z_post_url and mod/zfinger.php
*/
-function zot_finger($webbie,$channel) {
+function zot_finger($webbie,$channel,$autofallback = true) {
if(strpos($webbie,'@') === false) {
@@ -138,7 +140,7 @@ function zot_finger($webbie,$channel) {
$r = q("select xchan.*, hubloc.* from xchan
left join hubloc on xchan_hash = hubloc_hash
where xchan_addr = '%s' and (hubloc_flags & %d) limit 1",
- dbesc($xchan_address),
+ dbesc($xchan_addr),
intval(HUBLOC_FLAGS_PRIMARY)
);
@@ -165,7 +167,7 @@ function zot_finger($webbie,$channel) {
$result = z_post_url($url . $rhs,$postvars);
- if(! $result['success']) {
+ if((! $result['success']) && ($autofallback)) {
if($https) {
logger('zot_finger: https failed. falling back to http');
$result = z_post_url('http://' . $host . $rhs,$postvars);
@@ -176,7 +178,7 @@ function zot_finger($webbie,$channel) {
$rhs .= '?f=&address=' . urlencode($address);
$result = z_fetch_url($url . $rhs);
- if(! $result['success']) {
+ if((! $result['success']) && ($autofallback)) {
if($https) {
logger('zot_finger: https failed. falling back to http');
$result = z_fetch_url('http://' . $host . $rhs);
@@ -411,12 +413,13 @@ function zot_register_hub($arr) {
// If the xchan already exists, update the name and photo if these have changed.
//
-function import_xchan($arr) {
+function import_xchan($arr,$ud_flags = 1) {
$ret = array('success' => false);
$dirmode = intval(get_config('system','directory_mode'));
$changed = false;
+ $what = '';
if(! (is_array($arr) && array_key_exists('success',$arr) && $arr['success'])) {
logger('import_xchan: invalid data packet: ' . print_r($arr,true));
@@ -441,6 +444,11 @@ function import_xchan($arr) {
dbesc($xchan_hash)
);
+ if(! array_key_exists('connect_url', $arr))
+ $arr['connect_url'] = '';
+
+ if(strpos($arr['address'],'/') !== false)
+ $arr['address'] = substr($arr['address'],0,strpos($arr['address'],'/'));
if($r) {
if($r[0]['xchan_photo_date'] != $arr['photo_updated'])
@@ -462,18 +470,28 @@ function import_xchan($arr) {
$new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_HIDDEN;
else
$new_flags = $r[0]['xchan_flags'];
-
-
+
+ $adult = (($r[0]['xchan_flags'] & XCHAN_FLAGS_SELFCENSORED) ? true : false);
+ $adult_changed = ((intval($adult) != intval($arr['adult_content'])) ? true : false);
+ if($adult_changed)
+ $new_flags = $new_flags ^ XCHAN_FLAGS_SELFCENSORED;
+
+
if(($r[0]['xchan_name_date'] != $arr['name_updated'])
|| ($r[0]['xchan_connurl'] != $arr['connections_url'])
|| ($r[0]['xchan_flags'] != $new_flags)
|| ($r[0]['xchan_addr'] != $arr['address'])
+ || ($r[0]['xchan_follow'] != $arr['follow_url'])
+ || ($r[0]['xchan_connpage'] != $arr['connect_url'])
|| ($r[0]['xchan_url'] != $arr['url'])) {
- $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_flags = %d,
+ $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',
+ xchan_connpage = '%s', xchan_flags = %d,
xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s' limit 1",
dbesc($arr['name']),
dbesc($arr['name_updated']),
dbesc($arr['connections_url']),
+ dbesc($arr['follow_url']),
+ dbesc($arr['connect_url']),
intval($new_flags),
dbesc($arr['address']),
dbesc($arr['url']),
@@ -482,8 +500,7 @@ function import_xchan($arr) {
logger('import_xchan: existing: ' . print_r($r[0],true), LOGGER_DATA);
logger('import_xchan: new: ' . print_r($arr,true), LOGGER_DATA);
-
- update_modtime($xchan_hash);
+ $what .= 'xchan ';
$changed = true;
}
}
@@ -501,10 +518,12 @@ function import_xchan($arr) {
$new_flags = XCHAN_FLAGS_HIDDEN;
else
$new_flags = 0;
+ if($arr['adult_content'])
+ $new_flags |= XCHAN_FLAGS_SELFCENSORED;
$x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype,
- xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags)
- values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ",
+ xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags)
+ values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ",
dbesc($xchan_hash),
dbesc($arr['guid']),
dbesc($arr['guid_sig']),
@@ -514,13 +533,16 @@ function import_xchan($arr) {
dbesc($arr['address']),
dbesc($arr['url']),
dbesc($arr['connections_url']),
+ dbesc($arr['follow_url']),
+ dbesc($arr['connect_url']),
dbesc($arr['name']),
dbesc('zot'),
dbesc($arr['photo_updated']),
dbesc($arr['name_updated']),
intval($new_flags)
);
- update_modtime($xchan_hash);
+
+ $what .= 'new_xchan';
$changed = true;
}
@@ -541,7 +563,7 @@ function import_xchan($arr) {
dbesc($xchan_hash)
);
- update_modtime($xchan_hash);
+ $what .= 'photo ';
$changed = true;
}
@@ -567,23 +589,44 @@ function import_xchan($arr) {
}
}
- $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s'
- and hubloc_url = '%s' and hubloc_url_sig = '%s' limit 1",
+ // match as many fields as possible in case anything at all changed.
+
+ $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' limit 1",
dbesc($xchan_hash),
dbesc($arr['guid']),
dbesc($arr['guid_sig']),
dbesc($location['url']),
- dbesc($location['url_sig'])
+ dbesc($location['url_sig']),
+ dbesc($location['host']),
+ dbesc($location['address']),
+ dbesc($location['callback']),
+ dbesc($location['sitekey'])
);
if($r) {
logger('import_xchan: hub exists: ' . $location['url']);
+ // update connection timestamp
+ q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d limit 1",
+ dbesc(datetime_convert()),
+ intval($r[0]['hubloc_id'])
+ );
if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) && (! $location['primary']))
|| ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY)) && ($location['primary']))) {
- $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1",
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
intval(HUBLOC_FLAGS_PRIMARY),
+ dbesc(datetime_convert()),
intval($r[0]['hubloc_id'])
);
- update_modtime($xchan_hash);
+ $what = 'primary_hub ';
+ $changed = true;
+ }
+ if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) && (! $location['deleted']))
+ || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) && ($location['deleted']))) {
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_DELETED),
+ dbesc(datetime_convert()),
+ intval($r[0]['hubloc_id'])
+ );
+ $what = 'delete_hub ';
$changed = true;
}
continue;
@@ -594,18 +637,22 @@ function import_xchan($arr) {
continue;
}
+ if(strpos($location['address'],'/') !== false)
+ $location['address'] = substr($location['address'],0,strpos($location['address'],'/'));
+
// new hub claiming to be primary. Make it so.
if(intval($location['primary'])) {
- $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_hash = '%s' and (hubloc_flags & %d )",
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_hash = '%s' and (hubloc_flags & %d )",
intval(HUBLOC_FLAGS_PRIMARY),
+ dbesc(datetime_convert()),
dbesc($xchan_hash),
intval(HUBLOC_FLAGS_PRIMARY)
);
}
logger('import_xchan: new hub: ' . $location['url']);
- $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey)
- values ( '%s','%s','%s','%s', %d ,'%s','%s','%s','%s','%s')",
+ $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_updated, hubloc_connected)
+ values ( '%s','%s','%s','%s', %d ,'%s','%s','%s','%s','%s','%s','%s')",
dbesc($arr['guid']),
dbesc($arr['guid_sig']),
dbesc($xchan_hash),
@@ -615,9 +662,11 @@ function import_xchan($arr) {
dbesc($location['url_sig']),
dbesc($location['host']),
dbesc($location['callback']),
- dbesc($location['sitekey'])
+ dbesc($location['sitekey']),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert())
);
- update_modtime($xchan_hash);
+ $what .= 'newhub ';
$changed = true;
}
@@ -629,7 +678,7 @@ function import_xchan($arr) {
$r = q("delete from hubloc where hubloc_id = %d limit 1",
intval($x['hubloc_id'])
);
- update_modtime($xchan_hash);
+ $what .= 'removed_hub';
$changed = true;
}
}
@@ -641,9 +690,9 @@ function import_xchan($arr) {
if($dirmode != DIRECTORY_MODE_NORMAL) {
if(array_key_exists('profile',$arr) && is_array($arr['profile'])) {
- $profile_changed = import_directory_profile($xchan_hash,$arr['profile']);
+ $profile_changed = import_directory_profile($xchan_hash,$arr['profile'],$arr['address'],$ud_flags, 1);
if($profile_changed) {
- update_modtime($xchan_hash);
+ $what .= 'profile ';
$changed = true;
}
}
@@ -662,7 +711,7 @@ function import_xchan($arr) {
if(array_key_exists('site',$arr) && is_array($arr['site'])) {
$profile_changed = import_site($arr['site'],$arr['key']);
if($profile_changed) {
- update_modtime($xchan_hash);
+ $what .= 'site ';
$changed = true;
}
}
@@ -670,9 +719,9 @@ function import_xchan($arr) {
if($changed) {
- // send out a directory mirror update packet if we're a directory server or some kind
-
-
+ $guid = random_string() . '@' . get_app()->get_hostname();
+ update_modtime($xchan_hash,$guid,$arr['address'],$ud_flags);
+ logger('import_xchan: changed: ' . $what,LOGGER_DEBUG);
}
if(! x($ret,'message')) {
@@ -741,10 +790,6 @@ function zot_fetch($arr) {
logger('zot_fetch: no hub: ' . print_r($arr['sender'],true));
return;
}
-
-
- $ret_secret = json_encode(array($arr['secret'],'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))));
-
$data = array(
'type' => 'pickup',
@@ -755,12 +800,10 @@ function zot_fetch($arr) {
'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))
);
-
$datatosend = json_encode(aes_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey']));
$fetch = zot_zot($url,$datatosend);
-
- $result = zot_import($fetch);
+ $result = zot_import($fetch, $arr['sender']['url']);
return $result;
}
@@ -773,7 +816,7 @@ function zot_fetch($arr) {
* The message types handled here are 'activity' (e.g. posts), 'mail' and 'profile'
*/
-function zot_import($arr) {
+function zot_import($arr, $sender_url) {
$data = json_decode($arr['body'],true);
@@ -800,6 +843,13 @@ function zot_import($arr) {
logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA);
+ $hub = zot_gethub($i['notify']['sender']);
+ if((! $hub) || ($hub['hubloc_url'] != $sender_url)) {
+ logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true));
+ continue;
+ }
+
+
$i['notify']['sender']['hash'] = base64url_encode(hash('whirlpool',$i['notify']['sender']['guid'] . $i['notify']['sender']['guid_sig'], true));
$deliveries = null;
@@ -823,12 +873,19 @@ function zot_import($arr) {
}
else {
+ if((array_key_exists('flags',$i['message'])) && (in_array('private',$i['message']['flags']))) {
+ // This should not happen but until we can stop it...
+ logger('private message was delivered with no recipients.');
+ continue;
+ }
+
logger('public post');
// Public post. look for any site members who are or may be accepting posts from this sender
// and who are allowed to see them based on the sender's permissions
$deliveries = allowed_public_recips($i);
+
}
if(! $deliveries) {
logger('zot_import: no deliveries on this site');
@@ -881,8 +938,9 @@ function zot_import($arr) {
$result = process_channel_sync_delivery($i['notify']['sender'],$arr,$deliveries);
}
}
- if($result)
+ if($result){
$return = array_merge($return,$result);
+ }
}
}
@@ -901,14 +959,24 @@ function zot_import($arr) {
function public_recips($msg) {
+ $check_mentions = false;
if($msg['message']['type'] === 'activity') {
+ $col = 'channel_w_stream';
+ $field = PERMS_W_STREAM;
if(array_key_exists('flags',$msg['message']) && in_array('thread_parent', $msg['message']['flags'])) {
- $col = 'channel_w_stream';
- $field = PERMS_W_STREAM;
+ // check mention recipient permissions on top level posts only
+ $check_mentions = true;
}
else {
- $col = 'channel_w_comment';
- $field = PERMS_W_COMMENT;
+ // if this is a comment and it wasn't sent by the post owner, check to see who is allowing them to comment.
+ // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up their software.
+ // We may need this step to protect us from bad guys intentionally stuffing up their software.
+ // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the
+ // owner's stream (which was already set above) - as they control the comment permissions
+ if($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) {
+ $col = 'channel_w_comment';
+ $field = PERMS_W_COMMENT;
+ }
}
}
elseif($msg['message']['type'] === 'mail') {
@@ -919,18 +987,22 @@ function public_recips($msg) {
if(! $col)
return NULL;
+
if($msg['notify']['sender']['url'] === z_root())
- $sql = " where (( " . $col . " & " . PERMS_NETWORK . " ) or ( " . $col . " & " . PERMS_SITE . " )) ";
+ $sql = " where (( " . $col . " & " . PERMS_NETWORK . " ) or ( " . $col . " & " . PERMS_SITE . " ) or ( " . $col . " & " . PERMS_PUBLIC . ")) ";
else
- $sql = " where ( " . $col . " & " . PERMS_NETWORK . " ) " ;
+ $sql = " where (( " . $col . " & " . PERMS_NETWORK . " ) or ( " . $col . " & " . PERMS_PUBLIC . ")) ";
- $r = q("select channel_hash as hash from channel " . $sql );
+
+ $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s' ",
+ dbesc($msg['notify']['sender']['hash'])
+ );
if(! $r)
$r = array();
$x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s'
- and (( " . $col . " & " . PERMS_SPECIFIC . " ) OR ( " . $col . " & " . PERMS_CONTACTS . " )) and ( abook_my_perms & " . $field . " ) ",
+ and (( " . $col . " & " . PERMS_SPECIFIC . " ) and ( abook_my_perms & " . $field . " )) OR ( " . $col . " & " . PERMS_CONTACTS . " ) ",
dbesc($msg['notify']['sender']['hash'])
);
@@ -938,6 +1010,27 @@ function public_recips($msg) {
$x = array();
$r = array_merge($r,$x);
+
+ // look for any public mentions on this site
+ // They will get filtered by tgroup_check() so we don't need to check permissions now
+
+ if($check_mentions && $msg['message']['tags']) {
+ if(is_array($msg['message']['tags']) && $msg['message']['tags']) {
+ foreach($msg['message']['tags'] as $tag) {
+ if(($tag['type'] === 'mention') && (strpos($tag['url'],z_root()) !== false)) {
+ $address = basename($tag['url']);
+ if($address) {
+ $z = q("select channel_hash as hash from channel where channel_address = '%s' limit 1",
+ dbesc($address)
+ );
+ if($z)
+ $r = array_merge($r,$z);
+ }
+ }
+ }
+ }
+ }
+
logger('public_recips: ' . print_r($r,true), LOGGER_DATA);
return $r;
}
@@ -1008,6 +1101,14 @@ function allowed_public_recips($msg) {
function process_delivery($sender,$arr,$deliveries,$relay) {
$result = array();
+
+
+ // We've validated the sender. Now make sure that the sender is the owner or author
+
+ if($sender['hash'] != $arr['owner_xchan'] && $sender['hash'] != $arr['author_xchan']) {
+ logger('process_delivery: sender is not owner or author');
+ return;
+ }
foreach($deliveries as $d) {
$r = q("select * from channel where channel_hash = '%s' limit 1",
@@ -1108,8 +1209,9 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
else {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
- $item_id = item_store($arr);
- $result[] = array($d['hash'],(($item_id) ? 'posted' : 'storage failed'),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $item_result = item_store($arr);
+ $item_id = $item_result['item_id'];
+ $result[] = array($d['hash'],(($item_id) ? 'posted' : 'storage failed:' . $item_result['message']),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
}
if($relay && $item_id) {
@@ -1192,8 +1294,11 @@ function remove_community_tag($sender,$arr,$uid) {
function update_imported_item($sender,$item,$uid) {
- item_store_update($item);
- logger('update_imported_item');
+ $x = item_store_update($item);
+ if(! $x['item_id'])
+ logger('update_imported_item: failed: ' . $x['message']);
+ else
+ logger('update_imported_item');
}
@@ -1223,6 +1328,14 @@ function process_mail_delivery($sender,$arr,$deliveries) {
$result = array();
+
+
+ if($sender['hash'] != $arr['from_xchan']) {
+ logger('process_mail_delivery: sender is not mail author');
+ return;
+ }
+
+
foreach($deliveries as $d) {
$r = q("select * from channel where channel_hash = '%s' limit 1",
@@ -1277,7 +1390,12 @@ function process_profile_delivery($sender,$arr,$deliveries) {
// deliveries is irrelevant, what to do about birthday notification....?
logger('process_profile_delivery', LOGGER_DEBUG);
- import_directory_profile($sender['hash'],$arr);
+
+ $r = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
+ dbesc($sender['hash'])
+ );
+ if($r)
+ import_directory_profile($sender['hash'],$arr,$r[0]['xchan_addr'], 1, 0);
}
@@ -1288,7 +1406,7 @@ function process_profile_delivery($sender,$arr,$deliveries) {
*
*/
-function import_directory_profile($hash,$profile) {
+function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_update = 0) {
logger('import_directory_profile', LOGGER_DEBUG);
if(! $hash)
@@ -1314,12 +1432,24 @@ function import_directory_profile($hash,$profile) {
foreach($profile['keywords'] as $kw) {
$kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false));
$kw = trim($kw,',');
+ $clean[] = $kw;
}
- $clean[] = $kw;
}
$arr['xprof_keywords'] = implode(' ',$clean);
+ // Self censored, make it so
+ // These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult".
+
+
+ if(in_arrayi('nsfw',$clean) || in_arrayi('adult',$clean)) {
+ q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s' limit 1",
+ intval(XCHAN_FLAGS_SELFCENSORED),
+ dbesc($hash)
+ );
+ }
+
+
$r = q("select * from xprof where xprof_hash = '%s' limit 1",
dbesc($hash)
);
@@ -1327,6 +1457,7 @@ function import_directory_profile($hash,$profile) {
$update = false;
foreach($r[0] as $k => $v) {
if((array_key_exists($k,$arr)) && ($arr[$k] != $v)) {
+ logger('import_directory_profile: update' . $k . ' => ' . $arr[$k]);
$update = true;
break;
}
@@ -1362,6 +1493,7 @@ function import_directory_profile($hash,$profile) {
}
else {
$update = true;
+ logger('import_directory_profile: new profile');
$x = q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
dbesc($arr['xprof_hash']),
dbesc($arr['xprof_desc']),
@@ -1381,8 +1513,8 @@ function import_directory_profile($hash,$profile) {
$d = array('xprof' => $arr, 'profile' => $profile, 'update' => $update);
call_hooks('import_directory_profile', $d);
- if($d['update'])
- update_modtime($arr['xprof_hash']);
+ if(($d['update']) && (! $suppress_update))
+ update_modtime($arr['xprof_hash'],random_string() . '@' . get_app()->get_hostname(), $addr, $ud_flags);
return $d['update'];
}
@@ -1401,6 +1533,7 @@ function import_directory_keywords($hash,$keywords) {
$clean = array();
foreach($keywords as $kw) {
$kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false));
+ $kw = trim($kw,',');
$clean[] = $kw;
}
@@ -1421,20 +1554,23 @@ function import_directory_keywords($hash,$keywords) {
}
-function update_modtime($hash) {
- $r = q("select * from updates where ud_hash = '%s' limit 1",
- dbesc($hash)
- );
- if($r)
- q("update updates set ud_date = '%s' where ud_hash = '%s' limit 1",
+function update_modtime($hash,$guid,$addr,$flags = 0) {
+
+ if($flags) {
+ q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
+ dbesc($hash),
+ dbesc($guid),
dbesc(datetime_convert()),
- dbesc($hash)
+ intval($flags),
+ dbesc($addr)
);
- else
- q("insert into updates (ud_hash, ud_date) values ( '%s', '%s' )",
- dbesc($hash),
- dbesc(datetime_convert())
+ }
+ else {
+ q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d) ",
+ intval(UPDATE_FLAGS_UPDATED),
+ intval(UPDATE_FLAGS_UPDATED)
);
+ }
}
@@ -1448,12 +1584,15 @@ function import_site($arr,$pubkey) {
}
$update = false;
+ $exists = false;
$r = q("select * from site where site_url = '%s' limit 1",
dbesc($arr['url'])
);
- if($r)
- $update = true;
+ if($r) {
+ $exists = true;
+ $siterecord = $r[0];
+ }
$site_directory = 0;
if($arr['directory_mode'] == 'normal')
@@ -1474,34 +1613,66 @@ function import_site($arr,$pubkey) {
if($arr['register_policy'] == 'approve')
$register_policy = REGISTER_APPROVE;
- if($update) {
- $r = q("update site set site_flags = %d, site_directory = '%s', site_register = %d, site_update = '%s'
- where site_url = '%s' limit 1",
- intval($site_directory),
- dbesc(htmlentities($arr['directory_url'],ENT_COMPAT,'UTF-8',false)),
- intval($register_policy),
- dbesc(datetime_convert()),
- dbesc(htmlentities($arr['url'],ENT_COMPAT,'UTF-8',false))
- );
- if(! $r) {
- logger('import_site: update failed. ' . print_r($arr,true));
+ $access_policy = 0;
+ if(array_key_exists('access_policy',$arr)) {
+ if($arr['access_policy'] === 'private')
+ $access_policy = ACCESS_PRIVATE;
+ if($arr['access_policy'] === 'paid')
+ $access_policy = ACCESS_PAID;
+ if($arr['access_policy'] === 'free')
+ $access_policy = ACCESS_FREE;
+ if($arr['access_policy'] === 'tiered')
+ $access_policy = ACCESS_TIERED;
+ }
+
+ $directory_url = htmlentities($arr['directory_url'],ENT_COMPAT,'UTF-8',false);
+ $url = htmlentities($arr['url'],ENT_COMPAT,'UTF-8',false);
+ $sellpage = htmlentities($arr['sellpage'],ENT_COMPAT,'UTF-8',false);
+
+ if($exists) {
+ if(($siterecord['site_flags'] != $site_directory)
+ || ($siterecord['site_access'] != $access_policy)
+ || ($siterecord['site_directory'] != $directory_url)
+ || ($siterecord['site_sellpage'] != $sellpage)
+ || ($siterecord['site_register'] != $register_policy)) {
+ $update = true;
+
+// logger('import_site: input: ' . print_r($arr,true));
+// logger('import_site: stored: ' . print_r($siterecord,true));
+
+ $r = q("update site set site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s'
+ where site_url = '%s' limit 1",
+ intval($site_directory),
+ intval($access_policy),
+ dbesc($directory_url),
+ intval($register_policy),
+ dbesc(datetime_convert()),
+ dbesc($sellpage),
+ dbesc($url)
+ );
+ if(! $r) {
+ logger('import_site: update failed. ' . print_r($arr,true));
+ }
}
}
else {
- $r = q("insert into site ( site_url, site_flags, site_update, site_directory, site_register )
- values ( '%s', %d, '%s', '%s', %d )",
- dbesc(htmlentities($arr['url'],ENT_COMPAT,'UTF-8',false)),
+ $update = true;
+ $r = q("insert into site ( site_url, site_access, site_flags, site_update, site_directory, site_register, site_sellpage )
+ values ( '%s', %d, %d, '%s', '%s', %d, '%s' )",
+ dbesc($url),
intval($site_directory),
+ intval($access_policy),
dbesc(datetime_convert()),
- dbesc(htmlentities($arr['directory_url'],ENT_COMPAT,'UTF-8',false)),
- intval($register_policy)
+ dbesc($directory_url),
+ intval($register_policy),
+ dbesc($sellpage)
);
if(! $r) {
logger('import_site: record create failed. ' . print_r($arr,true));
}
}
- return $r;
+ return $update;
}
@@ -1675,7 +1846,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
$clean = array();
foreach($arr['abook'] as $abook) {
foreach($abook as $k => $v) {
- if(in_array($k,$disallowed))
+ if(in_array($k,$disallowed) || (strpos($k,'abook') !== 0))
continue;
$clean[$k] = $v;
}
@@ -1683,6 +1854,20 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
if(! array_key_exists('abook_xchan',$clean))
continue;
+ $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ dbesc($clean['abook_xchan']),
+ intval($channel['channel_id'])
+ );
+
+ // make sure we have an abook entry for this xchan on this system
+
+ if(! $r) {
+ q("insert into abook ( abook_xchan, abook_channel ) values ('%s', %d ) ",
+ dbesc($clean['abook_xchan']),
+ intval($channel['channel_id'])
+ );
+ }
+
if(count($clean)) {
foreach($clean as $k => $v) {
$r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v)