aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php2
-rw-r--r--include/ConversationObject.php17
-rw-r--r--include/acl_selectors.php10
-rw-r--r--include/api.php17
-rw-r--r--include/bbcode.php8
-rw-r--r--include/cache.php47
-rw-r--r--include/conversation.php120
-rw-r--r--include/directory.php5
-rw-r--r--include/enotify.php30
-rw-r--r--include/expire.php29
-rw-r--r--include/externals.php98
-rw-r--r--include/follow.php6
-rw-r--r--include/hubloc.php33
-rw-r--r--include/identity.php95
-rwxr-xr-xinclude/items.php221
-rw-r--r--include/nav.php2
-rw-r--r--include/network.php38
-rw-r--r--include/notifier.php38
-rwxr-xr-xinclude/oembed.php5
-rw-r--r--include/permissions.php28
-rw-r--r--include/photo/photo_driver.php2
-rw-r--r--include/photos.php13
-rw-r--r--include/poller.php22
-rw-r--r--include/probe.php99
-rw-r--r--include/queue.php8
-rw-r--r--include/reddav.php18
-rw-r--r--include/security.php19
-rw-r--r--include/socgraph.php5
-rwxr-xr-xinclude/text.php92
-rw-r--r--include/widgets.php14
-rw-r--r--include/zot.php166
31 files changed, 982 insertions, 325 deletions
diff --git a/include/Contact.php b/include/Contact.php
index 9883c598d..540e1169d 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -263,7 +263,7 @@ function channel_remove($channel_id, $local = true) {
q("DELETE FROM `event` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `item` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `item_id` WHERE `uid` = %d", intval($channel_id));
- q("DELETE FROM `mail` WHERE `uid` = %d", intval($channel_id));
+ q("DELETE FROM `mail` WHERE `channel_id` = %d", intval($channel_id));
q("DELETE FROM `notify` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `photo` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `attach` WHERE `uid` = %d", intval($channel_id));
diff --git a/include/ConversationObject.php b/include/ConversationObject.php
index 103c3664b..9bf410358 100644
--- a/include/ConversationObject.php
+++ b/include/ConversationObject.php
@@ -52,8 +52,14 @@ class Conversation extends BaseObject {
switch($mode) {
case 'network':
- $this->profile_owner = local_user();
- $this->writable = true;
+ if(array_key_exists('firehose',$a->data) && intval($a->data['firehose'])) {
+ $this->profile_owner = intval($a->data['firehose']);
+ $this->writable = false;
+ }
+ else {
+ $this->profile_owner = local_user();
+ $this->writable = true;
+ }
break;
case 'channel':
$this->profile_owner = $a->profile['profile_uid'];
@@ -175,6 +181,13 @@ class Conversation extends BaseObject {
$item->set_commentable(can_comment_on_post($this->observer['xchan_hash'],$item->data));
}
+ require_once('include/identity.php');
+ $sys = get_sys_channel();
+
+ if($sys && $item->get_data_value('uid') == $sys['channel_id']) {
+ $item->set_commentable(false);
+ }
+
$item->set_conversation($this);
$this->threads[] = $item;
return end($this->threads);
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index 749ca75eb..6ce4c3f9b 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -230,15 +230,21 @@ function populate_acl($defaults = null,$unused = false) {
array_walk($deny_gid,'fixacl');
}
+ $jotnets = '';
+ call_hooks('jot_networks', $jotnets);
+
$tpl = get_markup_template("acl_selector.tpl");
$o = replace_macros($tpl, array(
'$showall'=> t("Visible to everybody"),
- '$show' => t("show"),
- '$hide' => t("don't show"),
+ '$show' => t("Show"),
+ '$hide' => t("Don't show"),
'$allowcid' => json_encode($allow_cid),
'$allowgid' => json_encode($allow_gid),
'$denycid' => json_encode($deny_cid),
'$denygid' => json_encode($deny_gid),
+ '$jotnets' => $jotnets,
+ '$aclModalTitle' => t('Permissions'),
+ '$aclModalDismiss' => t('Close')
));
diff --git a/include/api.php b/include/api.php
index 47c78113a..57551a3b0 100644
--- a/include/api.php
+++ b/include/api.php
@@ -533,12 +533,6 @@ require_once('include/items.php');
api_register_func('api/red/channel/export/basic','api_export_basic', true);
-
-
-
-
-
-
function api_channel_stream(&$a, $type) {
if(api_user() === false) {
logger('api_channel_stream: no user');
@@ -700,12 +694,12 @@ require_once('include/items.php');
function red_item_new(&$a, $type) {
if (api_user() === false) {
- logger('api_statuses_update: no user');
+ logger('api_red_item_new: no user');
return false;
}
- logger('api_statuses_update: REQUEST ' . print_r($_REQUEST,true));
- logger('api_statuses_update: FILES ' . print_r($_FILES,true));
+ logger('api_red_item_new: REQUEST ' . print_r($_REQUEST,true));
+ logger('api_red_item_new: FILES ' . print_r($_FILES,true));
// set this so that the item_post() function is quiet and doesn't redirect or emit json
@@ -1552,7 +1546,8 @@ require_once('include/items.php');
'geo' => '',
'favorited' => (($item['item_flags'] & ITEM_STARRED) ? true : false),
'user' => $status_user ,
- 'statusnet_html' => trim(prepare_text($item['body']),$item['mimetype']),
+ 'statusnet_html' => trim(prepare_text($item['body'],$item['mimetype'])),
+
'statusnet_conversation_id' => $item['parent'],
);
@@ -1697,7 +1692,7 @@ require_once('include/items.php');
'broughtbyurl' => '', 'timezone' => 'UTC', 'closed' => $closed, 'inviteonly' => 'false',
'private' => $private, 'textlimit' => $textlimit, 'sslserver' => $sslserver, 'ssl' => $ssl,
'shorturllength' => '30',
- 'friendica' => array(
+ 'redmatrix' => array(
'RED_PLATFORM' => RED_PLATFORM,
'RED_VERSION' => RED_VERSION,
'ZOT_REVISION' => ZOT_REVISION,
diff --git a/include/bbcode.php b/include/bbcode.php
index cd0bf527e..96242fdac 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -229,9 +229,11 @@ function bb_location($match) {
function bbiframe($match) {
$a = get_app();
- if(strpos($match[1],get_app()->get_hostname()))
- return '<a href="' . $match[1] . '">' . $match[1] . '</a>';
- return '<iframe src="' . $match[1] . '" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>';
+
+
+ $sandbox = ((strpos($match[1],get_app()->get_hostname())) ? ' sandbox="allow-scripts" ' : '');
+
+ return '<iframe ' . $sandbox . ' src="' . $match[1] . '" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>';
}
function bb_ShareAttributesSimple($match) {
diff --git a/include/cache.php b/include/cache.php
index b546cd0e9..a70650b5e 100644
--- a/include/cache.php
+++ b/include/cache.php
@@ -6,52 +6,37 @@
class Cache {
public static function get($key){
- $r = q("SELECT `v` FROM `cache` WHERE `k`='%s' limit 1",
+ $r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
dbesc($key)
);
- if (count($r)) return $r[0]['v'];
+ if ($r)
+ return $r[0]['v'];
return null;
}
public static function set($key,$value) {
- q("REPLACE INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')",
+ $r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
+ dbesc($key)
+ );
+ if($r) {
+ q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s' limit 1",
+ dbesc($value),
+ dbesc(datetime_convert()),
+ dbesc($key));
+ }
+ else {
+ q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
dbesc($key),
dbesc($value),
dbesc(datetime_convert()));
+ }
}
-/*
- *
- * Leaving this legacy code temporaily to see how REPLACE fares
- * as opposed to non-atomic checks when faced with fast moving key duplication.
- * As a MySQL extension it isn't portable, but we're not yet very portable.
- */
-
-/*
- * $r = q("SELECT * FROM `cache` WHERE `k`='%s' limit 1",
- * dbesc($key)
- * );
- * if(count($r)) {
- * q("UPDATE `cache` SET `v` = '%s', `updated = '%s' WHERE `k` = '%s' limit 1",
- * dbesc($value),
- * dbesc(datetime_convert()),
- * dbesc($key));
- * }
- * else {
- * q("INSERT INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')",
- * dbesc($key),
- * dbesc($value),
- * dbesc(datetime_convert()));
- * }
- * }
- */
-
-
public static function clear(){
- q("DELETE FROM `cache` WHERE `updated` < '%s'",
+ q("DELETE FROM cache WHERE updated < '%s'",
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
}
diff --git a/include/conversation.php b/include/conversation.php
index 16ac4e909..2d72f3489 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -635,7 +635,11 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$star = false;
$isstarred = "unstarred icon-star-empty";
- $lock = false;
+ $lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
+ ? t('Private Message')
+ : false
+ );
+
$likebuttons = false;
$shareable = false;
@@ -911,7 +915,7 @@ function item_photo_menu($item){
}
}
- $profile_link = z_root() . "/chanview/?f=&hash=" . $item['author_xchan'];
+ $profile_link = chanlink_hash($item['author_xchan']);
$pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan'];
if($a->contacts && array_key_exists($item['author_xchan'],$a->contacts))
@@ -964,13 +968,7 @@ function like_puller($a,$item,&$arr,$mode) {
$verb = (($mode === 'like') ? ACTIVITY_LIKE : ACTIVITY_DISLIKE);
if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) {
- $url = $item['author']['xchan_url'];
- if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === 'dfrn') && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) {
- $url = $a->get_baseurl(true) . '/redir/' . $item['contact-id'];
- $sparkle = ' class="sparkle" ';
- }
- else
- $url = zid($url);
+ $url = chanlink_url($item['author']['xchan_url']);
if(! $item['thr_parent'])
$item['thr_parent'] = $item['parent_mid'];
@@ -981,7 +979,7 @@ function like_puller($a,$item,&$arr,$mode) {
$arr[$item['thr_parent']] = 1;
else
$arr[$item['thr_parent']] ++;
- $arr[$item['thr_parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['author']['xchan_name'] . '</a>';
+ $arr[$item['thr_parent'] . '-l'][] = '<a href="'. $url . '">' . $item['author']['xchan_name'] . '</a>';
}
return;
}
@@ -1052,6 +1050,13 @@ function status_editor($a,$x,$popup=false) {
}
+ if(array_key_exists('channel_select',$x) && $x['channel_select']) {
+ require_once('include/identity.php');
+ $id_select = identity_selector();
+ }
+ else
+ $id_select = '';
+
$webpage = ((x($x,'webpage')) ? $x['webpage'] : '');
@@ -1098,6 +1103,8 @@ function status_editor($a,$x,$popup=false) {
'$webpage' => $webpage,
'$placeholdpagetitle' => ((x($x,'ptlabel')) ? $x['ptlabel'] : t('Page link title')),
'$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''),
+ '$id_select' => $id_select,
+ '$id_seltext' => t('Post as'),
'$upload' => t('Upload photo'),
'$shortupload' => t('upload photo'),
'$attach' => t('Attach file'),
@@ -1126,7 +1133,6 @@ function status_editor($a,$x,$popup=false) {
'$baseurl' => $a->get_baseurl(true),
'$defloc' => $x['default_location'],
'$visitor' => $x['visitor'],
- '$pvisit' => (($notes_cid) ? 'none' : $x['visitor']),
'$public' => t('Public post'),
'$jotnets' => $jotnets,
'$emtitle' => t('Example: bob@example.com, mary@example.com'),
@@ -1134,20 +1140,20 @@ function status_editor($a,$x,$popup=false) {
'$acl' => $x['acl'],
'$mimeselect' => $mimeselect,
'$layoutselect' => $layoutselect,
- '$showacl' => ((array_key_exists('showacl',$x)) ? $x['showacl'] : 'yes'),
+ '$showacl' => ((array_key_exists('showacl',$x)) ? $x['showacl'] : true),
'$bang' => $x['bang'],
'$profile_uid' => $x['profile_uid'],
'$preview' => $preview,
'$source' => ((x($x,'source')) ? $x['source'] : ''),
'$jotplugins' => $jotplugins,
'$defexpire' => '',
- '$feature_expire' => ((feature_enabled($x['profile_uid'],'content_expire') && (! $webpage)) ? 'block' : 'none'),
+ '$feature_expire' => ((feature_enabled($x['profile_uid'],'content_expire') && (! $webpage)) ? true : false),
'$expires' => t('Set expiration date'),
- '$feature_encrypt' => ((feature_enabled($x['profile_uid'],'content_encrypt') && (! $webpage)) ? 'block' : 'none'),
+ '$feature_encrypt' => ((feature_enabled($x['profile_uid'],'content_encrypt') && (! $webpage)) ? true : false),
'$encrypt' => t('Encrypt text'),
'$cipher' => $cipher,
'$expiryModalOK' => t('OK'),
- '$expiryModalCANCEL' => t('Cancel'),
+ '$expiryModalCANCEL' => t('Cancel')
));
@@ -1287,7 +1293,7 @@ function render_location_default($item) {
if($coord) {
if($location)
- $location .= '<br /><span class="smalltext">(' . $coord . ')</span>';
+ $location .= '&nbsp;<span class="smalltext">(' . $coord . ')</span>';
else
$location = '<span class="smalltext">' . $coord . '</span>';
}
@@ -1297,11 +1303,9 @@ function render_location_default($item) {
function prepare_page($item) {
-
$a = get_app();
$naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
$observer = $a->get_observer();
- $zid = ($observer['xchan_addr']);
//240 chars is the longest we can have before we start hitting problems with suhosin sites
$preview = substr(urlencode($item['body']), 0, 240);
$link = z_root() . '/' . $a->cmd;
@@ -1312,8 +1316,7 @@ function prepare_page($item) {
}
return replace_macros(get_markup_template('page_display.tpl'),array(
'$author' => (($naked) ? '' : $item['author']['xchan_name']),
- '$auth_url' => (($naked) ? '' : $item['author']['xchan_url']),
- '$zid' => $zid,
+ '$auth_url' => (($naked) ? '' : zid($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' => prepare_body($item,true),
@@ -1333,6 +1336,7 @@ function network_tabs() {
$conv_active = '';
$spam_active = '';
$postord_active = '';
+ $public_active = '';
if(x($_GET,'new')) {
$new_active = 'active';
@@ -1354,13 +1358,18 @@ function network_tabs() {
$spam_active = 'active';
}
+ if(x($_GET,'fh')) {
+ $public_active = 'active';
+ }
+
if (($new_active == '')
&& ($starred_active == '')
&& ($conv_active == '')
&& ($search_active == '')
- && ($spam_active == '')) {
+ && ($spam_active == '')
+ && ($public_active == '')) {
$no_active = 'active';
}
@@ -1376,52 +1385,67 @@ function network_tabs() {
$cmd = $a->cmd;
// tabs
- $tabs = array(
- array(
- 'label' => t('Commented Order'),
- 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
- 'sel'=>$all_active,
- 'title'=> t('Sort by Comment Date'),
- ),
- array(
- 'label' => t('Posted Order'),
- 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
- 'sel'=>$postord_active,
- 'title' => t('Sort by Post Date'),
- ),
+ $tabs = array();
- array(
+ if(! get_config('system','disable_discover_tab')) {
+ $tabs[] = array(
+ 'label' => t('Discover'),
+ 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&fh=1' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
+ 'sel'=> $public_active,
+ 'title'=> t('Imported public streams'),
+ );
+ }
+
+ $tabs[] = array(
+ 'label' => t('Commented Order'),
+ 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
+ 'sel'=>$all_active,
+ 'title'=> t('Sort by Comment Date'),
+ );
+
+ $tabs[] = array(
+ 'label' => t('Posted Order'),
+ 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
+ 'sel'=>$postord_active,
+ 'title' => t('Sort by Post Date'),
+ );
+
+ if(feature_enabled(local_user(),'personal_tab')) {
+ $tabs[] = array(
'label' => t('Personal'),
'url' => $a->get_baseurl(true) . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&conv=1',
'sel' => $conv_active,
'title' => t('Posts that mention or involve you'),
- ),
- array(
+ );
+ }
+
+ if(feature_enabled(local_user(),'new_tab')) {
+ $tabs[] = array(
'label' => t('New'),
'url' => $a->get_baseurl(true) . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel' => $new_active,
'title' => t('Activity Stream - by date'),
- ),
-
- );
+ );
+ }
- if(feature_enabled(local_user(),'star_posts'))
+ if(feature_enabled(local_user(),'star_posts')) {
$tabs[] = array(
'label' => t('Starred'),
'url'=>$a->get_baseurl(true) . '/' . $cmd . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '') . '&star=1',
'sel'=>$starred_active,
'title' => t('Favourite Posts'),
);
-
+ }
// Not yet implemented
- if(feature_enabled(local_user(),'spam_filter'))
+ if(feature_enabled(local_user(),'spam_filter')) {
$tabs[] = array(
'label' => t('Spam'),
'url'=>$a->get_baseurl(true) . '/network?f=&spam=1',
'sel'=> $spam_active,
'title' => t('Posts flagged as SPAM'),
- );
+ );
+ }
$arr = array('tabs' => $tabs);
call_hooks('network_tabs', $arr);
@@ -1442,6 +1466,8 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
if (is_null($nickname))
$nickname = $channel['channel_address'];
+
+ $uid = (($a->profile['profile_uid']) ? $a->profile['profile_uid'] : local_user());
if(x($_GET,'tab'))
$tab = notags(trim($_GET['tab']));
@@ -1459,7 +1485,7 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
),
);
- $p = get_all_perms($a->profile['profile_uid'],get_observer_hash());
+ $p = get_all_perms($uid,get_observer_hash());
if($p['view_profile']) {
$tabs[] = array(
@@ -1490,7 +1516,7 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
}
require_once('include/chat.php');
- $chats = chatroom_list($a->profile['profile_uid']);
+ $chats = chatroom_list($uid);
$subdued = ((count($chats)) ? '' : ' subdued');
$tabs[] = array(
'label' => t('Chatrooms'),
@@ -1520,7 +1546,7 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
}
- if($is_owner && feature_enabled($a->profile['profile_uid'],'webpages')) {
+ if($is_owner && feature_enabled($uid,'webpages')) {
$tabs[] = array(
'label' => t('Webpages'),
'url' => $a->get_baseurl() . '/webpages/' . $nickname,
diff --git a/include/directory.php b/include/directory.php
index 794420b6f..c69fb1f4b 100644
--- a/include/directory.php
+++ b/include/directory.php
@@ -69,11 +69,12 @@ function directory_run($argv, $argc){
// the directory packet. That means we'll try again on the next poll run.
$hash = random_string();
- 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' )",
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg )
+ values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($channel['channel_account_id']),
intval($channel['channel_id']),
+ dbesc('zot'),
dbesc($url),
intval(1),
dbesc(datetime_convert()),
diff --git a/include/enotify.php b/include/enotify.php
index 036d5275e..7ab4fe5ed 100644
--- a/include/enotify.php
+++ b/include/enotify.php
@@ -18,8 +18,9 @@ function notification($params) {
}
if($params['to_xchan']) {
$y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id
- where channel_hash = '%s' limit 1",
- dbesc($params['to_xchan'])
+ where channel_hash = '%s' and not (channel_pageflags & %d) limit 1",
+ dbesc($params['to_xchan']),
+ intval(PAGE_REMOVED)
);
}
if($x & $y) {
@@ -88,7 +89,7 @@ function notification($params) {
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
- $itemlink = $siteurl . '/message/' . $params['item']['id'];
+ $itemlink = $siteurl . '/mail/' . $params['item']['id'];
}
if($params['type'] == NOTIFY_COMMENT) {
@@ -102,7 +103,7 @@ function notification($params) {
if(array_key_exists('item',$params) && (! visible_activity($params['item'])))
return;
- $parent_id = $params['parent'];
+ $parent_mid = $params['parent_mid'];
// Check to see if there was already a notify for this post.
// If so don't create a second notification
@@ -123,9 +124,9 @@ function notification($params) {
$p = null;
- if($params['otype'] === 'item' && $parent_id) {
- $p = q("select * from item where id = %d and uid = %d limit 1",
- intval($parent_id),
+ if($params['otype'] === 'item' && $parent_mid) {
+ $p = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($parent_mid),
intval($recip['channel_id'])
);
}
@@ -135,6 +136,7 @@ function notification($params) {
$item_post_type = item_post_type($p[0]);
$private = $p[0]['item_private'];
+ $parent_id = $p[0]['id'];
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
@@ -253,14 +255,14 @@ function notification($params) {
if($params['type'] == NOTIFY_INTRO) {
$subject = sprintf( t('[Red:Notify] Introduction received'));
- $preamble = sprintf( t('%1$s, you\'ve received an introduction from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
- $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]an introduction[/zrl] from %3$s.'),
+ $preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
+ $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'),
$recip['channel_name'],
$itemlink,
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = sprintf( t('You may visit their profile at %s'),$sender['xchan_url']);
- $sitelink = t('Please visit %s to approve or reject the introduction.');
+ $sitelink = t('Please visit %s to approve or reject the connection request.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
@@ -338,7 +340,7 @@ function notification($params) {
$datarray['aid'] = $recip['channel_account_id'];
$datarray['uid'] = $recip['channel_id'];
$datarray['link'] = $itemlink;
- $datarray['parent'] = $parent_id;
+ $datarray['parent'] = $parent_mid;
$datarray['type'] = $params['type'];
$datarray['verb'] = $params['verb'];
$datarray['otype'] = $params['otype'];
@@ -355,7 +357,7 @@ function notification($params) {
// create notification entry in DB
$r = q("insert into notify (hash,name,url,photo,date,aid,uid,link,parent,type,verb,otype)
- values('%s','%s','%s','%s','%s',%d,%d,'%s',%d,%d,'%s','%s')",
+ values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,'%s','%s')",
dbesc($datarray['hash']),
dbesc($datarray['name']),
dbesc($datarray['url']),
@@ -364,7 +366,7 @@ function notification($params) {
intval($datarray['aid']),
intval($datarray['uid']),
dbesc($datarray['link']),
- intval($datarray['parent']),
+ dbesc($datarray['parent']),
intval($datarray['type']),
dbesc($datarray['verb']),
dbesc($datarray['otype'])
@@ -432,7 +434,7 @@ function notification($params) {
$datarray['sitename'] = $sitename;
$datarray['siteurl'] = $siteurl;
$datarray['type'] = $params['type'];
- $datarray['parent'] = $params['parent'];
+ $datarray['parent'] = $params['parent_mid'];
$datarray['source_name'] = $sender['xchan_name'];
$datarray['source_link'] = $sender['xchan_url'];
$datarray['source_photo'] = $sender['xchan_photo_s'];
diff --git a/include/expire.php b/include/expire.php
index 2d94d64c0..442914a39 100644
--- a/include/expire.php
+++ b/include/expire.php
@@ -7,10 +7,20 @@ function expire_run($argv, $argc){
cli_startup();
+ $r = q("select id from item where (item_restrict & %d) and not (item_restrict & %d) and changed < UTC_TIMESTAMP() - INTERVAL 10 DAY",
+ intval(ITEM_DELETED),
+ intval(ITEM_PENDING_REMOVE)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ drop_item($rr['id'],false,DROPITEM_PHASE2);
+ }
+ }
+
// physically remove anything that has been deleted for more than two months
- $r = q("delete from item where ( item_flags & %d ) and changed < UTC_TIMESTAMP() - INTERVAL 60 DAY",
- intval(ITEM_DELETED)
+ $r = q("delete from item where ( item_restrict & %d ) and changed < UTC_TIMESTAMP() - INTERVAL 36 DAY",
+ intval(ITEM_PENDING_REMOVE)
);
// make this optional as it could have a performance impact on large sites
@@ -29,6 +39,21 @@ function expire_run($argv, $argc){
}
}
+
+ $x = get_sys_channel();
+ if($x) {
+
+ // this should probably just fetch the channel_expire_days from the sys channel,
+ // but there's no convenient way to set it.
+
+ $expire_days = get_config('externals','expire_days');
+ if($expire_days === false)
+ $expire_days = 30;
+ if($expire_days)
+ item_expire($x['channel_id'],$expire_days);
+ }
+
+
return;
}
diff --git a/include/externals.php b/include/externals.php
new file mode 100644
index 000000000..1d9fd2902
--- /dev/null
+++ b/include/externals.php
@@ -0,0 +1,98 @@
+<?php /** @file */
+
+require_once('boot.php');
+require_once('include/cli_startup.php');
+require_once('include/zot.php');
+require_once('include/identity.php');
+
+function externals_run($argv, $argc){
+
+ cli_startup();
+ $a = get_app();
+
+
+ $total = 0;
+ $attempts = 0;
+
+ // pull in some public posts
+
+
+ while($total == 0 && $attempts < 3) {
+ $arr = array('url' => '');
+ call_hooks('externals_url_select',$arr);
+
+ if($arr['url']) {
+ $url = $arr['url'];
+ }
+ else {
+ $r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d order by rand() limit 1",
+ dbesc(z_root()),
+ intval(DIRECTORY_MODE_STANDALONE)
+ );
+ if($r)
+ $url = $r[0]['site_url'];
+ }
+
+ $attempts ++;
+
+ if($url) {
+ if($r[0]['site_pull'] !== '0000-00-00 00:00:00')
+ $mindate = urlencode($r[0]['site_pull']);
+ else {
+ $days = get_config('externals','since_days');
+ if($days === false)
+ $days = 15;
+ $mindate = urlencode(datetime_convert('','','now - ' . intval($days) . ' days'));
+ }
+
+ $feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
+
+ logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
+
+ $x = z_fetch_url($feedurl);
+ if(($x) && ($x['success'])) {
+
+ q("update site set site_pull = '%s' where site_url = '%s' limit 1",
+ dbesc(datetime_convert()),
+ dbesc($url)
+ );
+
+ $j = json_decode($x['body'],true);
+ if($j['success'] && $j['messages']) {
+ $sys = get_sys_channel();
+ foreach($j['messages'] as $message) {
+ $results = process_delivery(array('hash' => 'undefined'), get_item_elements($message),
+ array(array('hash' => $sys['xchan_hash'])), false, true);
+ $total ++;
+// $z = q("select id from item where mid = '%s' and uid = %d limit 1",
+// dbesc($message['message_id']),
+// intval($sys['channel_id'])
+// );
+$z = null;
+ if($z) {
+ $flag_bits = ITEM_WALL|ITEM_ORIGIN|ITEM_UPLINK;
+ // preserve the source
+
+ $r = q("update item set source_xchan = owner_xchan where id = %d limit 1",
+ intval($z[0]['id'])
+ );
+
+ $r = q("update item set item_flags = ( item_flags | %d ), owner_xchan = '%s'
+ where id = %d limit 1",
+ intval($flag_bits),
+ dbesc($sys['xchan_hash']),
+ intval($z[0]['id'])
+ );
+ }
+ }
+ logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
+ }
+ }
+ }
+ }
+}
+
+if (array_search(__file__,get_included_files())===0){
+ externals_run($argv,$argc);
+ killme();
+}
diff --git a/include/follow.php b/include/follow.php
index 0508a8b37..d98a58198 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -75,11 +75,17 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
return $result;
}
+
// do we have an xchan and hubloc?
// If not, create them.
$x = import_xchan($j);
+ if(array_key_exists('deleted',$j) && intval($j['deleted'])) {
+ $result['message'] = t('Channel was deleted and no longer exists.');
+ return $result;
+ }
+
if(! $x['success'])
return $x;
diff --git a/include/hubloc.php b/include/hubloc.php
new file mode 100644
index 000000000..35d9dbeb1
--- /dev/null
+++ b/include/hubloc.php
@@ -0,0 +1,33 @@
+<?php /** @file */
+
+
+
+function prune_hub_reinstalls() {
+
+ $r = q("select site_url from site where true");
+ if($r) {
+ foreach($r as $rr) {
+ $x = q("select count(*) as t, hubloc_sitekey, max(hubloc_connected) as c from hubloc where hubloc_url = '%s' group by hubloc_sitekey order by c",
+ dbesc($rr['site_url'])
+ );
+
+ // see if this url has more than one sitekey, indicating it has been re-installed.
+
+ if(count($x) > 1) {
+
+ $d1 = datetime_convert('UTC','UTC',$x[0]['c']);
+ $d2 = datetime_convert('UTC','UTC','now - 3 days');
+
+ // allow some slop period, say 3 days - just in case this is a glitch or transient occurrence
+ // Then remove any hublocs pointing to the oldest entry.
+
+ if($d1 < $d2) {
+ logger('prune_hub_reinstalls: removing dead hublocs at ' . $rr['site_url']);
+ $y = q("delete from hubloc where hubloc_sitekey = '%s'",
+ dbesc($x[0]['hubloc_sitekey'])
+ );
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/include/identity.php b/include/identity.php
index efc0d7d87..b66eaad51 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -80,6 +80,16 @@ function validate_channelname($name) {
function create_sys_channel() {
if(get_sys_channel())
return;
+
+ // Ensure that there is a host keypair.
+
+ if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) {
+ require_once('include/crypto.php');
+ $hostkey = new_keypair(4096);
+ set_config('system','pubkey',$hostkey['pubkey']);
+ set_config('system','prvkey',$hostkey['prvkey']);
+ }
+
create_identity(array(
'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required
'nickname' => 'sys',
@@ -99,6 +109,15 @@ function get_sys_channel() {
return false;
}
+function is_sys_channel($channel_id) {
+ $r = q("select channel_pageflags from channel where channel_id = %d limit 1",
+ intval($channel_id)
+ );
+ if(($r) && ($r[0]['channel_pageflags'] & PAGE_SYSTEM))
+ return true;
+ return false;
+}
+
/**
* @channel_total()
@@ -167,6 +186,11 @@ function create_identity($arr) {
return $ret;
}
+ if($nick === 'sys' && (! ($pageflags & PAGE_SYSTEM))) {
+ $ret['message'] = t('Reserved nickname. Please choose another.');
+ return $ret;
+ }
+
if(check_webbie(array($nick)) !== $nick) {
$ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
return $ret;
@@ -200,10 +224,13 @@ function create_identity($arr) {
$perms_vals .= ', ' . intval($v);
}
+ $expire = get_config('system', 'default_expire_days');
+ $expire = (($expire===false)? '0': $expire);
+
$r = q("insert into channel ( channel_account_id, channel_primary,
channel_name, channel_address, channel_guid, channel_guid_sig,
- channel_hash, channel_prvkey, channel_pubkey, channel_pageflags $perms_keys )
- values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d $perms_vals ) ",
+ channel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_expire_days $perms_keys )
+ values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d $perms_vals ) ",
intval($arr['account_id']),
intval($primary),
@@ -214,7 +241,8 @@ function create_identity($arr) {
dbesc($hash),
dbesc($key['prvkey']),
dbesc($key['pubkey']),
- intval($pageflags)
+ intval($pageflags),
+ intval($expire)
);
@@ -523,12 +551,20 @@ function profile_load(&$a, $nickname, $profile = '') {
);
}
+
if(! $p) {
logger('profile error: ' . $a->query_string, LOGGER_DEBUG);
notice( t('Requested profile is not available.') . EOL );
$a->error = 404;
return;
}
+
+ $z = q("select xchan_photo_date from xchan where xchan_hash = '%s' limit 1",
+ dbesc($p[0]['channel_hash'])
+ );
+ if($z)
+ $p[0]['picdate'] = $z[0]['xchan_photo_date'];
+
// fetch user tags if this isn't the default profile
@@ -547,14 +583,16 @@ function profile_load(&$a, $nickname, $profile = '') {
}
+ $a->profile = $p[0];
+ $a->profile_uid = $p[0]['profile_uid'];
+ $a->page['title'] = $a->profile['channel_name'] . " - " . $a->profile['channel_address'] . "@" . $a->get_hostname();
+
+ $a->profile['permission_to_view'] = $can_view_profile;
+
if($can_view_profile) {
- $a->profile = $p[0];
$online = get_online_status($nickname);
$a->profile['online_status'] = $online['result'];
- $a->profile_uid = $p[0]['profile_uid'];
-
- $a->page['title'] = $a->profile['channel_name'] . " - " . $a->profile['channel_address'] . "@" . $a->get_hostname();
}
if(local_user()) {
@@ -568,18 +606,12 @@ function profile_load(&$a, $nickname, $profile = '') {
$_SESSION['theme'] = $p[0]['channel_theme'];
- $a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one
+// $a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one
- $theme_info_file = "view/theme/".current_theme()."/php/theme.php";
- if (file_exists($theme_info_file)){
- require_once($theme_info_file);
- }
-
- if(! $can_view_profile) {
- // permission denied
- notice( t(' Sorry, you don\'t have the permission to view this profile. ') . EOL);
- return;
- }
+// $theme_info_file = "view/theme/".current_theme()."/php/theme.php";
+// if (file_exists($theme_info_file)){
+// require_once($theme_info_file);
+// }
return;
}
@@ -703,7 +735,7 @@ logger('online: ' . $profile['online']);
$block = true;
}
- if(($profile['hidewall'] || $block) && (! local_user()) && (! remote_user())) {
+ if(($profile['hidewall'] && (! local_user()) && (! remote_user())) || $block ) {
$location = $pdesc = $gender = $marital = $homepage = $online = False;
}
@@ -715,7 +747,7 @@ logger('online: ' . $profile['online']);
$channel_menu = false;
$menu = get_pconfig($profile['uid'],'system','channel_menu');
- if($menu) {
+ if($menu && ! $block) {
require_once('include/menu.php');
$m = menu_fetch($menu,$profile['uid'],$observer['xchan_hash']);
if($m)
@@ -940,7 +972,7 @@ function advanced_profile(&$a) {
if($a->profile['marital']) $profile['marital'] = array( t('Status:'), $a->profile['marital']);
- if($a->profile['with']) $profile['marital']['with'] = $a->profile['with'];
+ if($a->profile['with']) $profile['marital']['with'] = bbcode($a->profile['with']);
if(strlen($a->profile['howlong']) && $a->profile['howlong'] !== '0000-00-00 00:00:00') {
$profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s'));
@@ -1221,3 +1253,24 @@ function get_channel_by_nick($nick) {
return(($r) ? $r[0] : false);
}
+
+
+function identity_selector() {
+ if(local_user()) {
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and not ( channel_pageflags & %d ) order by channel_name ",
+ intval(get_account_id()),
+ intval(PAGE_REMOVED)
+ );
+ if(count($r) > 1) {
+ $selected_channel = null;
+ $account = get_app()->get_account();
+ $o = replace_macros(get_markup_template('channel_id_select.tpl'),array(
+ '$channels' => $r,
+ '$selected' => local_user()
+ ));
+ return $o;
+ }
+ }
+
+ return '';
+}
diff --git a/include/items.php b/include/items.php
index 70e098415..487666e36 100755
--- a/include/items.php
+++ b/include/items.php
@@ -81,6 +81,19 @@ function collect_recipients($item,&$private) {
$recipients = check_list_permissions($item['uid'],$recipients,'view_stream');
+ // remove any upstream recipients from our list.
+ // If it is ourself we'll add it back in a second.
+ // This should prevent complex delivery chains from getting overly complex by not
+ // sending to anybody who is on our list of those who sent it to us.
+
+ if($item['route']) {
+ $route = explode(',',$item['route']);
+ if(count($route)) {
+ $route = array_unique($route);
+ $recipients = array_diff($recipients,$route);
+ }
+ }
+
// add ourself just in case we have nomadic clones that need to get a copy.
$recipients[] = $item['author_xchan'];
@@ -141,6 +154,25 @@ function can_comment_on_post($observer_xchan,$item) {
}
+function add_source_route($iid,$hash) {
+// logger('add_source_route ' . $iid . ' ' . $hash, LOGGER_DEBUG);
+
+ if((! $iid) || (! $hash))
+ return;
+ $r = q("select route from item where id = %d limit 1",
+ intval($iid)
+ );
+ if($r) {
+ $new_route = (($r[0]['route']) ? $r[0]['route'] . ',' : '') . $hash;
+ q("update item set route = '%s' where id = %d limit 1",
+ (dbesc($new_route)),
+ intval($iid)
+ );
+ }
+}
+
+
+
/**
* @function red_zrl_callback
* preg_match function when fixing 'naked' links in mod item.php
@@ -636,6 +668,7 @@ function get_item_elements($x) {
$arr['app'] = (($x['app']) ? htmlspecialchars($x['app'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['route'] = (($x['route']) ? htmlspecialchars($x['route'], ENT_COMPAT,'UTF-8',false) : '');
$arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
$arr['parent_mid'] = (($x['message_top']) ? htmlspecialchars($x['message_top'], ENT_COMPAT,'UTF-8',false) : '');
$arr['thr_parent'] = (($x['message_parent']) ? htmlspecialchars($x['message_parent'], ENT_COMPAT,'UTF-8',false) : '');
@@ -647,7 +680,7 @@ function get_item_elements($x) {
$arr['mimetype'] = (($x['mimetype']) ? htmlspecialchars($x['mimetype'], ENT_COMPAT,'UTF-8',false) : '');
$arr['obj_type'] = (($x['object_type']) ? htmlspecialchars($x['object_type'], ENT_COMPAT,'UTF-8',false) : '');
$arr['tgt_type'] = (($x['target_type']) ? htmlspecialchars($x['target_type'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['comment_policy'] = (($x['comment_scope']) ? htmlspecialchars($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts');
+ $arr['comment_policy'] = (($x['comment_scope']) ? htmlspecialchars($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts');
$arr['sig'] = (($x['signature']) ? htmlspecialchars($x['signature'], ENT_COMPAT,'UTF-8',false) : '');
@@ -809,14 +842,6 @@ function encode_item($item) {
$item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key);
}
- if($item['item_restrict'] & ITEM_DELETED) {
- $x['message_id'] = $item['mid'];
- $x['created'] = $item['created'];
- $x['flags'] = array('deleted');
- $x['owner'] = encode_item_xchan($item['owner']);
- $x['author'] = encode_item_xchan($item['author']);
- return $x;
- }
$x['message_id'] = $item['mid'];
$x['message_top'] = $item['parent_mid'];
@@ -836,6 +861,7 @@ function encode_item($item) {
$x['location'] = $item['location'];
$x['longlat'] = $item['coord'];
$x['signature'] = $item['sig'];
+ $x['route'] = $item['route'];
$x['owner'] = encode_item_xchan($item['owner']);
$x['author'] = encode_item_xchan($item['author']);
@@ -859,7 +885,7 @@ function encode_item($item) {
if($item['term'])
$x['tags'] = encode_item_terms($item['term']);
- logger('encode_item: ' . print_r($x,true));
+ logger('encode_item: ' . print_r($x,true), LOGGER_DATA);
return $x;
@@ -1000,9 +1026,11 @@ function encode_item_flags($item) {
// most of item_flags and item_restrict are local settings which don't apply when transmitted.
// We may need those for the case of syncing other hub locations which you are attached to.
-// ITEM_DELETED is handled in encode_item directly so we don't need to handle it here.
$ret = array();
+
+ if($item['item_restrict'] & ITEM_DELETED)
+ $ret[] = 'deleted';
if($item['item_flags'] & ITEM_THREAD_TOP)
$ret[] = 'thread_parent';
if($item['item_flags'] & ITEM_NSFW)
@@ -2294,6 +2322,7 @@ function tag_deliver($uid,$item_id) {
logger('tag_deliver: community tag activity received');
if(($item['owner_xchan'] === $u[0]['channel_hash']) && (! get_pconfig($u[0]['channel_id'],'system','blocktags'))) {
+ logger('tag_deliver: community tag recipient: ' . $u[0]['channel_name']);
$j_tgt = json_decode_plus($item['target']);
if($j_tgt && $j_tgt['id']) {
$p = q("select * from item where mid = '%s' and uid = %d limit 1",
@@ -2306,6 +2335,7 @@ function tag_deliver($uid,$item_id) {
if($j_obj && $j_obj['id'] && $j_obj['title']) {
if(is_array($j_obj['link']))
$taglink = get_rel_link($j_obj['link'],'alternate');
+
store_item_tag($u[0]['channel_id'],$p[0]['id'],TERM_OBJ_POST,TERM_HASHTAG,$j_obj['title'],$j_obj['id']);
$x = q("update item set edited = '%s', received = '%s', changed = '%s' where mid = '%s' and uid = %d limit 1",
dbesc(datetime_convert()),
@@ -2420,16 +2450,24 @@ function tag_deliver($uid,$item_id) {
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$body);
+ $tagged = false;
+ $plustagged = false;
+
$pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
+ if(preg_match($pattern,$body,$matches))
+ $tagged = true;
+
+ $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'] . '+','/') . '\[\/zrl\]/';
+ if(preg_match($pattern,$body,$matches))
+ $plustagged = true;
- if(! preg_match($pattern,$body,$matches)) {
+ if(! ($tagged || $plustagged)) {
logger('tag_deliver: mention was in a reshare - ignoring');
return;
}
-
- // All good.
- // Send a notification
+
+ // Valid tag. Send a notification
require_once('include/enotify.php');
notification(array(
@@ -2442,6 +2480,14 @@ function tag_deliver($uid,$item_id) {
'otype' => 'item'
));
+ // Just a normal tag?
+
+ if(! $plustagged) {
+ logger('tag_deliver: not a plus tag', LOGGER_DEBUG);
+ return;
+ }
+
+ // plustagged - keep going, next check permissions
if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) {
logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']);
@@ -2556,7 +2602,7 @@ function tgroup_check($uid,$item) {
$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('tgroup_check: mention was in a reshare - ignoring');
@@ -3493,7 +3539,12 @@ function drop_items($items) {
// permissions to carry out this act. If it is non-interactive, we are deleting something at the
// system's request and do not check permission. This is very important to know.
-function drop_item($id,$interactive = true) {
+// Some deletion requests (those coming from remote sites) must be staged.
+// $stage = 0 => unstaged
+// $stage = 1 => set deleted flag on the item and perform intial notifications
+// $stage = 2 => perform low level delete at a later stage
+
+function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL) {
$a = get_app();
@@ -3503,7 +3554,7 @@ function drop_item($id,$interactive = true) {
intval($id)
);
- if((! $r) || ($r[0]['item_restrict'] & ITEM_DELETED)) {
+ if((! $r) || (($r[0]['item_restrict'] & ITEM_DELETED) && ($stage === DROPITEM_NORMAL))) {
if(! $interactive)
return 0;
notice( t('Item not found.') . EOL);
@@ -3537,7 +3588,7 @@ function drop_item($id,$interactive = true) {
intval($item['id'])
);
- $arr = array('item' => $item);
+ $arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage);
call_hooks('drop_item', $arr );
$notify_id = intval($item['id']);
@@ -3548,10 +3599,10 @@ function drop_item($id,$interactive = true) {
);
if($items) {
foreach($items as $i)
- delete_item_lowlevel($i);
+ delete_item_lowlevel($i,$stage);
}
else
- delete_item_lowlevel($item);
+ delete_item_lowlevel($item,$stage);
if(! $interactive)
return 1;
@@ -3559,7 +3610,7 @@ function drop_item($id,$interactive = true) {
// send the notification upstream/downstream as the case may be
// only send notifications to others if this is the owner's wall item.
- if($item['item_flags'] & ITEM_WALL)
+ if(($item['item_flags'] & ITEM_WALL) && ($stage != DROPITEM_PHASE2))
proc_run('php','include/notifier.php','drop',$notify_id);
goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
@@ -3578,15 +3629,47 @@ function drop_item($id,$interactive = true) {
// It merely destroys all resources associated with an item.
// Please do not use without a suitable wrapper.
-function delete_item_lowlevel($item) {
+function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL) {
- $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), title = '', body = '',
- changed = '%s', edited = '%s' WHERE id = %d LIMIT 1",
- intval(ITEM_DELETED),
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval($item['id'])
- );
+
+ switch($stage) {
+ case DROPITEM_PHASE2:
+ $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), body = '', title = '',
+ changed = '%s', edited = '%s' WHERE id = %d LIMIT 1",
+ intval(ITEM_PENDING_REMOVE),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($item['id'])
+ );
+ break;
+
+ case DROPITEM_PHASE1:
+ $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ),
+ changed = '%s', edited = '%s' WHERE id = %d LIMIT 1",
+ intval(ITEM_DELETED),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($item['id'])
+ );
+ break;
+
+ case DROPITEM_NORMAL:
+ default:
+ $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), body = '', title = '',
+ changed = '%s', edited = '%s' WHERE id = %d LIMIT 1",
+ intval(ITEM_DELETED),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($item['id'])
+ );
+ break;
+ }
+
+ // network deletion request. Keep the message structure so that we can deliver delete notifications.
+ // Come back after several days (or perhaps a month) to do the lowlevel delete (DROPITEM_PHASE2).
+
+ if($stage == DROPITEM_PHASE1)
+ return true;
$r = q("delete from term where otype = %d and oid = %d limit 1",
intval(TERM_OBJ_POST),
@@ -3751,8 +3834,10 @@ function zot_feed($uid,$observer_xchan,$mindate) {
return $result;
}
- require_once('include/security.php');
- $sql_extra = item_permissions_sql($uid);
+ if(! is_sys_channel($uid)) {
+ require_once('include/security.php');
+ $sql_extra = item_permissions_sql($uid);
+ }
if($mindate != '0000-00-00 00:00:00') {
$sql_extra .= " and created > '$mindate' ";
@@ -3763,24 +3848,36 @@ function zot_feed($uid,$observer_xchan,$mindate) {
$items = array();
- $r = q("SELECT item.*, item.id as item_id from item
- WHERE uid = %d AND item_restrict = 0 and id = parent
- AND (item_flags & %d)
- $sql_extra ORDER BY created ASC $limit",
- intval($uid),
- intval(ITEM_WALL)
- );
- if($r) {
-
- $parents_str = ids_to_querystr($r,'id');
+ if(is_sys_channel($uid)) {
+ require_once('include/security.php');
+ $r = q("SELECT distinct parent from item
+ WHERE uid != %d
+ and uid in (" . stream_perms_api_uids(PERMS_PUBLIC) . ") AND item_restrict = 0
+ AND (item_flags & %d)
+ and item_private = 0 $sql_extra ORDER BY created ASC $limit",
+ intval($uid),
+ intval(ITEM_WALL)
+ );
+ }
+ else {
+ $r = q("SELECT distinct parent from item
+ WHERE uid = %d AND item_restrict = 0
+ AND (item_flags & %d)
+ $sql_extra ORDER BY created ASC $limit",
+ intval($uid),
+ intval(ITEM_WALL)
+ );
+ }
+ if($r) {
+ $parents_str = ids_to_querystr($r,'parent');
+ $sys_query = ((is_sys_channel($uid)) ? $sql_extra : '');
+
$items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item`
- WHERE `item`.`uid` = %d AND `item`.`item_restrict` = 0
- AND `item`.`parent` IN ( %s ) ",
- intval($uid),
+ WHERE `item`.`item_restrict` = 0
+ AND `item`.`parent` IN ( %s ) $sys_query ",
dbesc($parents_str)
);
-
}
if($items) {
@@ -3793,11 +3890,13 @@ function zot_feed($uid,$observer_xchan,$mindate) {
else
$items = array();
+
+ logger('zot_feed: number items: ' . count($items),LOGGER_DEBUG);
+
foreach($items as $item)
$result[] = encode_item($item);
return $result;
-
}
@@ -3931,23 +4030,25 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
if(isset($arr['start']) && isset($arr['records']))
$pager_sql = sprintf(" LIMIT %d, %d ",intval($arr['start']), intval($arr['records']));
- if(($arr['cmin'] != 0) || ($arr['cmax'] != 99)) {
+ if(array_key_exists('cmin',$arr) || array_key_exists('cmax',$arr)) {
+ if(($arr['cmin'] != 0) || ($arr['cmax'] != 99)) {
- // Not everybody who shows up in the network stream will be in your address book.
- // By default those that aren't are assumed to have closeness = 99; but this isn't
- // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
- // the stream with a NULL address book entry.
+ // Not everybody who shows up in the network stream will be in your address book.
+ // By default those that aren't are assumed to have closeness = 99; but this isn't
+ // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
+ // the stream with a NULL address book entry.
- $sql_nets .= " AND ";
+ $sql_nets .= " AND ";
- if($arr['cmax'] == 99)
- $sql_nets .= " ( ";
+ if($arr['cmax'] == 99)
+ $sql_nets .= " ( ";
- $sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " ";
- $sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) ";
- if($cmax == 99)
- $sql_nets .= " OR abook.abook_closeness IS NULL ) ";
- }
+ $sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " ";
+ $sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) ";
+ if($cmax == 99)
+ $sql_nets .= " OR abook.abook_closeness IS NULL ) ";
+ }
+ }
$simple_update = (($client_mode & CLIENT_MODE_UPDATE) ? " and ( item.item_flags & " . intval(ITEM_UNSEEN) . " ) " : '');
if($client_mode & CLIENT_MODE_LOAD)
diff --git a/include/nav.php b/include/nav.php
index 3aa50226d..a97b434bc 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -162,7 +162,7 @@ EOT;
$nav['home']['mark'] = array('', t('Mark all channel notifications seen'), '','');
- $nav['intros'] = array('connections/pending', t('Intros'), "", t('New Connections'));
+ $nav['intros'] = array('connections/ifpending', t('Connections'), "", t('Connections'));
$nav['notifications'] = array('notifications/system', t('Notices'), "", t('Notifications'));
diff --git a/include/network.php b/include/network.php
index 1fb4beaa7..9f68328b7 100644
--- a/include/network.php
+++ b/include/network.php
@@ -43,8 +43,12 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
@curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; Red)");
+ $ciphers = @get_config('system','curl_ssl_ciphers');
+ if($ciphers)
+ @curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
+
if (x($opts,'accept_content')){
- curl_setopt($ch,CURLOPT_HTTPHEADER, array (
+ @curl_setopt($ch,CURLOPT_HTTPHEADER, array (
"Accept: " . $opts['accept_content']
));
}
@@ -115,7 +119,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
if(! $ret['success']) {
+ $ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
+ logger('z_fetch_url: error:' . $ret['error'], LOGGER_DEBUG);
logger('z_fetch_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
}
$ret['body'] = substr($s,strlen($header));
@@ -136,21 +142,25 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if(($redirects > 8) || (! $ch))
return ret;
- curl_setopt($ch, CURLOPT_HEADER, true);
+ @curl_setopt($ch, CURLOPT_HEADER, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
- curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
- curl_setopt($ch, CURLOPT_POST,1);
- curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
- curl_setopt($ch, CURLOPT_USERAGENT, "Red");
+ @curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
+ @curl_setopt($ch, CURLOPT_POST,1);
+ @curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
+ @curl_setopt($ch, CURLOPT_USERAGENT, "Red");
+
+ $ciphers = @get_config('system','curl_ssl_ciphers');
+ if($ciphers)
+ @curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
if (x($opts,'accept_content')){
- curl_setopt($ch,CURLOPT_HTTPHEADER, array (
+ @curl_setopt($ch,CURLOPT_HTTPHEADER, array (
"Accept: " . $opts['accept_content']
));
}
if(x($opts,'headers'))
- curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
+ @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
@@ -170,11 +180,11 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$prx = get_config('system','proxy');
if(strlen($prx)) {
- curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
- curl_setopt($ch, CURLOPT_PROXY, $prx);
+ @curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
+ @curl_setopt($ch, CURLOPT_PROXY, $prx);
$prxusr = get_config('system','proxyuser');
if(strlen($prxusr))
- curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
+ @curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
}
// don't let curl abort the entire application
@@ -183,7 +193,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$s = @curl_exec($ch);
$base = $s;
- $curl_info = curl_getinfo($ch);
+ $curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
$header = '';
@@ -217,8 +227,10 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$ret['return_code'] = $rc;
$ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
if(! $ret['success']) {
+ $ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
- logger('z_fetch_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
+ logger('z_post_url: error:' . $ret['error'], LOGGER_DEBUG);
+ logger('z_post_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
}
$ret['body'] = substr($s,strlen($header));
diff --git a/include/notifier.php b/include/notifier.php
index 81f971107..dbae6211c 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -90,6 +90,9 @@ function notifier_run($argv, $argc){
if(! $item_id)
return;
+ require_once('include/identity.php');
+ $sys = get_sys_channel();
+
if($cmd == 'permission_update') {
// Get the recipient
$r = q("select abook.*, hubloc.* from abook
@@ -262,23 +265,9 @@ function notifier_run($argv, $argc){
if($target_item['item_restrict'] & ITEM_DELETED)
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
- if($target_item['item_restrict'] & ITEM_DELAYED_PUBLISH) {
- logger('notifier: target item ITEM_DELAYED_PUBLISH', LOGGER_DEBUG);
- return;
- }
-
- if($target_item['item_restrict'] & ITEM_WEBPAGE) {
- logger('notifier: target item ITEM_WEBPAGE', LOGGER_DEBUG);
- return;
- }
-
- if($target_item['item_restrict'] & ITEM_BUILDBLOCK) {
- logger('notifier: target item ITEM_BUILDBLOCK', LOGGER_DEBUG);
- return;
- }
-
- if($target_item['item_restrict'] & ITEM_PDL) {
- logger('notifier: target item ITEM_PDL', LOGGER_DEBUG);
+ $unforwardable = ITEM_UNPUBLISHED|ITEM_DELAYED_PUBLISH|ITEM_WEBPAGE|ITEM_BUILDBLOCK|ITEM_PDL;
+ if($target_item['item_restrict'] & $unforwardable) {
+ logger('notifier: target item not forwardable: flags ' . $target_item['item_restrict'], LOGGER_DEBUG);
return;
}
@@ -288,6 +277,11 @@ function notifier_run($argv, $argc){
if($s)
$channel = $s[0];
+ if($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
+ logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}");
+ return;
+ }
+
if($target_item['id'] == $target_item['parent']) {
$parent_item = $target_item;
@@ -308,6 +302,10 @@ function notifier_run($argv, $argc){
$top_level_post = false;
}
+ // avoid looping of discover items 12/4/2014
+
+ if($sys && $parent_item['uid'] == $sys['channel_id'])
+ return;
$encoded_item = encode_item($target_item);
@@ -481,10 +479,11 @@ function notifier_run($argv, $argc){
$hash = random_string();
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' )",
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($channel['channel_account_id']),
intval($channel['channel_id']),
+ dbesc('zot'),
dbesc($hub['hubloc_callback']),
intval(1),
dbesc(datetime_convert()),
@@ -495,10 +494,11 @@ function notifier_run($argv, $argc){
}
else {
$n = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash);
- 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' )",
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($target_item['aid']),
intval($target_item['uid']),
+ dbesc('zot'),
dbesc($hub['hubloc_callback']),
intval(1),
dbesc(datetime_convert()),
diff --git a/include/oembed.php b/include/oembed.php
index 57631b051..42a9881ed 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -164,8 +164,11 @@ function oembed_iframe($src,$width,$height) {
$a = get_app();
+ $sandbox = ((strpos($src,get_app()->get_hostname())) ? ' sandbox="allow-scripts" ' : '');
+
$s = $a->get_baseurl()."/oembed/".base64url_encode($src);
- return '<iframe height="' . $height . '" width="' . $width . '" src="' . $s . '" frameborder="no" >' . t('Embedded content') . '</iframe>';
+
+ return '<iframe ' . $sandbox . ' height="' . $height . '" width="' . $width . '" src="' . $s . '" frameborder="no" >' . t('Embedded content') . '</iframe>';
}
diff --git a/include/permissions.php b/include/permissions.php
index eb1a7966f..01dd18f8d 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -100,6 +100,13 @@ function get_all_perms($uid,$observer_xchan,$internal_use = true) {
dbesc($observer_xchan),
intval(ABOOK_FLAG_SELF)
);
+ if(! $x) {
+ // not in address book, see if they've got an xchan
+ $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1",
+ dbesc($observer_xchan)
+ );
+ }
+
$abook_checked = true;
}
@@ -144,9 +151,11 @@ function get_all_perms($uid,$observer_xchan,$internal_use = true) {
// If we're still here, we have an observer, check the network.
- if(($r[0][$channel_perm] & PERMS_NETWORK) && ($x[0]['xchan_network'] === 'zot')) {
- $ret[$perm_name] = true;
- continue;
+ if($r[0][$channel_perm] & PERMS_NETWORK) {
+ if(($x && $x[0]['xchan_network'] === 'zot') || ($y && $y[0]['xchan_network'] === 'zot')) {
+ $ret[$perm_name] = true;
+ continue;
+ }
}
// If PERMS_SITE is specified, find out if they've got an account on this hub
@@ -263,6 +272,12 @@ function perm_is_allowed($uid,$observer_xchan,$permission) {
if(($x) && (! $global_perms[$permission][2]) && ($x[0]['abook_flags'] & ABOOK_FLAG_IGNORED))
return false;
+ if(! $x) {
+ // not in address book, see if they've got an xchan
+ $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1",
+ dbesc($observer_xchan)
+ );
+ }
}
@@ -283,9 +298,10 @@ function perm_is_allowed($uid,$observer_xchan,$permission) {
// If we're still here, we have an observer, check the network.
- if(($r[0][$channel_perm] & PERMS_NETWORK) && ($x[0]['xchan_network'] === 'zot'))
- return true;
-
+ if($r[0][$channel_perm] & PERMS_NETWORK) {
+ if (($x && $x[0]['xchan_network'] === 'zot') || ($y && $y[0]['xchan_network'] === 'zot'))
+ return true;
+ }
// If PERMS_SITE is specified, find out if they've got an account on this hub
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 484550cb7..f5e915402 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -616,7 +616,7 @@ function import_profile_photo($photo,$xchan,$thing = false) {
$type = 'image/jpeg';
}
- return(array($photo,$thumb,$micro,$type));
+ return(array($photo,$thumb,$micro,$type,$photo_failure));
}
diff --git a/include/photos.php b/include/photos.php
index 82af4aaeb..65532e6c2 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -176,6 +176,7 @@ function photo_upload($channel, $observer, $args) {
if(! $r3)
$errors = true;
}
+
if($errors) {
q("delete from photo where resource_id = '%s' and uid = %d",
@@ -188,6 +189,10 @@ function photo_upload($channel, $observer, $args) {
return $ret;
}
+ // This will be the width and height of the smallest representation
+
+ $width_x_height = $ph->getWidth() . 'x' . $ph->getHeight();
+
$basename = basename($filename);
$mid = item_message_id();
@@ -219,9 +224,13 @@ function photo_upload($channel, $observer, $args) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ if ($width_x_height)
+ $tag = '[zmg=' . $width_x_height. ']';
+ else
+ $tag = '[zmg]';
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
- . '[zmg]' . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
+ . $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
. '[/zrl]';
$result = item_store($arr);
@@ -426,4 +435,4 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$item_id = $result['item_id'];
return $item_id;
-} \ No newline at end of file
+}
diff --git a/include/poller.php b/include/poller.php
index 423ee46c1..9592c29e4 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -105,6 +105,23 @@ function poller_run($argv, $argc){
if($d2 != intval($d1)) {
+ $d3 = intval(datetime_convert('UTC','UTC','now','N'));
+ if($d3 == 7) {
+
+ /**
+ * Cron Weekly
+ *
+ * Actions in the following block are executed once per day only on Sunday (once per week).
+ *
+ */
+
+ require_once('include/hubloc.php');
+ prune_hub_reinstalls();
+
+
+ }
+
+
// expire any read notifications over a month old
q("delete from notify where seen = 1 and date < UTC_TIMESTAMP() - INTERVAL 30 DAY");
@@ -151,6 +168,11 @@ function poller_run($argv, $argc){
}
+ // pull in some public posts
+ if(! get_config('system','disable_discover_tab'))
+ proc_run('php','include/externals.php');
+
+
$manual_id = 0;
$generation = 0;
diff --git a/include/probe.php b/include/probe.php
new file mode 100644
index 000000000..29635f963
--- /dev/null
+++ b/include/probe.php
@@ -0,0 +1,99 @@
+<?php /** @file */
+
+
+/**
+ * Functions to assist in probing various legacy networks to figure out what kind of capabilities might be present.
+ */
+
+
+function net_have_driver($net) {
+
+ if(function_exists('net_discover_' . $net))
+ return true;
+ return false;
+}
+
+function probe_well_known($addr) {
+
+ $ret = array();
+
+ $ret['src'] = $addr;
+
+ if(strpos($addr,'@') !== false) {
+ $ret['address'] = $addr;
+ }
+ else {
+ $ret['url'] = $addr;
+ }
+
+ if(stristr($addr,'facebook.com')) {
+ $ret['network'] = 'facebook';
+ }
+ if(stristr($addr,'google.com')) {
+ $ret['network'] = 'google';
+ }
+ if(stristr($addr,'linkedin.com')) {
+ $ret['network'] = 'linkedin';
+ }
+
+ call_hooks('probe_well_known', $ret);
+
+ if(array_key_exists('network',$ret) && net_have_driver($ret['network'])) {
+ $fn = 'net_discover_' . $ret['network'];
+ $ret = $fn($ret);
+ }
+
+
+ return $ret;
+
+}
+
+
+
+
+function probe_webfinger($addr) {
+
+
+
+
+
+}
+
+
+function probe_legacy_webfinger($addr) {
+
+
+
+
+}
+
+function probe_zot($addr) {
+
+
+
+}
+
+function probe_dfrn($addr) {
+
+
+}
+
+
+function probe_diaspora($addr) {
+
+
+}
+
+
+function probe_legacy_feed($addr) {
+
+
+
+}
+
+
+function probe_activity_stream($addr) {
+
+
+}
+
diff --git a/include/queue.php b/include/queue.php
index ec7246cb2..239d61fc0 100644
--- a/include/queue.php
+++ b/include/queue.php
@@ -33,8 +33,12 @@ function queue_run($argv, $argc){
// For the first 12 hours we'll try to deliver every 15 minutes
// After that, we'll only attempt delivery once per hour.
-
- $r = q("SELECT * FROM outq WHERE outq_delivered = 0 and (( outq_created > UTC_TIMESTAMP() - INTERVAL 12 HOUR and outq_updated < UTC_TIMESTAMP() - INTERVAL 15 MINUTE ) OR ( outq_updated < UTC_TIMESTAMP() - INTERVAL 1 HOUR ))");
+ // This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
+ // so that we don't start off a thousand deliveries for a couple of dead hubs.
+ // The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
+ // Other drivers will have to do something different here and may need their own query.
+
+ $r = q("SELECT * FROM outq WHERE outq_delivered = 0 and (( outq_created > UTC_TIMESTAMP() - INTERVAL 12 HOUR and outq_updated < UTC_TIMESTAMP() - INTERVAL 15 MINUTE ) OR ( outq_updated < UTC_TIMESTAMP() - INTERVAL 1 HOUR )) and outq_driver in ('','zot') group by outq_posturl");
}
if(! $r)
return;
diff --git a/include/reddav.php b/include/reddav.php
index 2a26ac42a..03cfe1aab 100644
--- a/include/reddav.php
+++ b/include/reddav.php
@@ -276,7 +276,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
for($x = 1; $x < count($path_arr); $x ++) {
- $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d)",
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and uid = %d and (flags & %d)",
dbesc($folder),
dbesc($path_arr[$x]),
intval($channel_id),
@@ -581,17 +581,19 @@ function RedCollectionData($file,&$auth) {
for($x = 1; $x < count($path_arr); $x ++) {
- $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d) $perms limit 1",
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and uid = %d and (flags & %d) $perms limit 1",
dbesc($folder),
dbesc($path_arr[$x]),
+ intval($channel_id),
intval(ATTACH_FLAG_DIR)
);
if(! $r) {
// path wasn't found. Try without permissions to see if it was the result of permissions.
$errors = true;
- $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d) limit 1",
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and uid = %d and (flags & %d) limit 1",
dbesc($folder),
basename($path_arr[$x]),
+ intval($channel_id),
intval(ATTACH_FLAG_DIR)
);
if($r) {
@@ -708,7 +710,7 @@ function RedFileData($file, &$auth,$test = false) {
$r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach
where folder = '%s' and filename = '%s' and uid = %d $perms group by filename limit 1",
dbesc($folder),
- basename($file),
+ dbesc(basename($file)),
intval($channel_id)
);
@@ -719,7 +721,7 @@ function RedFileData($file, &$auth,$test = false) {
$r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach
where folder = '%s' and filename = '%s' and uid = %d group by filename limit 1",
dbesc($folder),
- basename($file),
+ dbesc(basename($file)),
intval($channel_id)
);
if($r)
@@ -882,8 +884,12 @@ class RedBrowser extends DAV\Browser\Plugin {
date_default_timezone_set($this->auth->timezone);
$version = '';
+ require_once('include/conversation.php');
+
+ if($this->auth->channel_name)
+ $html = profile_tabs(get_app(),(($this->auth->owner_id == local_user()) ? true : false),$this->auth->owner_nick);
- $html = "
+ $html .= "
<body>
<h1>Index for " . $this->escapeHTML($path) . "/</h1>
<table>
diff --git a/include/security.php b/include/security.php
index f52615357..f15dea302 100644
--- a/include/security.php
+++ b/include/security.php
@@ -53,8 +53,9 @@ function authenticate_success($user_record, $login_initial = false, $interactive
/* This account has never created a channel. Send them to new_channel by default */
if($a->module === 'login') {
- $r = q("select count(channel_id) as total from channel where channel_account_id = %d",
- intval($a->account['account_id'])
+ $r = q("select count(channel_id) as total from channel where channel_account_id = %d and not ( channel_pageflags & %d)",
+ intval($a->account['account_id']),
+ intval(PAGE_REMOVED)
);
if(($r) && (! $r[0]['total']))
goaway(z_root() . '/new_channel');
@@ -346,8 +347,9 @@ 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 > 0 and channel_r_stream <= %d",
- intval($perms_min)
+ $r = q("select channel_id from channel where channel_r_stream > 0 and channel_r_stream <= %d and not (channel_pageflags & %d)",
+ intval($perms_min),
+ intval(PAGE_CENSORED|PAGE_SYSTEM|PAGE_REMOVED)
);
if($r)
foreach($r as $rr)
@@ -361,7 +363,7 @@ function stream_perms_api_uids($perms_min = PERMS_SITE) {
$str .= ',';
$str .= intval($rr);
}
-logger('stream_perms_api_uids: ' . $str);
+ logger('stream_perms_api_uids: ' . $str, LOGGER_DEBUG);
return $str;
}
@@ -370,8 +372,9 @@ function stream_perms_xchans($perms_min = PERMS_SITE) {
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)
+ $r = q("select channel_hash from channel where channel_r_stream > 0 and channel_r_stream <= %d and not (channel_pageflags & %d)",
+ intval($perms_min),
+ intval(PAGE_CENSORED|PAGE_SYETEM|PAGE_REMOVED)
);
if($r)
foreach($r as $rr)
@@ -385,6 +388,6 @@ function stream_perms_xchans($perms_min = PERMS_SITE) {
$str .= ',';
$str .= "'" . dbesc($rr) . "'";
}
-logger('stream_perms_xchans: ' . $str);
+ logger('stream_perms_xchans: ' . $str, LOGGER_DEBUG);
return $str;
}
diff --git a/include/socgraph.php b/include/socgraph.php
index 10d52da66..65e23f9df 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -62,6 +62,11 @@ function poco_load($xchan = '',$url = null) {
$j = json_decode($s['body'],true);
+ if(! $j) {
+ logger('poco_load: unable to json_decode returned data.');
+ return;
+ }
+
logger('poco_load: ' . print_r($j,true),LOGGER_DATA);
if($xchan) {
diff --git a/include/text.php b/include/text.php
index 53b92c05f..68542005b 100755
--- a/include/text.php
+++ b/include/text.php
@@ -278,6 +278,11 @@ function hex2bin($s) {
if(! (is_string($s) && strlen($s)))
return '';
+ if(strlen($s) & 1) {
+ logger('hex2bin: illegal hex string: ' . $s);
+ return $s;
+ }
+
if(! ctype_xdigit($s)) {
return($s);
}
@@ -569,9 +574,20 @@ function get_tags($s) {
$s = preg_replace('/\[style=(.*?)\]/sm','',$s);
+ // match any double quoted tags
+
+ if(preg_match_all('/([@#]\&quot\;.*?\&quot\;)/',$s,$match)) {
+ foreach($match[1] as $mtch) {
+ $ret[] = $mtch;
+ }
+ }
+
// Match full names against @tags including the space between first and last
// We will look these up afterward to see if they are full names or not recognisable.
+
+
+
if(preg_match_all('/(@[^ \x0D\x0A,:?]+ [^ \x0D\x0A@,:?]+)([ \x0D\x0A@,:?]|$)/',$s,$match)) {
foreach($match[1] as $mtch) {
if(strstr($mtch,"]")) {
@@ -602,6 +618,10 @@ function get_tags($s) {
// try not to catch url fragments
if(strpos($s,$mtch) && preg_match('/[a-zA-z0-9\/]/',substr($s,strpos($s,$mtch)-1,1)))
continue;
+ // or quote remnants from the quoted strings we already picked out earlier
+ if(strpos($mtch,'&quot'))
+ continue;
+
$ret[] = $mtch;
}
}
@@ -614,12 +634,28 @@ function get_tags($s) {
}
}
+ // make sure the longer tags are returned first so that if two or more have common substrings
+ // we'll replace the longest ones first. Otherwise the common substring would be found in
+ // both strings and the string replacement would link both to the shorter strings and
+ // fail to link the longer string. RedMatrix github issue #378
+
+ usort($ret,'tag_sort_length');
- // logger('get_tags: ' . print_r($ret,true));
+
+// logger('get_tags: ' . print_r($ret,true));
return $ret;
}
+function tag_sort_length($a,$b) {
+ if(mb_strlen($a) == mb_strlen($b))
+ return 0;
+ return((mb_strlen($b) < mb_strlen($a)) ? (-1) : 1);
+}
+
+
+
+
function strip_zids($s) {
return preg_replace('/[\?&]zid=(.*?)(&|$)/ism','$2',$s);
@@ -671,11 +707,10 @@ function contact_block() {
if((! is_array($a->profile)) || ($a->profile['hide_friends']))
return $o;
- $r = q("SELECT COUNT(abook_id) AS total FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and abook_flags = 0 and not (xchan_flags & %d) and not (xchan_flags & %d) and not (xchan_flags & %d)",
+ $r = q("SELECT COUNT(abook_id) AS total FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and not ( abook_flags & %d ) and not (xchan_flags & %d)",
intval($a->profile['uid']),
- intval(XCHAN_FLAGS_HIDDEN),
- intval(XCHAN_FLAGS_ORPHAN),
- intval(XCHAN_FLAGS_DELETED)
+ intval(ABOOK_FLAG_HIDDEN|ABOOK_FLAG_PENDING|ABOOK_FLAG_SELF),
+ intval(XCHAN_FLAGS_HIDDEN|XCHAN_FLAGS_ORPHAN|XCHAN_FLAGS_DELETED)
);
if(count($r)) {
$total = intval($r[0]['total']);
@@ -686,11 +721,10 @@ function contact_block() {
} else {
- $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash WHERE abook_channel = %d AND abook_flags = 0 and not (xchan_flags & %d ) and not (xchan_flags & %d ) and not (xchan_flags & %d ) ORDER BY RAND() LIMIT %d",
+ $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash WHERE abook_channel = %d AND not ( abook_flags & %d) and not (xchan_flags & %d ) ORDER BY RAND() LIMIT %d",
intval($a->profile['uid']),
- intval(XCHAN_FLAGS_HIDDEN),
- intval(XCHAN_FLAGS_ORPHAN),
- intval(XCHAN_FLAGS_DELETED),
+ intval(ABOOK_FLAG_HIDDEN|ABOOK_FLAG_PENDING|ABOOK_FLAG_SELF),
+ intval(XCHAN_FLAGS_HIDDEN|XCHAN_FLAGS_ORPHAN|XCHAN_FLAGS_DELETED),
intval($shown)
);
@@ -780,9 +814,9 @@ function searchbox($s,$id='search-box',$url='/search',$save = false) {
$o .= '<form action="' . z_root() . '/' . $url . '" method="get" >';
$o .= '<input type="hidden" name="f" value="" />';
$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') . '" />';
+ $o .= '<input type="submit" name="submit" class="btn btn-default" id="search-submit" value="' . t('Search') . '" />';
if(feature_enabled(local_user(),'savedsearch'))
- $o .= '<input type="submit" name="searchsave" id="search-save" value="' . t('Save') . '" />';
+ $o .= '<input type="submit" name="searchsave" class="btn btn-default" id="search-save" value="' . t('Save') . '" />';
$o .= '</form></div>';
return $o;
}
@@ -1169,6 +1203,33 @@ function format_categories(&$item,$writeable) {
return $s;
}
+// Add any hashtags which weren't mentioned in the message body, e.g. community tags
+
+function format_hashtags(&$item) {
+
+ $s = '';
+ $terms = get_terms_oftype($item['term'],TERM_HASHTAG);
+ if($terms) {
+ $categories = array();
+ foreach($terms as $t) {
+ $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
+ if(! trim($term))
+ continue;
+ if(strpos($item['body'], $t['url']))
+ continue;
+
+ if($s)
+ $s .= '&nbsp';
+
+ $s .= '#<a href="' . zid($t['url']) . '" >' . $term . '</a>';
+ }
+ }
+ return $s;
+}
+
+
+
+
function format_filer(&$item) {
@@ -1221,6 +1282,9 @@ function prepare_body(&$item,$attach = false) {
$writeable = ((get_observer_hash() == $item['owner_xchan']) ? true : false);
+
+ $s .= format_hashtags($item);
+
$s .= format_categories($item,$writeable);
if(local_user() == $item['uid'])
@@ -1712,6 +1776,7 @@ function check_webbie($arr) {
$str .= "'" . dbesc($y) . "'";
}
}
+
if(strlen($str)) {
$r = q("select channel_address from channel where channel_address in ( $str ) ");
if(count($r)) {
@@ -1720,8 +1785,9 @@ function check_webbie($arr) {
}
}
foreach($arr as $x) {
- if(! in_array($x,$taken)) {
- return $x;
+ $y = legal_webbie($x);
+ if(! in_array($y,$taken)) {
+ return $y;
}
}
}
diff --git a/include/widgets.php b/include/widgets.php
index 90586397f..678fed833 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -304,8 +304,12 @@ function widget_archive($arr) {
if(! feature_enabled($uid,'archives'))
return '';
+ if(! perm_is_allowed($uid,get_observer_hash(),'view_stream'))
+ return '';
+
$wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0);
+ $style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select');
$url = z_root() . '/' . $a->cmd;
@@ -318,6 +322,7 @@ function widget_archive($arr) {
'$title' => t('Archives'),
'$size' => ((count($ret) > 6) ? 6 : count($ret)),
'$url' => $url,
+ '$style' => $style,
'$dates' => $ret
));
return $o;
@@ -336,6 +341,12 @@ function widget_fullprofile($arr) {
function widget_categories($arr) {
$a = get_app();
+
+
+ if($a->profile['profile_uid'] && (! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_stream')))
+ return '';
+
+
$cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
$srchurl = $a->query_string;
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
@@ -348,6 +359,9 @@ function widget_tagcloud_wall($arr) {
$a = get_app();
if((! $a->profile['profile_uid']) || (! $a->profile['channel_hash']))
return '';
+ if(! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_stream'))
+ return '';
+
$limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50);
if(feature_enabled($a->profile['profile_uid'],'tagadelic'))
return tagblock('search',$a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
diff --git a/include/zot.php b/include/zot.php
index 934348d2d..c919b0981 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -425,6 +425,15 @@ function zot_refresh($them,$channel = null, $force = false) {
intval($channel['channel_id']),
dbesc($x['hash'])
);
+ if(($new_connection) && (! $default_perms)) {
+ require_once('include/enotify.php');
+ notification(array(
+ 'type' => NOTIFY_INTRO,
+ 'from_xchan' => $x['hash'],
+ 'to_xchan' => $channel['channel_hash'],
+ 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
+ ));
+ }
if($new_connection && (! ($new_connection[0]['abook_flags'] & ABOOK_FLAG_PENDING)) && ($their_perms & PERMS_R_STREAM))
proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']);
@@ -623,6 +632,10 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
if($adult_changed)
$new_flags = $new_flags ^ XCHAN_FLAGS_SELFCENSORED;
+ $deleted = (($r[0]['xchan_flags'] & XCHAN_FLAGS_DELETED) ? true : false);
+ $deleted_changed = ((intval($deleted) != intval($arr['deleted'])) ? true : false);
+ if($deleted_changed)
+ $new_flags = $new_flags ^ XCHAN_FLAGS_DELETED;
if(($r[0]['xchan_name_date'] != $arr['name_updated'])
|| ($r[0]['xchan_connurl'] != $arr['connections_url'])
@@ -667,6 +680,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
$new_flags = 0;
if($arr['adult_content'])
$new_flags |= XCHAN_FLAGS_SELFCENSORED;
+ if(array_key_exists('deleted',$arr) && $arr['deleted'])
+ $new_flags |= XCHAN_FLAGS_DELETED;
$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_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags)
@@ -713,7 +728,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
z_root() . '/photo/profile/l/' . $local[0]['channel_id'],
z_root() . '/photo/profile/m/' . $local[0]['channel_id'],
z_root() . '/photo/profile/s/' . $local[0]['channel_id'],
- $arr['photo_mimetype']
+ $arr['photo_mimetype'],
+ false
);
}
}
@@ -721,16 +737,29 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
$photos = import_profile_photo($arr['photo'],$xchan_hash);
}
if($photos) {
- $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
- where xchan_hash = '%s' limit 1",
- dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])),
- dbesc($photos[0]),
- dbesc($photos[1]),
- dbesc($photos[2]),
- dbesc($photos[3]),
- dbesc($xchan_hash)
- );
-
+ if($photos[4]) {
+ // importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
+ // This often happens when somebody joins the matrix with a bad cert.
+ $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
+ where xchan_hash = '%s' limit 1",
+ dbesc($photos[0]),
+ dbesc($photos[1]),
+ dbesc($photos[2]),
+ dbesc($photos[3]),
+ dbesc($xchan_hash)
+ );
+ }
+ else {
+ $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
+ where xchan_hash = '%s' limit 1",
+ dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])),
+ dbesc($photos[0]),
+ dbesc($photos[1]),
+ dbesc($photos[2]),
+ dbesc($photos[3]),
+ dbesc($xchan_hash)
+ );
+ }
$what .= 'photo ';
$changed = true;
}
@@ -872,21 +901,28 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
}
// get rid of any hubs we have for this channel which weren't reported.
+ // This was needed at one time to resolve complicated cross-site inconsistencies, but can cause sync conflict.
+ // currently disabled.
+
+// if($xisting) {
+// foreach($xisting as $x) {
+// if(! array_key_exists('updated',$x)) {
+// logger('import_xchan: removing unreferenced hub location ' . $x['hubloc_url']);
+// $r = q("delete from hubloc where hubloc_id = %d limit 1",
+// intval($x['hubloc_id'])
+// );
+// $what .= 'removed_hub';
+// $changed = true;
+// }
+// }
+// }
- if($xisting) {
- foreach($xisting as $x) {
- if(! array_key_exists('updated',$x)) {
- logger('import_xchan: removing unreferenced hub location ' . $x['hubloc_url']);
- $r = q("delete from hubloc where hubloc_id = %d limit 1",
- intval($x['hubloc_id'])
- );
- $what .= 'removed_hub';
- $changed = true;
- }
- }
- }
}
+
+
+
+
// Are we a directory server of some kind?
if($dirmode != DIRECTORY_MODE_NORMAL) {
@@ -936,6 +972,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
$ret['hash'] = $xchan_hash;
}
+
+
logger('import_xchan: result: ' . print_r($ret,true), LOGGER_DATA);
return $ret;
}
@@ -1345,16 +1383,18 @@ function allowed_public_recips($msg) {
}
-function process_delivery($sender,$arr,$deliveries,$relay) {
+function process_delivery($sender,$arr,$deliveries,$relay,$public = false) {
$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;
+ if(! $public) {
+ if($sender['hash'] != $arr['owner_xchan'] && $sender['hash'] != $arr['author_xchan']) {
+ logger("process_delivery: sender {$sender['hash']} is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}");
+ return;
+ }
}
foreach($deliveries as $d) {
@@ -1385,9 +1425,9 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
}
}
- if((! perm_is_allowed($channel['channel_id'],$sender['hash'],$perm)) && (! $tag_delivery)) {
- logger("permission denied for delivery {$channel['channel_id']}");
- $result[] = array($d['hash'],'permission denied',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ if((! perm_is_allowed($channel['channel_id'],$sender['hash'],$perm)) && (! $tag_delivery) && (! $public)) {
+ logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
+ $result[] = array($d['hash'],'permission denied',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
continue;
}
@@ -1397,12 +1437,12 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
remove_community_tag($sender,$arr,$channel['channel_id']);
$item_id = delete_imported_item($sender,$arr,$channel['channel_id']);
- $result[] = array($d['hash'],(($item_id) ? 'deleted' : 'delete_failed'),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result[] = array($d['hash'],(($item_id) ? 'deleted' : 'delete_failed'),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
if($relay && $item_id) {
logger('process_delivery: invoking relay');
proc_run('php','include/notifier.php','relay',intval($item_id));
- $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
}
continue;
@@ -1432,8 +1472,9 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
}
$xyz = event_store($ev);
+ add_source_route($xyz,$sender['hash']);
- $result = array($d['hash'],'event processed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result = array($d['hash'],'event processed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
continue;
}
}
@@ -1448,7 +1489,7 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
$arr['uid'] = $channel['channel_id'];
update_imported_item($sender,$arr,$channel['channel_id']);
}
- $result[] = array($d['hash'],'updated',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result[] = array($d['hash'],'updated',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
$item_id = $r[0]['id'];
}
else {
@@ -1456,18 +1497,20 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
$arr['uid'] = $channel['channel_id'];
$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() . '>');
+ add_source_route($item_id,$sender['hash']);
+
+ $result[] = array($d['hash'],(($item_id) ? 'posted' : 'storage failed:' . $item_result['message']),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
}
if($relay && $item_id) {
logger('process_delivery: invoking relay');
proc_run('php','include/notifier.php','relay',intval($item_id));
- $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result[] = array($d['hash'],'relayed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
}
}
if(! $deliveries)
- $result[] = array('','no recipients');
+ $result[] = array('','no recipients','',$arr['mid']);
logger('process_delivery: local results: ' . print_r($result,true), LOGGER_DEBUG);
@@ -1571,7 +1614,16 @@ function delete_imported_item($sender,$item,$uid) {
}
require_once('include/items.php');
- drop_item($r[0]['id'],false);
+
+ // FIXME issue #230 is related
+ // Chicken/egg problem because we have to drop_item, but this removes information that tag_deliver may need to do its stuff.
+ // We can't reverse the order because drop_item refuses to run if the item already has the deleted flag set and we need to
+ // set that flag prior to calling tag_deliver.
+
+ // Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
+ // and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2).
+
+ drop_item($r[0]['id'],false, DROPITEM_PHASE1);
tag_deliver($uid,$r[0]['id']);
@@ -1605,7 +1657,7 @@ function process_mail_delivery($sender,$arr,$deliveries) {
if(! perm_is_allowed($channel['channel_id'],$sender['hash'],'post_mail')) {
logger("permission denied for mail delivery {$channel['channel_id']}");
- $result[] = array($d['hash'],'permission denied',$channel['channel_name']);
+ $result[] = array($d['hash'],'permission denied',$channel['channel_name'],$arr['mid']);
continue;
}
@@ -1619,11 +1671,11 @@ function process_mail_delivery($sender,$arr,$deliveries) {
intval($r[0]['id']),
intval($channel['channel_id'])
);
- $result[] = array($d['hash'],'mail recalled',$channel['channel_name']);
+ $result[] = array($d['hash'],'mail recalled',$channel['channel_name'],$arr['mid']);
logger('mail_recalled');
}
else {
- $result[] = array($d['hash'],'duplicate mail received',$channel['channel_name']);
+ $result[] = array($d['hash'],'duplicate mail received',$channel['channel_name'],$arr['mid']);
logger('duplicate mail received');
}
continue;
@@ -1632,7 +1684,7 @@ function process_mail_delivery($sender,$arr,$deliveries) {
$arr['account_id'] = $channel['channel_account_id'];
$arr['channel_id'] = $channel['channel_id'];
$item_id = mail_store($arr);
- $result[] = array($d['hash'],'mail delivered',$channel['channel_name']);
+ $result[] = array($d['hash'],'mail delivered',$channel['channel_name'],$arr['mid']);
}
}
@@ -1669,20 +1721,19 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_
$arr = array();
$arr['xprof_hash'] = $hash;
- $arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_dob'] = datetime_convert('','',$profile['birthday'],'Y-m-d'); // !!!! check this for 0000 year
- $arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
- $arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
+ $arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
-
- $arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
$clean = array();
if(array_key_exists('keywords',$profile) and is_array($profile['keywords'])) {
@@ -2057,10 +2108,11 @@ function build_sync_packet($uid = 0, $packet = null) {
foreach($synchubs as $hub) {
$hash = random_string();
$n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hash);
- 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' )",
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($channel['channel_account']),
intval($channel['channel_id']),
+ dbesc('zot'),
dbesc($hub['hubloc_callback']),
intval(1),
dbesc(datetime_convert()),
@@ -2098,7 +2150,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
if($channel['channel_hash'] != $sender['hash']) {
logger('process_channel_sync_delivery: possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']);
- $result[] = array($d['hash'],'channel mismatch',$channel['channel_name']);
+ $result[] = array($d['hash'],'channel mismatch',$channel['channel_name'],'');
continue;
}
@@ -2193,7 +2245,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
}
}
- $result[] = array($d['hash'],'channel sync updated',$channel['channel_name']);
+ $result[] = array($d['hash'],'channel sync updated',$channel['channel_name'],'');
}