aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorredmatrix <git@macgirvin.com>2016-06-27 04:00:10 -0700
committerredmatrix <git@macgirvin.com>2016-06-27 04:00:10 -0700
commit85d2ad4aea106417dc3d8ce2429d13dd858c5201 (patch)
tree72e03b3fe379829a4e2f9c521366fb14e1eaa970 /include
parentd5d5d78e3aded9a3238ccb7e93b4c6fd4b873331 (diff)
parent8d298d5a068845856c9827c0d2ea3f02f1399d72 (diff)
downloadvolse-hubzilla-85d2ad4aea106417dc3d8ce2429d13dd858c5201.tar.gz
volse-hubzilla-85d2ad4aea106417dc3d8ce2429d13dd858c5201.tar.bz2
volse-hubzilla-85d2ad4aea106417dc3d8ce2429d13dd858c5201.zip
Merge branch 'dev' into perms
Diffstat (limited to 'include')
-rw-r--r--include/api.php17
-rw-r--r--include/attach.php16
-rw-r--r--include/bbcode.php34
-rw-r--r--include/cache.php44
-rw-r--r--include/channel.php38
-rw-r--r--include/config.php18
-rw-r--r--include/connections.php16
-rw-r--r--include/conversation.php19
-rw-r--r--include/datetime.php2
-rwxr-xr-xinclude/dba/dba_driver.php5
-rw-r--r--include/follow.php2
-rw-r--r--include/group.php18
-rw-r--r--include/help.php17
-rw-r--r--include/import.php110
-rwxr-xr-xinclude/items.php58
-rw-r--r--include/network.php69
-rwxr-xr-xinclude/oembed.php23
-rw-r--r--include/page_widgets.php11
-rw-r--r--include/photos.php79
-rwxr-xr-xinclude/plugin.php67
-rw-r--r--include/taxonomy.php2
-rw-r--r--include/text.php101
-rw-r--r--include/widgets.php83
-rw-r--r--include/wiki.php496
-rw-r--r--include/zot.php32
25 files changed, 1067 insertions, 310 deletions
diff --git a/include/api.php b/include/api.php
index be525f7e9..df6aba957 100644
--- a/include/api.php
+++ b/include/api.php
@@ -839,7 +839,7 @@ require_once('include/api_auth.php');
$_REQUEST['parent_mid'] = $parent;
if($_REQUEST['namespace'] && $parent) {
- $x = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
+ $x = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1",
dbesc($_REQUEST['namespace']),
dbesc($parent)
);
@@ -967,20 +967,10 @@ require_once('include/api_auth.php');
$ret = array();
$tmp = array();
- $str = '';
foreach($i as $ii) {
$tmp[] = encode_item($ii,true);
- if($str)
- $str .= ',';
- $str .= $ii['id'];
}
$ret['item'] = $tmp;
- if($str) {
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item.id in ( $str ) ");
-
- if($r)
- $ret['item_id'] = $r;
- }
json_return_and_die($ret);
}
@@ -1462,7 +1452,8 @@ require_once('include/api_auth.php');
}
else {
if($_REQUEST['namespace'] && $_REQUEST['remote_id']) {
- $r = q("select * from item_id where service = '%s' and sid = '%s' and uid = %d limit 1",
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id
+ where cat = 'system' and k = '%s' and v = '%s' and item.uid = %d limit 1",
dbesc($_REQUEST['namespace']),
dbesc($_REQUEST['remote_id']),
intval($user_info['uid'])
@@ -1472,7 +1463,7 @@ require_once('include/api_auth.php');
$id = $r[0]['iid'];
}
if($_REQUEST['namespace'] && $_REQUEST['comment_id']) {
- $r = q("select * from item_id left join item on item.id = item_id.iid where service = '%s' and sid = '%s' and uid = %d and item.id != item.parent limit 1",
+ $r = q("select * from iconfig left join item on item.id = iconfig.iid where cat = 'system' and k = '%s' and v = '%s' and uid = %d and item.id != item.parent limit 1",
dbesc($_REQUEST['namespace']),
dbesc($_REQUEST['comment_id']),
intval($user_info['uid'])
diff --git a/include/attach.php b/include/attach.php
index 78efde51f..4961d7f91 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -423,6 +423,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$observer = array();
+ $dosync = ((array_key_exists('nosync',$arr) && $arr['nosync']) ? 0 : 1);
+
if($observer_hash) {
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($observer_hash)
@@ -616,7 +618,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
);
if($r) {
$overwrite = get_pconfig($channel_id,'system','overwrite_dup_files');
- if($overwrite) {
+ if(($overwrite) || ($options === 'import')) {
$options = 'replace';
$existing_id = $x[0]['id'];
$existing_size = intval($x[0]['filesize']);
@@ -800,7 +802,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if($is_photo) {
- $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct);
+ $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options );
if($arr['contact_allow'])
$args['contact_allow'] = $arr['contact_allow'];
if($arr['group_allow'])
@@ -829,6 +831,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if($arr['description'])
$args['description'] = $arr['description'];
+ $args['deliver'] = $dosync;
+
$p = photo_upload($channel,$observer,$args);
if($p['success']) {
$ret['body'] = $p['body'];
@@ -865,10 +869,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
call_hooks('photo_upload_end',$ret);
}
- $sync = attach_export_data($channel,$hash);
+ if($dosync) {
+ $sync = attach_export_data($channel,$hash);
- if($sync)
- build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ if($sync)
+ build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ }
return $ret;
}
diff --git a/include/bbcode.php b/include/bbcode.php
index 42741b392..7f7be4300 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -242,6 +242,13 @@ function bb_ShareAttributes($match) {
if ($matches[1] != "")
$message_id = $matches[1];
+ if(! $message_id) {
+ preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+ if ($matches[1] != "")
+ $message_id = $matches[1];
+ }
+
+
$reldate = '<span class="autotime" title="' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'c') . '" >' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . '</span>';
$headline = '<div class="shared_container"> <div class="shared_header">';
@@ -484,6 +491,24 @@ function bb_code($match) {
return '<code class="inline-code">' . trim($match[1]) . '</code>';
}
+function bb_highlight($match) {
+ if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
+ 'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','json','sh']))
+ return text_highlight($match[2],strtolower($match[1]));
+ return $match[0];
+}
+
+function bb_fixtable_lf($match) {
+
+ // remove extraneous whitespace between table element tags since newlines will all
+ // be converted to '<br />' and turn your neatly crafted tables into a whole lot of
+ // empty space.
+
+ $x = preg_replace("/\]\s+\[/",'][',$match[1]);
+ return '[table]' . $x . '[/table]';
+
+}
+
// BBcode 2 HTML was written by WAY2WEB.net
@@ -559,6 +584,15 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = str_replace(">", "&gt;", $Text);
+ // Check for [code] text here, before the linefeeds are messed with.
+ // The highlighter will unescape and re-escape the content.
+
+ if (strpos($Text,'[code=') !== false) {
+ $Text = preg_replace_callback("/\[code=(.*?)\](.*?)\[\/code\]/ism", 'bb_highlight', $Text);
+ }
+
+ $Text = preg_replace_callback("/\[table\](.*?)\[\/table\]/ism",'bb_fixtable_lf',$Text);
+
// Convert new line chars to html <br /> tags
// nlbr seems to be hopelessly messed up
diff --git a/include/cache.php b/include/cache.php
deleted file mode 100644
index 4a3f453e1..000000000
--- a/include/cache.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php /** @file */
-
- /**
- * cache api
- */
-
- class Cache {
- public static function get($key){
- $r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
- dbesc($key)
- );
-
- if ($r)
- return $r[0]['v'];
- return null;
- }
-
- public static function set($key,$value) {
-
- $r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
- dbesc($key)
- );
- if($r) {
- q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
- dbesc($value),
- dbesc(datetime_convert()),
- dbesc($key));
- }
- else {
- q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
- dbesc($key),
- dbesc($value),
- dbesc(datetime_convert()));
- }
- }
-
-
- public static function clear(){
- q("DELETE FROM cache WHERE updated < '%s'",
- dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
- }
-
- }
-
diff --git a/include/channel.php b/include/channel.php
index 087bd4162..913768017 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -16,7 +16,7 @@ require_once('include/menu.php');
* @param int $account_id
* Account_id used for this request
*
- * @returns assoziative array with:
+ * @returns associative array with:
* * \e boolean \b success boolean true if creating a new channel is allowed for this account
* * \e string \b message (optional) if success is false, optional error text
* * \e int \b total_identities
@@ -496,8 +496,10 @@ function identity_basic_export($channel_id, $items = false) {
$r = q("select * from channel where channel_id = %d limit 1",
intval($channel_id)
);
- if($r)
+ if($r) {
$ret['channel'] = $r[0];
+ $ret['relocate'] = [ 'channel_address' => $r[0]['channel_address'], 'url' => z_root()];
+ }
$r = q("select * from profile where uid = %d",
intval($channel_id)
@@ -514,7 +516,7 @@ function identity_basic_export($channel_id, $items = false) {
for($x = 0; $x < count($ret['abook']); $x ++) {
$xchans[] = $ret['abook'][$x]['abook_chan'];
- $abconfig = load_abconfig($ret['channel']['channel_hash'],$ret['abook'][$x]['abook_xchan']);
+ $abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
if($abconfig)
$ret['abook'][$x]['abconfig'] = $abconfig;
}
@@ -676,14 +678,6 @@ function identity_basic_export($channel_id, $items = false) {
$ret['mail'] = $m;
}
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d",
- intval($channel_id)
- );
-
- if($r)
- $ret['item_id'] = $r;
-
- //$key = get_config('system','prvkey');
/** @warning this may run into memory limits on smaller systems */
@@ -725,6 +719,10 @@ function identity_export_year($channel_id,$year,$month = 0) {
$ret = array();
+ $ch = channelx_by_n($channel_id);
+ if($ch) {
+ $ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
+ }
$mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00');
if($month && $month < 12)
$maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00');
@@ -746,17 +744,6 @@ function identity_export_year($channel_id,$year,$month = 0) {
$ret['item'][] = encode_item($rr,true);
}
- $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d
- and item.created >= '%s' and item.created < '%s' order by created ",
- intval($channel_id),
- dbesc($mindate),
- dbesc($maxdate)
- );
-
- if($r)
- $ret['item_id'] = $r;
-
-
return $ret;
}
@@ -774,11 +761,10 @@ function identity_export_year($channel_id,$year,$month = 0) {
*
* The channel default theme is also selected for use, unless over-riden elsewhere.
*
- * @param[in,out] App &$a
* @param string $nickname
* @param string $profile
*/
-function profile_load(&$a, $nickname, $profile = '') {
+function profile_load($nickname, $profile = '') {
// logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : ''));
@@ -875,7 +861,7 @@ function profile_load(&$a, $nickname, $profile = '') {
);
if($z) {
$p[0]['picdate'] = $z[0]['xchan_photo_date'];
- $p[0]['reddress'] = str_replace('@','&#xff20;',$z[0]['xchan_addr']);
+ $p[0]['reddress'] = str_replace('@','&#x40;',$z[0]['xchan_addr']);
}
// fetch user tags if this isn't the default profile
@@ -1046,6 +1032,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
$diaspora = array(
'podloc' => z_root(),
+ 'guid' => $profile['channel_guid'] . str_replace('.','',App::get_hostname()),
'searchable' => (($block) ? 'false' : 'true'),
'nickname' => $profile['channel_address'],
'fullname' => $profile['channel_name'],
@@ -1243,6 +1230,7 @@ function advanced_profile(&$a) {
$things = get_things(App::$profile['profile_guid'],App::$profile['profile_uid']);
+
// logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);
return replace_macros($tpl, array(
diff --git a/include/config.php b/include/config.php
index 209d22d42..ece22793f 100644
--- a/include/config.php
+++ b/include/config.php
@@ -98,20 +98,20 @@ function del_aconfig($account_id, $family, $key) {
}
-function load_abconfig($chash,$xhash) {
- Zlib\AbConfig::Load($chash,$xhash);
+function load_abconfig($chan,$xhash) {
+ Zlib\AbConfig::Load($chan,$xhash);
}
-function get_abconfig($chash,$xhash,$family,$key) {
- return Zlib\AbConfig::Get($chash,$xhash,$family,$key);
+function get_abconfig($chan,$xhash,$family,$key) {
+ return Zlib\AbConfig::Get($chan,$xhash,$family,$key);
}
-function set_abconfig($chash,$xhash,$family,$key,$value) {
- return Zlib\AbConfig::Set($chash,$xhash,$family,$key,$value);
+function set_abconfig($chan,$xhash,$family,$key,$value) {
+ return Zlib\AbConfig::Set($chan,$xhash,$family,$key,$value);
}
-function del_abconfig($chash,$xhash,$family,$key) {
- return Zlib\AbConfig::Delete($chash,$xhash,$family,$key);
+function del_abconfig($chan,$xhash,$family,$key) {
+ return Zlib\AbConfig::Delete($chan,$xhash,$family,$key);
}
function load_iconfig(&$item) {
@@ -123,7 +123,7 @@ function get_iconfig(&$item, $family, $key) {
}
function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
- return Zlib\IConfig::Set($item, $family, $key, $value, $sharing = false);
+ return Zlib\IConfig::Set($item, $family, $key, $value, $sharing);
}
function del_iconfig(&$item, $family, $key) {
diff --git a/include/connections.php b/include/connections.php
index 2d10b8354..ed4526a09 100644
--- a/include/connections.php
+++ b/include/connections.php
@@ -283,18 +283,30 @@ function channel_remove($channel_id, $local = true, $unset_session=false) {
Zotlabs\Daemon\Master::Summon(array('Notifier','purge_all',$channel_id));
}
+
+ $r = q("select * from iconfig left join item on item.id = iconfig.iid
+ where item.uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ q("delete from iconfig where iid = %d",
+ intval($rr['iid'])
+ );
+ }
+ }
+
+
q("DELETE FROM `groups` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `group_member` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `event` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `item` WHERE `uid` = %d", intval($channel_id));
- q("DELETE FROM `item_id` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `mail` WHERE `channel_id` = %d", intval($channel_id));
q("DELETE FROM `notify` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `photo` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `attach` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `profile` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `pconfig` WHERE `uid` = %d", intval($channel_id));
- q("DELETE FROM `spam` WHERE `uid` = %d", intval($channel_id));
// @FIXME At this stage we need to remove the file resources located under /store/$nickname
diff --git a/include/conversation.php b/include/conversation.php
index 518193b08..d2d4ffca0 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -403,9 +403,12 @@ function count_descendants($item) {
* @return boolean
*/
function visible_activity($item) {
- $hidden_activities = array(ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
+ $hidden_activities = [ ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ];
- $post_types = array(ACTIVITY_OBJ_NOTE,ACTIVITY_OBJ_COMMENT,basename(ACTIVITY_OBJ_NOTE),basename(ACTIVITY_OBJ_COMMENT));
+ $post_types = [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT, basename(ACTIVITY_OBJ_NOTE), basename(ACTIVITY_OBJ_COMMENT)];
+
+ if(intval($item['item_notshown']))
+ return false;
foreach ($hidden_activities as $act) {
if ((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) {
@@ -1143,6 +1146,8 @@ function status_editor($a, $x, $popup = false) {
$weblink = (($mimetype === 'text/bbcode') ? t('Insert web link') : false);
if(x($x, 'hide_weblink'))
$weblink = false;
+
+ $embedPhotos = t('Embed image from photo albums');
$writefiles = (($mimetype === 'text/bbcode') ? perm_is_allowed($x['profile_uid'], get_observer_hash(), 'write_storage') : false);
if(x($x, 'hide_attach'))
@@ -1178,6 +1183,12 @@ function status_editor($a, $x, $popup = false) {
'$whereareu' => t('Where are you right now?'),
'$editor_autocomplete'=> ((x($x,'editor_autocomplete')) ? $x['editor_autocomplete'] : ''),
'$bbco_autocomplete'=> ((x($x,'bbco_autocomplete')) ? $x['bbco_autocomplete'] : ''),
+ '$modalchooseimages' => t('Choose images to embed'),
+ '$modalchoosealbum' => t('Choose an album'),
+ '$modaldiffalbum' => t('Choose a different album...'),
+ '$modalerrorlist' => t('Error getting album list'),
+ '$modalerrorlink' => t('Error getting photo link'),
+ '$modalerroralbum' => t('Error getting album'),
));
$tpl = get_markup_template('jot.tpl');
@@ -1219,6 +1230,10 @@ function status_editor($a, $x, $popup = false) {
'$code' => t('Code'),
'$attach' => t('Attach file'),
'$weblink' => $weblink,
+ '$embedPhotos' => $embedPhotos,
+ '$embedPhotosModalTitle' => t('Embed an image from your albums'),
+ '$embedPhotosModalCancel' => t('Cancel'),
+ '$embedPhotosModalOK' => t('OK'),
'$setloc' => $setloc,
'$voting' => t('Toggle voting'),
'$feature_voting' => $feature_voting,
diff --git a/include/datetime.php b/include/datetime.php
index bf58866e9..600ad6ec4 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -224,7 +224,7 @@ function datetimesel($format, $min, $max, $default, $label, $id = 'datetimepicke
$pickers = '';
if(!$pickdate) $pickers .= ',datepicker: false';
- if(!$picktime) $pickers .= ',timepicker: false';
+ if(!$picktime) $pickers .= ',timepicker: false, closeOnDateSelect:true';
$extra_js = '';
if($minfrom != '')
diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php
index df072ed76..f6091f6e1 100755
--- a/include/dba/dba_driver.php
+++ b/include/dba/dba_driver.php
@@ -90,7 +90,7 @@ abstract class dba_driver {
protected $db;
protected $pdo = array();
- public $debug = 0;
+ public $debug = 0;
public $connected = false;
public $error = false;
@@ -332,6 +332,9 @@ function q($sql) {
else
db_logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true),LOGGER_NORMAL,LOG_CRIT);
}
+ if(\DBA::$dba->debug)
+ db_logger('Sql: ' . $stmt, LOGGER_DEBUG, LOG_INFO);
+
return \DBA::$dba->q($stmt);
}
diff --git a/include/follow.php b/include/follow.php
index 0c3973175..e5a74f85e 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -275,7 +275,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
call_hooks('follow', $arr);
- /** If there is a default group for this channel, add this member to it */
+ /** If there is a default group for this channel, add this connection to it */
if($default_group) {
require_once('include/group.php');
diff --git a/include/group.php b/include/group.php
index a4938b848..10853ff6b 100644
--- a/include/group.php
+++ b/include/group.php
@@ -17,7 +17,7 @@ function group_add($uid,$name,$public = 0) {
$z = q("SELECT * FROM `groups` WHERE `id` = %d LIMIT 1",
intval($r)
);
- if(count($z) && $z[0]['deleted']) {
+ if(($z) && $z[0]['deleted']) {
/*$r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `gname` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
@@ -129,7 +129,7 @@ function group_byname($uid,$name) {
intval($uid),
dbesc($name)
);
- if(count($r))
+ if($r)
return $r[0]['id'];
return false;
}
@@ -178,11 +178,11 @@ function group_add_member($uid,$name,$member,$gid = 0) {
intval($gid),
dbesc($member)
);
- if(count($r))
+ if($r)
return true; // You might question this, but
// we indicate success because the group member was in fact created
// -- It was just created at another time
- if(! count($r))
+ if(! $r)
$r = q("INSERT INTO `group_member` (`uid`, `gid`, `xchan`)
VALUES( %d, %d, '%s' ) ",
intval($uid),
@@ -205,7 +205,7 @@ function group_get_members($gid) {
intval(local_channel()),
intval(local_channel())
);
- if(count($r))
+ if($r)
$ret = $r;
}
return $ret;
@@ -218,7 +218,7 @@ function group_get_members_xchan($gid) {
intval($gid),
intval(local_channel())
);
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
$ret[] = $rr['xchan'];
}
@@ -236,7 +236,7 @@ function mini_group_select($uid,$group = '') {
intval($uid)
);
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
}
@@ -279,7 +279,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$member_of = groups_containing(local_channel(),$cid);
}
- if(count($r)) {
+ if($r) {
foreach($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
@@ -356,7 +356,7 @@ function groups_containing($uid,$c) {
);
$ret = array();
- if(count($r)) {
+ if($r) {
foreach($r as $rr)
$ret[] = $rr['gid'];
}
diff --git a/include/help.php b/include/help.php
index 5518eeb70..7f57f3334 100644
--- a/include/help.php
+++ b/include/help.php
@@ -30,7 +30,8 @@ function search_doc_files($s) {
$regexop = db_getfunc('REGEXP');
- $r = q("select item_id.sid, item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
+ $r = q("select iconfig.v, item.* from item left join iconfig on item.id = iconfig.iid
+ where iconfig.cat = 'system' and iconfig.k = 'docfile' and
body $regexop '%s' and item_type = %d $pager_sql",
dbesc($s),
intval(ITEM_TYPE_DOC)
@@ -50,7 +51,7 @@ function search_doc_files($s) {
}
}
}
- if(stristr($r[$x]['sid'],$s))
+ if(stristr($r[$x]['v'],$s))
$r[$x]['rank'] ++;
$r[$x]['rank'] += substr_count(strtolower($r[$x]['text']),strtolower($s));
// bias the results to the observer's native language
@@ -123,12 +124,15 @@ function store_doc_file($s) {
$item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
$item['item_type'] = ITEM_TYPE_DOC;
- $r = q("select item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
- sid = '%s' and item_type = %d limit 1",
+ $r = q("select item.* from item left join iconfig on item.id = iconfig.iid
+ where iconfig.cat = 'system' and iconfig.k = 'docfile' and
+ iconfig.v = '%s' and item_type = %d limit 1",
dbesc($s),
intval(ITEM_TYPE_DOC)
);
+ \Zotlabs\Lib\IConfig::Set($item,'system','docfile',$s);
+
if($r) {
$item['id'] = $r[0]['id'];
$item['mid'] = $item['parent_mid'] = $r[0]['mid'];
@@ -139,10 +143,7 @@ function store_doc_file($s) {
$x = item_store($item);
}
- if($x['success']) {
- update_remote_id($sys,$x['item_id'],ITEM_TYPE_DOC,$s,'docfile',0,$item['mid']);
- }
-
+ return $x;
}
diff --git a/include/import.php b/include/import.php
index 6fcb08416..982eeb138 100644
--- a/include/import.php
+++ b/include/import.php
@@ -122,6 +122,11 @@ function import_profiles($channel,$profiles) {
$profile['aid'] = get_account_id();
$profile['uid'] = $channel['channel_id'];
+ convert_oldfields($profile,'name','fullname');
+ convert_oldfields($profile,'with','partner');
+ convert_oldfields($profile,'work','employment');
+
+
// we are going to reset all profile photos to the original
// somebody will have to fix this later and put all the applicable photos into the export
@@ -548,7 +553,7 @@ function sync_chatrooms($channel,$chatrooms) {
-function import_items($channel,$items,$sync = false) {
+function import_items($channel,$items,$sync = false,$relocate = null) {
if($channel && $items) {
$allow_code = false;
@@ -579,13 +584,6 @@ function import_items($channel,$items,$sync = false) {
$item['id'] = $r[0]['id'];
$item['uid'] = $channel['channel_id'];
$item_result = item_store_update($item,$allow_code,$deliver);
- if($sync && $item['item_wall']) {
- // deliver singletons if we have any
- if($item_result && $item_result['success']) {
- Zotlabs\Daemon\Master::Summon(array('Notifier','single_activity',$item_result['item_id']));
- }
- }
- continue;
}
}
else {
@@ -593,19 +591,37 @@ function import_items($channel,$items,$sync = false) {
$item['uid'] = $channel['channel_id'];
$item_result = item_store($item,$allow_code,$deliver);
}
+
if($sync && $item['item_wall']) {
// deliver singletons if we have any
if($item_result && $item_result['success']) {
Zotlabs\Daemon\Master::Summon(array('Notifier','single_activity',$item_result['item_id']));
}
}
+ if($relocate && $item_result['item_id']) {
+ $item = $item_result['item'];
+ if($item['mid'] === $item['parent_mid']) {
+ item_url_replace($channel,$item,$relocate['url'],z_root(),$relocate['channel_address']);
+ dbesc_array($item);
+ $item_id = $item_result['item_id'];
+ unset($item['id']);
+ $str = '';
+ foreach($item as $k => $v) {
+ if($str)
+ $str .= ",";
+ $str .= " `" . $k . "` = '" . $v . "' ";
+ }
+
+ $r = dbq("update `item` set " . $str . " where id = " . $item_id );
+ }
+ }
}
}
}
-function sync_items($channel,$items) {
- import_items($channel,$items,true);
+function sync_items($channel,$items,$relocate = null) {
+ import_items($channel,$items,true,$relocate);
}
@@ -619,19 +635,14 @@ function import_item_ids($channel,$itemids) {
);
if(! $r)
continue;
- $z = q("select * from item_id where service = '%s' and sid = '%s' and iid = %d and uid = %d limit 1",
+ $z = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = '%s'
+ and iconfig.v = '%s' and iid = %d limit 1",
dbesc($i['service']),
dbesc($i['sid']),
- intval($r[0]['id']),
- intval($channel['channel_id'])
+ intval($r[0]['id'])
);
if(! $z) {
- q("insert into item_id (iid,uid,sid,service) values(%d,%d,'%s','%s')",
- intval($r[0]['id']),
- intval($channel['channel_id']),
- dbesc($i['sid']),
- dbesc($i['service'])
- );
+ \Zotlabs\Lib\IConfig::Set($r[0]['id'],'system',$i['service'],$i['sid'],true);
}
}
}
@@ -644,6 +655,10 @@ function import_events($channel,$events) {
unset($event['id']);
$event['aid'] = $channel['channel_account_id'];
$event['uid'] = $channel['channel_id'];
+ convert_oldfields($event,'start','dtstart');
+ convert_oldfields($event,'finish','dtend');
+ convert_oldfields($event,'type','etype');
+ convert_oldfields($event,'ignore','dismissed');
dbesc_array($event);
$r = dbq("INSERT INTO event (`"
@@ -677,6 +692,12 @@ function sync_events($channel,$events) {
$event['aid'] = $channel['channel_account_id'];
$event['uid'] = $channel['channel_id'];
+ convert_oldfields($event,'start','dtstart');
+ convert_oldfields($event,'finish','dtend');
+ convert_oldfields($event,'type','etype');
+ convert_oldfields($event,'ignore','dismissed');
+
+
$exists = false;
$x = q("select * from event where event_hash = '%s' and uid = %d limit 1",
@@ -974,10 +995,7 @@ function sync_files($channel,$files) {
$attachment_stored = false;
foreach($f['attach'] as $att) {
- if(array_key_exists('data',$att)) {
- $att['content'] = $att['data'];
- unset($att['data']);
- }
+ convert_oldfields($att,'data','content');
if($att['deleted']) {
attach_delete($channel,$att['hash']);
@@ -1130,14 +1148,10 @@ function sync_files($channel,$files) {
$p['aid'] = $channel['channel_account_id'];
$p['uid'] = $channel['channel_id'];
- if(array_key_exists('data',$p)) {
- $p['content'] = $p['data'];
- unset($p['data']);
- }
- if(array_key_exists('scale',$p)) {
- $p['imgscale'] = $p['scale'];
- unset($p['scale']);
- }
+ convert_oldfields($p,'data','content');
+ convert_oldfields($p,'scale','imgscale');
+ convert_oldfields($p,'size','filesize');
+ convert_oldfields($p,'type','mimetype');
// if this is a profile photo, undo the profile photo bit
// for any other photo which previously held it.
@@ -1197,34 +1211,18 @@ function sync_files($channel,$files) {
}
}
if($f['item']) {
- sync_items($channel,$f['item']);
- foreach($f['item'] as $i) {
- if($i['message_id'] !== $i['message_parent'])
- continue;
- $r = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($i['message_id']),
- intval($channel['channel_id'])
- );
- if($r) {
- $item = $r[0];
- item_url_replace($channel,$item,$oldbase,z_root(),$original_channel);
-
- dbesc_array($item);
- $item_id = $item['id'];
- unset($item['id']);
- $str = '';
- foreach($item as $k => $v) {
- if($str)
- $str .= ",";
- $str .= " `" . $k . "` = '" . $v . "' ";
- }
-
- $r = dbq("update `item` set " . $str . " where id = " . $item_id );
- }
- }
+ sync_items($channel,$f['item'],
+ ['channel_address' => $original_channel,'url' => $oldbase]
+ );
}
}
}
}
+function convert_oldfields(&$arr,$old,$new) {
+ if(array_key_exists($old,$arr)) {
+ $arr[$new] = $arr[$old];
+ unset($arr[$old]);
+ }
+}
diff --git a/include/items.php b/include/items.php
index 93385c6e6..84683273d 100755
--- a/include/items.php
+++ b/include/items.php
@@ -677,13 +677,23 @@ function get_item_elements($x,$allow_code = false) {
$arr['item_flags'] = 0;
- if(array_key_exists('flags',$x) && in_array('consensus',$x['flags']))
- $arr['item_consensus'] = 1;
+ if(array_key_exists('flags',$x)) {
- if(array_key_exists('flags',$x) && in_array('deleted',$x['flags']))
- $arr['item_deleted'] = 1;
- if(array_key_exists('flags',$x) && in_array('hidden',$x['flags']))
- $arr['item_hidden'] = 1;
+ if(in_array('consensus',$x['flags']))
+ $arr['item_consensus'] = 1;
+
+ if(in_array('deleted',$x['flags']))
+ $arr['item_deleted'] = 1;
+
+ if(in_array('notshown',$x['flags']))
+ $arr['item_notshown'] = 1;
+
+ // hidden item are no longer propagated - notshown may be a suitable alternative
+
+ if(in_array('hidden',$x['flags']))
+ $arr['item_hidden'] = 1;
+
+ }
// Here's the deal - the site might be down or whatever but if there's a new person you've never
// seen before sending stuff to your stream, we MUST be able to look them up and import their data from their
@@ -1339,6 +1349,8 @@ function encode_item_flags($item) {
$ret[] = 'deleted';
if(intval($item['item_hidden']))
$ret[] = 'hidden';
+ if(intval($item['item_notshown']))
+ $ret[] = 'notshown';
if(intval($item['item_thread_top']))
$ret[] = 'thread_parent';
if(intval($item['item_nsfw']))
@@ -1877,6 +1889,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
}
+ $ret['item'] = $arr;
call_hooks('post_remote_end',$arr);
@@ -2127,6 +2140,15 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
return $ret;
}
+ // fetch an unescaped complete copy of the stored item
+
+ $r = q("select * from item where id = %d",
+ intval($orig_post_id)
+ );
+ if($r)
+ $arr = $r[0];
+
+
$r = q("delete from term where oid = %d and otype = %d",
intval($orig_post_id),
intval(TERM_OBJ_POST)
@@ -2158,6 +2180,8 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$arr['iconfig'] = $meta;
}
+ $ret['item'] = $arr;
+
call_hooks('post_remote_update_end',$arr);
if($deliver) {
@@ -3537,9 +3561,8 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
intval($item['id'])
);
- q("delete from item_id where iid = %d and uid = %d",
- intval($item['id']),
- intval($item['uid'])
+ q("delete from iconfig where iid = %d",
+ intval($item['id'])
);
q("delete from term where oid = %d and otype = %d",
@@ -4105,6 +4128,23 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
return $items;
}
+function webpage_to_namespace($webpage) {
+
+ if($webpage == ITEM_TYPE_WEBPAGE)
+ $page_type = 'WEBPAGE';
+ elseif($webpage == ITEM_TYPE_BLOCK)
+ $page_type = 'BUILDBLOCK';
+ elseif($webpage == ITEM_TYPE_PDL)
+ $page_type = 'PDL';
+ elseif($webpage == ITEM_TYPE_DOC)
+ $page_type = 'docfile';
+ else
+ $page_type = 'unknown';
+ return $page_type;
+
+}
+
+
function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) {
diff --git a/include/network.php b/include/network.php
index 0dd10e29b..96bf714f6 100644
--- a/include/network.php
+++ b/include/network.php
@@ -21,15 +21,18 @@ function get_capath() {
* TRUE if asked to return binary results (file download)
* @param int $redirects default 0
* internal use, recursion counter
- * @param array $opts (optional parameters) assoziative array with:
+ * @param array $opts (optional parameters) associative array with:
* * \b accept_content => supply Accept: header with 'accept_content' as the value
* * \b timeout => int seconds, default system config value or 60 seconds
* * \b http_auth => username:password
* * \b novalidate => do not validate SSL certs, default is to validate using our CA list
* * \b nobody => only return the header
* * \b filep => stream resource to write body to. header and body are not returned when using this option.
+ * * \b custom => custom request method: e.g. 'PUT', 'DELETE'
+ * * \b cookiejar => cookie file (write)
+ * * \B cookiefile => cookie file (read)
*
- * @return array an assoziative array with:
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -59,12 +62,27 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_HEADER, $false);
}
+ if(x($opts,'upload'))
+ @curl_setopt($ch, CURLOPT_UPLOAD, $opts['upload']);
+
+ if(x($opts,'infile'))
+ @curl_setopt($ch, CURLOPT_INFILE, $opts['infile']);
+
+ if(x($opts,'infilesize'))
+ @curl_setopt($ch, CURLOPT_INFILESIZE, $opts['infilesize']);
+
+ if(x($opts,'readfunc'))
+ @curl_setopt($ch, CURLOPT_READFUNCTION, $opts['readfunc']);
+
if(x($opts,'headers'))
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom'))
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -78,6 +96,11 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
+ if(x($opts,'cookiejar'))
+ @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
+ if(x($opts,'cookiefile'))
+ @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
+
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
@@ -165,7 +188,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'filep' => stream resource to write body to. header and body are not returned when using this option.
- * @return array an assoziative array with:
+ * 'custom' => custom request method: e.g. 'PUT', 'DELETE'
+ *
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -174,6 +199,10 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
*/
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
+// logger('url: ' . $url);
+// logger('params: ' . print_r($params,true));
+// logger('opts: ' . print_r($opts,true));
+
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
$ch = curl_init($url);
@@ -199,12 +228,17 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if(x($opts,'headers')) {
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
-logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
}
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom')) {
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+ @curl_setopt($ch, CURLOPT_POST,0);
+ }
+
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -218,6 +252,12 @@ logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
+
+ if(x($opts,'cookiejar'))
+ @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
+ if(x($opts,'cookiefile'))
+ @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
+
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
@@ -1296,8 +1336,20 @@ function discover_by_webbie($webbie) {
$fullname = $vcard['fn'];
if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0))
$vcard['photo'] = $diaspora_base . '/' . $vcard['photo'];
+ if(($vcard['key']) && (! $pubkey))
+ $pubkey = $vcard['key'];
if(! $avatar)
$avatar = $vcard['photo'];
+ if($diaspora) {
+ if(($vcard['guid']) && (! $diaspora_guid))
+ $diaspora_guid = $vcard['guid'];
+ if(($vcard['url']) && (! $diaspora_base))
+ $diaspora_base = $vcard['url'];
+
+
+
+
+ }
}
}
@@ -1962,14 +2014,7 @@ function get_site_info() {
else
$service_class = false;
- $visible_plugins = array();
- if(is_array(App::$plugins) && count(App::$plugins)) {
- $r = q("select * from addon where hidden = 0");
- if(count($r))
- foreach($r as $rr)
- $visible_plugins[] = $rr['aname'];
- }
- sort($visible_plugins);
+ $visible_plugins = visible_plugin_list();
if(@is_dir('.git') && function_exists('shell_exec'))
$commit = trim(@shell_exec('git log -1 --format="%h"'));
diff --git a/include/oembed.php b/include/oembed.php
index 08363e488..fe068278e 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -1,6 +1,8 @@
<?php /** @file */
+use Zotlabs\Lib as Zlib;
+
function oembed_replacecb($matches){
$embedurl=$matches[1];
@@ -25,12 +27,6 @@ function oembed_action($embedurl) {
logger('oembed_action: ' . $embedurl, LOGGER_DEBUG, LOG_INFO);
- // These media files should now be caught in bbcode.php
- // left here as a fallback in case this is called from another source
-
- $noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm","opus");
- $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION);
-
if(strpos($embedurl,'http://') === 0) {
if(intval(get_config('system','embed_sslonly'))) {
$action = 'block';
@@ -119,18 +115,23 @@ function oembed_fetch_url($embedurl){
// These media files should now be caught in bbcode.php
// left here as a fallback in case this is called from another source
- $noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm","opus");
- $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION);
+ $noexts = array(".mp3",".mp4",".ogg",".ogv",".oga",".ogm",".webm",".opus");
$result = oembed_action($embedurl);
$embedurl = $result['url'];
$action = $result['action'];
+ foreach($noexts as $ext) {
+ if(strpos(strtolower($embedurl),$ext) !== false) {
+ $action = 'block';
+ }
+ }
+
$txt = null;
if($action !== 'block') {
- $txt = Cache::get(App::$videowidth . $embedurl);
+ $txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $embedurl);
if(strstr($txt,'youtu') && strstr(z_root(),'https:')) {
$txt = str_replace('http:','https:',$txt);
@@ -151,7 +152,7 @@ function oembed_fetch_url($embedurl){
}
- if (! in_array($ext, $noexts) && $action !== 'block') {
+ if ($action !== 'block') {
// try oembed autodiscovery
$redirects = 0;
$result = z_fetch_url($furl, false, $redirects, array('timeout' => 15, 'accept_content' => "text/*", 'novalidate' => true ));
@@ -199,7 +200,7 @@ function oembed_fetch_url($embedurl){
//save in cache
if(! get_config('system','oembed_cache_disable'))
- Cache::set(App::$videowidth . $embedurl,$txt);
+ Zlib\Cache::set('[' . App::$videowidth . '] ' . $embedurl,$txt);
}
diff --git a/include/page_widgets.php b/include/page_widgets.php
index 49d1439be..3270de4a3 100644
--- a/include/page_widgets.php
+++ b/include/page_widgets.php
@@ -1,7 +1,8 @@
<?php
// A basic toolbar for observers with write_pages permissions
-function writepages_widget ($who,$which){
+
+function writepages_widget ($who,$which) {
return replace_macros(get_markup_template('write_pages.tpl'), array(
'$new' => t('New Page'),
'$newurl' => "webpages/$who",
@@ -13,9 +14,11 @@ function writepages_widget ($who,$which){
// Chan is channel_id, $which is channel_address - we'll need to pass observer later too.
-function pagelist_widget ($owner,$which){
- $r = q("select * from item_id left join item on item_id.iid = item.id where item_id.uid = %d and service = 'WEBPAGE' order by item.created desc",
+function pagelist_widget ($owner,$which) {
+
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id where item_id.uid = %d
+ and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' order by item.created desc",
intval($owner)
);
@@ -24,7 +27,7 @@ function pagelist_widget ($owner,$which){
if($r) {
$pages = array();
foreach($r as $rr) {
- $pages[$rr['iid']][] = array('url' => $rr['iid'],'pagetitle' => $rr['sid'],'title' => $rr['title'],'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']));
+ $pages[$rr['iid']][] = array('url' => $rr['iid'],'pagetitle' => $rr['v'],'title' => $rr['title'],'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']),'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']));
}
}
diff --git a/include/photos.php b/include/photos.php
index c64d662ea..c70478146 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -41,6 +41,10 @@ function photo_upload($channel, $observer, $args) {
else
$visible = 0;
+ $deliver = true;
+ if(array_key_exists('deliver',$args))
+ $deliver = intval($args['deliver']);
+
// Set to default channel permissions. If the parent directory (album) has permissions set,
// use those instead. If we have specific permissions supplied, they take precedence over
// all other settings. 'allow_cid' being passed from an external source takes priority over channel settings.
@@ -330,7 +334,7 @@ function photo_upload($channel, $observer, $args) {
if($item['mid'] === $item['parent_mid']) {
- $item['body'] = $args['body'];
+ $item['body'] = $summary;
$item['obj_type'] = ACTIVITY_OBJ_PHOTO;
$item['obj'] = json_encode($object);
@@ -355,14 +359,14 @@ function photo_upload($channel, $observer, $args) {
if(($item['edited'] > $r[0]['edited']) || $force) {
$item['id'] = $r[0]['id'];
$item['uid'] = $channel['channel_id'];
- item_store_update($item);
+ item_store_update($item,false,$deliver);
continue;
}
}
else {
$item['aid'] = $channel['channel_account_id'];
$item['uid'] = $channel['channel_id'];
- $item_result = item_store($item);
+ $item_result = item_store($item,false,$deliver);
}
}
}
@@ -414,10 +418,10 @@ function photo_upload($channel, $observer, $args) {
- $result = item_store($arr);
+ $result = item_store($arr,false,$deliver);
$item_id = $result['item_id'];
- if($visible)
+ if($visible && $deliver)
Zotlabs\Daemon\Master::Summon(array('Notifier', 'wall-new', $item_id));
}
@@ -703,40 +707,65 @@ function gps2Num($coordPart) {
return floatval($parts[0]) / floatval($parts[1]);
}
-function profile_photo_set_profile_perms($profileid = '') {
+function profile_photo_set_profile_perms($uid, $profileid = 0) {
$allowcid = '';
- if (x($profileid)) {
-
- $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.id = %d OR profile.profile_guid = '%s' LIMIT 1", intval($profileid), dbesc($profileid));
-
- } else {
-
+ if($profileid) {
+ $r = q("SELECT photo, profile_guid, id, is_default, uid
+ FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
+ intval($profileid),
+ dbesc($profileid)
+ );
+ }
+ else {
logger('Resetting permissions on default-profile-photo for user'.local_channel());
- $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.uid = %d AND is_default = 1 LIMIT 1", intval(local_channel()) ); //If no profile is given, we update the default profile
+
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile
+ WHERE profile.uid = %d AND is_default = 1 LIMIT 1",
+ intval($uid)
+ ); //If no profile is given, we update the default profile
}
+ if(! $r)
+ return;
$profile = $r[0];
- if(x($profile['id']) && x($profile['photo'])) {
- preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
- $resource_id = $resource_id[0];
+
+ if($profile['id'] && $profile['photo']) {
+ preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
+ $resource_id = $resource_id[0];
- if (intval($profile['is_default']) != 1) {
- $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_channel()) );
- $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids.
- $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid']));
+ if (! intval($profile['is_default'])) {
+ $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1",
+ intval($uid)
+ );
+ //Should not be needed in future. Catches old int-profile-ids.
+ $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ",
+ intval($profile['id'])
+ );
+ $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'",
+ dbesc($profile['profile_guid'])
+ );
$allowcid = "<" . $r0[0]['channel_hash'] . ">";
foreach ($r1 as $entry) {
$allowcid .= "<" . $entry['abook_xchan'] . ">";
}
foreach ($r2 as $entry) {
- $allowcid .= "<" . $entry['abook_xchan'] . ">";
- }
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
- q("UPDATE `photo` SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",dbesc($allowcid),dbesc($resource_id),intval($profile['uid']));
+ q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",
+ dbesc($allowcid),
+ dbesc($resource_id),
+ intval($uid)
+ );
- } else {
- q("UPDATE `photo` SET allow_cid = '' WHERE profile = 1 AND uid = %d",intval($profile['uid'])); //Reset permissions on default profile picture to public
+ }
+ else {
+ //Reset permissions on default profile picture to public
+ q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d",
+ intval(PHOTO_PROFILE),
+ intval($uid)
+ );
}
}
diff --git a/include/plugin.php b/include/plugin.php
index be4e92f03..6dfda1cc9 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -167,6 +167,12 @@ function reload_plugins() {
}
}
+function visible_plugin_list() {
+ $r = q("select * from addon where hidden = 0 order by aname asc");
+ return(($r) ? ids_to_array($r,'aname') : array());
+}
+
+
/**
* @brief registers a hook.
@@ -545,15 +551,21 @@ function head_get_css() {
}
function format_css_if_exists($source) {
- if (strpos($source[0], '/') !== false)
+ $path_prefix = script_path() . '/';
+
+ if (strpos($source[0], '/') !== false) {
+ // The source is a URL
$path = $source[0];
- else
+ // If the url starts with // then it's an absolute URL
+ if($source[0][0] === '/' && $source[0][1] === '/') $path_prefix = '';
+ } else {
+ // It's a file from the theme
$path = theme_include($source[0]);
+ }
if($path) {
- $path = script_path() . '/' . $path;
$qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
- return '<link rel="stylesheet" href="' . $path . $qstring . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ return '<link rel="stylesheet" href="' . $path_prefix . $path . $qstring . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
}
}
@@ -593,26 +605,37 @@ function script_path() {
return $scheme . '://' . $hostname;
}
-function head_add_js($src) {
- App::$js_sources[] = $src;
+function head_add_js($src, $priority = 0) {
+ if(! is_array(App::$js_sources[$priority]))
+ App::$js_sources[$priority] = array();
+ App::$js_sources[$priority][] = $src;
}
-function head_remove_js($src) {
+function head_remove_js($src, $priority = 0) {
- $index = array_search($src, App::$js_sources);
+ $index = array_search($src, App::$js_sources[$priority]);
if($index !== false)
- unset(App::$js_sources[$index]);
+ unset(App::$js_sources[$priority][$index]);
}
+// We should probably try to register main.js with a high priority, but currently we handle it
+// separately and put it at the end of the html head block in case any other javascript is
+// added outside the head_add_js construct.
+
function head_get_js() {
+
$str = '';
- $sources = App::$js_sources;
- if(count($sources))
- foreach($sources as $source) {
- if($source === 'main.js')
- continue;
- $str .= format_js_if_exists($source);
+ if(App::$js_sources) {
+ foreach(App::$js_sources as $sources) {
+ if(count($sources)) {
+ foreach($sources as $source) {
+ if($src === 'main.js')
+ continue;
+ $str .= format_js_if_exists($source);
+ }
+ }
}
+ }
return $str;
}
@@ -626,14 +649,20 @@ function head_get_main_js() {
}
function format_js_if_exists($source) {
- if(strpos($source,'/') !== false)
+ $path_prefix = script_path() . '/';
+
+ if(strpos($source,'/') !== false) {
+ // The source is a URL
$path = $source;
- else
+ // If the url starts with // then it's an absolute URL
+ if($source[0] === '/' && $source[1] === '/') $path_prefix = '';
+ } else {
+ // It's a file from the theme
$path = theme_include($source);
+ }
if($path) {
- $path = script_path() . '/' . $path;
$qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
- return '<script src="' . $path . $qstring . '" ></script>' . "\r\n" ;
+ return '<script src="' . $path_prefix . $path . $qstring . '" ></script>' . "\r\n" ;
}
}
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 177215fe8..067bd3246 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -400,7 +400,7 @@ function get_things($profile_hash,$uid) {
if(! $things[$rr['obj_verb']])
$things[$rr['obj_verb']] = array();
- $things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
+ $things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'editurl' => z_root() . '/thing/' . $rr['obj_obj'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
}
$sorted_things = array();
if($things) {
diff --git a/include/text.php b/include/text.php
index 1bc19da34..89c3a0539 100644
--- a/include/text.php
+++ b/include/text.php
@@ -376,30 +376,6 @@ function unxmlify($s) {
return $ret;
}
-/**
- * Convenience wrapper, reverse the operation "bin2hex"
- * This is a built-in function in php >= 5.4
- *
- * @FIXME We already have php >= 5.4 requirements, so can we remove this?
- */
-if(! function_exists('hex2bin')) {
-function hex2bin($s) {
- if(! (is_string($s) && strlen($s)))
- return '';
-
- if(strlen($s) & 1) {
- logger('hex2bin: illegal hex string: ' . $s);
- return $s;
- }
-
- if(! ctype_xdigit($s)) {
- return($s);
- }
-
- return(pack("H*",$s));
-}}
-
-
// Automatic pagination.
// To use, get the count of total items.
// Then call App::set_pager_total($number_items);
@@ -1283,7 +1259,7 @@ function normalise_link($url) {
* is https and the other isn't, or if one is www.something and the other
* isn't - and also ignore case differences.
*
- * @see normalis_link()
+ * @see normalise_link()
*
* @param string $a
* @param string $b
@@ -1635,7 +1611,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) {
function create_export_photo_body(&$item) {
if(($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) {
- $j = json_decode($item['object'],true);
+ $j = json_decode($item['obj'],true);
if($j) {
$item['body'] .= "\n\n" . (($j['body']) ? $j['body'] : $j['bbcode']);
$item['sig'] = '';
@@ -1743,7 +1719,8 @@ function unamp($s) {
}
function layout_select($channel_id, $current = '') {
- $r = q("select mid,sid from item left join item_id on iid = item.id where service = 'PDL' and item.uid = item_id.uid and item_id.uid = %d and item_type = %d ",
+ $r = q("select mid, v from item left join iconfig on iconfig.iid = item.id
+ where iconfig.cat = 'system' and iconfig.k = 'PDL' and item.uid = %d and item_type = %d ",
intval($channel_id),
intval(ITEM_TYPE_PDL)
);
@@ -1753,7 +1730,7 @@ function layout_select($channel_id, $current = '') {
$options .= '<option value="" ' . $empty_selected . '>' . t('default') . '</option>';
foreach($r as $rr) {
$selected = (($rr['mid'] == $current) ? ' selected="selected" ' : '');
- $options .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['sid'] . '</option>';
+ $options .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['v'] . '</option>';
}
}
@@ -2049,7 +2026,7 @@ function ids_to_array($arr,$idx = 'id') {
$t = array();
if($arr) {
foreach($arr as $x) {
- if(! in_array($x[$idx],$t)) {
+ if(array_key_exists($idx,$x) && strlen($x[$idx]) && (! in_array($x[$idx],$t))) {
$t[] = $x[$idx];
}
}
@@ -2088,9 +2065,9 @@ function xchan_query(&$items,$abook = true,$effective_uid = 0) {
}
foreach($items as $item) {
- if($item['owner_xchan'] && (! in_array($item['owner_xchan'],$arr)))
+ if($item['owner_xchan'] && (! in_array("'" . dbesc($item['owner_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['owner_xchan']) . "'";
- if($item['author_xchan'] && (! in_array($item['author_xchan'],$arr)))
+ if($item['author_xchan'] && (! in_array("'" . dbesc($item['author_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['author_xchan']) . "'";
}
}
@@ -2123,9 +2100,9 @@ function xchan_mail_query(&$item) {
$arr = array();
$chans = null;
if($item) {
- if($item['from_xchan'] && (! in_array($item['from_xchan'],$arr)))
+ if($item['from_xchan'] && (! in_array("'" . dbesc($item['from_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['from_xchan']) . "'";
- if($item['to_xchan'] && (! in_array($item['to_xchan'],$arr)))
+ if($item['to_xchan'] && (! in_array("'" . dbesc($item['to_xchan']) . "'",$arr)))
$arr[] = "'" . dbesc($item['to_xchan']) . "'";
}
@@ -2821,13 +2798,16 @@ function expand_acl($s) {
// If it has a pdl we'll load it as we know the mid and pass the body through comanche_parser() which will generate the
// page layout from the given description
+// @FIXME - there is apparently a very similar function called layout_select; this one should probably take precedence
+// and the other should be checked for compatibility and removed
function pdl_selector($uid, $current="") {
$o = '';
$sql_extra = item_permissions_sql($uid);
- $r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' $sql_extra order by sid asc",
+ $r = q("select iconfig.*, mid from item_id left join item on iconfig.iid = item.id
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' $sql_extra order by v asc",
intval($uid)
);
@@ -2841,7 +2821,7 @@ function pdl_selector($uid, $current="") {
$entries[] = array('title' => t('Default'), 'mid' => '');
foreach($entries as $selection) {
$selected = (($selection == $current) ? ' selected="selected" ' : '');
- $o .= "<option value=\"{$selection['mid']}\" $selected >{$selection['sid']}</option>";
+ $o .= "<option value=\"{$selection['mid']}\" $selected >{$selection['v']}</option>";
}
$o .= '</select>';
@@ -2877,3 +2857,54 @@ function flatten_array_recursive($arr) {
}
return($ret);
}
+
+function text_highlight($s,$lang) {
+
+ if($lang === 'js')
+ $lang = 'javascript';
+
+ if($lang === 'json') {
+ $lang = 'javascript';
+ if(! strpos(trim($s),"\n"))
+ $s = jindent($s);
+ }
+
+ if(! strpos('Text_Highlighter',get_include_path())) {
+ set_include_path(get_include_path() . PATH_SEPARATOR . 'library/Text_Highlighter');
+ }
+ require_once('library/Text_Highlighter/Text/Highlighter.php');
+ require_once('library/Text_Highlighter/Text/Highlighter/Renderer/Html.php');
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 4,
+ );
+ $tag_added = false;
+ $s = trim(html_entity_decode($s,ENT_COMPAT));
+ $s = str_replace(" ","\t",$s);
+
+ // The highlighter library insists on an opening php tag for php code blocks. If
+ // it isn't present, nothing is highlighted. So we're going to see if it's present.
+ // If not, we'll add it, and then quietly remove it after we get the processed output back.
+
+ if($lang === 'php') {
+ if(strpos('<?php',$s) !== 0) {
+ $s = '<?php' . "\n" . $s;
+ $tag_added = true;
+ }
+
+ }
+ $renderer = new Text_Highlighter_Renderer_HTML($options);
+ $hl = Text_Highlighter::factory($lang);
+ $hl->setRenderer($renderer);
+ $o = $hl->highlight($s);
+ $o = str_replace([" ","\n"],["&nbsp;&nbsp;&nbsp;&nbsp;",''],$o);
+
+ if($tag_added) {
+ $b = substr($o,0,strpos($o,'<li>'));
+ $e = substr($o,strpos($o,'</li>'));
+ $o = $b . $e;
+ }
+
+ return('<code>' . $o . '</code>');
+}
+
diff --git a/include/widgets.php b/include/widgets.php
index 312b63729..8a7f4b69f 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -856,6 +856,78 @@ function widget_chatroom_members() {
return $o;
}
+function widget_wiki_list($arr) {
+
+ require_once("include/wiki.php");
+ $channel = null;
+ if (argc() < 2 && local_channel()) {
+ // This should not occur because /wiki should redirect to /wiki/channel ...
+ $channel = \App::get_channel();
+ } else {
+ $channel = get_channel_by_nick(argv(1)); // Channel being viewed by observer
+ }
+ if (!$channel) {
+ return '';
+ }
+ $wikis = wiki_list($channel, get_observer_hash());
+ if ($wikis) {
+ return replace_macros(get_markup_template('wikilist.tpl'), array(
+ '$header' => t('Wiki List'),
+ '$channel' => $channel['channel_address'],
+ '$wikis' => $wikis['wikis'],
+ // If the observer is the local channel owner, show the wiki controls
+ '$showControls' => ((local_channel() === intval($channel['channel_id'])) ? true : false)
+ ));
+ }
+ return '';
+}
+
+function widget_wiki_pages($arr) {
+
+ require_once("include/wiki.php");
+ $channelname = ((array_key_exists('channel',$arr)) ? $arr['channel'] : '');
+ $wikiname = '';
+ if (array_key_exists('refresh', $arr)) {
+ $not_refresh = (($arr['refresh']=== true) ? false : true);
+ } else {
+ $not_refresh = true;
+ }
+ $pages = array();
+ if (!array_key_exists('resource_id', $arr)) {
+ $hide = true;
+ } else {
+ $p = wiki_page_list($arr['resource_id']);
+ if ($p['pages']) {
+ $pages = $p['pages'];
+ $w = $p['wiki'];
+ // Wiki item record is $w['wiki']
+ $wikiname = $w['urlName'];
+ if (!$wikiname) {
+ $wikiname = '';
+ }
+ }
+ }
+ return replace_macros(get_markup_template('wiki_page_list.tpl'), array(
+ '$hide' => $hide,
+ '$not_refresh' => $not_refresh,
+ '$header' => t('Wiki Pages'),
+ '$channel' => $channelname,
+ '$wikiname' => $wikiname,
+ '$pages' => $pages
+ ));
+}
+
+function widget_wiki_page_history($arr) {
+ require_once("include/wiki.php");
+ $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $pageHistory = wiki_page_history(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
+
+ return replace_macros(get_markup_template('wiki_page_history.tpl'), array(
+ '$pageHistory' => $pageHistory['history']
+ ));
+}
+
function widget_bookmarkedchats($arr) {
if(! feature_enabled(App::$profile['profile_uid'],'ajaxchat'))
@@ -922,8 +994,9 @@ function widget_item($arr) {
$sql_extra = item_permissions_sql($channel_id);
if($arr['title']) {
- $r = q("select item.* from item left join item_id on item.id = item_id.iid
- where item.uid = %d and sid = '%s' and service = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1",
+ $r = q("select item.* from item left join iconfig on item.id = iconfig.iid
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s'
+ and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1",
intval($channel_id),
dbesc($arr['title']),
intval(ITEM_TYPE_WEBPAGE)
@@ -1085,7 +1158,7 @@ function widget_cover_photo($arr) {
if(array_key_exists('subtitle', $arr) && isset($arr['subtitle']))
$subtitle = $arr['subtitle'];
else
- $subtitle = $channel['xchan_addr'];
+ $subtitle = str_replace('@','&#x40;',$channel['xchan_addr']);
$c = get_cover_photo($channel_id,'html');
@@ -1181,8 +1254,8 @@ function widget_random_block($arr) {
$randfunc = db_getfunc('RAND');
- $r = q("select item.* from item left join item_id on item.id = item_id.iid
- where item.uid = %d and sid like '%s' and service = 'BUILDBLOCK' and
+ $r = q("select item.* from item left join iconfig on item.id = iconfig.iid
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.v like '%s' and iconfig.k = 'BUILDBLOCK' and
item_type = %d $sql_options order by $randfunc limit 1",
intval($channel_id),
dbesc('%' . $contains . '%'),
diff --git a/include/wiki.php b/include/wiki.php
new file mode 100644
index 000000000..63cf70f3c
--- /dev/null
+++ b/include/wiki.php
@@ -0,0 +1,496 @@
+<?php
+/**
+ * @file include/wiki.php
+ * @brief Wiki related functions.
+ */
+
+use \Zotlabs\Storage\GitRepo as GitRepo;
+define ( 'WIKI_ITEM_RESOURCE_TYPE', 'wiki' );
+
+function wiki_list($channel, $observer_hash) {
+ $sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
+ $wikis = q("SELECT * FROM item WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ intval($channel['channel_id'])
+ );
+ foreach($wikis as &$w) {
+ $w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
+ $w['htmlName'] = get_iconfig($w, 'wiki', 'htmlName');
+ $w['urlName'] = get_iconfig($w, 'wiki', 'urlName');
+ $w['path'] = get_iconfig($w, 'wiki', 'path');
+ }
+ // TODO: query db for wikis the observer can access. Return with two lists, for read and write access
+ return array('wikis' => $wikis);
+}
+
+function wiki_page_list($resource_id) {
+ // TODO: Create item table records for pages so that metadata like title can be applied
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('pages' => null, 'wiki' => null);
+ }
+ $pages = array();
+ if (is_dir($w['path']) === true) {
+ $files = array_diff(scandir($w['path']), array('.', '..', '.git'));
+ // TODO: Check that the files are all text files
+
+ foreach($files as $file) {
+ // strip the .md file extension and unwrap URL encoding to leave HTML encoded name
+ $pages[] = array('title' => urldecode(substr($file, 0, -3)), 'url' => urlencode(substr($file, 0, -3)));
+ }
+ }
+
+ return array('pages' => $pages, 'wiki' => $w);
+}
+
+function wiki_init_wiki($channel, $wiki) {
+ // Store the path as a relative path, but pass absolute path to mkdir
+ $path = 'store/[data]/git/'.$channel['channel_address'].'/wiki/'.$wiki['urlName'];
+ if (!os_mkdir(__DIR__ . '/../' . $path, 0770, true)) {
+ logger('Error creating wiki path: ' . $path);
+ return null;
+ }
+ // Create GitRepo object
+ $git = new GitRepo($channel['channel_address'], null, false, $wiki['urlName'], __DIR__ . '/../' . $path);
+ if(!$git->initRepo()) {
+ logger('Error creating new git repo in ' . $git->path);
+ return null;
+ }
+
+ return array('path' => $path);
+}
+
+function wiki_create_wiki($channel, $observer_hash, $wiki, $acl) {
+ $wikiinit = wiki_init_wiki($channel, $wiki);
+ if (!$wikiinit['path']) {
+ notice('Error creating wiki');
+ return array('item' => null, 'success' => false);
+ }
+ $path = $wikiinit['path'];
+ // Generate unique resource_id using the same method as item_message_id()
+ do {
+ $dups = false;
+ $resource_id = random_string();
+ $r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
+ dbesc($resource_id),
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ intval($channel['channel_id'])
+ );
+ if (count($r))
+ $dups = true;
+ } while ($dups == true);
+ $ac = $acl->get();
+ $mid = item_message_id();
+ $arr = array(); // Initialize the array of parameters for the post
+ $item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
+ $wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
+ $arr['aid'] = $channel['channel_account_id'];
+ $arr['uid'] = $channel['channel_id'];
+ $arr['mid'] = $mid;
+ $arr['parent_mid'] = $mid;
+ $arr['item_hidden'] = $item_hidden;
+ $arr['resource_type'] = WIKI_ITEM_RESOURCE_TYPE;
+ $arr['resource_id'] = $resource_id;
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['author_xchan'] = $observer_hash;
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['llink'] = $arr['plink'];
+ $arr['title'] = $wiki['htmlName']; // name of new wiki;
+ $arr['allow_cid'] = $ac['allow_cid'];
+ $arr['allow_gid'] = $ac['allow_gid'];
+ $arr['deny_cid'] = $ac['deny_cid'];
+ $arr['deny_gid'] = $ac['deny_gid'];
+ $arr['item_wall'] = 1;
+ $arr['item_origin'] = 1;
+ $arr['item_thread_top'] = 1;
+ $arr['item_private'] = intval($acl->is_private());
+ $arr['verb'] = ACTIVITY_CREATE;
+ $arr['obj_type'] = ACTIVITY_OBJ_WIKI;
+ $arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
+ // Save the path using iconfig. The file path should not be shared with other hubs
+ if (!set_iconfig($arr, 'wiki', 'path', $path, false)) {
+ return array('item' => null, 'success' => false);
+ }
+ // Save the wiki name information using iconfig. This is shareable.
+ if (!set_iconfig($arr, 'wiki', 'rawName', $wiki['rawName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ if (!set_iconfig($arr, 'wiki', 'htmlName', $wiki['htmlName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ if (!set_iconfig($arr, 'wiki', 'urlName', $wiki['urlName'], true)) {
+ return array('item' => null, 'success' => false);
+ }
+ $post = item_store($arr);
+ $item_id = $post['item_id'];
+
+ if ($item_id) {
+ proc_run('php', "include/notifier.php", "activity", $item_id);
+ return array('item' => $arr, 'success' => true);
+ } else {
+ return array('item' => null, 'success' => false);
+ }
+}
+
+function wiki_delete_wiki($resource_id) {
+
+ $w = wiki_get_wiki($resource_id);
+ $item = $w['wiki'];
+ if (!$item || !$w['path']) {
+ return array('item' => null, 'success' => false);
+ } else {
+ $drop = drop_item($item['id'], false, DROPITEM_NORMAL, true);
+ $pathdel = rrmdir($w['path']);
+ if ($pathdel) {
+ info('Wiki files deleted successfully');
+ }
+ return array('item' => $item, 'success' => (($drop === 1 && $pathdel) ? true : false));
+ }
+}
+
+function wiki_get_wiki($resource_id) {
+ $item = q("SELECT * FROM item WHERE resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0 limit 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc($resource_id)
+ );
+ if (!$item) {
+ return array('wiki' => null, 'path' => null);
+ } else {
+ $w = $item[0]; // wiki item table record
+ // Get wiki metadata
+ $rawName = get_iconfig($w, 'wiki', 'rawName');
+ $htmlName = get_iconfig($w, 'wiki', 'htmlName');
+ $urlName = get_iconfig($w, 'wiki', 'urlName');
+ $path = get_iconfig($w, 'wiki', 'path');
+ if (!realpath(__DIR__ . '/../' . $path)) {
+ return array('wiki' => null, 'path' => null);
+ }
+ // Path to wiki exists
+ $abs_path = realpath(__DIR__ . '/../' . $path);
+ return array( 'wiki' => $w,
+ 'path' => $abs_path,
+ 'rawName' => $rawName,
+ 'htmlName' => $htmlName,
+ 'urlName' => $urlName
+ );
+ }
+}
+
+function wiki_exists_by_name($uid, $urlName) {
+ $item = q("SELECT id,resource_id FROM item WHERE resource_type = '%s' AND title = '%s' AND uid = '%s' AND item_deleted = 0 limit 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc(escape_tags(urldecode($urlName))),
+ dbesc($uid)
+ );
+ if (!$item) {
+ return array('id' => null, 'resource_id' => null);
+ } else {
+ return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
+ }
+}
+
+function wiki_get_permissions($resource_id, $owner_id, $observer_hash) {
+ // TODO: For now, only the owner can edit
+ $sql_extra = item_permissions_sql($owner_id, $observer_hash);
+ $r = q("SELECT * FROM item WHERE resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc($resource_id)
+ );
+
+ if (!$r) {
+ return array('read' => false, 'write' => false, 'success' => true);
+ } else {
+ $perms = get_all_perms($owner_id, $observer_hash);
+ // TODO: Create a new permission setting for wiki analogous to webpages. Until
+ // then, use webpage permissions
+ if (!$perms['write_pages']) {
+ $write = false;
+ } else {
+ $write = true;
+ }
+ return array('read' => true, 'write' => $write, 'success' => true);
+ }
+}
+
+function wiki_create_page($name, $resource_id) {
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Wiki not found.', 'success' => false);
+ }
+ $page = array('rawName' => $name, 'htmlName' => escape_tags($name), 'urlName' => urlencode(escape_tags($name)), 'fileName' => urlencode(escape_tags($name)).'.md');
+ $page_path = $w['path'] . '/' . $page['fileName'];
+ if (is_file($page_path)) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Page already exists.', 'success' => false);
+ }
+ // Create the page file in the wiki repo
+ if(!touch($page_path)) {
+ return array('page' => null, 'wiki' => null, 'message' => 'Page file cannot be created.', 'success' => false);
+ } else {
+ return array('page' => $page, 'wiki' => $w, 'message' => '', 'success' => true);
+ }
+
+}
+
+function wiki_rename_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $pageNewName = ((array_key_exists('pageNewName',$arr)) ? $arr['pageNewName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Wiki not found.', 'success' => false);
+ }
+ $page_path_old = $w['path'].'/'.$pageUrlName.'.md';
+ if (!is_readable($page_path_old) === true) {
+ return array('message' => 'Cannot read wiki page: ' . $page_path_old, 'success' => false);
+ }
+ $page = array('rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), 'urlName' => urlencode(escape_tags($pageNewName)), 'fileName' => urlencode(escape_tags($pageNewName)).'.md');
+ $page_path_new = $w['path'] . '/' . $page['fileName'] ;
+ if (is_file($page_path_new)) {
+ return array('message' => 'Page already exists.', 'success' => false);
+ }
+ // Rename the page file in the wiki repo
+ if(!rename($page_path_old, $page_path_new)) {
+ return array('message' => 'Error renaming page file.', 'success' => false);
+ } else {
+ return array('page' => $page, 'message' => '', 'success' => true);
+ }
+
+}
+
+function wiki_get_page_content($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_readable($page_path) === true) {
+ if(filesize($page_path) === 0) {
+ $content = '';
+ } else {
+ $content = file_get_contents($page_path);
+ if(!$content) {
+ return array('content' => null, 'message' => 'Error reading page content', 'success' => false);
+ }
+ }
+ // TODO: Check that the files are all text files
+ return array('content' => json_encode($content), 'message' => '', 'success' => true);
+ }
+}
+
+function wiki_page_history($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (!is_readable($page_path) === true) {
+ return array('history' => null, 'message' => 'Cannot read wiki page: ' . $page_path, 'success' => false);
+ }
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? $w['wiki']['title'] : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo('', null, false, $w['wiki']['title'], $w['path']);
+ try {
+ $gitlog = $git->git->log('', $page_path , array('limit' => 500));
+ return array('history' => $gitlog, 'message' => '', 'success' => true);
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('history' => null, 'message' => 'GitRepo error thrown', 'success' => false);
+ }
+}
+
+function wiki_save_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $content = ((array_key_exists('content',$arr)) ? purify_html($arr['content']) : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+ if(!file_put_contents($page_path, $content)) {
+ return array('message' => 'Error writing to page file', 'success' => false);
+ }
+ return array('message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_delete_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+ if(!unlink($page_path)) {
+ return array('message' => 'Error deleting page file', 'success' => false);
+ }
+ return array('message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_revert_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
+ if (! $commitHash) {
+ return array('content' => $content, 'message' => 'No commit was provided', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('content' => $content, 'message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_writable($page_path) === true) {
+
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo($observer['xchan_addr'], null, false, $w['wiki']['title'], $w['path']);
+ $content = null;
+ try {
+ $git->setIdentity($observer['xchan_name'], $observer['xchan_addr']);
+ foreach ($git->git->tree($commitHash) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $content = $git->git->cat->blob($object['hash']);
+ }
+ }
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('content' => $content, 'message' => 'GitRepo error thrown', 'success' => false);
+ }
+ return array('content' => $content, 'message' => '', 'success' => true);
+ } else {
+ return array('content' => $content, 'message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_compare_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : 'HEAD');
+ $compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : null);
+ if (! $compareCommit) {
+ return array('message' => 'No compare commit was provided', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ if (is_readable($page_path) === true) {
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo('', null, false, $w['wiki']['title'], $w['path']);
+ $compareContent = $currentContent = '';
+ try {
+ foreach ($git->git->tree($currentCommit) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $currentContent = $git->git->cat->blob($object['hash']);
+ }
+ }
+ foreach ($git->git->tree($compareCommit) as $object) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ $compareContent = $git->git->cat->blob($object['hash']);
+ }
+ }
+ require_once('library/class.Diff.php');
+ $diff = Diff::toTable(Diff::compare($currentContent, $compareContent));
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('message' => 'GitRepo error thrown', 'success' => false);
+ }
+ return array('diff' => $diff, 'message' => '', 'success' => true);
+ } else {
+ return array('message' => 'Page file not writable', 'success' => false);
+ }
+}
+
+function wiki_git_commit($arr) {
+ $files = ((array_key_exists('files', $arr)) ? $arr['files'] : null);
+ $all = ((array_key_exists('all', $arr)) ? $arr['all'] : false);
+ $commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : 'Repo updated');
+ if(array_key_exists('resource_id', $arr)) {
+ $resource_id = $arr['resource_id'];
+ } else {
+ return array('message' => 'Wiki resource_id required for git commit', 'success' => false);
+ }
+ if(array_key_exists('observer', $arr)) {
+ $observer = $arr['observer'];
+ } else {
+ return array('message' => 'Observer required for git commit', 'success' => false);
+ }
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Error reading wiki', 'success' => false);
+ }
+ $reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
+ if($reponame === '') {
+ $reponame = 'repo';
+ }
+ $git = new GitRepo($observer['xchan_addr'], null, false, $w['wiki']['title'], $w['path']);
+ try {
+ $git->setIdentity($observer['xchan_name'], $observer['xchan_addr']);
+ if ($files === null) {
+ $options = array('all' => true); // git commit option to include all changes
+ } else {
+ $options = array('all' => $all); // git commit options\
+ foreach ($files as $file) {
+ if (!$git->git->add($file)) { // add specified files to the git repo stage
+ if (!$git->git->reset->hard()) {
+ return array('message' => 'Error adding file to git stage: ' . $file . '. Error resetting git repo.', 'success' => false);
+ }
+ return array('message' => 'Error adding file to git stage: ' . $file, 'success' => false);
+ }
+ }
+ }
+ if ($git->commit($commit_msg, $options)) {
+ return array('message' => 'Wiki repo commit succeeded', 'success' => true);
+ } else {
+ return array('message' => 'Wiki repo commit failed', 'success' => false);
+ }
+ } catch (\PHPGit\Exception\GitException $e) {
+ return array('message' => 'GitRepo error thrown', 'success' => false);
+ }
+}
+
+function wiki_generate_page_filename($name) {
+ $file = urlencode(escape_tags($name));
+ if( $file === '') {
+ return null;
+ } else {
+ return $file . '.md';
+ }
+}
+
+function wiki_convert_links($s, $wikiURL) {
+
+ if (strpos($s,'[[') !== false) {
+ preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
+ $pages = $pageURLs = array();
+ foreach ($match[1] as $m) {
+ // TODO: Why do we need to double urlencode for this to work?
+ $pageURLs[] = urlencode(urlencode(escape_tags($m)));
+ $pages[] = $m;
+ }
+ $idx = 0;
+ while(strpos($s,'[[') !== false) {
+ $replace = '<a href="'.$wikiURL.'/'.$pageURLs[$idx].'">'.$pages[$idx].'</a>';
+ $s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
+ $idx++;
+ }
+ }
+ return $s;
+} \ No newline at end of file
diff --git a/include/zot.php b/include/zot.php
index af79b5723..6dd789181 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -538,11 +538,21 @@ function zot_refresh($them, $channel = null, $force = false) {
Zotlabs\Daemon\Master::Summon(array('Onepoll',$new_connection[0]['abook_id']));
}
+
+ /** If there is a default group for this channel, add this connection to it */
+ $default_group = $channel['channel_default_group'];
+ if($default_group) {
+ require_once('include/group.php');
+ $g = group_rec_byhash($channel['channel_id'],$default_group);
+ if($g)
+ group_add_member($channel['channel_id'],'',$x['hash'],$g['id']);
+ }
+
unset($new_connection[0]['abook_id']);
unset($new_connection[0]['abook_account']);
unset($new_connection[0]['abook_channel']);
- $abconfig = load_abconfig($channel['channel_hash'],$new_connection['abook_xchan']);
+ $abconfig = load_abconfig($channel['channel_id'],$new_connection['abook_xchan']);
if($abconfig)
$new_connection['abconfig'] = $abconfig;
@@ -3021,7 +3031,8 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
$info = (($packet) ? $packet : array());
$info['type'] = 'channel_sync';
- $info['encoding'] = 'red'; // note: not zot, this packet is very red specific
+ $info['encoding'] = 'red'; // note: not zot, this packet is very platform specific
+ $info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ];
if(array_key_exists($uid,App::$config) && array_key_exists('transient',App::$config[$uid])) {
$settings = App::$config[$uid]['transient'];
@@ -3159,10 +3170,13 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
sync_events($channel,$arr['event']);
if(array_key_exists('event_item',$arr) && $arr['event_item'])
- sync_items($channel,$arr['event_item']);
+ sync_items($channel,$arr['event_item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
if(array_key_exists('item',$arr) && $arr['item'])
- sync_items($channel,$arr['item']);
+ sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
+
+ // deprecated, maintaining for a few months for upward compatibility
+ // this should sync webpages, but the logic is a bit subtle
if(array_key_exists('item_id',$arr) && $arr['item_id'])
sync_items($channel,$arr['item_id']);
@@ -3321,8 +3335,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if($abconfig) {
// @fixme does not handle sync of del_abconfig
foreach($abconfig as $abc) {
- if($abc['chan'] === $channel['channel_hash'])
- set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
+ set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
}
}
}
@@ -3519,13 +3532,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
-
- if(array_key_exists('item',$arr) && $arr['item'])
- sync_items($channel,$arr['item']);
-
- if(array_key_exists('item_id',$arr) && $arr['item_id'])
- sync_items($channel,$arr['item_id']);
-
$addon = array('channel' => $channel,'data' => $arr);
call_hooks('process_channel_sync_delivery',$addon);