aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Import/import_diaspora.php148
-rw-r--r--include/Import/refimport.php1
-rw-r--r--include/acl_selectors.php10
-rw-r--r--include/activities.php2
-rw-r--r--include/api_zot.php14
-rw-r--r--include/attach.php127
-rw-r--r--include/auth.php2
-rw-r--r--include/bbcode.php94
-rw-r--r--include/bookmarks.php1
-rw-r--r--include/channel.php590
-rw-r--r--include/connections.php308
-rw-r--r--include/conversation.php203
-rwxr-xr-xinclude/dba/dba_driver.php2
-rw-r--r--include/event.php81
-rw-r--r--include/features.php18
-rw-r--r--include/feedutils.php135
-rw-r--r--include/follow.php76
-rw-r--r--include/group.php68
-rw-r--r--include/help.php4
-rw-r--r--include/html2plain.php2
-rw-r--r--include/hubloc.php127
-rw-r--r--include/import.php732
-rwxr-xr-xinclude/items.php116
-rw-r--r--include/markdown.php (renamed from include/bb2diaspora.php)44
-rw-r--r--include/menu.php2
-rw-r--r--include/message.php80
-rw-r--r--include/nav.php117
-rw-r--r--include/network.php72
-rwxr-xr-xinclude/oembed.php17
-rw-r--r--include/photo/photo_driver.php4
-rw-r--r--include/photos.php73
-rwxr-xr-xinclude/plugin.php68
-rw-r--r--include/queue_fn.php61
-rw-r--r--include/security.php39
-rw-r--r--include/text.php94
-rw-r--r--include/widgets.php76
-rw-r--r--include/wiki.php664
-rw-r--r--include/xchan.php139
-rw-r--r--include/zid.php4
-rw-r--r--include/zot.php178
40 files changed, 2585 insertions, 2008 deletions
diff --git a/include/Import/import_diaspora.php b/include/Import/import_diaspora.php
deleted file mode 100644
index c6dae0117..000000000
--- a/include/Import/import_diaspora.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-
-require_once('include/bb2diaspora.php');
-require_once('include/group.php');
-require_once('include/follow.php');
-require_once('include/photo/photo_driver.php');
-
-function import_diaspora($data) {
-
- $account = App::get_account();
- if(! $account)
- return false;
-
- $address = escape_tags($data['user']['username']);
- if(! $address) {
- notice( t('No username found in import file.') . EOL);
- return false;
- }
-
- $r = q("select * from channel where channel_address = '%s' limit 1",
- dbesc($address)
- );
- if($r) {
- // try at most ten times to generate a unique address.
- $x = 0;
- $found_unique = false;
- do {
- $tmp = $address . mt_rand(1000,9999);
- $r = q("select * from channel where channel_address = '%s' limit 1",
- dbesc($tmp)
- );
- if(! $r) {
- $address = $tmp;
- $found_unique = true;
- break;
- }
- $x ++;
- } while ($x < 10);
- if(! $found_unique) {
- logger('import_diaspora: duplicate channel address. randomisation failed.');
- notice( t('Unable to create a unique channel address. Import failed.') . EOL);
- return;
- }
- }
-
-
- $c = create_identity(array(
- 'name' => escape_tags($data['user']['name']),
- 'nickname' => $address,
- 'account_id' => $account['account_id'],
- 'permissions_role' => 'social'
- ));
-
- if(! $c['success'])
- return;
-
- $channel_id = $c['channel']['channel_id'];
-
- // Hubzilla only: Turn on the Diaspora protocol so that follow requests will be sent.
-
- set_pconfig($channel_id,'system','diaspora_allowed','1');
-
- // todo - add auto follow settings, (and strip exif in hubzilla)
-
- $location = escape_tags($data['user']['profile']['location']);
- if(! $location)
- $location = '';
-
-
- q("update channel set channel_location = '%s' where channel_id = %d",
- dbesc($location),
- intval($channel_id)
- );
-
- if($data['user']['profile']['nsfw']) {
- q("update channel set channel_pageflags = (channel_pageflags | %d) where channel_id = %d",
- intval(PAGE_ADULT),
- intval($channel_id)
- );
- }
-
- if($data['user']['profile']['image_url']) {
- $p = z_fetch_url($data['user']['profile']['image_url'],true);
- if($p['success']) {
- $rawbytes = $p['body'];
- $type = guess_image_type('dummyfile',$p['header']);
- import_channel_photo($rawbytes,$type,$c['channel']['channel_account_id'],$channel_id);
- }
- }
-
- $gender = escape_tags($data['user']['profile']['gender']);
- $about = markdown_to_bb($data['user']['profile']['bio']);
- $publish = intval($data['user']['profile']['searchable']);
- if($data['user']['profile']['birthday'])
- $dob = datetime_convert('UTC','UTC',$data['user']['profile']['birthday'],'Y-m-d');
- else
- $dob = '0000-00-00';
-
- // we're relying on the fact that this channel was just created and will only
- // have the default profile currently
-
- $r = q("update profile set gender = '%s', about = '%s', dob = '%s', publish = %d where uid = %d",
- dbesc($gender),
- dbesc($about),
- dbesc($dob),
- dbesc($publish),
- intval($channel_id)
- );
-
- if($data['user']['aspects']) {
- foreach($data['user']['aspects'] as $aspect) {
- group_add($channel_id,escape_tags($aspect['name']),intval($aspect['contacts_visible']));
- }
- }
-
- // now add connections and send friend requests
-
-
- if($data['user']['contacts']) {
- foreach($data['user']['contacts'] as $contact) {
- $result = new_contact($channel_id, $contact['person_diaspora_handle'], $c['channel']);
- if($result['success']) {
- if($contact['aspects']) {
- foreach($contact['aspects'] as $aspect) {
- group_add_member($channel_id,$aspect['name'],$result['abook']['xchan_hash']);
- }
- }
- }
- }
- }
-
-
- // Then add items - note this can't be done until Diaspora adds guids to exported
- // items and comments
-
-
-
- // This will indirectly perform a refresh_all *and* update the directory
-
- proc_run('php', 'include/directory.php', $channel_id);
-
- notice( t('Import completed.') . EOL);
-
- change_channel($channel_id);
-
- goaway(z_root() . '/network' );
-
-} \ No newline at end of file
diff --git a/include/Import/refimport.php b/include/Import/refimport.php
index 3ef8870ac..04540a9bd 100644
--- a/include/Import/refimport.php
+++ b/include/Import/refimport.php
@@ -1,7 +1,6 @@
<?php
require_once('include/html2bbcode.php');
-require_once('include/hubloc.php');
// Sample module for importing conversation data from Reflection CMS. Some preparation was used to
// dump relevant posts, categories and comments into individual JSON files, and also JSON dump of
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index dcf0fe9a2..09c24f82c 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -174,6 +174,16 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
$custom = false;
}
+ $r = q("SELECT id, profile_guid, profile_name from profile where is_default = 0 and uid = %d order by profile_name",
+ intval(local_channel())
+ );
+ if($r) {
+ foreach($r as $rv) {
+ $selected = (($single_group && 'vp.' . $rr['hash'] === $allow_gid[0]) ? ' selected = "selected" ' : '');
+ $groups .= '<option id="' . 'vp' . $rv['id'] . '" value="' . 'vp.' . $rv['profile_guid'] . '"' . $selected . '>' . t('Profile','acl') . ' ' . $rv['profile_name'] . '</option>' . "\r\n";
+ }
+ }
+
$r = q("SELECT id, hash, gname FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval(local_channel())
);
diff --git a/include/activities.php b/include/activities.php
index 3271db993..2671e668c 100644
--- a/include/activities.php
+++ b/include/activities.php
@@ -27,7 +27,7 @@ function profile_activity($changed, $value) {
$arr['verb'] = ACTIVITY_UPDATE;
$arr['obj_type'] = ACTIVITY_OBJ_PROFILE;
- $arr['plink'] = z_root() . '/channel/' . $self['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['plink'] = z_root() . '/channel/' . $self['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
$A = '[url=' . z_root() . '/channel/' . $self['channel_address'] . ']' . $self['channel_name'] . '[/url]';
diff --git a/include/api_zot.php b/include/api_zot.php
index fe3a95d25..aaa9ee497 100644
--- a/include/api_zot.php
+++ b/include/api_zot.php
@@ -69,8 +69,13 @@
logger('api_export_basic: no user');
return false;
}
-
- json_return_and_die(identity_basic_export(api_user(),(($_REQUEST['posts']) ? intval($_REQUEST['posts']) : 0 )));
+ $sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : '');
+ if($_REQUEST['posts']) {
+ $sections = get_default_export_sections();
+ $sections[] = 'items';
+ }
+
+ json_return_and_die(identity_basic_export(api_user(),$sections));
}
@@ -350,10 +355,9 @@
if(api_user() === false)
return false;
logger('api_xchan');
- require_once('include/hubloc.php');
- if($_SERVER['REQUEST_METHOD'] === 'POST') {
- // $r = xchan_store($_REQUEST);
+ if($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $r = xchan_store($_REQUEST);
}
$r = xchan_fetch($_REQUEST);
json_return_and_die($r);
diff --git a/include/attach.php b/include/attach.php
index ba2f60a90..79313ab1a 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -28,29 +28,31 @@ function z_mime_content_type($filename) {
$mime_types = array(
- 'txt' => 'text/plain',
- 'htm' => 'text/html',
+ 'txt' => 'text/plain',
+ 'htm' => 'text/html',
'html' => 'text/html',
- 'php' => 'text/html',
- 'css' => 'text/css',
- 'js' => 'application/javascript',
+ 'php' => 'text/html',
+ 'css' => 'text/css',
+ 'md' => 'text/markdown',
+ 'bb' => 'text/bbcode',
+ 'js' => 'application/javascript',
'json' => 'application/json',
- 'xml' => 'application/xml',
- 'swf' => 'application/x-shockwave-flash',
- 'flv' => 'video/x-flv',
+ 'xml' => 'application/xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 'flv' => 'video/x-flv',
'epub' => 'application/epub+zip',
// images
- 'png' => 'image/png',
- 'jpe' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'gif' => 'image/gif',
- 'bmp' => 'image/bmp',
- 'ico' => 'image/vnd.microsoft.icon',
+ 'jpg' => 'image/jpeg',
+ 'gif' => 'image/gif',
+ 'bmp' => 'image/bmp',
+ 'ico' => 'image/vnd.microsoft.icon',
'tiff' => 'image/tiff',
- 'tif' => 'image/tiff',
- 'svg' => 'image/svg+xml',
+ 'tif' => 'image/tiff',
+ 'svg' => 'image/svg+xml',
'svgz' => 'image/svg+xml',
// archives
@@ -61,27 +63,27 @@ function z_mime_content_type($filename) {
'cab' => 'application/vnd.ms-cab-compressed',
// audio/video
- 'mp3' => 'audio/mpeg',
- 'wav' => 'audio/wav',
- 'qt' => 'video/quicktime',
- 'mov' => 'video/quicktime',
- 'ogg' => 'audio/ogg',
- 'ogv' => 'video/ogg',
- 'ogx' => 'application/ogg',
+ 'mp3' => 'audio/mpeg',
+ 'wav' => 'audio/wav',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'ogg' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'ogx' => 'application/ogg',
'flac' => 'audio/flac',
'opus' => 'audio/ogg',
'webm' => 'video/webm',
// 'webm' => 'audio/webm',
- 'mp4' => 'video/mp4',
-// 'mp4' => 'audio/mp4',
- 'mkv' => 'video/x-matroska',
+ 'mp4' => 'video/mp4',
+// 'mp4' => 'audio/mp4',
+ 'mkv' => 'video/x-matroska',
// adobe
'pdf' => 'application/pdf',
'psd' => 'image/vnd.adobe.photoshop',
- 'ai' => 'application/postscript',
+ 'ai' => 'application/postscript',
'eps' => 'application/postscript',
- 'ps' => 'application/postscript',
+ 'ps' => 'application/postscript',
// ms office
'doc' => 'application/msword',
@@ -1279,8 +1281,10 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
intval($channel_id)
);
- if(! $r)
+ if(! $r) {
+ attach_drop_photo($channel_id,$resource);
return;
+ }
$cloudpath = get_parent_cloudpath($channel_id, $channel_address, $resource);
$object = get_file_activity_object($channel_id, $resource, $cloudpath);
@@ -1326,19 +1330,10 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
);
if($r[0]['is_photo']) {
- $x = q("select id, item_hidden from item where resource_id = '%s' and resource_type = 'photo' and uid = %d",
- dbesc($resource),
- intval($channel_id)
- );
- if($x) {
- drop_item($x[0]['id'],false,(($x[0]['item_hidden']) ? DROPITEM_NORMAL : DROPITEM_PHASE1),true);
- }
- q("DELETE FROM photo WHERE uid = %d AND resource_id = '%s'",
- intval($channel_id),
- dbesc($resource)
- );
+ attach_drop_photo($channel_id,$resource);
}
+
// update the parent folder's lastmodified timestamp
$e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d",
dbesc(datetime_convert()),
@@ -1351,6 +1346,24 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
return;
}
+
+function attach_drop_photo($channel_id,$resource) {
+
+ $x = q("select id, item_hidden from item where resource_id = '%s' and resource_type = 'photo' and uid = %d",
+ dbesc($resource),
+ intval($channel_id)
+ );
+ if($x) {
+ drop_item($x[0]['id'],false,(($x[0]['item_hidden']) ? DROPITEM_NORMAL : DROPITEM_PHASE1),true);
+ }
+ q("DELETE FROM photo WHERE uid = %d AND resource_id = '%s'",
+ intval($channel_id),
+ dbesc($resource)
+ );
+
+}
+
+
/**
* @brief Returns path to file in cloud/.
*
@@ -1464,18 +1477,34 @@ function find_folder_hash_by_attach_hash($channel_id, $attachHash, $recurse = fa
function find_folder_hash_by_path($channel_id, $path) {
- $filename = end(explode('/', $path));
+ if(! $path)
+ return '';
- $r = q("SELECT hash FROM attach WHERE uid = %d AND filename = '%s' LIMIT 1",
- intval($channel_id),
- dbesc($filename)
- );
+ $comps = explode('/',$path);
+ $errors = false;
+ $parent_hash = '';
- $hash = '';
- if($r && $r[0]['hash']) {
- $hash = $r[0]['hash'];
+ for($x = 0; $x < count($comps); $x ++) {
+ $element = $comps[$x];
+ $r = q("SELECT hash FROM attach WHERE uid = %d AND filename = '%s' AND folder = '%s' LIMIT 1",
+ intval($channel_id),
+ dbesc($element),
+ dbesc($parent_hash)
+ );
+ if($r) {
+ $parent_hash = $r[0]['hash'];
+ }
+ else {
+ $errors ++;
+ break;
+ }
}
- return $hash;
+
+ if($errors)
+ return '';
+
+ return $parent_hash;
+
}
/**
diff --git a/include/auth.php b/include/auth.php
index fdcecec36..c7be69583 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -300,7 +300,7 @@ else {
// (i.e. expire when the browser is closed), even when there's a time expiration
// on the cookie
- if($_POST['remember_me']) {
+ if(($_POST['remember_me']) || ($_POST['remember'])) {
$_SESSION['remember_me'] = 1;
App::$session->new_cookie(31449600); // one year
}
diff --git a/include/bbcode.php b/include/bbcode.php
index 32354aeda..c0033f280 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -7,7 +7,7 @@
require_once('include/oembed.php');
require_once('include/event.php');
require_once('include/zot.php');
-require_once('include/hubloc.php');
+
function tryoembed($match) {
$url = ((count($match) == 2) ? $match[1] : $match[2]);
@@ -473,11 +473,40 @@ function bb_sanitize_style($input) {
return '<span style="' . $css_string_san . '">' . $input[2] . '</span>';
}
+function oblanguage_callback($matches) {
+ if(strlen($matches[1]) == 2) {
+ $compare = strtolower(substr(\App::$language,0,2));
+ }
+ else {
+ $compare = strtolower(\App::$language);
+ }
+
+ if($compare === strtolower($matches[1]))
+ return $matches[2];
+
+ return '';
+}
+
+function oblanguage_necallback($matches) {
+ if(strlen($matches[1]) == 2) {
+ $compare = strtolower(substr(\App::$language,0,2));
+ }
+ else {
+ $compare = strtolower(\App::$language);
+ }
+
+ if($compare !== strtolower($matches[1]))
+ return $matches[2];
+
+ return '';
+}
+
function bb_observer($Text) {
$observer = App::get_observer();
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
+
if ($observer) {
$Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text);
$Text = preg_replace("/\[observer\=0\].*?\[\/observer\]/ism", '', $Text);
@@ -511,6 +540,20 @@ function bb_code($match) {
return '<code class="inline-code">' . trim($match[1]) . '</code>';
}
+function bb_code_options($match) {
+ if(strpos($match[0], "<br />")) {
+ $class = "";
+ } else {
+ $class = "inline-code";
+ }
+ if(strpos($match[1], 'nowrap')) {
+ $style = "overflow-x: auto; white-space: pre;";
+ } else {
+ $style = "";
+ }
+ return '<code class="'. $class .'" style="'. $style .'">' . trim($match[2]) . '</code>';
+}
+
function bb_highlight($match) {
$lang = ((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']))
@@ -530,13 +573,28 @@ function bb_fixtable_lf($match) {
}
function parseIdentityAwareHTML($Text) {
-
+
+ // Hide all [noparse] contained bbtags by spacefying them
+ if (strpos($Text,'[noparse]') !== false) {
+ $Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_spacefy',$Text);
+ }
+ if (strpos($Text,'[nobb]') !== false) {
+ $Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_spacefy',$Text);
+ }
+ if (strpos($Text,'[pre]') !== false) {
+ $Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_spacefy',$Text);
+ }
// process [observer] tags before we do anything else because we might
// be stripping away stuff that then doesn't need to be worked on anymore
$observer = App::get_observer();
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
+
+ $Text = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_callback', $Text);
+
+ $Text = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_necallback', $Text);
+
if ($observer) {
$Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text);
$Text = preg_replace("/\[observer\=0\].*?\[\/observer\]/ism", '', $Text);
@@ -568,9 +626,21 @@ function parseIdentityAwareHTML($Text) {
$Text = str_replace('[observer.photo]','', $Text);
}
- $Text = str_replace(array('[baseurl]','[sitename]'),array(z_root(),get_config('system','sitename')),$Text);
+ $Text = str_replace(array('[baseurl]','[sitename]'),array(z_root(),get_config('system','sitename')),$Text);
- return $Text;
+
+ // Unhide all [noparse] contained bbtags unspacefying them
+ // and triming the [noparse] tag.
+ if (strpos($Text,'[noparse]') !== false) {
+ $Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_unspacefy_and_trim', $Text);
+ }
+ if (strpos($Text,'[nobb]') !== false) {
+ $Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_unspacefy_and_trim', $Text);
+ }
+ if (strpos($Text,'[pre]') !== false) {
+ $Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_unspacefy_and_trim', $Text);
+ }
+ return $Text;
}
// BBcode 2 HTML was written by WAY2WEB.net
@@ -607,6 +677,9 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$observer = App::get_observer();
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
+ $Text = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_callback', $Text);
+ $Text = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_necallback', $Text);
+
if ($observer) {
$Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text);
$Text = preg_replace("/\[observer\=0\].*?\[\/observer\]/ism", '', $Text);
@@ -891,8 +964,8 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
}
if (strpos($Text,'[/table]') !== false) {
$Text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '<table>$1</table>', $Text);
- $Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table border="1" >$1</table>', $Text);
- $Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table border="0" >$1</table>', $Text);
+ $Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table class="table table-responsive table-bordered" >$1</table>', $Text);
+ $Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table class="table table-responsive" >$1</table>', $Text);
}
$Text = str_replace('</tr><br /><tr>', "</tr>\n<tr>", $Text);
$Text = str_replace('[hr]', '<hr />', $Text);
@@ -911,6 +984,11 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace_callback("/\[code\](.*?)\[\/code\]/ism", 'bb_code', $Text);
}
+ // Check for [code options] text
+ if (strpos($Text,'[code ') !== false) {
+ $Text = preg_replace_callback("/\[code(.*?)\](.*?)\[\/code\]/ism", 'bb_code_options', $Text);
+ }
+
// Check for [spoiler] text
$endlessloop = 0;
while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) {
@@ -1127,9 +1205,9 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism", '<$1$2=$3&$4>', $Text);
// This is subtle - it's an XSS filter. It only accepts links with a protocol scheme and where
- // the scheme begins with z (zhttp), h (http(s)), f (ftp), m (mailto), and named anchors.
+ // the scheme begins with z (zhttp), h (http(s)), f (ftp(s)), m (mailto), t (tel) and named anchors.
- $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism", '<$1$2="">', $Text);
+ $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfmt#](.*?)\>/ism", '<$1$2="">', $Text);
$Text = bb_replace_images($Text, $saved_images);
diff --git a/include/bookmarks.php b/include/bookmarks.php
index c6e8e86f2..0db103054 100644
--- a/include/bookmarks.php
+++ b/include/bookmarks.php
@@ -23,7 +23,6 @@ function bookmark_add($channel,$sender,$taxonomy,$private,$opts = null) {
$iarr['mitem_desc'] = $taxonomy['term'];
$iarr['mitem_flags'] = (($ischat) ? MENU_ITEM_CHATROOM : 0);
- require_once('include/hubloc.php');
$zrl = is_matrix_url($taxonomy['url']);
if($zrl)
diff --git a/include/channel.php b/include/channel.php
index 4fc873402..71ba2476f 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -291,59 +291,63 @@ function create_identity($arr) {
// Create a verified hub location pointing to this site.
- $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary,
- hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )
- values ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
- dbesc($guid),
- dbesc($sig),
- dbesc($hash),
- dbesc(channel_reddress($ret['channel'])),
- intval($primary),
- dbesc(z_root()),
- dbesc(base64url_encode(rsa_sign(z_root(),$ret['channel']['channel_prvkey']))),
- dbesc(App::get_hostname()),
- dbesc(z_root() . '/post'),
- dbesc(get_config('system','pubkey')),
- dbesc('zot')
+ $r = hubloc_store_lowlevel(
+ [
+ 'hubloc_guid' => $guid,
+ 'hubloc_guid_sig' => $sig,
+ 'hubloc_hash' => $hash,
+ 'hubloc_addr' => channel_reddress($ret['channel']),
+ 'hubloc_primary' => $primary,
+ 'hubloc_url' => z_root(),
+ 'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$ret['channel']['channel_prvkey'])),
+ 'hubloc_host' => App::get_hostname(),
+ 'hubloc_callback' => z_root() . '/post',
+ 'hubloc_sitekey' => get_config('system','pubkey'),
+ 'hubloc_network' => 'zot',
+ 'hubloc_updated' => datetime_convert()
+ ]
);
if(! $r)
logger('create_identity: Unable to store hub location');
$newuid = $ret['channel']['channel_id'];
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_system ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
- dbesc($hash),
- dbesc($guid),
- dbesc($sig),
- dbesc($key['pubkey']),
- dbesc(z_root() . "/photo/profile/l/{$newuid}"),
- dbesc(z_root() . "/photo/profile/m/{$newuid}"),
- dbesc(z_root() . "/photo/profile/s/{$newuid}"),
- dbesc(channel_reddress($ret['channel'])),
- dbesc(z_root() . '/channel/' . $ret['channel']['channel_address']),
- dbesc(z_root() . '/follow?f=&url=%s'),
- dbesc(z_root() . '/poco/' . $ret['channel']['channel_address']),
- dbesc($ret['channel']['channel_name']),
- dbesc('zot'),
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval($system)
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $hash,
+ 'xchan_guid' => $guid,
+ 'xchan_guid_sig' => $sig,
+ 'xchan_pubkey' => $key['pubkey'],
+ 'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
+ 'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
+ 'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
+ 'xchan_addr' => channel_reddress($ret['channel']),
+ 'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
+ 'xchan_follow' => z_root() . '/follow?f=&url=%s',
+ 'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
+ 'xchan_name' => $ret['channel']['channel_name'],
+ 'xchan_network' => 'zot',
+ 'xchan_photo_date' => datetime_convert(),
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_system' => $system
+ ]
);
// Not checking return value.
// It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate
- $r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, fullname, photo, thumb)
- VALUES ( %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s') ",
- intval($ret['channel']['channel_account_id']),
- intval($newuid),
- dbesc(random_string()),
- t('Default Profile'),
- 1,
- $publish,
- dbesc($ret['channel']['channel_name']),
- dbesc(z_root() . "/photo/profile/l/{$newuid}"),
- dbesc(z_root() . "/photo/profile/m/{$newuid}")
+ $r = profile_store_lowlevel(
+ [
+ 'aid' => intval($ret['channel']['channel_account_id']),
+ 'uid' => intval($newuid),
+ 'profile_guid' => random_string(),
+ 'profile_name' => t('Default Profile'),
+ 'is_default' => 1,
+ 'publish' => $publish,
+ 'fullname' => $ret['channel']['channel_name'],
+ 'photo' => z_root() . "/photo/profile/l/{$newuid}",
+ 'thumb' => z_root() . "/photo/profile/m/{$newuid}"
+ ]
);
if($role_permissions) {
@@ -354,15 +358,16 @@ function create_identity($arr) {
$myperms = $x['perms_connect'];
}
- $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_self )
- values ( %d, %d, '%s', %d, '%s', '%s', %d ) ",
- intval($ret['channel']['channel_account_id']),
- intval($newuid),
- dbesc($hash),
- intval(0),
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval(1)
+ $r = abook_store_lowlevel(
+ [
+ 'abook_account' => intval($ret['channel']['channel_account_id']),
+ 'abook_channel' => intval($newuid),
+ 'abook_xchan' => $hash,
+ 'abook_closeness' => 0,
+ 'abook_created' => datetime_convert(),
+ 'abook_updated' => datetime_convert(),
+ 'abook_self' => 1
+ ]
);
$x = \Zotlabs\Access\Permissions::FilledPerms($myperms);
@@ -387,6 +392,7 @@ function create_identity($arr) {
set_pconfig($newuid,'autoperms',$k,$v);
}
}
+ // as this is a new channel, this shouldn't do anything and probaby is not needed
else {
$r = q("delete from pconfig where uid = %d and cat = 'autoperms'",
intval($newuid)
@@ -459,6 +465,7 @@ function create_identity($arr) {
* if true, set this default unconditionally
* if $force is false only do this if there is no existing default
*/
+
function set_default_login_identity($account_id, $channel_id, $force = true) {
$r = q("select account_default_channel from account where account_id = %d limit 1",
intval($account_id)
@@ -473,6 +480,16 @@ function set_default_login_identity($account_id, $channel_id, $force = true) {
}
}
+
+function get_default_export_sections() {
+ $sections = [ 'channel', 'connections', 'config', 'apps', 'chatrooms', 'events', 'webpages', 'mail', 'wikis' ];
+
+ $cb = [ 'sections' => $sections ];
+ call_hooks('get_default_export_sections', $cb);
+ return $cb['sections'];
+}
+
+
/**
* @brief Create an array representing the important channel information
* which would be necessary to create a nomadic identity clone. This includes
@@ -486,214 +503,280 @@ function set_default_login_identity($account_id, $channel_id, $force = true) {
* @returns array
* See function for details
*/
-function identity_basic_export($channel_id, $items = false) {
+
+function identity_basic_export($channel_id, $sections = null) {
/*
- * Red basic channel export
+ * basic channel export
*/
- $ret = array();
+ if(! $sections) {
+ $sections = get_default_export_sections();
+ }
+
+ $ret = [];
// use constants here as otherwise we will have no idea if we can import from a site
// with a non-standard platform and version.
- $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => STD_VERSION, 'database' => DB_UPDATE_VERSION, 'server_role' => Zotlabs\Lib\System::get_server_role());
+
+ $ret['compatibility'] = [
+ 'project' => PLATFORM_NAME,
+ 'version' => STD_VERSION,
+ 'database' => DB_UPDATE_VERSION,
+ 'server_role' => Zotlabs\Lib\System::get_server_role()
+ ];
+
+ /*
+ * Process channel information regardless of it is one of the sections desired
+ * because we need the channel relocation information in all export files/streams.
+ */
$r = q("select * from channel where channel_id = %d limit 1",
intval($channel_id)
);
if($r) {
translate_channel_perms_outbound($r[0]);
- $ret['channel'] = $r[0];
$ret['relocate'] = [ 'channel_address' => $r[0]['channel_address'], 'url' => z_root()];
- }
-
- $r = q("select * from profile where uid = %d",
- intval($channel_id)
- );
- if($r)
- $ret['profile'] = $r;
-
- $xchans = array();
- $r = q("select * from abook where abook_channel = %d ",
- intval($channel_id)
- );
- if($r) {
- $ret['abook'] = $r;
-
- for($x = 0; $x < count($ret['abook']); $x ++) {
- $xchans[] = $ret['abook'][$x]['abook_xchan'];
- $abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
- if($abconfig)
- $ret['abook'][$x]['abconfig'] = $abconfig;
- translate_abook_perms_outbound($ret['abook'][$x]);
+ if(in_array('channel',$sections)) {
+ $ret['channel'] = $r[0];
}
- stringify_array_elms($xchans);
}
- if($xchans) {
- $r = q("select * from xchan where xchan_hash in ( " . implode(',',$xchans) . " ) ");
+ if(in_array('channel',$sections)) {
+ $r = q("select * from profile where uid = %d",
+ intval($channel_id)
+ );
if($r)
- $ret['xchan'] = $r;
+ $ret['profile'] = $r;
- $r = q("select * from hubloc where hubloc_hash in ( " . implode(',',$xchans) . " ) ");
- if($r)
- $ret['hubloc'] = $r;
- }
- $r = q("select * from groups where uid = %d ",
- intval($channel_id)
- );
+ $r = q("select mimetype, content, os_storage from photo
+ where imgscale = 4 and photo_usage = %d and uid = %d limit 1",
+ intval(PHOTO_PROFILE),
+ intval($channel_id)
+ );
- if($r)
- $ret['group'] = $r;
+ if($r) {
+ $ret['photo'] = [
+ 'type' => $r[0]['mimetype'],
+ 'data' => (($r[0]['os_storage'])
+ ? base64url_encode(file_get_contents($r[0]['content'])) : base64url_encode($r[0]['content']))
+ ];
+ }
+ }
- $r = q("select * from group_member where uid = %d ",
- intval($channel_id)
- );
- if($r)
- $ret['group_member'] = $r;
+ if(in_array('connections',$sections)) {
+ $xchans = array();
+ $r = q("select * from abook where abook_channel = %d ",
+ intval($channel_id)
+ );
+ if($r) {
+ $ret['abook'] = $r;
+
+ for($x = 0; $x < count($ret['abook']); $x ++) {
+ $xchans[] = $ret['abook'][$x]['abook_xchan'];
+ $abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
+ if($abconfig)
+ $ret['abook'][$x]['abconfig'] = $abconfig;
+ translate_abook_perms_outbound($ret['abook'][$x]);
+ }
+ stringify_array_elms($xchans);
+ }
- $r = q("select * from pconfig where uid = %d",
- intval($channel_id)
- );
- if($r)
- $ret['config'] = $r;
+ if($xchans) {
+ $r = q("select * from xchan where xchan_hash in ( " . implode(',',$xchans) . " ) ");
+ if($r)
+ $ret['xchan'] = $r;
- $r = q("select mimetype, content, os_storage from photo where imgscale = 4 and photo_usage = %d and uid = %d limit 1",
- intval(PHOTO_PROFILE),
- intval($channel_id)
- );
+ $r = q("select * from hubloc where hubloc_hash in ( " . implode(',',$xchans) . " ) ");
+ if($r)
+ $ret['hubloc'] = $r;
+ }
- if($r) {
- $ret['photo'] = array('type' => $r[0]['mimetype'], 'data' => (($r[0]['os_storage']) ? base64url_encode(file_get_contents($r[0]['content'])) : base64url_encode($r[0]['content'])));
- }
+ $r = q("select * from groups where uid = %d ",
+ intval($channel_id)
+ );
- // All other term types will be included in items, if requested.
+ if($r)
+ $ret['group'] = $r;
- $r = q("select * from term where ttype in (%d,%d) and uid = %d",
- intval(TERM_SAVEDSEARCH),
- intval(TERM_THING),
- intval($channel_id)
- );
- if($r)
- $ret['term'] = $r;
+ $r = q("select * from group_member where uid = %d ",
+ intval($channel_id)
+ );
+ if($r)
+ $ret['group_member'] = $r;
- // add psuedo-column obj_baseurl to aid in relocations
+ }
- $r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d",
- dbesc(z_root()),
- intval($channel_id)
- );
+ if(in_array('config',$sections)) {
+ $r = q("select * from pconfig where uid = %d",
+ intval($channel_id)
+ );
+ if($r)
+ $ret['config'] = $r;
+
+ // All other term types will be included in items, if requested.
+
+ $r = q("select * from term where ttype in (%d,%d) and uid = %d",
+ intval(TERM_SAVEDSEARCH),
+ intval(TERM_THING),
+ intval($channel_id)
+ );
+ if($r)
+ $ret['term'] = $r;
- if($r)
- $ret['obj'] = $r;
+ // add psuedo-column obj_baseurl to aid in relocations
- $r = q("select * from app where app_channel = %d and app_system = 0",
- intval($channel_id)
- );
- if($r) {
- for($x = 0; $x < count($r); $x ++) {
- $r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
- intval(TERM_OBJ_APP),
- intval($r[$x]['id'])
- );
- }
- $ret['app'] = $r;
- }
+ $r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d",
+ dbesc(z_root()),
+ intval($channel_id)
+ );
- $r = q("select * from chatroom where cr_uid = %d",
- intval($channel_id)
- );
- if($r)
- $ret['chatroom'] = $r;
+ if($r)
+ $ret['obj'] = $r;
- $r = q("select * from event where uid = %d",
- intval($channel_id)
- );
- if($r)
- $ret['event'] = $r;
+ $r = q("select * from likes where channel_id = %d",
+ intval($channel_id)
+ );
+
+ if($r)
+ $ret['likes'] = $r;
- $r = q("select * from item where resource_type = 'event' and uid = %d",
- intval($channel_id)
- );
- if($r) {
- $ret['event_item'] = array();
- xchan_query($r);
- $r = fetch_post_tags($r,true);
- foreach($r as $rr)
- $ret['event_item'][] = encode_item($rr,true);
}
- $x = menu_list($channel_id);
- if($x) {
- $ret['menu'] = array();
- for($y = 0; $y < count($x); $y ++) {
- $m = menu_fetch($x[$y]['menu_name'],$channel_id,$ret['channel']['channel_hash']);
- if($m)
- $ret['menu'][] = menu_element($ret['channel'],$m);
+ if(in_array('apps',$sections)) {
+ $r = q("select * from app where app_channel = %d and app_system = 0",
+ intval($channel_id)
+ );
+ if($r) {
+ for($x = 0; $x < count($r); $x ++) {
+ $r[$x]['term'] = q("select * from term where otype = %d and oid = %d",
+ intval(TERM_OBJ_APP),
+ intval($r[$x]['id'])
+ );
+ }
+ $ret['app'] = $r;
}
}
- $addon = array('channel_id' => $channel_id,'data' => $ret);
- call_hooks('identity_basic_export',$addon);
- $ret = $addon['data'];
+ if(in_array('chatrooms',$sections)) {
+ $r = q("select * from chatroom where cr_uid = %d",
+ intval($channel_id)
+ );
+ if($r)
+ $ret['chatroom'] = $r;
+ }
- if(! $items)
- return $ret;
- $r = q("select * from likes where channel_id = %d",
- intval($channel_id)
- );
+ if(in_array('events',$sections)) {
+ $r = q("select * from event where uid = %d",
+ intval($channel_id)
+ );
+ if($r)
+ $ret['event'] = $r;
- if($r)
- $ret['likes'] = $r;
+ $r = q("select * from item where resource_type = 'event' and uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ $ret['event_item'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rr)
+ $ret['event_item'][] = encode_item($rr,true);
+ }
+ }
+ if(in_array('webpages',$sections)) {
+ $x = menu_list($channel_id);
+ if($x) {
+ $ret['menu'] = array();
+ for($y = 0; $y < count($x); $y ++) {
+ $m = menu_fetch($x[$y]['menu_name'],$channel_id,$ret['channel']['channel_hash']);
+ if($m)
+ $ret['menu'][] = menu_element($ret['channel'],$m);
+ }
+ }
+ $r = q("select * from item where item_type in ( "
+ . ITEM_TYPE_BLOCK . "," . ITEM_TYPE_PDL . "," . ITEM_TYPE_WEBPAGE . " ) and uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ $ret['webpages'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rr)
+ $ret['webpages'][] = encode_item($rr,true);
- $r = q("select * from conv where uid = %d",
- intval($channel_id)
- );
- if($r) {
- for($x = 0; $x < count($r); $x ++) {
- $r[$x]['subject'] = base64url_decode(str_rot47($r[$x]['subject']));
}
- $ret['conv'] = $r;
}
- $r = q("select * from mail where mail.uid = %d",
- intval($channel_id)
- );
- if($r) {
- $m = array();
- foreach($r as $rr) {
- xchan_mail_query($rr);
- $m[] = mail_encode($rr,true);
+ if(in_array('mail',$sections)) {
+ $r = q("select * from conv where uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ for($x = 0; $x < count($r); $x ++) {
+ $r[$x]['subject'] = base64url_decode(str_rot47($r[$x]['subject']));
+ }
+ $ret['conv'] = $r;
}
- $ret['mail'] = $m;
- }
+ $r = q("select * from mail where mail.uid = %d",
+ intval($channel_id)
+ );
+ if($r) {
+ $m = array();
+ foreach($r as $rr) {
+ xchan_mail_query($rr);
+ $m[] = mail_encode($rr,true);
+ }
+ $ret['mail'] = $m;
+ }
+ }
- /** @warning this may run into memory limits on smaller systems */
+ if(in_array('wikis',$sections)) {
+ $r = q("select * from item where resource_type like 'nwiki%%' and uid = %d order by created",
+ intval($channel_id)
+ );
+ if($r) {
+ $ret['wiki'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rv) {
+ $ret['wiki'][] = encode_item($rv,true);
+ }
+ }
+ }
+ if(in_array('items',$sections)) {
+ /** @warning this may run into memory limits on smaller systems */
- /** export three months of posts. If you want to export and import all posts you have to start with
- * the first year and export/import them in ascending order.
- *
- * Don't export linked resource items. we'll have to pull those out separately.
- */
+ /** export three months of posts. If you want to export and import all posts you have to start with
+ * the first year and export/import them in ascending order.
+ *
+ * Don't export linked resource items. we'll have to pull those out separately.
+ */
- $r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created > %s - INTERVAL %s and resource_type = '' order by created",
- intval($channel_id),
- db_utcnow(),
- db_quoteinterval('3 MONTH')
- );
- if($r) {
- $ret['item'] = array();
- xchan_query($r);
- $r = fetch_post_tags($r,true);
- foreach($r as $rr)
- $ret['item'][] = encode_item($rr,true);
+ $r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d
+ and created > %s - INTERVAL %s and resource_type = '' order by created",
+ intval($channel_id),
+ db_utcnow(),
+ db_quoteinterval('3 MONTH')
+ );
+ if($r) {
+ $ret['item'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rr)
+ $ret['item'][] = encode_item($rr,true);
+ }
}
+ $addon = [ 'channel_id' => $channel_id, 'sections' => $sections, 'data' => $ret];
+ call_hooks('identity_basic_export',$addon);
+ $ret = $addon['data'];
+
return $ret;
}
@@ -768,7 +851,7 @@ function channel_export_items($channel_id, $start, $finish) {
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
}
- $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
+ $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created <= '%s' and resource_type = '' order by created",
intval(ITEM_TYPE_POST),
intval($channel_id),
dbesc($start),
@@ -1218,7 +1301,7 @@ function advanced_profile(&$a) {
$profile['marital'] = array( t('Status:'), App::$profile['marital']);
if(App::$profile['partner'])
- $profile['marital']['partner'] = bbcode(App::$profile['partner']);
+ $profile['marital']['partner'] = zidify_links(bbcode(App::$profile['partner']));
if(strlen(App::$profile['howlong']) && App::$profile['howlong'] > NULL_DATE) {
$profile['howlong'] = relative_date(App::$profile['howlong'], t('for %1$d %2$s'));
@@ -1278,10 +1361,14 @@ function advanced_profile(&$a) {
// logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);
+ $exportlink = ((App::$profile['profile_vcard']) ? zid(z_root() . '/profile/' . App::$profile['channel_address'] . '/vcard') : '');
+
return replace_macros($tpl, array(
'$title' => t('Profile'),
'$canlike' => (($profile['canlike'])? true : false),
'$likethis' => t('Like this thing'),
+ '$export' => t('Export'),
+ '$exportlink' => $exportlink,
'$profile' => $profile,
'$fields' => $clean_fields,
'$editmenu' => profile_edit_menu(App::$profile['profile_uid']),
@@ -1705,21 +1792,26 @@ function get_zcard($channel, $observer_hash = '', $args = array()) {
$maxwidth = (($args['width']) ? intval($args['width']) : 0);
$maxheight = (($args['height']) ? intval($args['height']) : 0);
- if(($maxwidth > 1200) || ($maxwidth < 1))
+ if(($maxwidth > 1200) || ($maxwidth < 1)) {
$maxwidth = 1200;
+ $cover_width = 1200;
+ }
if($maxwidth <= 425) {
$width = 425;
+ $cover_width = 425;
$size = 'hz_small';
$cover_size = PHOTO_RES_COVER_425;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
} elseif($maxwidth <= 900) {
$width = 900;
+ $cover_width = 850;
$size = 'hz_medium';
$cover_size = PHOTO_RES_COVER_850;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
} elseif($maxwidth <= 1200) {
$width = 1200;
+ $cover_width = 1200;
$size = 'hz_large';
$cover_size = PHOTO_RES_COVER_1200;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
@@ -1741,7 +1833,8 @@ function get_zcard($channel, $observer_hash = '', $args = array()) {
$cover = $r[0];
$cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
} else {
- $cover = $pphoto;
+ $default_cover = get_config('system','default_cover_photo','pexels-94622');
+ $cover = [ 'href' => z_root() . '/images/default_cover_photos/' . $default_cover . '/' . $cover_width . '.jpg' ];
}
$o .= replace_macros(get_markup_template('zcard.tpl'), array(
@@ -1765,23 +1858,28 @@ function get_zcard_embed($channel, $observer_hash = '', $args = array()) {
$maxwidth = (($args['width']) ? intval($args['width']) : 0);
$maxheight = (($args['height']) ? intval($args['height']) : 0);
- if(($maxwidth > 1200) || ($maxwidth < 1))
+ if(($maxwidth > 1200) || ($maxwidth < 1)) {
$maxwidth = 1200;
+ $cover_width = 1200;
+ }
if($maxwidth <= 425) {
$width = 425;
+ $cover_width = 425;
$size = 'hz_small';
$cover_size = PHOTO_RES_COVER_425;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
}
elseif($maxwidth <= 900) {
$width = 900;
+ $cover_width = 850;
$size = 'hz_medium';
$cover_size = PHOTO_RES_COVER_850;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
}
elseif($maxwidth <= 1200) {
$width = 1200;
+ $cover_width = 1200;
$size = 'hz_large';
$cover_size = PHOTO_RES_COVER_1200;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
@@ -1799,8 +1897,10 @@ function get_zcard_embed($channel, $observer_hash = '', $args = array()) {
if($r) {
$cover = $r[0];
$cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
- } else {
- $cover = $pphoto;
+ }
+ else {
+ $default_cover = get_config('system','default_cover_photo','pexels-94622');
+ $cover = [ 'href' => z_root() . '/images/default_cover_photos/' . $default_cover . '/' . $cover_width . '.jpg' ];
}
$o .= replace_macros(get_markup_template('zcard_embed.tpl'),array(
@@ -1876,8 +1976,74 @@ function channel_manual_conv_update($channel_id) {
$x = get_pconfig($channel_id, 'system','manual_conversation_update');
if($x === false)
- $x = get_config('system','manual_conversation_update');
+ $x = get_config('system','manual_conversation_update', 1);
return intval($x);
+}
+
+
+function remote_login() {
+
+ $o = replace_macros(get_markup_template('remote_login.tpl'),array(
+ '$title' => t('Remote Authentication'),
+ '$desc' => t('Enter your channel address (e.g. channel@example.com)'),
+ '$submit' => t('Authenticate')
+ ));
+ return $o;
+
+}
+
+
+
+function profile_store_lowlevel($arr) {
+
+ $store = [
+ 'profile_guid' => ((array_key_exists('profile_guid',$arr)) ? $arr['profile_guid'] : ''),
+ 'aid' => ((array_key_exists('aid',$arr)) ? $arr['aid'] : 0),
+ 'uid' => ((array_key_exists('uid',$arr)) ? $arr['uid'] : 0),
+ 'profile_name' => ((array_key_exists('profile_name',$arr)) ? $arr['profile_name'] : ''),
+ 'is_default' => ((array_key_exists('is_default',$arr)) ? $arr['is_default'] : 0),
+ 'hide_friends' => ((array_key_exists('hide_friends',$arr)) ? $arr['hide_friends'] : 0),
+ 'fullname' => ((array_key_exists('fullname',$arr)) ? $arr['fullname'] : ''),
+ 'pdesc' => ((array_key_exists('pdesc',$arr)) ? $arr['pdesc'] : ''),
+ 'chandesc' => ((array_key_exists('chandesc',$arr)) ? $arr['chandesc'] : ''),
+ 'dob' => ((array_key_exists('dob',$arr)) ? $arr['dob'] : ''),
+ 'dob_tz' => ((array_key_exists('dob_tz',$arr)) ? $arr['dob_tz'] : ''),
+ 'address' => ((array_key_exists('address',$arr)) ? $arr['address'] : ''),
+ 'locality' => ((array_key_exists('locality',$arr)) ? $arr['locality'] : ''),
+ 'region' => ((array_key_exists('region',$arr)) ? $arr['region'] : ''),
+ 'postal_code' => ((array_key_exists('postal_code',$arr)) ? $arr['postal_code'] : ''),
+ 'country_name' => ((array_key_exists('country_name',$arr)) ? $arr['country_name'] : ''),
+ 'hometown' => ((array_key_exists('hometown',$arr)) ? $arr['hometown'] : ''),
+ 'gender' => ((array_key_exists('gender',$arr)) ? $arr['gender'] : ''),
+ 'marital' => ((array_key_exists('marital',$arr)) ? $arr['marital'] : ''),
+ 'partner' => ((array_key_exists('partner',$arr)) ? $arr['partner'] : ''),
+ 'howlong' => ((array_key_exists('howlong',$arr)) ? $arr['howlong'] : NULL_DATE),
+ 'sexual' => ((array_key_exists('sexual',$arr)) ? $arr['sexual'] : ''),
+ 'politic' => ((array_key_exists('politic',$arr)) ? $arr['politic'] : ''),
+ 'religion' => ((array_key_exists('religion',$arr)) ? $arr['religion'] : ''),
+ 'keywords' => ((array_key_exists('keywords',$arr)) ? $arr['keywords'] : ''),
+ 'likes' => ((array_key_exists('likes',$arr)) ? $arr['likes'] : ''),
+ 'dislikes' => ((array_key_exists('dislikes',$arr)) ? $arr['dislikes'] : ''),
+ 'about' => ((array_key_exists('about',$arr)) ? $arr['about'] : ''),
+ 'summary' => ((array_key_exists('summary',$arr)) ? $arr['summary'] : ''),
+ 'music' => ((array_key_exists('music',$arr)) ? $arr['music'] : ''),
+ 'book' => ((array_key_exists('book',$arr)) ? $arr['book'] : ''),
+ 'tv' => ((array_key_exists('tv',$arr)) ? $arr['tv'] : ''),
+ 'film' => ((array_key_exists('film',$arr)) ? $arr['film'] : ''),
+ 'interest' => ((array_key_exists('interest',$arr)) ? $arr['interest'] : ''),
+ 'romance' => ((array_key_exists('romance',$arr)) ? $arr['romance'] : ''),
+ 'employment' => ((array_key_exists('employment',$arr)) ? $arr['employment'] : ''),
+ 'education' => ((array_key_exists('education',$arr)) ? $arr['education'] : ''),
+ 'contact' => ((array_key_exists('contact',$arr)) ? $arr['contact'] : ''),
+ 'channels' => ((array_key_exists('channels',$arr)) ? $arr['channels'] : ''),
+ 'homepage' => ((array_key_exists('homepage',$arr)) ? $arr['homepage'] : ''),
+ 'photo' => ((array_key_exists('photo',$arr)) ? $arr['photo'] : ''),
+ 'thumb' => ((array_key_exists('thumb',$arr)) ? $arr['thumb'] : ''),
+ 'publish' => ((array_key_exists('publish',$arr)) ? $arr['publish'] : 0),
+ 'profile_vcard' => ((array_key_exists('profile_vcard',$arr)) ? $arr['profile_vcard'] : '')
+ ];
+
+ return create_table_from_array('profile',$store);
} \ No newline at end of file
diff --git a/include/connections.php b/include/connections.php
index b08d046b3..e26943b68 100644
--- a/include/connections.php
+++ b/include/connections.php
@@ -1,6 +1,38 @@
<?php /** @file */
+function abook_store_lowlevel($arr) {
+
+ $store = [
+ 'abook_account' => ((array_key_exists('abook_account',$arr)) ? $arr['abook_account'] : 0),
+ 'abook_channel' => ((array_key_exists('abook_channel',$arr)) ? $arr['abook_channel'] : 0),
+ 'abook_xchan' => ((array_key_exists('abook_xchan',$arr)) ? $arr['abook_xchan'] : ''),
+ 'abook_my_perms' => ((array_key_exists('abook_my_perms',$arr)) ? $arr['abook_my_perms'] : 0),
+ 'abook_their_perms' => ((array_key_exists('abook_their_perms',$arr)) ? $arr['abook_their_perms'] : 0),
+ 'abook_closeness' => ((array_key_exists('abook_closeness',$arr)) ? $arr['abook_closeness'] : 99),
+ 'abook_created' => ((array_key_exists('abook_created',$arr)) ? $arr['abook_created'] : NULL_DATE),
+ 'abook_updated' => ((array_key_exists('abook_updated',$arr)) ? $arr['abook_updated'] : NULL_DATE),
+ 'abook_connected' => ((array_key_exists('abook_connected',$arr)) ? $arr['abook_connected'] : NULL_DATE),
+ 'abook_dob' => ((array_key_exists('abook_dob',$arr)) ? $arr['abook_dob'] : NULL_DATE),
+ 'abook_flags' => ((array_key_exists('abook_flags',$arr)) ? $arr['abook_flags'] : 0),
+ 'abook_blocked' => ((array_key_exists('abook_blocked',$arr)) ? $arr['abook_blocked'] : 0),
+ 'abook_ignored' => ((array_key_exists('abook_ignored',$arr)) ? $arr['abook_ignored'] : 0),
+ 'abook_hidden' => ((array_key_exists('abook_hidden',$arr)) ? $arr['abook_hidden'] : 0),
+ 'abook_archived' => ((array_key_exists('abook_archived',$arr)) ? $arr['abook_archived'] : 0),
+ 'abook_pending' => ((array_key_exists('abook_pending',$arr)) ? $arr['abook_pending'] : 0),
+ 'abook_unconnected' => ((array_key_exists('abook_unconnected',$arr)) ? $arr['abook_unconnected'] : 0),
+ 'abook_self' => ((array_key_exists('abook_self',$arr)) ? $arr['abook_self'] : 0),
+ 'abook_feed' => ((array_key_exists('abook_feed',$arr)) ? $arr['abook_feed'] : 0),
+ 'abook_profile' => ((array_key_exists('abook_profile',$arr)) ? $arr['abook_profile'] : ''),
+ 'abook_incl' => ((array_key_exists('abook_incl',$arr)) ? $arr['abook_incl'] : ''),
+ 'abook_excl' => ((array_key_exists('abook_excl',$arr)) ? $arr['abook_excl'] : ''),
+ 'abook_instance' => ((array_key_exists('abook_instance',$arr)) ? $arr['abook_instance'] : '')
+ ];
+
+ return create_table_from_array('abook',$store);
+
+}
+
function rconnect_url($channel_id,$xchan) {
@@ -630,3 +662,279 @@ function random_profile() {
return '';
}
+function update_vcard($arr,$vcard = null) {
+
+
+ // logger('update_vcard: ' . print_r($arr,true));
+
+ $fn = $arr['fn'];
+
+
+ // This isn't strictly correct and could be a cause for concern.
+ // 'N' => array_reverse(explode(' ', $fn))
+
+
+ // What we really want is
+ // 'N' => Adams;John;Quincy;Reverend,Dr.;III
+ // which is a very difficult parsing problem especially if you allow
+ // the surname to contain spaces. The only way to be sure to get it
+ // right is to provide a form to input all the various fields and not
+ // try to extract it from the FN.
+
+ if(! $vcard) {
+ $vcard = new \Sabre\VObject\Component\VCard([
+ 'FN' => $fn,
+ 'N' => array_reverse(explode(' ', $fn))
+ ]);
+ }
+ else {
+ $vcard->FN = $fn;
+ $vcard->N = array_reverse(explode(' ', $fn));
+ }
+
+ $org = $arr['org'];
+ if($org) {
+ $vcard->ORG = $org;
+ }
+
+ $title = $arr['title'];
+ if($title) {
+ $vcard->TITLE = $title;
+ }
+
+ $tel = $arr['tel'];
+ $tel_type = $arr['tel_type'];
+ if($tel) {
+ $i = 0;
+ foreach($tel as $item) {
+ if($item) {
+ $vcard->add('TEL', $item, ['type' => $tel_type[$i]]);
+ }
+ $i++;
+ }
+ }
+
+ $email = $arr['email'];
+ $email_type = $arr['email_type'];
+ if($email) {
+ $i = 0;
+ foreach($email as $item) {
+ if($item) {
+ $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]);
+ }
+ $i++;
+ }
+ }
+
+ $impp = $arr['impp'];
+ $impp_type = $arr['impp_type'];
+ if($impp) {
+ $i = 0;
+ foreach($impp as $item) {
+ if($item) {
+ $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]);
+ }
+ $i++;
+ }
+ }
+
+ $url = $arr['url'];
+ $url_type = $arr['url_type'];
+ if($url) {
+ $i = 0;
+ foreach($url as $item) {
+ if($item) {
+ $vcard->add('URL', $item, ['type' => $url_type[$i]]);
+ }
+ $i++;
+ }
+ }
+
+ $adr = $arr['adr'];
+ $adr_type = $arr['adr_type'];
+
+ if($adr) {
+ $i = 0;
+ foreach($adr as $item) {
+ if($item) {
+ $vcard->add('ADR', $item, ['type' => $adr_type[$i]]);
+ }
+ $i++;
+ }
+ }
+
+ $note = $arr['note'];
+ if($note) {
+ $vcard->NOTE = $note;
+ }
+
+ return $vcard->serialize();
+
+}
+
+function get_vcard_array($vc,$id) {
+
+ $photo = '';
+ if($vc->PHOTO) {
+ $photo_value = strtolower($vc->PHOTO->getValueType()); // binary or uri
+ if($photo_value === 'binary') {
+ $photo_type = strtolower($vc->PHOTO['TYPE']); // mime jpeg, png or gif
+ $photo = 'data:image/' . $photo_type . ';base64,' . base64_encode((string)$vc->PHOTO);
+ }
+ else {
+ $url = parse_url((string)$vc->PHOTO);
+ $photo = 'data:' . $url['path'];
+ }
+ }
+
+ $fn = '';
+ if($vc->FN) {
+ $fn = (string) escape_tags($vc->FN);
+ }
+
+ $org = '';
+ if($vc->ORG) {
+ $org = (string) escape_tags($vc->ORG);
+ }
+
+ $title = '';
+ if($vc->TITLE) {
+ $title = (string) escape_tags($vc->TITLE);
+ }
+
+ $tels = [];
+ if($vc->TEL) {
+ foreach($vc->TEL as $tel) {
+ $type = (($tel['TYPE']) ? vcard_translate_type((string)$tel['TYPE']) : '');
+ $tels[] = [
+ 'type' => $type,
+ 'nr' => (string) escape_tags($tel)
+ ];
+ }
+ }
+ $emails = [];
+ if($vc->EMAIL) {
+ foreach($vc->EMAIL as $email) {
+ $type = (($email['TYPE']) ? vcard_translate_type((string)$email['TYPE']) : '');
+ $emails[] = [
+ 'type' => $type,
+ 'address' => (string) escape_tags($email)
+ ];
+ }
+ }
+
+ $impps = [];
+ if($vc->IMPP) {
+ foreach($vc->IMPP as $impp) {
+ $type = (($impp['TYPE']) ? vcard_translate_type((string)$impp['TYPE']) : '');
+ $impps[] = [
+ 'type' => $type,
+ 'address' => (string) escape_tags($impp)
+ ];
+ }
+ }
+
+ $urls = [];
+ if($vc->URL) {
+ foreach($vc->URL as $url) {
+ $type = (($url['TYPE']) ? vcard_translate_type((string)$url['TYPE']) : '');
+ $urls[] = [
+ 'type' => $type,
+ 'address' => (string) escape_tags($url)
+ ];
+ }
+ }
+
+ $adrs = [];
+ if($vc->ADR) {
+ foreach($vc->ADR as $adr) {
+ $type = (($adr['TYPE']) ? vcard_translate_type((string)$adr['TYPE']) : '');
+ $adrs[] = [
+ 'type' => $type,
+ 'address' => $adr->getParts()
+ ];
+ $last_entry = end($adrs);
+ if($adrs[$last_entry]['address'])
+ array_walk($adrs[$last_entry]['address'],'array_escape_tags');
+ }
+ }
+
+ $note = '';
+ if($vc->NOTE) {
+ $note = (string) escape_tags($vc->NOTE);
+ }
+
+ $card = [
+ 'id' => $id,
+ 'photo' => $photo,
+ 'fn' => $fn,
+ 'org' => $org,
+ 'title' => $title,
+ 'tels' => $tels,
+ 'emails' => $emails,
+ 'impps' => $impps,
+ 'urls' => $urls,
+ 'adrs' => $adrs,
+ 'note' => $note
+ ];
+
+ return $card;
+
+}
+
+
+function vcard_translate_type($type) {
+
+ if(!$type)
+ return;
+
+ $type = strtoupper($type);
+
+ $map = [
+ 'CELL' => t('Mobile'),
+ 'HOME' => t('Home'),
+ 'HOME,VOICE' => t('Home, Voice'),
+ 'HOME,FAX' => t('Home, Fax'),
+ 'WORK' => t('Work'),
+ 'WORK,VOICE' => t('Work, Voice'),
+ 'WORK,FAX' => t('Work, Fax'),
+ 'OTHER' => t('Other')
+ ];
+
+ if (array_key_exists($type, $map)) {
+ return [$type, $map[$type]];
+ }
+ else {
+ return [$type, t('Other') . ' (' . $type . ')'];
+ }
+}
+
+
+function vcard_query(&$r) {
+
+ $arr = [];
+
+ if($r && is_array($r) && count($r)) {
+ $uid = $r[0]['abook_channel'];
+ foreach($r as $rv) {
+ if($rv['abook_xchan'] && (! in_array("'" . dbesc($rv['abook_xchan']) . "'",$arr)))
+ $arr[] = "'" . dbesc($rv['abook_xchan']) . "'";
+ }
+ }
+
+ if($arr) {
+ $a = q("select * from abconfig where chan = %d and xchan in (" . protect_sprintf(implode(',', $arr)) . ") and cat = 'system' and k = 'vcard'",
+ intval($uid)
+ );
+ if($a) {
+ foreach($a as $av) {
+ for($x = 0; $x < count($r); $x ++) {
+ if($r[$x]['abook_xchan'] == $av['xchan']) {
+ $vctmp = \Sabre\VObject\Reader::read($av['v']);
+ $r[$x]['vcard'] = (($vctmp) ? get_vcard_array($vctmp,$r[$x]['abook_id']) : [] );
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/include/conversation.php b/include/conversation.php
index d367c27a6..a1acc456a 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -689,7 +689,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
'id' => (($preview) ? 'P0' : $item['item_id']),
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, $profile_url),
'profile_url' => $profile_link,
- 'item_photo_menu' => item_photo_menu($item),
+ 'thread_action_menu' => thread_action_menu($item,$mode),
+ 'thread_author_menu' => thread_author_menu($item,$mode),
'name' => $profile_name,
'sparkle' => $sparkle,
'lock' => $lock,
@@ -732,7 +733,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
'like' => '',
'dislike' => '',
'comment' => '',
- 'conv' => (($preview) ? '' : array('href'=> z_root() . '/display/' . $item['mid'], 'title'=> t('View in context'))),
+ 'conv' => (($preview) ? '' : array('href'=> z_root() . '/display/' . gen_link_id($item['mid']), 'title'=> t('View in context'))),
'previewing' => $previewing,
'wait' => t('Please wait'),
'thread_level' => 1,
@@ -960,6 +961,169 @@ function item_photo_menu($item){
return $o;
}
+
+function thread_action_menu($item,$mode = '') {
+
+ $menu = [];
+
+ if((local_channel()) && local_channel() == $item['uid']) {
+ $menu[] = [
+ 'menu' => 'view_source',
+ 'title' => t('View Source'),
+ 'icon' => 'eye',
+ 'action' => 'viewsrc(' . $item['id'] . '); return false;',
+ 'href' => '#'
+ ];
+
+ if(! in_array($mode, [ 'network-new', 'search', 'community'])) {
+ if($item['parent'] == $item['id'] && (get_observer_hash() != $item['author_xchan'])) {
+ $menu[] = [
+ 'menu' => 'follow_thread',
+ 'title' => t('Follow Thread'),
+ 'icon' => 'plus',
+ 'action' => 'dosubthread(' . $item['id'] . '); return false;',
+ 'href' => '#'
+ ];
+ }
+
+ $menu[] = [
+ 'menu' => 'unfollow_thread',
+ 'title' => t('Unfollow Thread'),
+ 'icon' => 'minus',
+ 'action' => 'dounsubthread(' . $item['id'] . '); return false;',
+ 'href' => '#'
+ ];
+ }
+
+ }
+
+
+
+
+ $args = [ 'item' => $item, 'mode' => $mode, 'menu' => $menu ];
+ call_hooks('thread_action_menu', $args);
+
+ return $args['menu'];
+
+}
+
+function thread_author_menu($item, $mode = '') {
+
+ $menu = [];
+
+ $local_channel = local_channel();
+
+ if($local_channel) {
+ if(! count(App::$contacts))
+ load_contact_links($local_channel);
+ $channel = App::get_channel();
+ $channel_hash = (($channel) ? $channel['channel_hash'] : '');
+ }
+
+ $profile_link = chanlink_hash($item['author_xchan']);
+ if($item['uid'] > 0)
+ $pm_url = z_root() . '/mail/new/?f=&hash=' . $item['author_xchan'];
+
+ if(App::$contacts && array_key_exists($item['author_xchan'],App::$contacts))
+ $contact = App::$contacts[$item['author_xchan']];
+ else
+ if($local_channel && $item['author']['xchan_addr'])
+ $follow_url = z_root() . '/follow/?f=&url=' . $item['author']['xchan_addr'];
+
+ if($contact) {
+ $poke_link = z_root() . '/poke/?f=&c=' . $contact['abook_id'];
+ if (! intval($contact['abook_self']))
+ $contact_url = z_root() . '/connedit/' . $contact['abook_id'];
+ $posts_link = z_root() . '/network/?cid=' . $contact['abook_id'];
+
+ $clean_url = normalise_link($item['author-link']);
+ }
+
+ $rating_enabled = get_config('system','rating_enabled');
+
+ $ratings_url = (($rating_enabled) ? z_root() . '/ratings/' . urlencode($item['author_xchan']) : '');
+
+ if($profile_link) {
+ $menu[] = [
+ 'menu' => 'view_profile',
+ 'title' => t('View Profile'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $profile_link
+ ];
+ }
+
+ if($posts_link) {
+ $menu[] = [
+ 'menu' => 'view_posts',
+ 'title' => t('Activity/Posts'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $posts_link
+ ];
+ }
+
+ if($follow_url) {
+ $menu[] = [
+ 'menu' => 'follow',
+ 'title' => t('Connect'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $follow_url
+ ];
+ }
+
+ if($contact_url) {
+ $menu[] = [
+ 'menu' => 'connedit',
+ 'title' => t('Edit Connection'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $contact_url
+ ];
+ }
+
+ if($pm_url) {
+ $menu[] = [
+ 'menu' => 'prv_message',
+ 'title' => t('Message'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $pm_url
+ ];
+ }
+
+ if($ratings_url) {
+ $menu[] = [
+ 'menu' => 'ratings',
+ 'title' => t('Ratings'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $ratings_url
+ ];
+ }
+
+ if($poke_link) {
+ $menu[] = [
+ 'menu' => 'poke',
+ 'title' => t('Poke'),
+ 'icon' => 'fw',
+ 'action' => '',
+ 'href' => $poke_link
+ ];
+ }
+
+ $args = [ 'item' => $item, 'mode' => $mode, 'menu' => $menu ];
+ call_hooks('thread_author_menu', $args);
+
+ return $args['menu'];
+
+}
+
+
+
+
+
/**
* @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.)
*
@@ -1011,8 +1175,8 @@ function builtin_activity_puller($item, &$conv_responses) {
if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
$name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown'));
- $url = (($item['author']['xchan_url'] && $item['author']['xchan_photo_s'])
- ? '<a href="' . chanlink_url($item['author']['xchan_url']) . '">' . '<img class="dropdown-menu-img-xs" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" />' . $name . '</a>'
+ $url = (($item['author_xchan'] && $item['author']['xchan_photo_s'])
+ ? '<a href="' . chanlink_hash($item['author_xchan']) . '">' . '<img class="dropdown-menu-img-xs" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" />' . $name . '</a>'
: '<a href="#" class="disabled">' . $name . '</a>'
);
@@ -1232,11 +1396,11 @@ function status_editor($a, $x, $popup = false) {
'$setloc' => $setloc,
'$voting' => t('Toggle voting'),
'$feature_voting' => $feature_voting,
- '$consensus' => 0,
+ '$consensus' => ((array_key_exists('item',$x)) ? $x['item']['item_consensus'] : 0),
'$nocommenttitle' => t('Disable comments'),
'$nocommenttitlesub' => t('Toggle comments'),
'$feature_nocomment' => $feature_nocomment,
- '$nocomment' => 0,
+ '$nocomment' => ((array_key_exists('item',$x)) ? $x['item']['item_nocomment'] : 0),
'$clearloc' => $clearloc,
'$title' => ((x($x, 'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''),
'$placeholdertitle' => ((x($x, 'placeholdertitle')) ? $x['placeholdertitle'] : t('Title (optional)')),
@@ -1400,7 +1564,7 @@ function format_location($item) {
if(strpos($item['location'],'#') === 0) {
$location = substr($item['location'],1);
- $location = ((strpos($location,'[') !== false) ? bbcode($location) : $location);
+ $location = ((strpos($location,'[') !== false) ? zidify_links(bbcode($location)) : $location);
}
else {
$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
@@ -1452,7 +1616,7 @@ function prepare_page($item) {
'$author' => (($naked) ? '' : $item['author']['xchan_name']),
'$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'])),
+ '$title' => zidify_links(smilies(bbcode($item['title']))),
'$body' => $body['html'],
'$preview' => $preview,
'$link' => $link,
@@ -1622,6 +1786,20 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
$cal_link = '/cal/' . $nickname;
}
+ require_once('include/security.php');
+ $sql_options = item_permissions_sql($uid);
+
+ $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 item.item_delayed = 0 and item.item_deleted = 0
+ and ( iconfig.k = 'WEBPAGE' and item_type = %d )
+ $sql_options limit 1",
+ intval($uid),
+ dbesc('home'),
+ intval(ITEM_TYPE_WEBPAGE)
+ );
+
+ $has_webpages = (($r) ? true : false);
if (get_pconfig($uid, 'system', 'noprofiletabs'))
return;
@@ -1706,15 +1884,16 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
);
}
- if ($p['write_pages'] && feature_enabled($uid,'webpages')) {
+ if($has_webpages && feature_enabled($uid,'webpages')) {
$tabs[] = array(
'label' => t('Webpages'),
- 'url' => z_root() . '/webpages/' . $nickname,
+ 'url' => z_root() . '/page/' . $nickname . '/home',
'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
- 'title' => t('Manage Webpages'),
+ 'title' => t('View Webpages'),
'id' => 'webpages-tab',
);
- }
+ }
+
if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
$tabs[] = array(
diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php
index 81a3bd590..e47f97387 100755
--- a/include/dba/dba_driver.php
+++ b/include/dba/dba_driver.php
@@ -337,7 +337,7 @@ function db_concat($fld, $sep) {
function q($sql) {
$args = func_get_args();
- unset($args[0]);
+ array_shift($args);
if(\DBA::$dba && \DBA::$dba->connected) {
$stmt = vsprintf($sql, $args);
diff --git a/include/event.php b/include/event.php
index cbee2b759..cf1cc331d 100644
--- a/include/event.php
+++ b/include/event.php
@@ -25,7 +25,7 @@ function format_event_html($ev) {
$o = '<div class="vevent">' . "\r\n";
- $o .= '<div class="event-title"><h3><i class="fa fa-calendar"></i>&nbsp;' . bbcode($ev['summary']) . '</h3></div>' . "\r\n";
+ $o .= '<div class="event-title"><h3><i class="fa fa-calendar"></i>&nbsp;' . zidify_links(smilies(bbcode($ev['summary']))) . '</h3></div>' . "\r\n";
$o .= '<div class="event-start"><span class="event-label">' . t('Starts:') . '</span>&nbsp;<span class="dtstart" title="'
. datetime_convert('UTC', 'UTC', $ev['dtstart'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
@@ -46,11 +46,11 @@ function format_event_html($ev) {
$ev['dtend'] , $bd_format )))
. '</span></div>' . "\r\n";
- $o .= '<div class="event-description">' . bbcode($ev['description']) . '</div>' . "\r\n";
+ $o .= '<div class="event-description">' . zidify_links(smilies(bbcode($ev['description']))) . '</div>' . "\r\n";
if(strlen($ev['location']))
$o .= '<div class="event-location"><span class="event-label"> ' . t('Location:') . '</span>&nbsp;<span class="location">'
- . bbcode($ev['location'])
+ . zidify_links(smilies(bbcode($ev['location'])))
. '</span></div>' . "\r\n";
$o .= '</div>' . "\r\n";
@@ -69,7 +69,7 @@ function format_event_obj($jobject) {
$bd_format = t('l F d, Y \@ g:i A'); // Friday January 18, 2011 @ 8:01 AM
$event['header'] = replace_macros(get_markup_template('event_item_header.tpl'),array(
- '$title' => bbcode($object['title']),
+ '$title' => zidify_links(smilies(bbcode($object['title']))),
'$dtstart_label' => t('Starts:'),
'$dtstart_title' => datetime_convert('UTC', 'UTC', $object['dtstart'], (($object['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )),
'$dtstart_dt' => (($object['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $object['dtstart'] , $bd_format )) : day_translate(datetime_convert('UTC', 'UTC', $object['dtstart'] , $bd_format))),
@@ -80,9 +80,9 @@ function format_event_obj($jobject) {
));
$event['content'] = replace_macros(get_markup_template('event_item_content.tpl'),array(
- '$description' => bbcode($object['description']),
+ '$description' => zidify_links(smilies(bbcode($object['description']))),
'$location_label' => t('Location:'),
- '$location' => bbcode($object['location'])
+ '$location' => zidify_links(smilies(bbcode($object['location'])))
));
}
@@ -127,12 +127,18 @@ function format_event_ical($ev) {
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['dtend'] && ! $ev['nofinish'])
$o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
- if($ev['summary'])
+ if($ev['summary']) {
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
- if($ev['location'])
+ $o .= "\r\nX-ZOT-SUMMARY:" . format_ical_sourcetext($ev['summary']);
+ }
+ if($ev['location']) {
$o .= "\r\nLOCATION:" . format_ical_text($ev['location']);
- if($ev['description'])
+ $o .= "\r\nX-ZOT-LOCATION:" . format_ical_sourcetext($ev['location']);
+ }
+ if($ev['description']) {
$o .= "\r\nDESCRIPTION:" . format_ical_text($ev['description']);
+ $o .= "\r\nX-ZOT-DESCRIPTION:" . format_ical_sourcetext($ev['description']);
+ }
if($ev['event_priority'])
$o .= "\r\nPRIORITY:" . intval($ev['event_priority']);
$o .= "\r\nUID:" . $ev['event_hash'] ;
@@ -154,8 +160,10 @@ function format_todo_ical($ev) {
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['dtend'] && ! $ev['nofinish'])
$o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
- if($ev['summary'])
+ if($ev['summary']) {
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
+ $o .= "\r\nX-ZOT-SUMMARY:" . format_ical_sourcetext($ev['summary']);
+ }
if($ev['event_status']) {
$o .= "\r\nSTATUS:" . $ev['event_status'];
if($ev['event_status'] === 'COMPLETED')
@@ -165,10 +173,14 @@ function format_todo_ical($ev) {
$o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent'];
if(intval($ev['event_sequence']))
$o .= "\r\nSEQUENCE:" . $ev['event_sequence'];
- if($ev['location'])
+ if($ev['location']) {
$o .= "\r\nLOCATION:" . format_ical_text($ev['location']);
- if($ev['description'])
+ $o .= "\r\nX-ZOT-LOCATION:" . format_ical_sourcetext($ev['location']);
+ }
+ if($ev['description']) {
$o .= "\r\nDESCRIPTION:" . format_ical_text($ev['description']);
+ $o .= "\r\nX-ZOT-DESCRIPTION:" . format_ical_sourcetext($ev['description']);
+ }
$o .= "\r\nUID:" . $ev['event_hash'] ;
if($ev['event_priority'])
$o .= "\r\nPRIORITY:" . intval($ev['event_priority']);
@@ -178,7 +190,6 @@ function format_todo_ical($ev) {
}
-
function format_ical_text($s) {
require_once('include/bbcode.php');
require_once('include/html2plain.php');
@@ -186,6 +197,12 @@ function format_ical_text($s) {
$s = html2plain(bbcode($s));
$s = str_replace(["\r\n","\n"],["",""],$s);
return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
+
+}
+
+function format_ical_sourcetext($s) {
+ $s = base64_encode($s);
+ return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
}
@@ -623,12 +640,21 @@ function event_import_ical($ical, $uid) {
$ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C));
}
- if(isset($ical->LOCATION))
+ if(isset($ical->{'X-ZOT-LOCATION'}))
+ $ev['location'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-LOCATION'});
+ elseif(isset($ical->LOCATION))
$ev['location'] = (string) $ical->LOCATION;
- if(isset($ical->DESCRIPTION))
+
+ if(isset($ical->{'X-ZOT-DESCRIPTION'}))
+ $ev['description'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-DESCRIPTION'});
+ elseif(isset($ical->DESCRIPTION))
$ev['description'] = (string) $ical->DESCRIPTION;
- if(isset($ical->SUMMARY))
+
+ if(isset($ical->{'X-ZOT-SUMMARY'}))
+ $ev['summary'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-SUMMARY'});
+ elseif(isset($ical->SUMMARY))
$ev['summary'] = (string) $ical->SUMMARY;
+
if(isset($ical->PRIORITY))
$ev['event_priority'] = intval((string) $ical->PRIORITY);
@@ -663,6 +689,10 @@ function event_import_ical($ical, $uid) {
}
+function event_ical_get_sourcetext($s) {
+ return base64_decode($s);
+}
+
function event_import_ical_task($ical, $uid) {
$c = q("select * from channel where channel_id = %d limit 1",
@@ -718,12 +748,21 @@ function event_import_ical_task($ical, $uid) {
$ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C));
}
- if(isset($ical->LOCATION))
+ if(isset($ical->{'X-ZOT-LOCATION'}))
+ $ev['location'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-LOCATION'});
+ elseif(isset($ical->LOCATION))
$ev['location'] = (string) $ical->LOCATION;
- if(isset($ical->DESCRIPTION))
+
+ if(isset($ical->{'X-ZOT-DESCRIPTION'}))
+ $ev['description'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-DESCRIPTION'});
+ elseif(isset($ical->DESCRIPTION))
$ev['description'] = (string) $ical->DESCRIPTION;
- if(isset($ical->SUMMARY))
+
+ if(isset($ical->{'X-ZOT-SUMMARY'}))
+ $ev['summary'] = event_ical_get_sourcetext( (string) $ical->{'X-ZOT-SUMMARY'});
+ elseif(isset($ical->SUMMARY))
$ev['summary'] = (string) $ical->SUMMARY;
+
if(isset($ical->PRIORITY))
$ev['event_priority'] = intval((string) $ical->PRIORITY);
@@ -977,9 +1016,9 @@ function event_store_item($arr, $event) {
// otherwise we'll fallback to /display/$message_id
if($wall)
- $item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . $item_arr['mid'];
+ $item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . urlencode($item_arr['mid']);
else
- $item_arr['plink'] = z_root() . '/display/' . $item_arr['mid'];
+ $item_arr['plink'] = z_root() . '/display/' . gen_link_id($item_arr['mid']);
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['event_xchan'])
diff --git a/include/features.php b/include/features.php
index 1ccdbf015..0fc6fbc1d 100644
--- a/include/features.php
+++ b/include/features.php
@@ -149,6 +149,15 @@ function get_features($filtered = true) {
],
[
+ 'permcats',
+ t('Permission Groups'),
+ t('Provide alternate connection permission roles.'),
+ false,
+ get_config('feature_lock','permcats'),
+ feature_level('permcats',2),
+ ],
+
+ [
'smart_birthdays',
t('Smart Birthdays'),
t('Make birthday events timezone aware in case your friends are scattered across the planet.'),
@@ -157,6 +166,15 @@ function get_features($filtered = true) {
feature_level('smart_birthdays',2),
],
+ [
+ 'event_tz_select',
+ t('Event Timezone Selection'),
+ t('Allow event creation in timezones other than your own.'),
+ false,
+ get_config('feature_lock','event_tz_select'),
+ feature_level('event_tz_select',2),
+ ],
+
[
'advanced_dirsearch',
t('Advanced Directory Search'),
diff --git a/include/feedutils.php b/include/feedutils.php
index 1d58ec317..b122a8e4b 100644
--- a/include/feedutils.php
+++ b/include/feedutils.php
@@ -236,7 +236,7 @@ function get_atom_elements($feed, $item, &$author) {
if(substr($author['author_link'],-1,1) == '/')
$author['author_link'] = substr($author['author_link'],0,-1);
- $res['mid'] = base64url_encode(unxmlify($item->get_id()));
+ $res['mid'] = unxmlify($item->get_id());
$res['title'] = unxmlify($item->get_title());
$res['body'] = unxmlify($item->get_content());
$res['plink'] = unxmlify($item->get_link(0));
@@ -331,6 +331,8 @@ function get_atom_elements($feed, $item, &$author) {
}
}
+ $ostatus_protocol = (($item->get_item_tags(NAMESPACE_OSTATUS,'conversation')) ? true : false);
+
$apps = $item->get_item_tags(NAMESPACE_STATUSNET,'notice_info');
if($apps && $apps[0]['attribs']['']['source']) {
$res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source']));
@@ -343,6 +345,8 @@ function get_atom_elements($feed, $item, &$author) {
$have_real_body = false;
$rawenv = $item->get_item_tags(NAMESPACE_DFRN, 'env');
+ if(! $rawenv)
+ $rawenv = $item->get_item_tags(NAMESPACE_ZOT,'source');
if($rawenv) {
$have_real_body = true;
$res['body'] = $rawenv[0]['data'];
@@ -388,7 +392,15 @@ function get_atom_elements($feed, $item, &$author) {
$res['body'] = escape_tags($res['body']);
}
- if($res['plink'] && $res['title']) {
+
+ // strip title and don't apply "title-in-body" if the feed involved
+ // uses the OStatus stack. We need a more generalised way for the calling
+ // function to specify this behaviour or for plugins to alter it.
+
+ if($ostatus_protocol) {
+ $res['title'] = '';
+ }
+ elseif($res['plink'] && $res['title']) {
$res['body'] = '#^[url=' . $res['plink'] . ']' . $res['title'] . '[/url]' . "\n\n" . $res['body'];
$terms = array();
$terms[] = array(
@@ -623,14 +635,16 @@ function get_atom_elements($feed, $item, &$author) {
$res['target'] = $obj;
}
- $arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
+
+ $arr = array('feed' => $feed, 'item' => $item, 'author' => $author, 'result' => $res);
call_hooks('parse_atom', $arr);
- logger('get_atom_elements: author: ' . print_r($author,true),LOGGER_DATA);
- logger('get_atom_elements: ' . print_r($res,true),LOGGER_DATA);
+ logger('get_atom_elements: author: ' . print_r($arr['author'],true),LOGGER_DATA);
+
+ logger('get_atom_elements: ' . print_r($arr['result'],true),LOGGER_DATA);
- return $res;
+ return $arr['result'];
}
function encode_rel_links($links) {
@@ -718,7 +732,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
foreach($del_entries as $dentry) {
$deleted = false;
if(isset($dentry['attribs']['']['ref'])) {
- $mid = $dentry['attribs']['']['ref'];
+ $mid = normalise_id($dentry['attribs']['']['ref']);
$deleted = true;
if(isset($dentry['attribs']['']['when'])) {
$when = $dentry['attribs']['']['when'];
@@ -730,7 +744,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
if($deleted && is_array($contact)) {
$r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1",
- dbesc(base64url_encode($mid)),
+ dbesc($mid),
dbesc($contact['xchan_hash']),
intval($importer['channel_id'])
);
@@ -739,7 +753,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$item = $r[0];
if(! intval($item['item_deleted'])) {
- logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG);
+ logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . $item['mid'], LOGGER_DEBUG);
drop_item($item['id'],false);
}
}
@@ -758,14 +772,14 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
foreach($items as $item) {
$is_reply = false;
- $item_id = base64url_encode($item->get_id());
+ $item_id = normalise_id($item->get_id());
- logger('consume_feed: processing ' . $item_id, LOGGER_DEBUG);
+ logger('consume_feed: processing ' . $raw_item_id, LOGGER_DEBUG);
$rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
if(isset($rawthread[0]['attribs']['']['ref'])) {
$is_reply = true;
- $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
+ $parent_mid = normalise_id($rawthread[0]['attribs']['']['ref']);
}
if($is_reply) {
@@ -775,7 +789,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// Have we seen it? If not, import it.
- $item_id = base64url_encode($item->get_id());
+ $item_id = normalise_id($item->get_id());
$author = array();
$datarray = get_atom_elements($feed,$item,$author);
@@ -824,7 +838,16 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
continue;
}
+ $x = q("select mid from item where mid = '%s' and uid = %d limit 1",
+ dbesc($parent_mid),
+ intval($importer['channel_id'])
+ );
+ if($x)
+ $parent_mid = $x[0]['mid'];
+
$datarray['parent_mid'] = $parent_mid;
+
+
$datarray['aid'] = $importer['channel_account_id'];
$datarray['uid'] = $importer['channel_id'];
@@ -838,7 +861,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// Head post of a conversation. Have we seen it? If not, import it.
- $item_id = base64url_encode($item->get_id());
+ $item_id = normalise_id($item->get_id());
$author = array();
$datarray = get_atom_elements($feed,$item,$author);
@@ -943,6 +966,11 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
}
+function normalise_id($id) {
+ return str_replace('X-ZOT:','',$id);
+}
+
+
/**
* @brief Process atom feed and return the first post and structure
*
@@ -983,14 +1011,14 @@ function process_salmon_feed($xml, $importer) {
foreach($items as $item) {
- $item_id = base64url_encode($item->get_id());
+ $item_id = normalise_id($item->get_id());
logger('processing ' . $item_id, LOGGER_DEBUG);
$rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
if(isset($rawthread[0]['attribs']['']['ref'])) {
$is_reply = true;
- $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
+ $parent_mid = normalise_id($rawthread[0]['attribs']['']['ref']);
}
if($is_reply)
@@ -1159,7 +1187,8 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
if(($item['parent'] != $item['id']) || ($item['parent_mid'] !== $item['mid']) || (($item['thr_parent'] !== '') && ($item['thr_parent'] !== $item['mid']))) {
$parent_item = (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']);
- $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+ $o .= '<thr:in-reply-to ref="' . 'X-ZOT:' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n";
+
}
if(activity_match($item['obj_type'],ACTIVITY_OBJ_EVENT) && activity_match($item['verb'],ACTIVITY_POST)) {
@@ -1177,7 +1206,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
$o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n";
}
- $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n";
+ $o .= '<id>' . 'X-ZOT:' . xmlify($item['mid']) . '</id>' . "\r\n";
$o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n";
$o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n";
@@ -1206,26 +1235,68 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
if(strlen($actarg))
$o .= $actarg;
- // FIXME
-// $tags = item_getfeedtags($item);
-// if(count($tags)) {
-// foreach($tags as $t) {
-// $o .= '<category scheme="X-DFRN:' . xmlify($t[0]) . ':' . xmlify($t[1]) . '" term="' . xmlify($t[2]) . '" />' . "\r\n";
-// }
-// }
-// FIXME
-// $o .= item_getfeedattach($item);
+ if($item['attach']) {
+ $enclosures = json_decode($item['attach'],true);
+ if($enclosures) {
+ foreach($enclosures as $enc) {
+ $o .= '<link rel="enclosure" '
+ . (($enc['href']) ? 'href="' . $enc['href'] . '" ' : '')
+ . (($enc['length']) ? 'length="' . $enc['length'] . '" ' : '')
+ . (($enc['type']) ? 'type="' . $enc['type'] . '" ' : '')
+ . ' />';
+ }
+ }
+ }
-// $mentioned = get_mentions($item,$tags);
-// if($mentioned)
-// $o .= $mentioned;
+ if($item['term']) {
+ foreach($item['term'] as $term) {
+ $scheme = '';
+ $label = '';
+ switch($term['ttype']) {
+ case TERM_UNKNOWN:
+ $scheme = NAMESPACE_ZOT . '/term/unknown';
+ $label = $term['term'];
+ break;
+ case TERM_HASHTAG:
+ case TERM_COMMUNITYTAG:
+ $scheme = NAMESPACE_ZOT . '/term/hashtag';
+ $label = '#' . $term['term'];
+ break;
+ case TERM_MENTION:
+ $scheme = NAMESPACE_ZOT . '/term/mention';
+ $label = '@' . $term['term'];
+ break;
+ case TERM_CATEGORY:
+ $scheme = NAMESPACE_ZOT . '/term/category';
+ $label = $term['term'];
+ break;
+ default:
+ break;
+ }
+ if(! $scheme)
+ continue;
- call_hooks('atom_entry', $o);
+ $o .= '<category scheme="' . $scheme . '" term="' . $term['term'] . '" label="' . $label . '" />' . "\r\n";
+ }
+ }
$o .= '</entry>' . "\r\n";
- return $o;
+ $x = [
+ 'item' => $item,
+ 'type' => $type,
+ 'author' => $author,
+ 'owner' => $owner,
+ 'comment' => $comment,
+ 'abook_id' => $cid,
+ 'entry' => $o
+ ];
+
+
+ call_hooks('atom_entry', $x);
+
+ return $x['entry'];
}
diff --git a/include/follow.php b/include/follow.php
index fa198e402..751d86db1 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -13,12 +13,11 @@ require_once('include/zot.php');
function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) {
+ $result = [ 'success' => false, 'message' => '' ];
-
- $result = array('success' => false,'message' => '');
-
- $is_red = false;
- $is_http = ((strpos($url,'://') !== false) ? true : false);
+ $my_perms = false;
+ $is_zot = false;
+ $is_http = ((strpos($url,'://') !== false) ? true : false);
if($is_http && substr($url,-1,1) === '/')
$url = substr($url,0,-1);
@@ -58,20 +57,14 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$ret = Zotlabs\Zot\Finger::run($url,$channel);
if($ret && is_array($ret) && $ret['success']) {
- $is_red = true;
+ $is_zot = true;
$j = $ret;
}
- $my_perms = get_channel_default_perms($uid);
+ $p = \Zotlabs\Access\Permissions::connect_perms($uid);
+ $my_perms = $p['perms'];
- $role = get_pconfig($uid,'system','permissions_role');
- if($role) {
- $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
- if($x['perms_connect'])
- $my_perms = $x['perms_connect'];
- }
-
- if($is_red && $j) {
+ if($is_zot && $j) {
logger('follow: ' . $url . ' ' . print_r($j,true), LOGGER_DEBUG);
@@ -166,14 +159,13 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
}
}
-
if(! $xchan_hash) {
$result['message'] = t('Channel discovery failed.');
logger('follow: ' . $result['message']);
return $result;
}
- $allowed = (($is_red || $r[0]['xchan_network'] === 'rss') ? 1 : 0);
+ $allowed = (($is_zot || $r[0]['xchan_network'] === 'rss') ? 1 : 0);
$x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0);
@@ -211,7 +203,8 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
return $result;
}
- $r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ $r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook
+ where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($xchan_hash),
intval($uid)
);
@@ -226,6 +219,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
}
if($r) {
+
$abook_instance = $r[0]['abook_instance'];
if(($singleton) && strpos($abook_instance,z_root()) === false) {
@@ -240,21 +234,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
);
if(intval($r[0]['abook_pending'])) {
-
- $abook_my_perms = get_channel_default_perms($uid);
- $role = get_pconfig($uid,'system','permissions_role');
- if($role) {
- $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
- if($x['perms_connect']) {
- $abook_my_perms = $x['perms_connect'];
- }
- }
-
- $filled_perms = \Zotlabs\Access\Permissions::FilledPerms($abook_my_perms);
- foreach($filled_perms as $k => $v) {
- set_abconfig($uid,$r[0]['abook_xchan'],'my_perms',$k,$v);
- }
-
$x = q("update abook set abook_pending = 0 where abook_id = %d",
intval($r[0]['abook_id'])
);
@@ -265,29 +244,26 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if($closeness === false)
$closeness = 80;
- $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_created, abook_updated, abook_instance )
- values( %d, %d, %d, '%s', %d, '%s', '%s', '%s' ) ",
- intval($aid),
- intval($uid),
- intval($closeness),
- dbesc($xchan_hash),
- intval(($is_http) ? 1 : 0),
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- dbesc(($singleton) ? z_root() : '')
+ $r = abook_store_lowlevel(
+ [
+ 'abook_account' => intval($aid),
+ 'abook_channel' => intval($uid),
+ 'abook_closeness' => intval($closeness),
+ 'abook_xchan' => $xchan_hash,
+ 'abook_feed' => intval(($is_http) ? 1 : 0),
+ 'abook_created' => datetime_convert(),
+ 'abook_updated' => datetime_convert(),
+ 'abook_instance' => (($singleton) ? z_root() : '')
+ ]
);
}
if(! $r)
logger('mod_follow: abook creation failed');
- $all_perms = \Zotlabs\Access\Permissions::Perms();
- if($all_perms) {
- foreach($all_perms as $k => $v) {
- if(in_array($k,$my_perms))
- set_abconfig($uid,$xchan_hash,'my_perms',$k,1);
- else
- set_abconfig($uid,$xchan_hash,'my_perms',$k,0);
+ if($my_perms) {
+ foreach($my_perms as $k => $v) {
+ set_abconfig($uid,$xchan_hash,'my_perms',$k,$v);
}
}
diff --git a/include/group.php b/include/group.php
index 38d9d190f..3b208ef95 100644
--- a/include/group.php
+++ b/include/group.php
@@ -227,6 +227,26 @@ function group_get_members_xchan($gid) {
return $ret;
}
+function group_get_profile_members_xchan($uid,$gid) {
+ $ret = [];
+
+ if(intval($gid)) {
+ $r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
+ intval($gid),
+ intval($uid)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $ret[] = $rr['xchan'];
+ }
+ }
+ }
+ return $ret;
+}
+
+
+
+
function mini_group_select($uid,$group = '') {
$grps = array();
@@ -320,20 +340,46 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
return $o;
}
-function expand_groups($a) {
- if(! (is_array($a) && count($a)))
+function expand_groups($g) {
+ if(! (is_array($g) && count($g)))
return array();
- $x = $a;
- stringify_array_elms($x,true);
- $groups = implode(',', $x);
- if($groups)
- $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))");
- $ret = array();
+ $ret = [];
+ $x = [];
- if($r)
- foreach($r as $rr)
- $ret[] = $rr['xchan'];
+ // private profile linked virtual groups
+
+ foreach($g as $gv) {
+ if(substr($gv,0,3) === 'vp.') {
+ $profile_hash = substr($gv,3);
+ if($profile_hash) {
+ $r = q("select abook_xchan from abook where abook_profile = '%s'",
+ dbesc($profile_hash)
+ );
+ if($r) {
+ foreach($r as $rv) {
+ $ret[] = $rv['abook_xchan'];
+ }
+ }
+ }
+ }
+ else {
+ $x[] = $gv;
+ }
+ }
+
+ if($x) {
+ stringify_array_elms($x,true);
+ $groups = implode(',', $x);
+ if($groups) {
+ $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))");
+ if($r) {
+ foreach($r as $rr) {
+ $ret[] = $rr['xchan'];
+ }
+ }
+ }
+ }
return $ret;
}
diff --git a/include/help.php b/include/help.php
index 03d01d1a1..6e779f000 100644
--- a/include/help.php
+++ b/include/help.php
@@ -79,7 +79,7 @@ function get_help_content($tocpath = false) {
}
if($doctype === 'bbcode') {
require_once('include/bbcode.php');
- $content = bbcode($text);
+ $content = zidify_links(bbcode($text));
// bbcode retargets external content to new windows. This content is internal.
$content = str_replace(' target="_blank"', '', $content);
}
@@ -95,7 +95,7 @@ function preg_callback_help_include($matches) {
$include = str_replace($matches[0],load_doc_file($matches[1]),$matches[0]);
if(preg_match('/\.bb$/', $matches[1]) || preg_match('/\.txt$/', $matches[1])) {
require_once('include/bbcode.php');
- $include = bbcode($include);
+ $include = zidify_links(bbcode($include));
$include = str_replace(' target="_blank"','',$include);
}
elseif(preg_match('/\.md$/', $matches[1])) {
diff --git a/include/html2plain.php b/include/html2plain.php
index 2f5be7f69..979354079 100644
--- a/include/html2plain.php
+++ b/include/html2plain.php
@@ -113,7 +113,7 @@ function html2plain($html, $wraplength = 75, $compact = false)
$xpath = new DomXPath($doc);
$list = $xpath->query("//pre");
foreach ($list as $node) {
- $node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
+ $node->nodeValue = str_replace("\n", "\r", htmlspecialchars($node->nodeValue));
}
$message = $doc->saveHTML();
diff --git a/include/hubloc.php b/include/hubloc.php
index 17f921f67..e17be028c 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -1,5 +1,36 @@
<?php /** @file */
+
+function hubloc_store_lowlevel($arr) {
+
+ $store = [
+ 'hubloc_guid' => ((array_key_exists('hubloc_guid',$arr)) ? $arr['hubloc_guid'] : ''),
+ 'hubloc_guid_sig' => ((array_key_exists('hubloc_guid_sig',$arr)) ? $arr['hubloc_guid_sig'] : ''),
+ 'hubloc_hash' => ((array_key_exists('hubloc_hash',$arr)) ? $arr['hubloc_hash'] : ''),
+ 'hubloc_addr' => ((array_key_exists('hubloc_addr',$arr)) ? $arr['hubloc_addr'] : ''),
+ 'hubloc_network' => ((array_key_exists('hubloc_network',$arr)) ? $arr['hubloc_network'] : ''),
+ 'hubloc_flags' => ((array_key_exists('hubloc_flags',$arr)) ? $arr['hubloc_flags'] : 0),
+ 'hubloc_status' => ((array_key_exists('hubloc_status',$arr)) ? $arr['hubloc_status'] : 0),
+ 'hubloc_url' => ((array_key_exists('hubloc_url',$arr)) ? $arr['hubloc_url'] : ''),
+ 'hubloc_url_sig' => ((array_key_exists('hubloc_url_sig',$arr)) ? $arr['hubloc_url_sig'] : ''),
+ 'hubloc_host' => ((array_key_exists('hubloc_host',$arr)) ? $arr['hubloc_host'] : ''),
+ 'hubloc_callback' => ((array_key_exists('hubloc_callback',$arr)) ? $arr['hubloc_callback'] : ''),
+ 'hubloc_connect' => ((array_key_exists('hubloc_connect',$arr)) ? $arr['hubloc_connect'] : ''),
+ 'hubloc_sitekey' => ((array_key_exists('hubloc_sitekey',$arr)) ? $arr['hubloc_sitekey'] : ''),
+ 'hubloc_updated' => ((array_key_exists('hubloc_updated',$arr)) ? $arr['hubloc_updated'] : NULL_DATE),
+ 'hubloc_connected' => ((array_key_exists('hubloc_connected',$arr)) ? $arr['hubloc_connected'] : NULL_DATE),
+ 'hubloc_primary' => ((array_key_exists('hubloc_primary',$arr)) ? $arr['hubloc_primary'] : 0),
+ 'hubloc_orphancheck' => ((array_key_exists('hubloc_orphancheck',$arr)) ? $arr['hubloc_orphancheck'] : 0),
+ 'hubloc_error' => ((array_key_exists('hubloc_error',$arr)) ? $arr['hubloc_error'] : 0),
+ 'hubloc_deleted' => ((array_key_exists('hubloc_deleted',$arr)) ? $arr['hubloc_deleted'] : 0)
+ ];
+
+ return create_table_from_array('hubloc',$store);
+
+}
+
+
+
function prune_hub_reinstalls() {
$r = q("select site_url from site where site_type = %d",
@@ -176,102 +207,6 @@ function hubloc_mark_as_down($posturl) {
}
-function xchan_store($arr) {
-
- logger('xchan_store: ' . print_r($arr,true));
-
- if(! $arr['hash'])
- $arr['hash'] = $arr['guid'];
- if(! $arr['hash'])
- return false;
-
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($arr['hash'])
- );
- if($r)
- return true;
-
- if(! $arr['network'])
- $arr['network'] = 'unknown';
- if(! $arr['name'])
- $arr['name'] = 'unknown';
- if(! $arr['url'])
- $arr['url'] = z_root();
- if(! $arr['photo'])
- $arr['photo'] = z_root() . '/' . get_default_profile_photo();
-
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_instance_url, xchan_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s',%d, %d, %d, %d, %d, %d, %d, '%s') ",
- dbesc($arr['hash']),
- dbesc($arr['guid']),
- dbesc($arr['guid_sig']),
- dbesc($arr['pubkey']),
- dbesc($arr['address']),
- dbesc($arr['url']),
- dbesc($arr['connurl']),
- dbesc($arr['follow']),
- dbesc($arr['connpage']),
- dbesc($arr['name']),
- dbesc($arr['network']),
- dbesc($arr['instance_url']),
- intval($arr['hidden']),
- intval($arr['orphan']),
- intval($arr['censored']),
- intval($arr['selfcensored']),
- intval($arr['system']),
- intval($arr['pubforum']),
- intval($arr['deleted']),
- dbesc(datetime_convert())
- );
- if(! $r)
- return $r;
-
- $photos = import_xchan_photo($arr['photo'],$arr['hash']);
- $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'",
- dbesc(datetime_convert()),
- dbesc($photos[0]),
- dbesc($photos[1]),
- dbesc($photos[2]),
- dbesc($photos[3]),
- dbesc($arr['hash'])
- );
- return $r;
-
-}
-
-
-function xchan_fetch($arr) {
-
- $key = '';
- if($arr['hash']) {
- $key = 'xchan_hash';
- $v = $arr['hash'];
- }
- elseif($arr['guid']) {
- $key = 'xchan_guid';
- $v = $arr['guid'];
- }
- elseif($arr['address']) {
- $key = 'xchan_addr';
- $v = $arr['address'];
- }
-
- if(! $key)
- return false;
-
- $r = q("select * from xchan where $key = '$v' limit 1");
- if(! $r)
- return false;
-
- $ret = array();
- foreach($r[0] as $k => $v) {
- if($k === 'xchan_addr')
- $ret['address'] = $v;
- else
- $ret[str_replace('xchan_','',$k)] = $v;
- }
- return $ret;
-}
-
function ping_site($url) {
diff --git a/include/import.php b/include/import.php
index 61134000a..e1880fe6e 100644
--- a/include/import.php
+++ b/include/import.php
@@ -156,7 +156,7 @@ function import_profiles($channel,$profiles) {
}
-function import_hublocs($channel,$hublocs,$seize) {
+function import_hublocs($channel,$hublocs,$seize,$moving = false) {
if($channel && $hublocs) {
foreach($hublocs as $hubloc) {
@@ -174,19 +174,32 @@ function import_hublocs($channel,$hublocs,$seize) {
$hubloc['hubloc_deleted'] = (($hubloc['hubloc_flags'] & 0x1000) ? 1 : 0);
}
+ if($moving && $hubloc['hubloc_hash'] === $channel['channel_hash'] && $hubloc['hubloc_url'] !== z_root()) {
+ $hubloc['hubloc_deleted'] = 1;
+ }
+
$arr = array(
'guid' => $hubloc['hubloc_guid'],
'guid_sig' => $hubloc['hubloc_guid_sig'],
'url' => $hubloc['hubloc_url'],
- 'url_sig' => $hubloc['hubloc_url_sig']
+ 'url_sig' => $hubloc['hubloc_url_sig'],
+ 'sitekey' => ((array_key_exists('hubloc_sitekey',$hubloc)) ? $hubloc['hubloc_sitekey'] : '')
);
if(($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize))
$hubloc['hubloc_primary'] = 0;
- if(! zot_gethub($arr)) {
+ if(($x = zot_gethub($arr,false)) === false) {
unset($hubloc['hubloc_id']);
create_table_from_array('hubloc',$hubloc);
}
+ else {
+ q("UPDATE hubloc set hubloc_primary = %d, hubloc_deleted = %d where hubloc_id = %d",
+ intval($hubloc['hubloc_primary']),
+ intval($hubloc['hubloc_deleted']),
+ intval($x['hubloc_id'])
+ );
+
+ }
}
}
}
@@ -1175,413 +1188,424 @@ function convert_oldfields(&$arr,$old,$new) {
}
function scan_webpage_elements($path, $type, $cloud = false) {
- $channel = \App::get_channel();
- $dirtoscan = $path;
- switch ($type) {
- case 'page':
- $dirtoscan .= '/pages/';
- $json_filename = 'page.json';
- break;
- case 'layout':
- $dirtoscan .= '/layouts/';
- $json_filename = 'layout.json';
- break;
- case 'block':
- $dirtoscan .= '/blocks/';
- $json_filename = 'block.json';
- break;
- default :
- return array();
- }
- if($cloud) {
- $dirtoscan = get_dirpath_by_cloudpath($channel, $dirtoscan);
- }
- $elements = [];
- if (is_dir($dirtoscan)) {
- $dirlist = scandir($dirtoscan);
- if ($dirlist) {
- foreach ($dirlist as $element) {
- if ($element === '.' || $element === '..') {
- continue;
+ $channel = \App::get_channel();
+ $dirtoscan = $path;
+ switch ($type) {
+ case 'page':
+ $dirtoscan .= '/pages/';
+ $json_filename = 'page.json';
+ break;
+ case 'layout':
+ $dirtoscan .= '/layouts/';
+ $json_filename = 'layout.json';
+ break;
+ case 'block':
+ $dirtoscan .= '/blocks/';
+ $json_filename = 'block.json';
+ break;
+ default :
+ return array();
+ }
+ if($cloud) {
+ $dirtoscan = get_dirpath_by_cloudpath($channel, $dirtoscan);
+ }
+ $elements = [];
+ if(is_dir($dirtoscan)) {
+ $dirlist = scandir($dirtoscan);
+ if($dirlist) {
+ foreach($dirlist as $element) {
+ if($element === '.' || $element === '..') {
+ continue;
+ }
+ $folder = $dirtoscan . '/' . $element;
+ if(is_dir($folder)) {
+ if($cloud) {
+ $jsonfilepath = $folder . '/' . get_filename_by_cloudname($json_filename, $channel, $folder);
}
- $folder = $dirtoscan . '/' . $element;
- if (is_dir($folder)) {
+ else {
+ $jsonfilepath = $folder . '/' . $json_filename;
+ }
+ if(is_file($jsonfilepath)) {
+ $metadata = json_decode(file_get_contents($jsonfilepath), true);
if($cloud) {
- $jsonfilepath = $folder . '/' . get_filename_by_cloudname($json_filename, $channel, $folder);
- } else {
- $jsonfilepath = $folder . '/' . $json_filename;
+ $contentfilename = get_filename_by_cloudname($metadata['contentfile'], $channel, $folder);
+ $metadata['path'] = $folder . '/' . $contentfilename;
+ }
+ else {
+ $contentfilename = $metadata['contentfile'];
+ $metadata['path'] = $folder . '/' . $contentfilename;
+ }
+ if($metadata['contentfile'] === '') {
+ logger('Invalid ' . $type . ' content file');
+ return false;
}
- if (is_file($jsonfilepath)) {
- $metadata = json_decode(file_get_contents($jsonfilepath), true);
- if($cloud) {
- $contentfilename = get_filename_by_cloudname($metadata['contentfile'], $channel, $folder);
- $metadata['path'] = $folder . '/' . $contentfilename;
- } else {
- $contentfilename = $metadata['contentfile'];
- $metadata['path'] = $folder . '/' . $contentfilename;
+ $content = file_get_contents($folder . '/' . $contentfilename);
+ if(!$content) {
+ if(is_readable($folder . '/' . $contentfilename)) {
+ $content = '';
}
- if ($metadata['contentfile'] === '') {
- logger('Invalid ' . $type . ' content file');
+ else {
+ logger('Failed to get file content for ' . $metadata['contentfile']);
return false;
}
- $content = file_get_contents($folder . '/' . $contentfilename);
- if (!$content) {
- if(is_readable($folder . '/' . $contentfilename)) {
- $content = '';
- } else {
- logger('Failed to get file content for ' . $metadata['contentfile']);
- return false;
- }
- }
- $elements[] = $metadata;
}
+ $elements[] = $metadata;
}
}
}
}
- return $elements;
}
+ return $elements;
+}
- function import_webpage_element($element, $channel, $type) {
+function import_webpage_element($element, $channel, $type) {
- $arr = array(); // construct information for the webpage element item table record
+ $arr = array(); // construct information for the webpage element item table record
- switch ($type) {
- //
- // PAGES
- //
- case 'page':
- $arr['item_type'] = ITEM_TYPE_WEBPAGE;
- $namespace = 'WEBPAGE';
- $name = $element['pagelink'];
- if($name) {
- require_once('library/urlify/URLify.php');
- $name = strtolower(\URLify::transliterate($name));
- }
- $arr['title'] = $element['title'];
- $arr['term'] = $element['term'];
- $arr['layout_mid'] = ''; // by default there is no layout associated with the page
- // If a layout was specified, find it in the database and get its info. If
- // it does not exist, leave layout_mid empty
- if($element['layout'] !== '') {
- $liid = q("select iid from iconfig where k = 'PDL' and v = '%s' and cat = 'system'",
- dbesc($element['layout'])
- );
- if($liid) {
- $linfo = q("select mid from item where id = %d",
- intval($liid[0]['iid'])
- );
- $arr['layout_mid'] = $linfo[0]['mid'];
- }
- }
- break;
- //
- // LAYOUTS
- //
- case 'layout':
- $arr['item_type'] = ITEM_TYPE_PDL;
- $namespace = 'PDL';
- $name = $element['name'];
- $arr['title'] = $element['description'];
- $arr['term'] = $element['term'];
- break;
- //
- // BLOCKS
- //
- case 'block':
- $arr['item_type'] = ITEM_TYPE_BLOCK;
- $namespace = 'BUILDBLOCK';
- $name = $element['name'];
- $arr['title'] = $element['title'];
+ switch($type) {
+ //
+ // PAGES
+ //
+ case 'page':
+ $arr['item_type'] = ITEM_TYPE_WEBPAGE;
+ $namespace = 'WEBPAGE';
+ $name = $element['pagelink'];
+ if($name) {
+ require_once('library/urlify/URLify.php');
+ $name = strtolower(\URLify::transliterate($name));
+ }
+ $arr['title'] = $element['title'];
+ $arr['term'] = $element['term'];
+ $arr['layout_mid'] = ''; // by default there is no layout associated with the page
+ // If a layout was specified, find it in the database and get its info. If
+ // it does not exist, leave layout_mid empty
+ if($element['layout'] !== '') {
+ $liid = q("select iid from iconfig where k = 'PDL' and v = '%s' and cat = 'system'",
+ dbesc($element['layout'])
+ );
+ if($liid) {
+ $linfo = q("select mid from item where id = %d",
+ intval($liid[0]['iid'])
+ );
+ $arr['layout_mid'] = $linfo[0]['mid'];
+ }
+ }
+ break;
+ //
+ // LAYOUTS
+ //
+ case 'layout':
+ $arr['item_type'] = ITEM_TYPE_PDL;
+ $namespace = 'PDL';
+ $name = $element['name'];
+ $arr['title'] = $element['description'];
+ $arr['term'] = $element['term'];
+ break;
+ //
+ // BLOCKS
+ //
+ case 'block':
+ $arr['item_type'] = ITEM_TYPE_BLOCK;
+ $namespace = 'BUILDBLOCK';
+ $name = $element['name'];
+ $arr['title'] = $element['title'];
- break;
- default :
- return null; // return null if invalid element type
- }
-
- $arr['uid'] = $channel['channel_id'];
- $arr['aid'] = $channel['channel_account_id'];
+ break;
+ default :
+ return null; // return null if invalid element type
+ }
- // Check if an item already exists based on the name
- $iid = q("select iid from iconfig where k = '" . $namespace . "' and v = '%s' and cat = 'system'",
- dbesc($name)
- );
- if($iid) { // If the item does exist, get the item metadata
- $iteminfo = q("select mid,created,edited from item where id = %d",
- intval($iid[0]['iid'])
- );
- $arr['mid'] = $arr['parent_mid'] = $iteminfo[0]['mid'];
- $arr['created'] = $iteminfo[0]['created'];
- } else { // otherwise, generate the creation times and unique id
- $arr['created'] = datetime_convert('UTC', 'UTC');
- $arr['mid'] = $arr['parent_mid'] = item_message_id();
- }
- // Update the edited time whether or not the element already exists
- $arr['edited'] = datetime_convert('UTC', 'UTC');
- // Import the actual element content
- $arr['body'] = file_get_contents($element['path']);
- // The element owner is the channel importing the elements
- $arr['owner_xchan'] = get_observer_hash();
- // The author is either the owner or whomever was specified
- $arr['author_xchan'] = (($element['author_xchan']) ? $element['author_xchan'] : get_observer_hash());
- // Import mimetype if it is a valid mimetype for the element
- $mimetypes = [ 'text/bbcode',
- 'text/html',
- 'text/markdown',
- 'text/plain',
- 'application/x-pdl',
- 'application/x-php'
- ];
- // Blocks and pages can have any of the valid mimetypes, but layouts must be text/bbcode
- if((in_array($element['mimetype'], $mimetypes)) && ($type === 'page' || $type === 'block') ) {
- $arr['mimetype'] = $element['mimetype'];
- } else {
- $arr['mimetype'] = 'text/bbcode';
- }
-
- // Verify ability to use html or php!!!
- $execflag = false;
- if ($arr['mimetype'] === 'application/x-php' || $arr['mimetype'] === 'text/html') {
- $z = q("select account_id, account_roles, channel_pageflags from account "
- . "left join channel on channel_account_id = account_id where channel_id = %d limit 1",
- intval(local_channel())
- );
-
- if ($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
- $execflag = true;
- } else {
- logger('Unable to import element "' . $name .'" because AllowCode permission is denied.');
- notice( t('Unable to import element "' . $name .'" because AllowCode permission is denied.') . EOL);
- $element['import_success'] = 0;
- return $element;
- }
- }
+ $arr['uid'] = local_channel();
+ $arr['aid'] = $channel['channel_account_id'];
- $z = q("select * from iconfig where v = '%s' and k = '%s' and cat = 'system' limit 1",
- dbesc($name),
- dbesc($namespace)
+ // Check if an item already exists based on the name
+ $iid = q("select iid from iconfig where k = '" . $namespace . "' and v = '%s' and cat = 'system'",
+ dbesc($name)
+ );
+ if($iid) { // If the item does exist, get the item metadata
+ $iteminfo = q("select mid,created,edited from item where id = %d",
+ intval($iid[0]['iid'])
);
+ $arr['mid'] = $arr['parent_mid'] = $iteminfo[0]['mid'];
+ $arr['created'] = $iteminfo[0]['created'];
+ }
+ else { // otherwise, generate the creation times and unique id
+ $arr['created'] = datetime_convert('UTC', 'UTC');
+ $arr['mid'] = $arr['parent_mid'] = item_message_id();
+ }
+ // Update the edited time whether or not the element already exists
+ $arr['edited'] = datetime_convert('UTC', 'UTC');
+ // Import the actual element content
+ $arr['body'] = file_get_contents($element['path']);
+ // The element owner is the channel importing the elements
+ $arr['owner_xchan'] = get_observer_hash();
+ // The author is either the owner or whomever was specified
+ $arr['author_xchan'] = (($element['author_xchan']) ? $element['author_xchan'] : get_observer_hash());
+ // Import mimetype if it is a valid mimetype for the element
+ $mimetypes = [ 'text/bbcode',
+ 'text/html',
+ 'text/markdown',
+ 'text/plain',
+ 'application/x-pdl',
+ 'application/x-php'
+ ];
+ // Blocks and pages can have any of the valid mimetypes, but layouts must be text/bbcode
+ if((in_array($element['mimetype'], $mimetypes)) && ($type === 'page' || $type === 'block') ) {
+ $arr['mimetype'] = $element['mimetype'];
+ }
+ else {
+ $arr['mimetype'] = 'text/bbcode';
+ }
- $i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
- dbesc($arr['mid']),
+ // Verify ability to use html or php!!!
+ $execflag = false;
+ if($arr['mimetype'] === 'application/x-php' || $arr['mimetype'] === 'text/html') {
+ $z = q("select account_id, account_roles, channel_pageflags from account "
+ . "left join channel on channel_account_id = account_id where channel_id = %d limit 1",
intval(local_channel())
);
- $remote_id = 0;
- if ($z && $i) {
- $remote_id = $z[0]['id'];
- $arr['id'] = $i[0]['id'];
- // don't update if it has the same timestamp as the original
- if ($arr['edited'] > $i[0]['edited'])
- $x = item_store_update($arr, $execflag);
- } else {
- if (($i) && (intval($i[0]['item_deleted']))) {
- // was partially deleted already, finish it off
- q("delete from item where mid = '%s' and uid = %d",
- dbesc($arr['mid']),
- intval(local_channel())
- );
- }
- $x = item_store($arr, $execflag);
+
+ if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) {
+ $execflag = true;
}
- if ($x['success']) {
- $item_id = $x['item_id'];
- update_remote_id($channel, $item_id, $arr['item_type'], $name, $namespace, $remote_id, $arr['mid']);
- $element['import_success'] = 1;
- } else {
- $element['import_success'] = 0;
+ else {
+ logger('Unable to import element "' . $name .'" because AllowCode permission is denied.');
+ notice( t('Unable to import element "' . $name .'" because AllowCode permission is denied.') . EOL);
+ $element['import_success'] = 0;
+ return $element;
+ }
+ }
+
+// $z = q("select * from iconfig where v = '%s' and k = '%s' and cat = 'system' limit 1",
+// dbesc($name),
+// dbesc($namespace)
+// );
+
+ $i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
+ dbesc($arr['mid']),
+ intval(local_channel())
+ );
+
+ \Zotlabs\Lib\IConfig::Set($arr,'system',$namespace,(($name) ? $name : substr($arr['mid'],0,16)),true);
+
+
+ if($i) {
+ $arr['id'] = $i[0]['id'];
+ // don't update if it has the same timestamp as the original
+ if($arr['edited'] > $i[0]['edited'])
+ $x = item_store_update($arr,$execflag);
+ }
+ else {
+ if(($i) && (intval($i[0]['item_deleted']))) {
+ // was partially deleted already, finish it off
+ q("delete from item where mid = '%s' and uid = %d",
+ dbesc($arr['mid']),
+ intval(local_channel())
+ );
}
+ else
+ $x = item_store($arr,$execflag);
+ }
+
+ if($x && $x['success']) {
+ $item_id = $x['item_id'];
+ //update_remote_id($channel, $item_id, $arr['item_type'], $name, $namespace, $remote_id, $arr['mid']);
+ $element['import_success'] = 1;
+ }
+ else {
+ $element['import_success'] = 0;
+ }
- return $element;
-
+ return $element;
}
function get_webpage_elements($channel, $type = 'all') {
- $elements = array();
- if(!$channel['channel_id']) {
- return null;
- }
- switch ($type) {
- case 'all':
- // If all, execute all the pages, layouts, blocks case statements
- case 'pages':
- $elements['pages'] = null;
- $owner = $channel['channel_id'];
+ $elements = array();
+ if(!$channel['channel_id']) {
+ return null;
+ }
+ switch($type) {
+ case 'all':
+ // If all, execute all the pages, layouts, blocks case statements
+ case 'pages':
+ $elements['pages'] = null;
+ $owner = $channel['channel_id'];
- $sql_extra = item_permissions_sql($owner);
+ $sql_extra = item_permissions_sql($owner);
- $r = q("select * from iconfig left join item on iconfig.iid = item.id
- where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d
- $sql_extra order by item.created desc",
- intval($owner),
- intval(ITEM_TYPE_WEBPAGE)
- );
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d
+ $sql_extra order by item.created desc",
+ intval($owner),
+ intval(ITEM_TYPE_WEBPAGE)
+ );
- $pages = null;
+ $pages = null;
- if($r) {
- $elements['pages'] = array();
- $pages = array();
- foreach($r as $rr) {
- unobscure($rr);
-
- //$lockstate = (($rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid']) ? 'lock' : 'unlock');
-
- $element_arr = array(
- 'type' => 'webpage',
- 'title' => $rr['title'],
- 'body' => $rr['body'],
- 'created' => $rr['created'],
- 'edited' => $rr['edited'],
- 'mimetype' => $rr['mimetype'],
- 'pagetitle' => $rr['v'],
- 'mid' => $rr['mid'],
- 'layout_mid' => $rr['layout_mid']
- );
- $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']),
- 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]',
- //'lockstate' => $lockstate
- );
- $elements['pages'][] = $element_arr;
- }
+ if($r) {
+ $elements['pages'] = array();
+ $pages = array();
+ foreach($r as $rr) {
+ unobscure($rr);
+
+ //$lockstate = (($rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid']) ? 'lock' : 'unlock');
+
+ $element_arr = array(
+ 'type' => 'webpage',
+ 'title' => $rr['title'],
+ 'body' => $rr['body'],
+ 'created' => $rr['created'],
+ 'edited' => $rr['edited'],
+ 'mimetype' => $rr['mimetype'],
+ 'pagetitle' => $rr['v'],
+ 'mid' => $rr['mid'],
+ 'layout_mid' => $rr['layout_mid']
+ );
+ $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']),
+ 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]',
+ //'lockstate' => $lockstate
+ );
+ $elements['pages'][] = $element_arr;
+ }
- }
- if($type !== 'all') {
- break;
- }
+ }
+ if($type !== 'all') {
+ break;
+ }
- case 'layouts':
- $elements['layouts'] = null;
- $owner = $channel['channel_id'];
+ case 'layouts':
+ $elements['layouts'] = null;
+ $owner = $channel['channel_id'];
- $sql_extra = item_permissions_sql($owner);
+ $sql_extra = item_permissions_sql($owner);
- $r = q("select * from iconfig left join item on iconfig.iid = item.id
- where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' and item_type = %d
- $sql_extra order by item.created desc",
- intval($owner),
- intval(ITEM_TYPE_PDL)
- );
+ $r = q("select * from iconfig left join item on iconfig.iid = item.id
+ where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' and item_type = %d
+ $sql_extra order by item.created desc",
+ intval($owner),
+ intval(ITEM_TYPE_PDL)
+ );
- $layouts = null;
+ $layouts = null;
- if($r) {
- $elements['layouts'] = array();
- $layouts = array();
- foreach($r as $rr) {
- unobscure($rr);
-
- $elements['layouts'][] = array(
- 'type' => 'layout',
- 'description' => $rr['title'], // description of the layout
- 'body' => $rr['body'],
- 'created' => $rr['created'],
- 'edited' => $rr['edited'],
- 'mimetype' => $rr['mimetype'],
- 'name' => $rr['v'], // name of reference for the layout
- 'mid' => $rr['mid'],
- );
- }
-
- }
+ if($r) {
+ $elements['layouts'] = array();
+ $layouts = array();
+ foreach($r as $rr) {
+ unobscure($rr);
+
+ $elements['layouts'][] = array(
+ 'type' => 'layout',
+ 'description' => $rr['title'], // description of the layout
+ 'body' => $rr['body'],
+ 'created' => $rr['created'],
+ 'edited' => $rr['edited'],
+ 'mimetype' => $rr['mimetype'],
+ 'name' => $rr['v'], // name of reference for the layout
+ 'mid' => $rr['mid'],
+ );
+ }
+ }
- if($type !== 'all') {
- break;
- }
+ if($type !== 'all') {
+ break;
+ }
- case 'blocks':
- $elements['blocks'] = null;
- $owner = $channel['channel_id'];
+ case 'blocks':
+ $elements['blocks'] = null;
+ $owner = $channel['channel_id'];
- $sql_extra = item_permissions_sql($owner);
+ $sql_extra = item_permissions_sql($owner);
- $r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
- left join item on iconfig.iid = item.id
- where uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'
- and item_type = %d order by item.created desc",
- intval($owner),
- intval(ITEM_TYPE_BLOCK)
- );
+ $r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
+ left join item on iconfig.iid = item.id
+ where uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'
+ and item_type = %d order by item.created desc",
+ intval($owner),
+ intval(ITEM_TYPE_BLOCK)
+ );
- $blocks = null;
+ $blocks = null;
- if($r) {
- $elements['blocks'] = array();
- $blocks = array();
- foreach($r as $rr) {
- unobscure($rr);
-
- $elements['blocks'][] = array(
- 'type' => 'block',
- 'title' => $rr['title'],
- 'body' => $rr['body'],
- 'created' => $rr['created'],
- 'edited' => $rr['edited'],
- 'mimetype' => $rr['mimetype'],
- 'name' => $rr['v'],
- 'mid' => $rr['mid']
- );
- }
+ if($r) {
+ $elements['blocks'] = array();
+ $blocks = array();
+ foreach($r as $rr) {
+ unobscure($rr);
+
+ $elements['blocks'][] = array(
+ 'type' => 'block',
+ 'title' => $rr['title'],
+ 'body' => $rr['body'],
+ 'created' => $rr['created'],
+ 'edited' => $rr['edited'],
+ 'mimetype' => $rr['mimetype'],
+ 'name' => $rr['v'],
+ 'mid' => $rr['mid']
+ );
+ }
- }
+ }
- if($type !== 'all') {
- break;
- }
+ if($type !== 'all') {
+ break;
+ }
- default:
- break;
- }
- return $elements;
+ default:
+ break;
+ }
+ return $elements;
}
/* creates a compressed zip file */
function create_zip_file($files = array(), $destination = '', $overwrite = false) {
- //if the zip file already exists and overwrite is false, return false
- if (file_exists($destination) && !$overwrite) {
- return false;
+ // if the zip file already exists and overwrite is false, return false
+ if(file_exists($destination) && !$overwrite) {
+ return false;
+ }
+ //vars
+ $valid_files = array();
+ // if files were passed in...
+ if(is_array($files)) {
+ // cycle through each file
+ foreach($files as $file) {
+ // make sure the file exists
+ if(file_exists($file)) {
+ $valid_files[] = $file;
+ }
}
- //vars
- $valid_files = array();
- //if files were passed in...
- if (is_array($files)) {
- //cycle through each file
- foreach ($files as $file) {
- //make sure the file exists
- if (file_exists($file)) {
- $valid_files[] = $file;
- }
- }
- }
-
- //if we have good files...
- if (count($valid_files)) {
- //create the archive
- $zip = new ZipArchive();
- if ($zip->open($destination, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
- return false;
- }
- //add the files
- foreach ($valid_files as $file) {
- $zip->addFile($file, $file);
- }
- //debug
- //echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
- //close the zip -- done!
- $zip->close();
-
- //check to make sure the file exists
- return file_exists($destination);
- } else {
- return false;
+ }
+
+ // if we have good files...
+ if(count($valid_files)) {
+ //create the archive
+ $zip = new ZipArchive();
+ if($zip->open($destination, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
+ return false;
}
+ // add the files
+ foreach($valid_files as $file) {
+ $zip->addFile($file, $file);
+ }
+ //debug
+ //echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
+ //close the zip -- done!
+ $zip->close();
+
+ // check to make sure the file exists
+ return file_exists($destination);
+ }
+ else {
+ return false;
+ }
}
diff --git a/include/items.php b/include/items.php
index 82cde9911..36445a46b 100755
--- a/include/items.php
+++ b/include/items.php
@@ -302,7 +302,7 @@ function add_source_route($iid, $hash) {
* * \e boolean \b success true or false
* * \e array \b activity the resulting activity if successful
*/
-function post_activity_item($arr) {
+function post_activity_item($arr,$allow_code = false,$deliver = true) {
$ret = array('success' => false);
@@ -328,7 +328,8 @@ function post_activity_item($arr) {
return $ret;
}
- $arr['public_policy'] = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
+ $arr['public_policy'] = ((array_key_exists('public_policy',$arr)) ? escape_tags($arr['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
+
if($arr['public_policy'])
$arr['item_private'] = 1;
@@ -359,15 +360,18 @@ function post_activity_item($arr) {
if(($is_comment) && ($arr['obj_type'] === ACTIVITY_OBJ_NOTE))
$arr['obj_type'] = ACTIVITY_OBJ_COMMENT;
- $arr['allow_cid'] = ((x($arr,'allow_cid')) ? $arr['allow_cid'] : $channel['channel_allow_cid']);
- $arr['allow_gid'] = ((x($arr,'allow_gid')) ? $arr['allow_gid'] : $channel['channel_allow_gid']);
- $arr['deny_cid'] = ((x($arr,'deny_cid')) ? $arr['deny_cid'] : $channel['channel_deny_cid']);
- $arr['deny_gid'] = ((x($arr,'deny_gid')) ? $arr['deny_gid'] : $channel['channel_deny_gid']);
+ if(! ( array_key_exists('allow_cid',$arr) || array_key_exists('allow_gid',$arr)
+ || array_key_exists('deny_cid',$arr) || array_key_exists('deny_gid',$arr))) {
+ $arr['allow_cid'] = $channel['channel_allow_cid'];
+ $arr['allow_gid'] = $channel['channel_allow_gid'];
+ $arr['deny_cid'] = $channel['channel_deny_cid'];
+ $arr['deny_gid'] = $channel['channel_deny_gid'];
+ }
$arr['comment_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'));
if ((! $arr['plink']) && (intval($arr['item_thread_top']))) {
- $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
}
@@ -382,18 +386,22 @@ function post_activity_item($arr) {
return $ret;
}
- $post = item_store($arr);
- if($post['success'])
- $post_id = $post['item_id'];
+ $post = item_store($arr,$allow_code,$deliver);
- if($post_id) {
- $arr['id'] = $post_id;
- call_hooks('post_local_end', $arr);
- Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id));
+ if($post['success']) {
+ $post_id = $post['item_id'];
$ret['success'] = true;
+ $ret['item_id'] = $post_id;
$ret['activity'] = $post['item'];
+ call_hooks('post_local_end', $ret['activity']);
}
+ if($post_id && $deliver) {
+ Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id));
+ }
+
+
+ $ret['success'] = true;
return $ret;
}
@@ -420,7 +428,7 @@ function validate_item_elements($message,$arr) {
/**
- * @brief Limit lenght on imported system messages.
+ * @brief Limit length on imported system messages.
*
* The purpose of this function is to apply system message length limits to
* imported messages without including any embedded photos in the length.
@@ -829,13 +837,15 @@ function import_author_rss($x) {
}
$name = trim($x['name']);
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network )
- values ( '%s', '%s', '%s', '%s', '%s' )",
- dbesc($x['guid']),
- dbesc($x['guid']),
- dbesc($x['url']),
- dbesc(($name) ? $name : t('(Unknown)')),
- dbesc('rss')
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $x['guid'],
+ 'xchan_guid' => $x['guid'],
+ 'xchan_url' => $x['url'],
+ 'xchan_name' => (($name) ? $name : t('(Unknown)')),
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_network' => 'rss'
+ ]
);
if($r && $x['photo']) {
@@ -874,14 +884,17 @@ function import_author_unknown($x) {
$name = trim($x['name']);
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network )
- values ( '%s', '%s', '%s', '%s', '%s' )",
- dbesc($x['url']),
- dbesc($x['url']),
- dbesc($x['url']),
- dbesc(($name) ? $name : t('(Unknown)')),
- dbesc('unknown')
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $x['url'],
+ 'xchan_guid' => $x['url'],
+ 'xchan_url' => $x['url'],
+ 'xchan_name' => (($name) ? $name : t('(Unknown)')),
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_network' => 'unknown'
+ ]
);
+
if($r && $x['photo']) {
$photos = import_xchan_photo($x['photo']['src'],$x['url']);
@@ -1512,6 +1525,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$arr['deny_cid'] = ((x($arr,'deny_cid')) ? trim($arr['deny_cid']) : '');
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? trim($arr['deny_gid']) : '');
$arr['postopts'] = ((x($arr,'postopts')) ? trim($arr['postopts']) : '');
+ $arr['route'] = ((x($arr,'route')) ? trim($arr['route']) : '');
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 );
$arr['item_wall'] = ((x($arr,'item_wall')) ? intval($arr['item_wall']) : 0 );
$arr['item_type'] = ((x($arr,'item_type')) ? intval($arr['item_type']) : 0 );
@@ -1528,7 +1542,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
// apply the input filter here - if it is obscured it has been filtered already
$arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
- if(local_channel() && (! $arr['sig'])) {
+ if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) {
$channel = App::get_channel();
if($channel['channel_hash'] === $arr['author_xchan']) {
$arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
@@ -1565,8 +1579,11 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$arr['attach'] = json_encode($arr['attach']);
}
- $arr['aid'] = ((x($arr,'aid')) ? intval($arr['aid']) : 0);
- $arr['mid'] = ((x($arr,'mid')) ? notags(trim($arr['mid'])) : random_string());
+ $arr['aid'] = ((x($arr,'aid')) ? intval($arr['aid']) : 0);
+ $arr['mid'] = ((x($arr,'mid')) ? notags(trim($arr['mid'])) : random_string());
+ $arr['revision'] = ((x($arr,'revision') && intval($arr['revision']) > 0) ? intval($arr['revision']) : 0);
+logger('revision: ' . $arr['revision']);
+
$arr['author_xchan'] = ((x($arr,'author_xchan')) ? notags(trim($arr['author_xchan'])) : '');
$arr['owner_xchan'] = ((x($arr,'owner_xchan')) ? notags(trim($arr['owner_xchan'])) : '');
$arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
@@ -1622,7 +1639,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
if($d2 > $d1)
$arr['item_delayed'] = 1;
- $arr['llink'] = z_root() . '/display/' . $arr['mid'];
+ $arr['llink'] = z_root() . '/display/' . gen_link_id($arr['mid']);
if(! $arr['plink'])
$arr['plink'] = $arr['llink'];
@@ -1727,9 +1744,10 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
if($parent_deleted)
$arr['item_deleted'] = 1;
- $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
+ $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d and revision = %d LIMIT 1",
dbesc($arr['mid']),
- intval($arr['uid'])
+ intval($arr['uid']),
+ intval($arr['revision'])
);
if($r) {
logger('item_store: duplicate item ignored. ' . print_r($arr,true));
@@ -1784,9 +1802,10 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
// find the item we just created
- $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d ORDER BY id ASC ",
+ $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d and revision = %d ORDER BY id ASC ",
$arr['mid'], // already dbesc'd
- intval($arr['uid'])
+ intval($arr['uid']),
+ intval($arr['revision'])
);
if($r && count($r)) {
@@ -1945,7 +1964,7 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
// apply the input filter here - if it is obscured it has been filtered already
$arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
- if(local_channel() && (! $arr['sig'])) {
+ if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) {
$channel = App::get_channel();
if($channel['channel_hash'] === $arr['author_xchan']) {
$arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
@@ -1997,6 +2016,8 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$arr['edited'] = ((x($arr,'edited') !== false) ? datetime_convert('UTC','UTC',$arr['edited']) : datetime_convert());
$arr['expires'] = ((x($arr,'expires') !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : $orig[0]['expires']);
+ $arr['revision'] = ((x($arr,'revision') && $arr['revision'] > 0) ? intval($arr['revision']) : 0);
+
if(array_key_exists('comments_closed',$arr) && $arr['comments_closed'] > NULL_DATE)
$arr['comments_closed'] = datetime_convert('UTC','UTC',$arr['comments_closed']);
else
@@ -2174,7 +2195,7 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id,
// since Diaspora doesn't handle edits we can only do this for the original text and not update it.
- require_once('include/bb2diaspora.php');
+ require_once('include/markdown.php');
$signed_body = bb2diaspora_itembody($datarray,$walltowall);
if($walltowall) {
@@ -2273,7 +2294,7 @@ function send_status_notifications($post_id,$item) {
if($unfollowed)
return;
- $link = z_root() . '/display/' . $item['mid'];
+ $link = z_root() . '/display/' . gen_link_id($item['mid']);
$y = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($link),
@@ -3300,7 +3321,7 @@ function retain_item($id) {
);
}
-function drop_items($items) {
+function drop_items($items,$interactive = false,$stage = DROPITEM_NORMAL,$force = false) {
$uid = 0;
if(! local_channel() && ! remote_channel())
@@ -3308,7 +3329,7 @@ function drop_items($items) {
if(count($items)) {
foreach($items as $item) {
- $owner = drop_item($item,false);
+ $owner = drop_item($item,$interactive,$stage,$force);
if($owner && ! $uid)
$uid = $owner;
}
@@ -3332,6 +3353,11 @@ function drop_items($items) {
function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = false) {
+ // These resource types have linked items that should only be removed at the same time
+ // as the linked resource; if we encounter one set it to item_hidden rather than item_deleted.
+
+ $linked_resource_types = [ 'photo' ];
+
// locate item to be deleted
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
@@ -3347,7 +3373,7 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
$item = $r[0];
- $linked_item = (($item['resource_id']) ? true : false);
+ $linked_item = (($item['resource_id'] && $item['resource_type'] && in_array($item['resource_type'], $linked_resource_types)) ? true : false);
$ok_to_delete = false;
@@ -4464,9 +4490,9 @@ function item_create_edit_activity($post) {
$new_item['verb'] = ACTIVITY_UPDATE;
$new_item['item_thread_top'] = 0;
$new_item['created'] = $new_item['edited'] = datetime_convert();
-
+ $new_item['obj_type'] = (($update_item['item_thread_top']) ? ACTIVITY_OBJ_NOTE : ACTIVITY_OBJ_COMMENT);
$new_item['obj'] = json_encode(array(
- 'type' => (($update_item['item_thread_top']) ? ACTIVITY_OBJ_NOTE : ACTIVITY_OBJ_COMMENT),
+ 'type' => $new_item['obj_type'],
'id' => $update_item['mid'],
'parent' => $update_item['parent_mid'],
'link' => array(array('rel' => 'alternate','type' => 'text/html', 'href' => $update_item['plink'])),
diff --git a/include/bb2diaspora.php b/include/markdown.php
index 87a8551ae..7afdc6c54 100644
--- a/include/bb2diaspora.php
+++ b/include/markdown.php
@@ -1,6 +1,6 @@
<?php
/**
- * @file include/bb2diaspora.php
+ * @file include/markdown.php
* @brief Some functions for BB conversions for Diaspora protocol.
*/
@@ -110,6 +110,39 @@ function diaspora_mention_callback($matches) {
}
+function diaspora_mention_callback2($matches) {
+
+ $webbie = $matches[1] . '@' . $matches[2];
+ $link = '';
+ if($webbie) {
+ $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1",
+ dbesc($webbie)
+ );
+ if(! $r) {
+ $x = discover_by_webbie($webbie);
+ if($x) {
+ $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1",
+ dbesc($webbie)
+ );
+ }
+ }
+ if($r)
+ $link = $r[0]['xchan_url'];
+ }
+
+ $name = (($r) ? $r[0]['xchan_name'] : $matches[1]);
+
+ if(! $link)
+ $link = 'https://' . $matches[2] . '/u/' . $matches[1];
+
+ if($r && $r[0]['hubloc_network'] === 'zot')
+ return '@[zrl=' . $link . ']' . trim($name) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/zrl]' ;
+ else
+ return '@[url=' . $link . ']' . trim($name) . ((substr($matches[0],-1,1) === '+') ? '+' : '') . '[/url]' ;
+
+}
+
+
/**
* @brief
@@ -128,6 +161,11 @@ function markdown_to_bb($s, $use_zrl = false) {
$s = str_replace("&#xD;","\r",$s);
$s = str_replace("&#xD;\n&gt;","",$s);
+ if(is_array($s)) {
+ btlogger('markdown_to_bb called with array. ' . print_r($s,true), LOGGER_NORMAL, LOG_WARNING);
+ return '';
+ }
+
$s = html_entity_decode($s,ENT_COMPAT,'UTF-8');
// if empty link text replace with the url
@@ -136,9 +174,11 @@ function markdown_to_bb($s, $use_zrl = false) {
// first try plustags
$s = preg_replace_callback('/\@\{(.+?)\; (.+?)\@(.+?)\}\+/','diaspora_mention_callback',$s);
-
$s = preg_replace_callback('/\@\{(.+?)\; (.+?)\@(.+?)\}/','diaspora_mention_callback',$s);
+ $s = preg_replace_callback('/\@\{(.+?)\@(.+?)\}\+/','diaspora_mention_callback2',$s);
+ $s = preg_replace_callback('/\@\{(.+?)\@(.+?)\}/','diaspora_mention_callback2',$s);
+
// Escaping the hash tags - doesn't always seem to work
// $s = preg_replace('/\#([^\s\#])/','\\#$1',$s);
// This seems to work
diff --git a/include/menu.php b/include/menu.php
index b54ff7f9e..4add78c39 100644
--- a/include/menu.php
+++ b/include/menu.php
@@ -102,7 +102,7 @@ function menu_render($menu, $class='', $edit = false, $var = array()) {
if($menu['items'][$x]['mitem_flags'] & MENU_ITEM_NEWWIN)
$menu['items'][$x]['newwin'] = '1';
- $menu['items'][$x]['mitem_desc'] = bbcode($menu['items'][$x]['mitem_desc']);
+ $menu['items'][$x]['mitem_desc'] = zidify_links(smilies(bbcode($menu['items'][$x]['mitem_desc'])));
}
$wrap = (($var['wrap'] === 'none') ? false : true);
diff --git a/include/message.php b/include/message.php
index 7cbea3c6b..bde07afd8 100644
--- a/include/message.php
+++ b/include/message.php
@@ -8,7 +8,7 @@ require_once('include/attach.php');
// send a private message
-function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='',$expires = ''){
+function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $replyto = '', $expires = NULL_DATE) {
$ret = array('success' => false);
$is_reply = false;
@@ -16,19 +16,6 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
$a = get_app();
$observer_hash = get_observer_hash();
- if(! $recipient) {
- $ret['message'] = t('No recipient provided.');
- return $ret;
- }
-
- if(! strlen($subject))
- $subject = t('[no subject]');
-
-// if(! $expires)
-// $expires = NULL_DATE;
-// else
-// $expires = datetime_convert(date_default_timezone_get(),'UTC',$expires);
-
if($uid) {
$r = q("select * from channel where channel_id = %d limit 1",
@@ -47,6 +34,46 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
}
+ $body = cleanup_bbcode($body);
+ $results = linkify_tags($a, $body, $uid);
+
+
+ if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$match))
+ $attaches = $match[1];
+
+ $attachments = '';
+
+ if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
+ $attachments = array();
+ foreach($match[2] as $mtch) {
+ $hash = substr($mtch,0,strpos($mtch,','));
+ $rev = intval(substr($mtch,strpos($mtch,',')));
+ $r = attach_by_hash_nodata($hash,get_observer_hash(),$rev);
+ if($r['success']) {
+ $attachments[] = array(
+ 'href' => z_root() . '/attach/' . $r['data']['hash'],
+ 'length' => $r['data']['filesize'],
+ 'type' => $r['data']['filetype'],
+ 'title' => urlencode($r['data']['filename']),
+ 'revision' => $r['data']['revision']
+ );
+ }
+ $body = trim(str_replace($match[1],'',$body));
+ }
+ }
+
+ $jattach = (($attachments) ? json_encode($attachments) : '');
+
+
+ if(! $recipient) {
+ $ret['message'] = t('No recipient provided.');
+ return $ret;
+ }
+
+ if(! strlen($subject))
+ $subject = t('[no subject]');
+
+
// look for any existing conversation structure
$conv_guid = '';
@@ -156,31 +183,6 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
$match = false;
- if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$match))
- $attaches = $match[1];
-
- $attachments = '';
-
- if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
- $attachments = array();
- foreach($match[2] as $mtch) {
- $hash = substr($mtch,0,strpos($mtch,','));
- $rev = intval(substr($mtch,strpos($mtch,',')));
- $r = attach_by_hash_nodata($hash,get_observer_hash(),$rev);
- if($r['success']) {
- $attachments[] = array(
- 'href' => z_root() . '/attach/' . $r['data']['hash'],
- 'length' => $r['data']['filesize'],
- 'type' => $r['data']['filetype'],
- 'title' => urlencode($r['data']['filename']),
- 'revision' => $r['data']['revision']
- );
- }
- $body = trim(str_replace($match[1],'',$body));
- }
- }
-
- $jattach = (($attachments) ? json_encode($attachments) : '');
if($subject)
$subject = str_rot47(base64url_encode($subject));
diff --git a/include/nav.php b/include/nav.php
index 2762e2a14..144509cd0 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -1,6 +1,8 @@
<?php /** @file */
-function nav(&$a) {
+use \Zotlabs\Lib as Zlib;
+
+function nav() {
/**
*
@@ -12,8 +14,8 @@ function nav(&$a) {
App::$page['nav'] = '';
$base = z_root();
- App::$page['htmlhead'] .= <<< EOT
+ App::$page['htmlhead'] .= <<< EOT
<script>$(document).ready(function() {
$("#nav-search-text").search_autocomplete('$base/acl');
});
@@ -21,8 +23,6 @@ function nav(&$a) {
</script>
EOT;
-
-
if(local_channel()) {
$channel = App::get_channel();
$observer = App::get_observer();
@@ -76,6 +76,20 @@ EOT;
$userinfo = null;
$nav['loginmenu']=array();
+ if($observer) {
+ $userinfo = array(
+ 'icon' => $observer['xchan_photo_m'],
+ 'name' => $observer['xchan_addr'],
+ );
+ }
+
+ elseif(! $_SESSION['authenticated']) {
+ $nav['remote_login'] = remote_login();
+ $nav['loginmenu'][] = Array('rmagic',t('Remote authentication'),'',t('Click to authenticate to your home hub'),'rmagic_nav_btn');
+ }
+
+
+
if(local_channel()) {
@@ -85,34 +99,42 @@ EOT;
$nav['logout'] = Array('logout',t('Logout'), "", t('End this session'),'logout_nav_btn');
// user menu
- $nav['usermenu'][] = Array('channel/' . $channel['channel_address'], t('Home'), "", t('Your posts and conversations'),'channel_nav_btn');
+ //$nav['usermenu'][] = Array('channel/' . $channel['channel_address'], t('Home'), "", t('Your posts and conversations'),'channel_nav_btn');
$nav['usermenu'][] = Array('profile/' . $channel['channel_address'], t('View Profile'), "", t('Your profile page'),'profile_nav_btn');
if(feature_enabled(local_channel(),'multi_profiles') && (! $basic))
$nav['usermenu'][] = Array('profiles', t('Edit Profiles'),"", t('Manage/Edit profiles'),'profiles_nav_btn');
else
$nav['usermenu'][] = Array('profiles/' . $prof[0]['id'], t('Edit Profile'),"", t('Edit your profile'),'profiles_nav_btn');
- $nav['usermenu'][] = Array('photos/' . $channel['channel_address'], t('Photos'), "", t('Your photos'),'photos_nav_btn');
- $nav['usermenu'][] = Array('cloud/' . $channel['channel_address'],t('Files'),"",t('Your files'),'cloud_nav_btn');
+ //$nav['usermenu'][] = Array('photos/' . $channel['channel_address'], t('Photos'), "", t('Your photos'),'photos_nav_btn');
+ //$nav['usermenu'][] = Array('cloud/' . $channel['channel_address'],t('Files'),"",t('Your files'),'cloud_nav_btn');
- if((! $basic) && feature_enabled(local_channel(),'ajaxchat'))
- $nav['usermenu'][] = Array('chat/' . $channel['channel_address'], t('Chat'),"",t('Your chatrooms'),'chat_nav_btn');
+ //if((! $basic) && feature_enabled(local_channel(),'ajaxchat'))
+ // $nav['usermenu'][] = Array('chat/' . $channel['channel_address'], t('Chat'),"",t('Your chatrooms'),'chat_nav_btn');
- require_once('include/menu.php');
- $has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
- if(($has_bookmarks) && (! $basic)) {
- $nav['usermenu'][] = Array('bookmarks', t('Bookmarks'), "", t('Your bookmarks'),'bookmarks_nav_btn');
- }
+ //require_once('include/menu.php');
+ //$has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
+ //if(($has_bookmarks) && (! $basic)) {
+ // $nav['usermenu'][] = Array('bookmarks', t('Bookmarks'), "", t('Your bookmarks'),'bookmarks_nav_btn');
+ //}
- if(feature_enabled($channel['channel_id'],'webpages') && (! $basic))
- $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'),'webpages_nav_btn');
- if(feature_enabled($channel['channel_id'],'wiki') && (! $basic))
- $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wikis'),"",t('Your wikis'),'wiki_nav_btn');
+ //if(feature_enabled($channel['channel_id'],'webpages') && (! $basic))
+ // $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'),'webpages_nav_btn');
+ //if(feature_enabled($channel['channel_id'],'wiki') && (! $basic))
+ // $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wikis'),"",t('Your wikis'),'wiki_nav_btn');
}
else {
if(! get_account_id()) {
+ $nav['login'] = login(true,'main-login',false,false);
$nav['loginmenu'][] = Array('login',t('Login'),'',t('Sign in'),'login_nav_btn');
+ App::$page['content'] .= replace_macros(get_markup_template('nav_login.tpl'),
+ [
+ '$nav' => $nav,
+ 'userinfo' => $userinfo
+ ]
+ );
+
}
else
$nav['alogout'] = Array('logout',t('Logout'), "", t('End this session'),'logout_nav_btn');
@@ -120,16 +142,6 @@ EOT;
}
- if($observer) {
- $userinfo = array(
- 'icon' => $observer['xchan_photo_m'],
- 'name' => $observer['xchan_addr'],
- );
- }
-
- elseif(! $_SESSION['authenticated']) {
- $nav['loginmenu'][] = Array('rmagic',t('Remote authentication'),'',t('Click to authenticate to your home hub'),'rmagic_nav_btn');
- }
$homelink = get_my_url();
if(! $homelink) {
@@ -180,9 +192,11 @@ EOT;
$nav['network'] = array('network', t('Grid'), "", t('Your grid'),'network_nav_btn');
+ $nav['network']['all'] = [ 'network', t('View your network/grid'), '','' ];
$nav['network']['mark'] = array('', t('Mark all grid notifications seen'), '','');
$nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'),'home_nav_btn');
+ $nav['home']['all'] = [ 'channel/' . $channel['channel_address'], t('View your channel home'), '' , '' ];
$nav['home']['mark'] = array('', t('Mark all channel notifications seen'), '','');
@@ -190,11 +204,11 @@ EOT;
$nav['notifications'] = array('notifications/system', t('Notices'), "", t('Notifications'),'notifications_nav_btn');
- $nav['notifications']['all']=array('notifications/system', t('See all notifications'), "", "");
+ $nav['notifications']['all']=array('notifications/system', t('View all notifications'), "", "");
$nav['notifications']['mark'] = array('', t('Mark all system notifications seen'), '','');
$nav['messages'] = array('mail/combined', t('Mail'), "", t('Private mail'),'mail_nav_btn');
- $nav['messages']['all']=array('mail/combined', t('See all private messages'), "", "");
+ $nav['messages']['all']=array('mail/combined', t('View your private messages'), "", "");
$nav['messages']['mark'] = array('', t('Mark all private messages seen'), '','');
$nav['messages']['inbox'] = array('mail/inbox', t('Inbox'), "", t('Inbox'));
$nav['messages']['outbox']= array('mail/outbox', t('Outbox'), "", t('Outbox'));
@@ -202,7 +216,7 @@ EOT;
$nav['all_events'] = array('events', t('Events'), "", t('Event Calendar'),'events_nav_btn');
- $nav['all_events']['all']=array('events', t('See all events'), "", "");
+ $nav['all_events']['all']=array('events', t('View events'), "", "");
$nav['all_events']['mark'] = array('', t('Mark all events seen'), '','');
if(! $basic)
@@ -234,16 +248,44 @@ EOT;
$x = array('nav' => $nav, 'usermenu' => $userinfo );
call_hooks('nav', $x);
-// Not sure the best place to put this on the page. So I'm implementing it but leaving it
-// turned off until somebody discovers this and figures out a good location for it.
-$powered_by = '';
+ // Not sure the best place to put this on the page. So I'm implementing it but leaving it
+ // turned off until somebody discovers this and figures out a good location for it.
+ $powered_by = '';
+
+ // $powered_by = '<strong>red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="r#" />matrix</strong>';
+
+
+ //app bin
+ if(local_channel()) {
+ if(get_pconfig(local_channel(), 'system','initial_import_system_apps') === false) {
+ Zlib\Apps::import_system_apps();
+ set_pconfig(local_channel(), 'system','initial_import_system_apps', 1);
+ }
+
+ $syslist = array();
+ $list = Zlib\Apps::app_list(local_channel(), false, 'nav_featured_app');
+ if($list) {
+ foreach($list as $li) {
+ $syslist[] = Zlib\Apps::app_encode($li);
+ }
+ }
+ Zlib\Apps::translate_system_apps($syslist);
+ }
+ else {
+ $syslist = Zlib\Apps::get_system_apps(true);
+ }
-// $powered_by = '<strong>red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="r#" />matrix</strong>';
+ usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
+
+ foreach($syslist as $app) {
+ $navapps[] = Zlib\Apps::app_render($app,'nav');
+ }
$tpl = get_markup_template('nav.tpl');
App::$page['nav'] .= replace_macros($tpl, array(
'$baseurl' => z_root(),
+ '$fulldocs' => t('Help'),
'$sitelocation' => $sitelocation,
'$nav' => $x['nav'],
'$banner' => $banner,
@@ -253,10 +295,11 @@ $powered_by = '';
'$sel' => App::$nav_sel,
'$powered_by' => $powered_by,
'$help' => t('@name, #tag, ?doc, content'),
- '$pleasewait' => t('Please wait...')
+ '$pleasewait' => t('Please wait...'),
+ '$navapps' => $navapps,
+ '$addapps' => t('Add Apps')
));
-
if(x($_SESSION, 'reload_avatar') && $observer) {
// The avatar has been changed on the server but the browser doesn't know that,
// force the browser to reload the image from the server instead of its cache.
diff --git a/include/network.php b/include/network.php
index 451ce12a1..66716ef9e 100644
--- a/include/network.php
+++ b/include/network.php
@@ -51,7 +51,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
- @curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; Red)");
+ @curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; zot)");
$ciphers = @get_config('system','curl_ssl_ciphers');
if($ciphers)
@@ -84,7 +84,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
if(x($opts,'timeout') && intval($opts['timeout'])) {
- @curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
+ @curl_setopt($ch, CURLOPT_TIMEOUT, intval($opts['timeout']));
}
else {
$curl_time = intval(@get_config('system','curl_timeout'));
@@ -218,7 +218,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
@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_USERAGENT, "Mozilla/5.0 (compatible; zot)");
$ciphers = @get_config('system','curl_ssl_ciphers');
if($ciphers)
@@ -714,6 +714,10 @@ function scale_external_images($s, $include_link = true, $scale_replace = false)
if($i['success']) {
$ph = photo_factory($i['body'], $type);
+
+ if(! is_object($ph))
+ continue;
+
if($ph->is_valid()) {
$orig_width = $ph->getWidth();
$orig_height = $ph->getHeight();
@@ -1117,16 +1121,17 @@ function discover_by_url($url,$arr = null) {
if(! $photo)
$photo = z_root() . '/images/rss_icon.png';
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_instance_url, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
- dbesc($guid),
- dbesc($guid),
- dbesc($pubkey),
- dbesc($addr),
- dbesc($profile),
- dbesc($name),
- dbesc($network),
- dbesc(z_root()),
- dbesc(datetime_convert())
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $guid,
+ 'xchan_guid' => $guid,
+ 'xchan_pubkey' => $pubkey,
+ 'xchan_addr' => $addr,
+ 'xchan_url' => $profile,
+ 'xchan_name' => $name,
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_network' => $network
+ ]
);
$photos = import_xchan_photo($photo,$guid);
@@ -1445,15 +1450,17 @@ function discover_by_webbie($webbie) {
);
}
else {
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
- dbesc($address),
- dbesc(($diaspora_guid) ? $diaspora_guid : $location),
- dbesc($pubkey),
- dbesc($address),
- dbesc($location),
- dbesc($fullname),
- dbesc($network),
- dbescdate(datetime_convert())
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $address,
+ 'xchan_guid' => (($diaspora_guid) ? $diaspora_guid : $location),
+ 'xchan_pubkey' => $pubkey,
+ 'xchan_addr' => $address,
+ 'xchan_url' => $location,
+ 'xchan_name' => $fullname,
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_network' => $network
+ ]
);
}
@@ -1462,15 +1469,18 @@ function discover_by_webbie($webbie) {
);
if(! $r) {
- $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)",
- dbesc(($diaspora_guid) ? $diaspora_guid : $location),
- dbesc($address),
- dbesc($address),
- dbesc($network),
- dbesc($base),
- dbesc($host),
- dbesc($notify),
- dbescdate(datetime_convert())
+ $r = hubloc_store_lowlevel(
+ [
+ 'hubloc_guid' => (($diaspora_guid) ? $diaspora_guid : $location),
+ 'hubloc_hash' => $address,
+ 'hubloc_addr' => $address,
+ 'hubloc_network' => $network,
+ 'hubloc_url' => $base,
+ 'hubloc_host' => $host,
+ 'hubloc_callback' => $notify,
+ 'hubloc_updated' => datetime_convert(),
+ 'hubloc_primary' => 1
+ ]
);
}
$photos = import_xchan_photo($avatar,$address);
diff --git a/include/oembed.php b/include/oembed.php
index 8c78e2807..aac7d15b4 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -2,8 +2,6 @@
use Zotlabs\Lib as Zlib;
-require_once('include/hubloc.php');
-
function oembed_replacecb($matches){
@@ -107,7 +105,7 @@ function oembed_action($embedurl) {
function oembed_process($url) {
$j = oembed_fetch_url($url);
- logger('oembed_process: ' . print_r($j,true));
+ logger('oembed_process: ' . print_r($j,true), LOGGER_DATA, LOG_DEBUG);
if($j && $j['type'] !== 'error')
return '[embed]' . $url . '[/embed]';
return false;
@@ -138,19 +136,15 @@ function oembed_fetch_url($embedurl){
// we should try to cache this and avoid a lookup on each render
$zrl = is_matrix_url($embedurl);
+ $furl = ((local_channel() && $zrl) ? zid($embedurl) : $embedurl);
+
if($action !== 'block') {
- $txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $embedurl);
+ $txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $furl);
}
if(is_null($txt)) {
$txt = "";
- $furl = $embedurl;
-
- logger('local_channel: ' . local_channel());
-
- if(local_channel() && $zrl)
- $furl = zid($furl);
if ($action !== 'block') {
// try oembed autodiscovery
@@ -209,11 +203,10 @@ function oembed_fetch_url($embedurl){
//save in cache
if(! get_config('system','oembed_cache_disable'))
- Zlib\Cache::set('[' . App::$videowidth . '] ' . $embedurl,$txt);
+ Zlib\Cache::set('[' . App::$videowidth . '] ' . $furl, $txt);
}
-
$j = json_decode($txt,true);
if(! $j)
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index af4fd0a30..c8b3c3782 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -11,8 +11,10 @@ function photo_factory($data, $type = null) {
'image/svg+xml'
);
- if($type && in_array(strtolower($type),$unsupported_types))
+ if($type && in_array(strtolower($type),$unsupported_types)) {
+ logger('photo_factory: unsupported image type');
return null;
+ }
$ignore_imagick = get_config('system', 'ignore_imagick');
diff --git a/include/photos.php b/include/photos.php
index 5e4d755e3..c0f7dc8c4 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -402,7 +402,7 @@ function photo_upload($channel, $observer, $args) {
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['item_private'] = intval($acl->is_private());
- $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
$arr['body'] = $summary;
@@ -464,10 +464,15 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction
$sort_key = dbesc($sort_key);
$direction = dbesc($direction);
- $albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and photo_usage IN ( %d, %d ) $sql_extra group by album order by $sort_key $direction",
- intval($channel_id),
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE)
+ //$albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and photo_usage IN ( %d, %d ) $sql_extra group by album order by $sort_key $direction",
+ // intval($channel_id),
+ // intval(PHOTO_NORMAL),
+ // intval(PHOTO_PROFILE)
+ //);
+
+ // this query provides the same results but might perform better
+ $albums = q("SELECT count( distinct resource_id ) as total, album from photo where uid = %d and os_storage = 1 $sql_extra group by album order by $sort_key $direction",
+ intval($channel_id)
);
// add various encodings to the array so we can just loop through and pick them out in a template
@@ -480,6 +485,7 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction
foreach($albums as $k => $album) {
$entry = array(
'text' => (($album['album']) ? $album['album'] : '/'),
+ 'jstext' => (($album['album']) ? addslashes($album['album']) : '/'),
'total' => $album['total'],
'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']),
'urlencode' => urlencode($album['album']),
@@ -489,6 +495,8 @@ function photos_albums_list($channel, $observer, $sort_key = 'album', $direction
}
}
+ App::$data['albums'] = $ret;
+
return $ret;
}
@@ -663,7 +671,7 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$arr['deny_cid'] = $photo['deny_cid'];
$arr['deny_gid'] = $photo['deny_gid'];
- $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']'
. '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['imgscale'] . '[/zmg]'
@@ -710,10 +718,59 @@ function gps2Num($coordPart) {
return floatval($parts[0]) / floatval($parts[1]);
}
+
+function photo_profile_setperms($channel_id,$resource_id,$profile_id) {
+
+ if(! $profile_id)
+ return;
+
+ $r = q("select profile_guid, is_default from profile where id = %d and uid = %d limit 1",
+ dbesc($profile_id),
+ intval($channel_id)
+ );
+
+ if(! $r)
+ return;
+
+ $is_default = $r[0]['is_default'];
+ $profile_guid = $r[0]['profile_guid'];
+
+ if($is_default) {
+ $r = q("update photo set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
+ where resource_id = '%s' and uid = %d",
+ dbesc($resource_id),
+ intval($channel_id)
+ );
+ $r = q("update attach set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
+ where hash = '%s' and uid = %d",
+ dbesc($resource_id),
+ intval($channel_id)
+ );
+ }
+ else {
+ $r = q("update photo set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
+ where resource_id = '%s' and uid = %d",
+ dbesc('<vp.' . $profile_guid . '>'),
+ dbesc($resource_id),
+ intval($channel_id)
+ );
+
+ $r = q("update attach set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
+ where hash = '%s' and uid = %d",
+ dbesc('<vp.' . $profile_guid . '>'),
+ dbesc($resource_id),
+ intval($channel_id)
+ );
+ }
+}
+
function profile_photo_set_profile_perms($uid, $profileid = 0) {
- $allowcid = '';
- if($profileid) {
+ $allowcid = '';
+
+
+ if($profileid) {
+
$r = q("SELECT photo, profile_guid, id, is_default, uid
FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
intval($uid),
diff --git a/include/plugin.php b/include/plugin.php
index 80c303b42..29474735e 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -471,6 +471,8 @@ function get_theme_info($theme){
'description' => '',
'author' => array(),
'version' => '',
+ 'minversion' => '',
+ 'maxversion' => '',
'compat' => '',
'credits' => '',
'maintainer' => array(),
@@ -556,32 +558,65 @@ function head_add_css($src, $media = 'screen') {
function head_remove_css($src, $media = 'screen') {
$index = array_search(array($src, $media), App::$css_sources);
- if ($index !== false)
+ if($index !== false)
unset(App::$css_sources[$index]);
}
function head_get_css() {
$str = '';
$sources = App::$css_sources;
- if (count($sources)) {
- foreach ($sources as $source)
+ if(count($sources)) {
+ foreach($sources as $source)
$str .= format_css_if_exists($source);
}
return $str;
}
+function head_add_link($arr) {
+ if($arr) {
+ App::$linkrel[] = $arr;
+ }
+}
+
+function head_get_links() {
+ $str = '';
+ $sources = App::$linkrel;
+ if(count($sources)) {
+ foreach($sources as $source) {
+ if(is_array($source) && count($source)) {
+ $str .= '<link';
+ foreach($source as $k => $v) {
+ $str .= ' ' . $k . '="' . $v . '"';
+ }
+ $str .= ' />' . "\r\n";
+
+ }
+ }
+ }
+
+ return $str;
+}
+
+
function format_css_if_exists($source) {
- $path_prefix = script_path() . '/';
- if (strpos($source[0], '/') !== false) {
- // The source is a URL
- $path = $source[0];
+ // script_path() returns https://yoursite.tld
+
+ $path_prefix = script_path();
+
+ $script = $source[0];
+
+ if(strpos($script, '/') !== false) {
+ // The script is a path relative to the server root
+ $path = $script;
// If the url starts with // then it's an absolute URL
- if($source[0][0] === '/' && $source[0][1] === '/') $path_prefix = '';
+ if(substr($script,0,2) === '//') {
+ $path_prefix = '';
+ }
} else {
// It's a file from the theme
- $path = theme_include($source[0]);
+ $path = '/' . theme_include($script);
}
if($path) {
@@ -651,7 +686,7 @@ function head_get_js() {
foreach(App::$js_sources as $sources) {
if(count($sources)) {
foreach($sources as $source) {
- if($src === 'main.js')
+ if($source === 'main.js')
continue;
$str .= format_js_if_exists($source);
}
@@ -671,16 +706,19 @@ function head_get_main_js() {
}
function format_js_if_exists($source) {
- $path_prefix = script_path() . '/';
+ $path_prefix = script_path();
if(strpos($source,'/') !== false) {
- // The source is a URL
+ // The source is a known path on the system
$path = $source;
// If the url starts with // then it's an absolute URL
- if($source[0] === '/' && $source[1] === '/') $path_prefix = '';
- } else {
+ if(substr($source,0,2) === '//') {
+ $path_prefix = '';
+ }
+ }
+ else {
// It's a file from the theme
- $path = theme_include($source);
+ $path = '/' . theme_include($source);
}
if($path) {
$qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
diff --git a/include/queue_fn.php b/include/queue_fn.php
index 0950faf85..ede6c8f11 100644
--- a/include/queue_fn.php
+++ b/include/queue_fn.php
@@ -2,9 +2,57 @@
function update_queue_item($id, $add_priority = 0) {
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
- q("UPDATE outq SET outq_updated = '%s', outq_priority = outq_priority + %d WHERE outq_hash = '%s'",
+ $x = q("select outq_created, outq_posturl from outq where outq_hash = '%s' limit 1",
+ dbesc($id)
+ );
+ if(! $x)
+ return;
+
+
+ $y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'",
+ dbesc($x[0]['outq_posturl'])
+ );
+
+ // look for the oldest queue entry with this destination URL. If it's older than a couple of days,
+ // the destination is considered to be down and only scheduled once an hour, regardless of the
+ // age of the current queue item.
+
+ $might_be_down = false;
+
+ if($y)
+ $might_be_down = ((datetime_convert('UTC','UTC',$y[0]['earliest']) < datetime_convert('UTC','UTC','now - 2 days')) ? true : false);
+
+
+ // Set all other records for this destination way into the future.
+ // The queue delivers by destination. We'll keep one queue item for
+ // this destination (this one) with a shorter delivery. If we succeed
+ // once, we'll try to deliver everything for that destination.
+ // The delivery will be set to at most once per hour, and if the
+ // queue item is less than 12 hours old, we'll schedule for fifteen
+ // minutes.
+
+ $r = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
+ dbesc(datetime_convert('UTC','UTC','now + 5 days')),
+ dbesc($x[0]['outq_posturl'])
+ );
+
+ $since = datetime_convert('UTC','UTC',$x[0]['outq_created']);
+
+ if(($might_be_down) || ($since < datetime_convert('UTC','UTC','now - 12 hour'))) {
+ $next = datetime_convert('UTC','UTC','now + 1 hour');
+ }
+ else {
+ $next = datetime_convert('UTC','UTC','now + 15 minutes');
+ }
+
+ q("UPDATE outq SET outq_updated = '%s',
+ outq_priority = outq_priority + %d,
+ outq_scheduled = '%s'
+ WHERE outq_hash = '%s'",
+
dbesc(datetime_convert()),
intval($add_priority),
+ dbesc($next),
dbesc($id)
);
}
@@ -33,8 +81,12 @@ function queue_set_delivered($id,$channel = 0) {
logger('queue: set delivered ' . $id,LOGGER_DEBUG);
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
- q("update outq set outq_delivered = 1, outq_updated = '%s' where outq_hash = '%s' $sql_extra ",
+ // Set the next scheduled run date so far in the future that it will be expired
+ // long before it ever makes it back into the delivery chain.
+
+ q("update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ",
dbesc(datetime_convert()),
+ dbesc(datetime_convert('UTC','UTC','now + 5 days')),
dbesc($id)
);
}
@@ -44,8 +96,8 @@ function queue_set_delivered($id,$channel = 0) {
function queue_insert($arr) {
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
- outq_created, outq_updated, outq_notify, outq_msg )
- values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' )",
+ outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
+ values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )",
dbesc($arr['hash']),
intval($arr['account_id']),
intval($arr['channel_id']),
@@ -55,6 +107,7 @@ function queue_insert($arr) {
intval(($arr['priority']) ? $arr['priority'] : 0),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
dbesc($arr['notify']),
dbesc(($arr['msg']) ? $arr['msg'] : '')
);
diff --git a/include/security.php b/include/security.php
index 2f5de54c7..b49ceec0d 100644
--- a/include/security.php
+++ b/include/security.php
@@ -171,19 +171,16 @@ function atoken_create_xchan($xchan) {
if($r)
return;
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_photo_mimetype, xchan_photo_l, xchan_photo_m, xchan_photo_s )
- values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
- dbesc($xchan['xchan_hash']),
- dbesc($xchan['xchan_hash']),
- dbesc($xchan['xchan_addr']),
- dbesc($xchan['xchan_url']),
- dbesc($xchan['xchan_name']),
- dbesc($xchan['xchan_network']),
- dbesc($xchan['xchan_photo_mimetype']),
- dbesc($xchan['xchan_photo_l']),
- dbesc($xchan['xchan_photo_m']),
- dbesc($xchan['xchan_photo_s'])
- );
+ $xchan['xchan_guid'] = $xchan['xchan_hash'];
+
+ $store = [];
+ foreach($xchan as $k => $v) {
+ if(strpos($k,'xchan_') === 0) {
+ $store[$k] = $v;
+ }
+ }
+
+ $r = xchan_store_lowlevel($store);
return true;
}
@@ -556,7 +553,21 @@ function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'f
// var $contact_id = xchan_hash of connection
function init_groups_visitor($contact_id) {
- $groups = array();
+ $groups = [];
+
+ // private profiles are treated as a virtual group
+
+ $r = q("SELECT abook_profile from abook where abook_xchan = '%s' and abook_profile != '' ",
+ dbesc($contact_id)
+ );
+ if($r) {
+ foreach($r as $rv) {
+ $groups[] = 'vp.' . $rv['abook_profile'];
+ }
+ }
+
+ // physical groups this channel is a member of
+
$r = q("SELECT hash FROM groups left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ",
dbesc($contact_id)
);
diff --git a/include/text.php b/include/text.php
index b25eb8e46..eb8147f9a 100644
--- a/include/text.php
+++ b/include/text.php
@@ -4,7 +4,7 @@
*/
require_once("include/bbcode.php");
-require_once('include/hubloc.php');
+
// random string, there are 86 characters max in text mode, 128 for hex
// output is urlsafe
@@ -586,8 +586,10 @@ function photo_new_resource() {
* @return boolean true if found
*/
function attribute_contains($attr, $s) {
+ // remove quotes
+ $attr = str_replace([ '"',"'" ],['',''],$attr);
$a = explode(' ', $attr);
- if(count($a) && in_array($s, $a))
+ if($a && in_array($s, $a))
return true;
return false;
@@ -655,12 +657,28 @@ function logger($msg, $level = LOGGER_NORMAL, $priority = LOG_INFO) {
*/
function btlogger($msg, $level = LOGGER_NORMAL, $priority = LOG_INFO) {
+ if(! defined('BTLOGGER_DEBUG_FILE'))
+ define('BTLOGGER_DEBUG_FILE','btlogger.out');
+
logger($msg, $level, $priority);
+
+ if(file_exists(BTLOGGER_DEBUG_FILE) && is_writable(BTLOGGER_DEBUG_FILE)) {
+ $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
+ $where = basename($stack[0]['file']) . ':' . $stack[0]['line'] . ':' . $stack[1]['function'] . ': ';
+ $s = datetime_convert() . ':' . log_priority_str($priority) . ':' . session_id() . ':' . $where . $msg . PHP_EOL;
+ @file_put_contents(BTLOGGER_DEBUG_FILE, $s, FILE_APPEND);
+ }
+
if(version_compare(PHP_VERSION, '5.4.0') >= 0) {
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
if($stack) {
for($x = 1; $x < count($stack); $x ++) {
- logger('stack: ' . basename($stack[$x]['file']) . ':' . $stack[$x]['line'] . ':' . $stack[$x]['function'] . '()',$level, $priority);
+ $s = 'stack: ' . basename($stack[$x]['file']) . ':' . $stack[$x]['line'] . ':' . $stack[$x]['function'] . '()';
+ logger($s,$level, $priority);
+
+ if(file_exists(BTLOGGER_DEBUG_FILE) && is_writable(BTLOGGER_DEBUG_FILE)) {
+ @file_put_contents(BTLOGGER_DEBUG_FILE, $s . PHP_EOL, FILE_APPEND);
+ }
}
}
}
@@ -1565,11 +1583,6 @@ function prepare_body(&$item,$attach = false) {
$photo = $prep_arr['photo'];
$event = $prep_arr['event'];
-// q("update item set html = '%s' where id = %d",
-// dbesc($s),
-// intval($item['id'])
-// );
-
if(! $attach) {
return $s;
}
@@ -3061,4 +3074,67 @@ function create_table_from_array($table, $arr) {
}
return $r;
-} \ No newline at end of file
+}
+
+
+
+function cleanup_bbcode($body) {
+
+
+ /**
+ * fix naked links by passing through a callback to see if this is a hubzilla site
+ * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
+ * First protect any url inside certain bbcode tags so we don't double link it.
+ */
+
+ $body = preg_replace_callback('/\[code(.*?)\[\/(code)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[url(.*?)\[\/(url)\]/ism','\red_escape_codeblock',$body);
+ $body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','\red_escape_codeblock',$body);
+
+
+ $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
++\,\(\)]+)/ism", '\nakedoembed', $body);
+ $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
++\,\(\)]+)/ism", '\red_zrl_callback', $body);
+
+ $body = preg_replace_callback('/\[\$b64zrl(.*?)\[\/(zrl)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body);
+ $body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);
+
+ // fix any img tags that should be zmg
+
+ $body = preg_replace_callback('/\[img(.*?)\](.*?)\[\/img\]/ism','\red_zrlify_img_callback',$body);
+
+
+ $body = bb_translate_video($body);
+
+ /**
+ * Fold multi-line [code] sequences
+ */
+
+ $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
+
+ $body = scale_external_images($body,false);
+
+
+ return $body;
+
+}
+
+function gen_link_id($mid) {
+ if(strpbrk($mid,':/&?<>"\'') !== false)
+ return 'b64.' . base64url_encode($mid);
+ return $mid;
+}
+
+
+// callback for array_walk
+
+function array_trim(&$v,$k) {
+ $v = trim($v);
+}
+
+function array_escape_tags(&$v,$k) {
+ $v = escape_tags($v);
+}
+
diff --git a/include/widgets.php b/include/widgets.php
index dde8e7cd0..04cf0d30b 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -96,19 +96,6 @@ function widget_collections($args) {
return group_side($every, $each, $edit, $current, $abook_id, $wmode);
}
-
-function widget_appselect($arr) {
- return replace_macros(get_markup_template('app_select.tpl'),array(
- '$title' => t('Apps'),
- '$system' => t('System'),
- '$authed' => ((local_channel()) ? true : false),
- '$personal' => t('Personal'),
- '$new' => t('New App'),
- '$edit' => t('Edit App')
- ));
-}
-
-
function widget_suggestions($arr) {
if((! local_channel()) || (! feature_enabled(local_channel(),'suggest')))
@@ -441,11 +428,13 @@ function widget_appcategories($arr) {
if(! local_channel())
return '';
- $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
- $srchurl = App::$query_string;
+ $selected = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
+
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
+ $srchurl = z_root() . '/apps';
+
$terms = array();
$r = q("select distinct(term.term)
@@ -453,6 +442,7 @@ function widget_appcategories($arr) {
where app_channel = %d
and term.uid = app_channel
and term.otype = %d
+ and term.term != 'nav_featured_app'
order by term.term asc",
intval(local_channel()),
intval(TERM_OBJ_APP)
@@ -518,9 +508,16 @@ function widget_affinity($arr) {
if(! local_channel())
return '';
-
- $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0);
- $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99);
+
+ // Get default cmin value from pconfig, but allow GET parameter to override
+ $cmin = intval(get_pconfig(local_channel(),'affinity','cmin'));
+ $cmin = (($cmin) ? $cmin : 0);
+ $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $cmin);
+
+ // Get default cmax value from pconfig, but allow GET parameter to override
+ $cmax = intval(get_pconfig(local_channel(),'affinity','cmax'));
+ $cmax = (($cmax) ? $cmax : 99);
+ $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $cmax);
if(feature_enabled(local_channel(),'affinity')) {
@@ -650,6 +647,14 @@ function widget_settings_menu($arr) {
);
}
+ if(feature_enabled(local_channel(),'permcats')) {
+ $tabs[] = array(
+ 'label' => t('Permission Groups'),
+ 'url' => z_root() . '/settings/permcats',
+ 'selected' => ((argv(1) === 'permcats') ? 'active' : ''),
+ );
+ }
+
if($role === false || $role === 'custom') {
$tabs[] = array(
@@ -898,9 +903,11 @@ function widget_chatroom_members() {
}
function widget_wiki_list($arr) {
- require_once("include/wiki.php");
+
$channel = channelx_by_n(App::$profile_uid);
- $wikis = wiki_list($channel, get_observer_hash());
+
+ $wikis = Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash());
+
if($wikis) {
return replace_macros(get_markup_template('wikilist_widget.tpl'), array(
'$header' => t('Wiki List'),
@@ -913,8 +920,9 @@ function widget_wiki_list($arr) {
function widget_wiki_pages($arr) {
- require_once("include/wiki.php");
$channelname = ((array_key_exists('channel',$arr)) ? $arr['channel'] : '');
+ $c = channelx_by_nick($channelname);
+
$wikiname = '';
if (array_key_exists('refresh', $arr)) {
$not_refresh = (($arr['refresh']=== true) ? false : true);
@@ -922,11 +930,12 @@ function widget_wiki_pages($arr) {
$not_refresh = true;
}
$pages = array();
- if (!array_key_exists('resource_id', $arr)) {
+ if (! array_key_exists('resource_id', $arr)) {
$hide = true;
} else {
- $p = wiki_page_list($arr['resource_id']);
- if ($p['pages']) {
+ $p = Zotlabs\Lib\NativeWikiPage::page_list($c['channel_id'],get_observer_hash(),$arr['resource_id']);
+
+ if($p['pages']) {
$pages = $p['pages'];
$w = $p['wiki'];
// Wiki item record is $w['wiki']
@@ -936,31 +945,38 @@ function widget_wiki_pages($arr) {
}
}
}
- $can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_pages');
+ $can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki');
+
+ $can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false);
return replace_macros(get_markup_template('wiki_page_list.tpl'), array(
'$hide' => $hide,
+ '$resource_id' => $arr['resource_id'],
'$not_refresh' => $not_refresh,
'$header' => t('Wiki Pages'),
'$channel' => $channelname,
'$wikiname' => $wikiname,
'$pages' => $pages,
'$canadd' => $can_create,
+ '$candel' => $can_delete,
'$addnew' => t('Add new page'),
'$pageName' => array('pageName', t('Page name')),
));
}
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'],
- '$permsWrite' => $arr['permsWrite']
+ $pageHistory = Zotlabs\Lib\NativeWikiPage::page_history(array('channel_id' => App::$profile_uid, 'observer_hash' => get_observer_hash(), 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
+ return replace_macros(get_markup_template('nwiki_page_history.tpl'), array(
+ '$pageHistory' => $pageHistory['history'],
+ '$permsWrite' => $arr['permsWrite'],
+ '$name_lbl' => t('Name'),
+ '$msg_label' => t('Message','wiki_history')
));
+
}
function widget_bookmarkedchats($arr) {
diff --git a/include/wiki.php b/include/wiki.php
deleted file mode 100644
index 922be6924..000000000
--- a/include/wiki.php
+++ /dev/null
@@ -1,664 +0,0 @@
-<?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'])
- );
- if($wikis) {
- 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');
- $w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
- $w['lock'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? true : false);
- }
- }
- // 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[] = [
- 'resource_id' => '',
- 'title' => 'Home',
- 'url' => 'Home',
- 'link_id' => 'id_wiki_home_0'
- ];
-
- if (is_dir($w['path']) === true) {
- $files = array_diff(scandir($w['path']), array('.', '..', '.git'));
- // TODO: Check that the files are all text files
- $i = 1;
- foreach($files as $file) {
- // strip the file extension and unwrap URL encoding to leave HTML encoded name
- $title = substr($file, 0, strrpos($file,'.'));
- if(urldecode($title) !== 'Home') {
- $pages[] = [
- 'resource_id' => $resource_id,
- 'title' => urldecode($title),
- 'url' => $title,
- 'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $i
- ];
- $i++;
- }
- }
- }
-
- 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);
- }
- if (!set_iconfig($arr, 'wiki', 'mimeType', $wiki['mimeType'], true)) {
- return array('item' => null, 'success' => false);
- }
- $post = item_store($arr);
- $item_id = $post['item_id'];
-
- if ($item_id) {
- \Zotlabs\Daemon\Master::Summon(array('Notifier', 'activity', $item_id));
- return array('item' => $post['item'], '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');
- $mimeType = get_iconfig($w, 'wiki', 'mimeType');
-
- $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,
- 'mimeType' => $mimeType
- );
- }
-}
-
-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);
-
- if(local_channel() && local_channel == $owner_id) {
- return [ 'read' => true, 'write' => true, 'success' => true ];
- }
-
- $r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
- intval($owner_id),
- dbesc(WIKI_ITEM_RESOURCE_TYPE),
- dbesc($resource_id)
- );
-
- if (!$r) {
- return array('read' => false, 'write' => false, 'success' => true);
- } else {
- // TODO: Create a new permission setting for wiki analogous to webpages. Until
- // then, use webpage permissions
- $write = perm_is_allowed($owner_id, $observer_hash,'write_pages');
- 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)) . wiki_get_file_ext($w));
- $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 . wiki_get_file_ext($w);
- 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)) . wiki_get_file_ext($w));
- $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 . wiki_get_file_ext($w);
- 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), 'mimeType' => $w['mimeType'], '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 . wiki_get_file_ext($w);
- 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_prepare_content($s) {
-
- $text = preg_replace_callback('{
- (?:\n\n|\A\n?)
- ( # $1 = the code block -- one or more lines, starting with a space/tab
- (?>
- [ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
- .*\n+
- )+
- )
- ((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
- }xm',
- 'wiki_prepare_content_callback', $s);
-
- return $text;
-}
-
-function wiki_prepare_content_callback($matches) {
- $codeblock = $matches[1];
-
- $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES, UTF8, false);
- return "\n\n" . $codeblock ;
-}
-
-
-
-function wiki_save_page($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $content = ((array_key_exists('content',$arr)) ? purify_html(wiki_prepare_content($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);
- }
-
- $fileName = $pageUrlName . wiki_get_file_ext($w);
- $page_path = $w['path'] . '/' . $fileName;
- 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' => '', 'filename' => $filename, '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 . wiki_get_file_ext($w);
- 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 . wiki_get_file_ext($w);
- 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 . wiki_get_file_ext($w)) {
- $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 . wiki_get_file_ext($w);
- 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 . wiki_get_file_ext($w)) {
- $currentContent = $git->git->cat->blob($object['hash']);
- }
- }
- foreach ($git->git->tree($compareCommit) as $object) {
- if ($object['type'] == 'blob' && $object['file'] === $pageUrlName . wiki_get_file_ext($w)) {
- $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_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;
-}
-
-/**
- * Replace the instances of the string [toc] with a list element that will be populated by
- * a table of contents by the JavaScript library
- * @param string $s
- * @return string
- */
-function wiki_generate_toc($s) {
- if (strpos($s,'[toc]') !== false) {
- //$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
- $toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
- $s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
- }
- return $s;
-}
-
-/**
- * Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
- * @param string $s
- * @return string
- */
-function wiki_bbcode($s) {
-
- $s = str_replace(array('[baseurl]', '[sitename]'), array(z_root(), get_config('system', 'sitename')), $s);
-
- $observer = App::get_observer();
- if ($observer) {
- $s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
- $s2 = '</span>';
- $obsBaseURL = $observer['xchan_connurl'];
- $obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
- $s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
- $s = str_replace('[observer.url]', $observer['xchan_url'], $s);
- $s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
- $s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
- $s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
- $s = str_replace('[observer.photo]', '', $s);
- } else {
- $s = str_replace('[observer.baseurl]', '', $s);
- $s = str_replace('[observer.url]', '', $s);
- $s = str_replace('[observer.name]', '', $s);
- $s = str_replace('[observer.address]', '', $s);
- $s = str_replace('[observer.webname]', '', $s);
- $s = str_replace('[observer.photo]', '', $s);
- }
-
- return $s;
-}
-
-function wiki_get_file_ext($arr) {
- if($arr['mimeType'] == 'text/bbcode')
- return '.bb';
- else
- return '.md';
-}
-
-// This function is derived from
-// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
-function wiki_toc($content) {
- // ensure using only "\n" as line-break
- $source = str_replace(["\r\n", "\r"], "\n", $content);
-
- // look for markdown TOC items
- preg_match_all(
- '/^(?:=|-|#).*$/m',
- $source,
- $matches,
- PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
- );
-
- // preprocess: iterate matched lines to create an array of items
- // where each item is an array(level, text)
- $file_size = strlen($source);
- foreach ($matches[0] as $item) {
- $found_mark = substr($item[0], 0, 1);
- if ($found_mark == '#') {
- // text is the found item
- $item_text = $item[0];
- $item_level = strrpos($item_text, '#') + 1;
- $item_text = substr($item_text, $item_level);
- } else {
- // text is the previous line (empty if <hr>)
- $item_offset = $item[1];
- $prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
- $item_text =
- substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
- $item_text = trim($item_text);
- $item_level = $found_mark == '=' ? 1 : 2;
- }
- if (!trim($item_text) OR strpos($item_text, '|') !== FALSE) {
- // item is an horizontal separator or a table header, don't mind
- continue;
- }
- $raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
- }
- $o = '';
- foreach($raw_toc as $t) {
- $level = intval($t['level']);
- $text = $t['text'];
- switch ($level) {
- case 1:
- $li = '* ';
- break;
- case 2:
- $li = ' * ';
- break;
- case 3:
- $li = ' * ';
- break;
- case 4:
- $li = ' * ';
- break;
- default:
- $li = '* ';
- break;
- }
- $o .= $li . $text . "\n";
- }
- return $o;
-}
diff --git a/include/xchan.php b/include/xchan.php
new file mode 100644
index 000000000..12eb674fa
--- /dev/null
+++ b/include/xchan.php
@@ -0,0 +1,139 @@
+<?php
+
+
+function xchan_store_lowlevel($arr) {
+
+ $store = [
+ 'xchan_hash' => ((array_key_exists('xchan_hash',$arr)) ? $arr['xchan_hash'] : ''),
+ 'xchan_guid' => ((array_key_exists('xchan_guid',$arr)) ? $arr['xchan_guid'] : ''),
+ 'xchan_guid_sig' => ((array_key_exists('xchan_guid_sig',$arr)) ? $arr['xchan_guid_sig'] : ''),
+ 'xchan_pubkey' => ((array_key_exists('xchan_pubkey',$arr)) ? $arr['xchan_pubkey'] : ''),
+ 'xchan_photo_mimetype' => ((array_key_exists('xchan_photo_mimetype',$arr)) ? $arr['xchan_photo_mimetype'] : ''),
+ 'xchan_photo_l' => ((array_key_exists('xchan_photo_l',$arr)) ? $arr['xchan_photo_l'] : ''),
+ 'xchan_photo_m' => ((array_key_exists('xchan_photo_m',$arr)) ? $arr['xchan_photo_m'] : ''),
+ 'xchan_photo_s' => ((array_key_exists('xchan_photo_s',$arr)) ? $arr['xchan_photo_s'] : ''),
+ 'xchan_addr' => ((array_key_exists('xchan_addr',$arr)) ? $arr['xchan_addr'] : ''),
+ 'xchan_url' => ((array_key_exists('xchan_url',$arr)) ? $arr['xchan_url'] : ''),
+ 'xchan_connurl' => ((array_key_exists('xchan_connurl',$arr)) ? $arr['xchan_connurl'] : ''),
+ 'xchan_follow' => ((array_key_exists('xchan_follow',$arr)) ? $arr['xchan_follow'] : ''),
+ 'xchan_connpage' => ((array_key_exists('xchan_connpage',$arr)) ? $arr['xchan_connpage'] : ''),
+ 'xchan_name' => ((array_key_exists('xchan_name',$arr)) ? $arr['xchan_name'] : ''),
+ 'xchan_network' => ((array_key_exists('xchan_network',$arr)) ? $arr['xchan_network'] : ''),
+ 'xchan_instance_url' => ((array_key_exists('xchan_instance_url',$arr)) ? $arr['xchan_instance_url'] : ''),
+ 'xchan_flags' => ((array_key_exists('xchan_flags',$arr)) ? intval($arr['xchan_flags']) : 0),
+ 'xchan_photo_date' => ((array_key_exists('xchan_photo_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_photo_date']) : NULL_DATE),
+ 'xchan_name_date' => ((array_key_exists('xchan_name_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_name_date']) : NULL_DATE),
+ 'xchan_hidden' => ((array_key_exists('xchan_hidden',$arr)) ? intval($arr['xchan_hidden']) : 0),
+ 'xchan_orphan' => ((array_key_exists('xchan_orphan',$arr)) ? intval($arr['xchan_orphan']) : 0),
+ 'xchan_censored' => ((array_key_exists('xchan_censored',$arr)) ? intval($arr['xchan_censored']) : 0),
+ 'xchan_selfcensored' => ((array_key_exists('xchan_selfcensored',$arr)) ? intval($arr['xchan_selfcensored']) : 0),
+ 'xchan_system' => ((array_key_exists('xchan_system',$arr)) ? intval($arr['xchan_system']) : 0),
+ 'xchan_pubforum' => ((array_key_exists('xchan_pubforum',$arr)) ? intval($arr['xchan_pubforum']) : 0),
+ 'xchan_deleted' => ((array_key_exists('xchan_deleted',$arr)) ? intval($arr['xchan_deleted']) : 0)
+ ];
+
+ return create_table_from_array('xchan',$store);
+}
+
+
+
+function xchan_store($arr) {
+
+ logger('xchan_store: ' . print_r($arr,true));
+
+ if(! $arr['hash'])
+ $arr['hash'] = $arr['guid'];
+ if(! $arr['hash'])
+ return false;
+
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($arr['hash'])
+ );
+ if($r)
+ return true;
+
+ if(! $arr['network'])
+ $arr['network'] = 'unknown';
+ if(! $arr['name'])
+ $arr['name'] = 'unknown';
+ if(! $arr['url'])
+ $arr['url'] = z_root();
+ if(! $arr['photo'])
+ $arr['photo'] = z_root() . '/' . get_default_profile_photo();
+
+
+ if($arr['network'] === 'zot') {
+ if((! $arr['key']) || (! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key']))) {
+ logger('Unable to verify signature for ' . $arr['hash']);
+ return false;
+ }
+ }
+
+ $x = [];
+ foreach($arr as $k => $v) {
+ if($k === 'key') {
+ $x['xchan_pubkey'] = $v;
+ continue;
+ }
+ if($k === 'photo') {
+ continue;
+ }
+
+ $x['xchan_' . $k] = $v;
+ }
+
+ $x['xchan_name_date'] = datetime_convert();
+
+ $r = xchan_store_lowlevel($x);
+
+ if(! $r)
+ return $r;
+
+ $photos = import_xchan_photo($arr['photo'],$arr['hash']);
+ $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'",
+ dbesc(datetime_convert()),
+ dbesc($photos[0]),
+ dbesc($photos[1]),
+ dbesc($photos[2]),
+ dbesc($photos[3]),
+ dbesc($arr['hash'])
+ );
+ return $r;
+
+}
+
+
+function xchan_fetch($arr) {
+
+ $key = '';
+ if($arr['hash']) {
+ $key = 'xchan_hash';
+ $v = $arr['hash'];
+ }
+ elseif($arr['guid']) {
+ $key = 'xchan_guid';
+ $v = $arr['guid'];
+ }
+ elseif($arr['address']) {
+ $key = 'xchan_addr';
+ $v = $arr['address'];
+ }
+
+ if(! $key)
+ return false;
+
+ $r = q("select * from xchan where $key = '$v' limit 1");
+ if(! $r)
+ return false;
+
+ $ret = array();
+ foreach($r[0] as $k => $v) {
+ if($k === 'xchan_addr')
+ $ret['address'] = $v;
+ else
+ $ret[str_replace('xchan_','',$k)] = $v;
+ }
+ return $ret;
+}
+
+
diff --git a/include/zid.php b/include/zid.php
index ac6433e4c..f5df1c611 100644
--- a/include/zid.php
+++ b/include/zid.php
@@ -170,7 +170,7 @@ function zidify_text($s) {
* @return string
*/
function red_zrl_callback($matches) {
- require_once('include/hubloc.php');
+
$zrl = is_matrix_url($matches[2]);
$t = strip_zids($matches[2]);
@@ -215,7 +215,7 @@ function red_unescape_codeblock($m) {
function red_zrlify_img_callback($matches) {
- require_once('include/hubloc.php');
+
$zrl = is_matrix_url($matches[2]);
$t = strip_zids($matches[2]);
diff --git a/include/zot.php b/include/zot.php
index d4e75fe91..9fa2f98a8 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -10,7 +10,6 @@
require_once('include/crypto.php');
require_once('include/items.php');
-require_once('include/hubloc.php');
require_once('include/queue_fn.php');
require_once('include/perm_upgrade.php');
@@ -169,6 +168,11 @@ function zot_best_algorithm($methods) {
if(\Zotlabs\Lib\System::get_server_role() !== 'pro')
return 'aes256cbc';
+ $x = [ 'methods' => $methods, 'result' => '' ];
+ call_hooks('zot_best_algorithm',$x);
+ if($x['result'])
+ return $x['result'];
+
if($methods) {
$x = explode(',',$methods);
if($x) {
@@ -413,28 +417,12 @@ function zot_refresh($them, $channel = null, $force = false) {
}
else {
- // new connection
-
- $my_perms = null;
- $automatic = false;
+ $p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
- $role = get_pconfig($channel['channel_id'],'system','permissions_role');
- if($role) {
- $xx = \Zotlabs\Access\PermissionRoles::role_perms($role);
- if($xx['perms_auto']) {
- $automatic = true;
- $default_perms = $xx['perms_connect'];
- $my_perms = \Zotlabs\Access\Permissions::FilledPerms($default_perms);
- }
- }
+ $my_perms = $p['perms'];
+ $automatic = $p['automatic'];
- if(! $my_perms) {
- $m = \Zotlabs\Access\Permissions::FilledAutoperms($channel['channel_id']);
- if($m) {
- $automatic = true;
- $my_perms = $m;
- }
- }
+ // new connection
if($my_perms) {
foreach($my_perms as $k => $v) {
@@ -446,15 +434,17 @@ function zot_refresh($them, $channel = null, $force = false) {
if($closeness === false)
$closeness = 80;
- $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_created, abook_updated, abook_dob, abook_pending ) values ( %d, %d, %d, '%s', '%s', '%s', '%s', %d )",
- intval($channel['channel_account_id']),
- intval($channel['channel_id']),
- intval($closeness),
- dbesc($x['hash']),
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- dbesc($next_birthday),
- intval(($automatic) ? 0 : 1)
+ $y = abook_store_lowlevel(
+ [
+ 'abook_account' => intval($channel['channel_account_id']),
+ 'abook_channel' => intval($channel['channel_id']),
+ 'abook_closeness' => intval($closeness),
+ 'abook_xchan' => $x['hash'],
+ 'abook_created' => datetime_convert(),
+ 'abook_updated' => datetime_convert(),
+ 'abook_dob' => $next_birthday,
+ 'abook_pending' => intval(($automatic) ? 0 : 1)
+ ]
);
if($y) {
@@ -563,7 +553,7 @@ function zot_gethub($arr, $multiple = false) {
}
logger('zot_gethub: not found: ' . print_r($arr,true), LOGGER_DEBUG);
- return null;
+ return false;
}
/**
@@ -754,28 +744,28 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
&& ($arr['site']['url'] != z_root()))
$arr['searchable'] = false;
- $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_hidden, xchan_selfcensored, xchan_deleted, xchan_pubforum )
- values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d) ",
- dbesc($xchan_hash),
- dbesc($arr['guid']),
- dbesc($arr['guid_sig']),
- dbesc($arr['key']),
- dbesc($arr['photo_mimetype']),
- dbesc($arr['photo']),
- dbesc($arr['address']),
- dbesc($arr['url']),
- dbesc($arr['connections_url']),
- dbesc($arr['follow_url']),
- dbesc($arr['connect_url']),
- dbesc(($arr['name']) ? $arr['name'] : '-'),
- dbesc('zot'),
- dbescdate($arr['photo_updated']),
- dbescdate($arr['name_updated']),
- intval(1 - intval($arr['searchable'])),
- intval($arr['adult_content']),
- intval($arr['deleted']),
- intval($arr['public_forum'])
+ $x = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $xchan_hash,
+ 'xchan_guid' => $arr['guid'],
+ 'xchan_guid_sig' => $arr['guid_sig'],
+ 'xchan_pubkey' => $arr['key'],
+ 'xchan_photo_mimetype' => $arr['photo_mimetype'],
+ 'xchan_photo_l' => $arr['photo'],
+ 'xchan_addr' => $arr['address'],
+ 'xchan_url' => $arr['url'],
+ 'xchan_connurl' => $arr['connections_url'],
+ 'xchan_follow' => $arr['follow_url'],
+ 'xchan_connpage' => $arr['connect_url'],
+ 'xchan_name' => (($arr['name']) ? $arr['name'] : '-'),
+ 'xchan_network' => 'zot',
+ 'xchan_photo_date' => $arr['photo_updated'],
+ 'xchan_name_date' => $arr['name_updated'],
+ 'xchan_hidden' => intval(1 - intval($arr['searchable'])),
+ 'xchan_selfcensored' => $arr['adult_content'],
+ 'xchan_deleted' => $arr['deleted'],
+ 'xchan_pubforum' => $arr['public_forum']
+ ]
);
$what .= 'new_xchan';
@@ -1946,6 +1936,7 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) {
return;
}
+
$x = item_store_update($item);
// If we're updating an event that we've saved locally, we store the item info first
@@ -2463,22 +2454,25 @@ function sync_locations($sender, $arr, $absolute = false) {
);
}
logger('sync_locations: new hub: ' . $location['url']);
- $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_primary, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_updated, hubloc_connected)
- values ( '%s','%s','%s','%s', '%s', %d ,'%s','%s','%s','%s','%s','%s','%s')",
- dbesc($sender['guid']),
- dbesc($sender['guid_sig']),
- dbesc($sender['hash']),
- dbesc($location['address']),
- dbesc('zot'),
- intval($location['primary']),
- dbesc($location['url']),
- dbesc($location['url_sig']),
- dbesc($location['host']),
- dbesc($location['callback']),
- dbesc($location['sitekey']),
- dbesc(datetime_convert()),
- dbesc(datetime_convert())
+
+ $r = hubloc_store_lowlevel(
+ [
+ 'hubloc_guid' => $sender['guid'],
+ 'hubloc_guid_sig' => $sender['guid_sig'],
+ 'hubloc_hash' => $sender['hash'],
+ 'hubloc_addr' => $location['address'],
+ 'hubloc_network' => 'zot',
+ 'hubloc_primary' => $location['primary'],
+ 'hubloc_url' => $location['url'],
+ 'hubloc_url_sig' => $location['url_sig'],
+ 'hubloc_host' => $location['host'],
+ 'hubloc_callback' => $location['callback'],
+ 'hubloc_sitekey' => $location['sitekey'],
+ 'hubloc_updated' => datetime_convert(),
+ 'hubloc_connected' => datetime_convert()
+ ]
);
+
$what .= 'newhub ';
$changed = true;
@@ -3168,8 +3162,11 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('menu',$arr) && $arr['menu'])
sync_menus($channel,$arr['menu']);
- if(array_key_exists('file',$arr) && $arr['file'])
- sync_files($channel,$arr['file']);
+ if(array_key_exists('menu',$arr) && $arr['menu'])
+ sync_menus($channel,$arr['menu']);
+
+ if(array_key_exists('wiki',$arr) && $arr['wiki'])
+ sync_items($channel,$arr['wiki'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) {
@@ -3312,10 +3309,12 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
logger('process_channel_sync_delivery: total_feeds service class limit exceeded');
continue;
}
- q("insert into abook ( abook_xchan, abook_account, abook_channel ) values ('%s', %d, %d ) ",
- dbesc($clean['abook_xchan']),
- intval($channel['channel_account_id']),
- intval($channel['channel_id'])
+ abook_store_lowlevel(
+ [
+ 'abook_xchan' => $clean['abook_xchan'],
+ 'abook_account' => $channel['channel_account_id'],
+ 'abook_channel' => $channel['channel_id']
+ ]
);
$total_friends ++;
if(intval($clean['abook_feed']))
@@ -4048,21 +4047,24 @@ function check_zotinfo($channel,$locations,&$ret) {
q("delete from hubloc where hubloc_hash = '%s'",
dbesc($channel['channel_hash'])
);
- $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary,
- hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )
- values ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
- dbesc($channel['channel_guid']),
- dbesc($channel['channel_guid_sig']),
- dbesc($channel['channel_hash']),
- dbesc(channel_reddress($channel)),
- intval(1),
- dbesc(z_root()),
- dbesc(base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey']))),
- dbesc(App::get_hostname()),
- dbesc(z_root() . '/post'),
- dbesc(get_config('system','pubkey')),
- dbesc('zot')
+
+ $r = hubloc_store_lowlevel(
+ [
+ 'hubloc_guid' => $channel['channel_guid'],
+ 'hubloc_guid_sig' => $channel['channel_guid_sig'],
+ 'hubloc_hash' => $channel['channel_hash'],
+ 'hubloc_addr' => channel_reddress($channel),
+ 'hubloc_network' => 'zot',
+ 'hubloc_primary' => 1,
+ 'hubloc_url' => z_root(),
+ 'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
+ 'hubloc_host' => App::get_hostname(),
+ 'hubloc_callback' => z_root() . '/post',
+ 'hubloc_sitekey' => get_config('system','pubkey'),
+ 'hubloc_updated' => datetime_convert(),
+ ]
);
+
if($r) {
$x = zot_encode_locations($channel);
if($x) {