aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Access/PermissionLimits.php2
-rw-r--r--Zotlabs/Access/PermissionRoles.php79
-rw-r--r--Zotlabs/Access/Permissions.php39
-rw-r--r--Zotlabs/Daemon/Channel_purge.php34
-rw-r--r--Zotlabs/Daemon/Content_importer.php77
-rw-r--r--Zotlabs/Daemon/Cron.php18
-rw-r--r--Zotlabs/Daemon/Cron_daily.php2
-rw-r--r--Zotlabs/Daemon/Deliver.php4
-rw-r--r--Zotlabs/Daemon/Delxitems.php25
-rw-r--r--Zotlabs/Daemon/Directory.php9
-rw-r--r--Zotlabs/Daemon/Expire.php1
-rw-r--r--Zotlabs/Daemon/Externals.php193
-rw-r--r--Zotlabs/Daemon/File_importer.php71
-rw-r--r--Zotlabs/Daemon/Gprobe.php28
-rw-r--r--Zotlabs/Daemon/Notifier.php672
-rw-r--r--Zotlabs/Daemon/Onedirsync.php14
-rw-r--r--Zotlabs/Daemon/Onepoll.php62
-rw-r--r--Zotlabs/Daemon/Poller.php11
-rw-r--r--Zotlabs/Daemon/Queue.php17
-rw-r--r--Zotlabs/Daemon/Ratenotif.php126
-rw-r--r--Zotlabs/Daemon/Thumbnail.php1
-rw-r--r--Zotlabs/Lib/AccessList.php236
-rw-r--r--Zotlabs/Lib/Activity.php1041
-rw-r--r--Zotlabs/Lib/ActivityStreams.php41
-rw-r--r--Zotlabs/Lib/Apps.php179
-rw-r--r--Zotlabs/Lib/Connect.php7
-rw-r--r--Zotlabs/Lib/Crypto.php4
-rw-r--r--Zotlabs/Lib/DReport.php3
-rw-r--r--Zotlabs/Lib/Enotify.php145
-rw-r--r--Zotlabs/Lib/Group.php405
-rw-r--r--Zotlabs/Lib/LDSignatures.php11
-rw-r--r--Zotlabs/Lib/Libsync.php110
-rw-r--r--Zotlabs/Lib/Libzot.php429
-rw-r--r--Zotlabs/Lib/Libzotdir.php48
-rw-r--r--Zotlabs/Lib/MessageFilter.php216
-rw-r--r--Zotlabs/Lib/NativeWiki.php48
-rw-r--r--Zotlabs/Lib/NativeWikiPage.php579
-rw-r--r--Zotlabs/Lib/PConfig.php85
-rw-r--r--Zotlabs/Lib/Permcat.php173
-rw-r--r--Zotlabs/Lib/Queue.php94
-rw-r--r--Zotlabs/Lib/Share.php42
-rw-r--r--Zotlabs/Lib/ThreadItem.php54
-rw-r--r--Zotlabs/Lib/ThreadStream.php8
-rw-r--r--Zotlabs/Lib/ZotURL.php2
-rw-r--r--Zotlabs/Lib/Zotfinger.php26
-rw-r--r--Zotlabs/Module/Acl.php15
-rw-r--r--Zotlabs/Module/Admin.php1
-rw-r--r--Zotlabs/Module/Admin/Queue.php40
-rw-r--r--Zotlabs/Module/Admin/Site.php13
-rw-r--r--Zotlabs/Module/Affinity.php11
-rw-r--r--Zotlabs/Module/Album.php103
-rw-r--r--Zotlabs/Module/Appman.php138
-rw-r--r--Zotlabs/Module/Apps.php14
-rw-r--r--Zotlabs/Module/Apschema.php7
-rw-r--r--Zotlabs/Module/Article_edit.php3
-rw-r--r--Zotlabs/Module/Articles.php6
-rw-r--r--Zotlabs/Module/Authtest.php31
-rw-r--r--Zotlabs/Module/Bookmarks.php64
-rw-r--r--Zotlabs/Module/Cards.php6
-rw-r--r--Zotlabs/Module/Cdav.php7
-rw-r--r--Zotlabs/Module/Channel.php59
-rw-r--r--Zotlabs/Module/Chanview.php58
-rw-r--r--Zotlabs/Module/Chat.php110
-rw-r--r--Zotlabs/Module/Connections.php132
-rw-r--r--Zotlabs/Module/Connedit.php810
-rw-r--r--Zotlabs/Module/Contactedit.php675
-rw-r--r--Zotlabs/Module/Contactgroup.php26
-rw-r--r--Zotlabs/Module/Defperms.php127
-rw-r--r--Zotlabs/Module/Directory.php13
-rw-r--r--Zotlabs/Module/Dirsearch.php271
-rw-r--r--Zotlabs/Module/Display.php44
-rw-r--r--Zotlabs/Module/Dreport.php88
-rw-r--r--Zotlabs/Module/Events.php750
-rw-r--r--Zotlabs/Module/Fhublocs.php18
-rw-r--r--Zotlabs/Module/File_upload.php3
-rw-r--r--Zotlabs/Module/Follow.php4
-rw-r--r--Zotlabs/Module/Group.php178
-rw-r--r--Zotlabs/Module/Hcard.php38
-rw-r--r--Zotlabs/Module/Home.php2
-rw-r--r--Zotlabs/Module/Hq.php91
-rw-r--r--Zotlabs/Module/Impel.php71
-rw-r--r--Zotlabs/Module/Import.php490
-rw-r--r--Zotlabs/Module/Import_items.php207
-rw-r--r--Zotlabs/Module/Import_progress.php122
-rw-r--r--Zotlabs/Module/Invite.php22
-rw-r--r--Zotlabs/Module/Item.php1018
-rw-r--r--Zotlabs/Module/Lang.php58
-rw-r--r--Zotlabs/Module/Like.php6
-rw-r--r--Zotlabs/Module/Linkinfo.php193
-rw-r--r--Zotlabs/Module/Lockview.php218
-rw-r--r--Zotlabs/Module/Locs.php18
-rw-r--r--Zotlabs/Module/Manage.php19
-rw-r--r--Zotlabs/Module/Manifest.php55
-rw-r--r--Zotlabs/Module/Message.php108
-rw-r--r--Zotlabs/Module/Mood.php86
-rw-r--r--Zotlabs/Module/Network.php178
-rw-r--r--Zotlabs/Module/New_channel.php14
-rw-r--r--Zotlabs/Module/Notes.php20
-rw-r--r--Zotlabs/Module/Notifications.php50
-rw-r--r--Zotlabs/Module/Notify.php54
-rw-r--r--Zotlabs/Module/Oauth.php46
-rw-r--r--Zotlabs/Module/Oauth2.php44
-rw-r--r--Zotlabs/Module/Oep.php51
-rw-r--r--Zotlabs/Module/Outbox.php124
-rw-r--r--Zotlabs/Module/Owa.php4
-rw-r--r--Zotlabs/Module/Pdledit.php26
-rw-r--r--Zotlabs/Module/Pdledit_gui.php553
-rw-r--r--Zotlabs/Module/Permcats.php287
-rw-r--r--Zotlabs/Module/Photo.php118
-rw-r--r--Zotlabs/Module/Photos.php12
-rw-r--r--Zotlabs/Module/Pin.php2
-rw-r--r--Zotlabs/Module/Ping.php707
-rw-r--r--Zotlabs/Module/Poke.php96
-rw-r--r--Zotlabs/Module/Post.php34
-rw-r--r--Zotlabs/Module/Prate.php107
-rw-r--r--Zotlabs/Module/Probe.php60
-rw-r--r--Zotlabs/Module/Profile_photo.php727
-rw-r--r--Zotlabs/Module/Profiles.php176
-rw-r--r--Zotlabs/Module/Pubsites.php1
-rw-r--r--Zotlabs/Module/Pubstream.php97
-rw-r--r--Zotlabs/Module/Randprof.php10
-rw-r--r--Zotlabs/Module/Rate.php174
-rw-r--r--Zotlabs/Module/Ratings.php109
-rw-r--r--Zotlabs/Module/Ratingsearch.php78
-rw-r--r--Zotlabs/Module/Rbmark.php67
-rw-r--r--Zotlabs/Module/Regate.php20
-rw-r--r--Zotlabs/Module/Removeme.php50
-rw-r--r--Zotlabs/Module/Rpost.php72
-rw-r--r--Zotlabs/Module/Search.php60
-rw-r--r--Zotlabs/Module/Settings.php45
-rw-r--r--Zotlabs/Module/Settings/Calendar.php10
-rw-r--r--Zotlabs/Module/Settings/Channel.php752
-rw-r--r--Zotlabs/Module/Settings/Channel_home.php10
-rw-r--r--Zotlabs/Module/Settings/Connections.php10
-rw-r--r--Zotlabs/Module/Settings/Directory.php10
-rw-r--r--Zotlabs/Module/Settings/Display.php3
-rw-r--r--Zotlabs/Module/Settings/Editor.php10
-rw-r--r--Zotlabs/Module/Settings/Events.php10
-rw-r--r--Zotlabs/Module/Settings/Manage.php10
-rw-r--r--Zotlabs/Module/Settings/Network.php8
-rw-r--r--Zotlabs/Module/Settings/Photos.php12
-rw-r--r--Zotlabs/Module/Settings/Privacy.php127
-rw-r--r--Zotlabs/Module/Settings/Profiles.php12
-rw-r--r--Zotlabs/Module/Setup.php14
-rw-r--r--Zotlabs/Module/Sources.php56
-rw-r--r--Zotlabs/Module/Sse.php13
-rw-r--r--Zotlabs/Module/Sse_bs.php46
-rw-r--r--Zotlabs/Module/Suggest.php6
-rw-r--r--Zotlabs/Module/Tokens.php263
-rw-r--r--Zotlabs/Module/Uexport.php202
-rw-r--r--Zotlabs/Module/Viewconnections.php44
-rw-r--r--Zotlabs/Module/Vote.php13
-rw-r--r--Zotlabs/Module/Webpages.php203
-rw-r--r--Zotlabs/Module/Well_known.php36
-rw-r--r--Zotlabs/Module/Wfinger.php67
-rw-r--r--Zotlabs/Module/Wiki.php146
-rw-r--r--Zotlabs/Module/Xrd.php27
-rw-r--r--Zotlabs/Module/Zfinger.php43
-rw-r--r--Zotlabs/Module/Zotfeed.php116
-rw-r--r--Zotlabs/Module/Zping.php33
-rw-r--r--Zotlabs/Photo/PhotoDriver.php10
-rw-r--r--Zotlabs/Render/Comanche.php5
-rw-r--r--Zotlabs/Render/Theme.php4
-rw-r--r--Zotlabs/Update/_1246.php24
-rw-r--r--Zotlabs/Update/_1247.php23
-rw-r--r--Zotlabs/Update/_1248.php27
-rw-r--r--Zotlabs/Update/_1249.php31
-rw-r--r--Zotlabs/Update/_1250.php31
-rw-r--r--Zotlabs/Update/_1251.php23
-rw-r--r--Zotlabs/Update/_1252.php23
-rw-r--r--Zotlabs/Web/HTTPSig.php429
-rw-r--r--Zotlabs/Web/HttpMeta.php109
-rw-r--r--Zotlabs/Web/Session.php75
-rw-r--r--Zotlabs/Web/SessionHandler.php18
-rw-r--r--Zotlabs/Web/WebServer.php3
-rw-r--r--Zotlabs/Widget/Activity.php15
-rw-r--r--Zotlabs/Widget/Activity_filter.php7
-rw-r--r--Zotlabs/Widget/Activity_order.php8
-rw-r--r--Zotlabs/Widget/Admin.php5
-rw-r--r--Zotlabs/Widget/Affinity.php12
-rw-r--r--Zotlabs/Widget/Album.php8
-rw-r--r--Zotlabs/Widget/Appcategories.php8
-rw-r--r--Zotlabs/Widget/Appcloud.php6
-rw-r--r--Zotlabs/Widget/Appstore.php13
-rw-r--r--Zotlabs/Widget/Archive.php6
-rw-r--r--Zotlabs/Widget/Bookmarkedchats.php9
-rw-r--r--Zotlabs/Widget/Catcloud.php9
-rw-r--r--Zotlabs/Widget/Catcloud_wall.php6
-rw-r--r--Zotlabs/Widget/Categories.php6
-rw-r--r--Zotlabs/Widget/Cdav.php10
-rw-r--r--Zotlabs/Widget/Chatroom_list.php6
-rw-r--r--Zotlabs/Widget/Chatroom_members.php6
-rw-r--r--Zotlabs/Widget/Clock.php5
-rw-r--r--Zotlabs/Widget/Collections.php54
-rw-r--r--Zotlabs/Widget/Common_friends.php8
-rw-r--r--Zotlabs/Widget/Conversations.php76
-rw-r--r--Zotlabs/Widget/Cover_photo.php6
-rw-r--r--Zotlabs/Widget/Design_tools.php8
-rw-r--r--Zotlabs/Widget/Dirsort.php6
-rw-r--r--Zotlabs/Widget/Dirtags.php8
-rw-r--r--Zotlabs/Widget/Eventstools.php19
-rw-r--r--Zotlabs/Widget/Filer.php7
-rw-r--r--Zotlabs/Widget/Findpeople.php5
-rw-r--r--Zotlabs/Widget/Follow.php7
-rw-r--r--Zotlabs/Widget/Forums.php41
-rw-r--r--Zotlabs/Widget/Fullprofile.php8
-rw-r--r--Zotlabs/Widget/Helpindex.php7
-rw-r--r--Zotlabs/Widget/Hq_controls.php46
-rw-r--r--Zotlabs/Widget/Item.php8
-rw-r--r--Zotlabs/Widget/Mailmenu.php36
-rw-r--r--Zotlabs/Widget/Menu_preview.php6
-rw-r--r--Zotlabs/Widget/Messages.php251
-rw-r--r--Zotlabs/Widget/Newmember.php9
-rw-r--r--Zotlabs/Widget/Notes.php23
-rw-r--r--Zotlabs/Widget/Notifications.php61
-rw-r--r--Zotlabs/Widget/Permcats.php103
-rw-r--r--Zotlabs/Widget/Photo.php6
-rw-r--r--Zotlabs/Widget/Photo_albums.php6
-rw-r--r--Zotlabs/Widget/Photo_rand.php11
-rw-r--r--Zotlabs/Widget/Pinned.php67
-rw-r--r--Zotlabs/Widget/Portfolio.php10
-rw-r--r--Zotlabs/Widget/Privacygroups.php62
-rw-r--r--Zotlabs/Widget/Profile.php19
-rw-r--r--Zotlabs/Widget/Pubsites.php16
-rw-r--r--Zotlabs/Widget/Pubtagcloud.php5
-rw-r--r--Zotlabs/Widget/Random_block.php5
-rw-r--r--Zotlabs/Widget/Rating.php6
-rw-r--r--Zotlabs/Widget/Savedsearch.php6
-rw-r--r--Zotlabs/Widget/Settings_menu.php10
-rw-r--r--Zotlabs/Widget/Shortprofile.php18
-rw-r--r--Zotlabs/Widget/Sitesearch.php6
-rw-r--r--Zotlabs/Widget/Suggestedchats.php10
-rw-r--r--Zotlabs/Widget/Suggestions.php13
-rw-r--r--Zotlabs/Widget/Tagcloud.php5
-rw-r--r--Zotlabs/Widget/Tagcloud_wall.php6
-rw-r--r--Zotlabs/Widget/Tasklist.php9
-rw-r--r--Zotlabs/Widget/Tokens.php57
-rw-r--r--Zotlabs/Widget/Vcard.php5
-rw-r--r--Zotlabs/Widget/Website_portation_tools.php7
-rw-r--r--Zotlabs/Widget/Wiki_list.php5
-rw-r--r--Zotlabs/Widget/Wiki_page_history.php8
-rw-r--r--Zotlabs/Widget/Wiki_pages.php10
-rw-r--r--Zotlabs/Widget/Zcard.php5
-rw-r--r--Zotlabs/Zot/Auth.php363
-rw-r--r--Zotlabs/Zot/Finger.php155
-rw-r--r--Zotlabs/Zot/IHandler.php24
-rw-r--r--Zotlabs/Zot/Receiver.php304
-rw-r--r--Zotlabs/Zot/ZotHandler.php39
-rw-r--r--Zotlabs/Zot6/Finger.php145
-rw-r--r--Zotlabs/Zot6/IHandler.php10
-rw-r--r--Zotlabs/Zot6/Receiver.php18
-rw-r--r--Zotlabs/Zot6/Zot6Handler.php103
252 files changed, 10953 insertions, 11087 deletions
diff --git a/Zotlabs/Access/PermissionLimits.php b/Zotlabs/Access/PermissionLimits.php
index fb5fe6133..7a574ba6a 100644
--- a/Zotlabs/Access/PermissionLimits.php
+++ b/Zotlabs/Access/PermissionLimits.php
@@ -89,4 +89,4 @@ class PermissionLimits {
return false;
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Access/PermissionRoles.php b/Zotlabs/Access/PermissionRoles.php
index 998b6d8d2..2078b52a8 100644
--- a/Zotlabs/Access/PermissionRoles.php
+++ b/Zotlabs/Access/PermissionRoles.php
@@ -17,7 +17,7 @@ class PermissionRoles {
* @return number
*/
static public function version() {
- return 2;
+ return 3;
}
static function role_perms($role) {
@@ -27,6 +27,54 @@ class PermissionRoles {
$ret['role'] = $role;
switch($role) {
+
+ case 'public':
+ $ret['default_collection'] = false;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'post_wall', 'chat', 'post_like', 'republish'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['limits']['post_comments'] = PERMS_AUTHED;
+ $ret['limits']['post_mail'] = PERMS_AUTHED;
+ $ret['limits']['post_like'] = PERMS_AUTHED;
+ $ret['limits']['chat'] = PERMS_AUTHED;
+ break;
+
+ // Hubzilla default role
+ case 'personal':
+ $ret['default_collection'] = true;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['limits']['view_contacts'] = PERMS_SPECIFIC;
+ break;
+
+ case 'group':
+ $ret['default_collection'] = false;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'view_wiki', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like', 'chat'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['channel_type'] = 'group';
+ break;
+
+ // Provide some defaults for the custom role so that we do not start
+ // with no permissions at all if we create a new channel with this role
+ case 'custom':
+ $ret['default_collection'] = true;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ break;
+
+/*
case 'social':
$ret['perms_auto'] = false;
$ret['default_collection'] = false;
@@ -193,13 +241,14 @@ class PermissionRoles {
$ret['channel_type'] = 'group';
break;
+*/
- case 'custom':
default:
break;
}
$x = get_config('system','role_perms');
+
// let system settings over-ride any or all
if($x && is_array($x) && array_key_exists($role,$x))
$ret = array_merge($ret,$x[$role]);
@@ -284,6 +333,7 @@ class PermissionRoles {
*/
static public function roles() {
$roles = [
+
t('Social Networking') => [
'social_federation' => t('Social - Federation'),
'social' => t('Social - Mostly Public'),
@@ -317,4 +367,29 @@ class PermissionRoles {
return $roles;
}
+ /**
+ * @brief Array with translated role names and grouping.
+ *
+ * Return an associative array with role names that can be used
+ * to create select groups like in \e field_select_grouped.tpl.
+ *
+ * @return array
+ */
+ static public function channel_roles() {
+ $channel_roles = [
+ //'public' => [t('Public'), t('A very permissive role suited for participation in the fediverse')],
+ //'personal' => [t('Personal'), t('The $Projectname default role suited for a personal channel')],
+ //'forum' => [t('Community forum'), t('This role configures your channel to act as an community forum')],
+ //'custom' => [t('Custom'), t('This role comes with the presets of the personal role but allows you to configure it to your needs')]
+ 'public' => t('Public'),
+ 'personal' => t('Personal'),
+ 'group' => t('Community forum'),
+ 'custom' => t('Custom')
+ ];
+
+ call_hooks('list_channel_roles', $channel_roles);
+
+ return $channel_roles;
+ }
+
}
diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php
index df5472cc3..09f4c9678 100644
--- a/Zotlabs/Access/Permissions.php
+++ b/Zotlabs/Access/Permissions.php
@@ -41,7 +41,7 @@ class Permissions {
* @return number
*/
static public function version() {
- return 2;
+ return 3;
}
/**
@@ -65,11 +65,11 @@ class Permissions {
'write_wiki' => t('Can write to my wiki pages'),
'post_wall' => t('Can post on my channel (wall) page'),
'post_comments' => t('Can comment on or like my posts'),
- 'post_mail' => t('Can send me private mail messages'),
+ 'post_mail' => t('Can send me direct messages'),
'post_like' => t('Can like/dislike profiles and profile things'),
- 'tag_deliver' => t('Can forward to all my channel connections via ! mentions in posts'),
'chat' => t('Can chat with me'),
- 'republish' => t('Can source my public posts in derived channels'),
+ 'republish' => t('Can source/mirror my public posts in derived channels'),
+ //'tag_deliver' => t('Can forward to my contacts via direct messages (forum)'),
'delegate' => t('Can administer my channel')
];
@@ -217,25 +217,23 @@ class Permissions {
$my_perms = [];
$permcat = null;
- $automatic = 0;
+ $automatic = get_pconfig($channel_id, 'system', 'autoperms');
// If a default permcat exists, use that
- $pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
- if (!in_array($pc, ['', 'default'])) {
- $pcp = new Zlib\Permcat($channel_id);
- $permcat = $pcp->fetch($pc);
- if ($permcat && $permcat['perms']) {
- foreach ($permcat['perms'] as $p) {
- $my_perms[$p['name']] = $p['value'];
- }
+ $pc = get_pconfig($channel_id, 'system', 'default_permcat', 'default');
+ $pcp = new Zlib\Permcat($channel_id);
+ $permcat = $pcp->fetch($pc);
+ if ($permcat && $permcat['perms']) {
+ foreach ($permcat['perms'] as $p) {
+ $my_perms[$p['name']] = $p['value'];
}
}
// look up the permission role to see if it specified auto-connect
// and if there was no permcat or a default permcat, set the perms
// from the role
-
+/*
$role = get_pconfig($channel_id, 'system', 'permissions_role');
if ($role) {
$xx = PermissionRoles::role_perms($role);
@@ -247,11 +245,12 @@ class Permissions {
$my_perms = Permissions::FilledPerms($default_perms);
}
}
+*/
// If we reached this point without having any permission information,
// it is likely a custom permissions role. First see if there are any
// automatic permissions.
-
+/*
if (!$my_perms) {
$m = Permissions::FilledAutoperms($channel_id);
if ($m) {
@@ -259,11 +258,12 @@ class Permissions {
$my_perms = $m;
}
}
-
+*/
// If we reached this point with no permissions, the channel is using
// custom perms but they are not automatic. They will be stored in abconfig with
// the channel's channel_hash (the 'self' connection).
+/*
if (!$my_perms) {
$r = q("select channel_hash from channel where channel_id = %d",
intval($channel_id)
@@ -280,10 +280,10 @@ class Permissions {
}
}
}
-
- return (['perms' => $my_perms, 'automatic' => $automatic]);
+*/
+ return (['perms' => $my_perms, 'automatic' => $automatic, 'role' => $pc]);
}
-
+/*
static public function serialise($p) {
$n = [];
if ($p) {
@@ -295,4 +295,5 @@ class Permissions {
}
return implode(',', $n);
}
+*/
}
diff --git a/Zotlabs/Daemon/Channel_purge.php b/Zotlabs/Daemon/Channel_purge.php
new file mode 100644
index 000000000..9fceb0fb9
--- /dev/null
+++ b/Zotlabs/Daemon/Channel_purge.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Zotlabs\Daemon;
+
+class Channel_purge {
+
+ static public function run($argc,$argv) {
+
+ cli_startup();
+
+ $channel_id = intval($argv[1]);
+
+ $channel = q("select * from channel where channel_id = %d and channel_removed = 1",
+ intval($channel_id)
+ );
+
+ if (! $channel) {
+ return;
+ }
+
+ do {
+ $r = q("select id from item where uid = %d and item_deleted = 0 limit 1000",
+ intval($channel_id)
+ );
+ if ($r) {
+ foreach ($r as $rv) {
+ drop_item($rv['id'], false);
+ }
+ }
+ } while ($r);
+
+ return;
+ }
+}
diff --git a/Zotlabs/Daemon/Content_importer.php b/Zotlabs/Daemon/Content_importer.php
new file mode 100644
index 000000000..67f1c8e80
--- /dev/null
+++ b/Zotlabs/Daemon/Content_importer.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Zotlabs\Daemon;
+
+use Zotlabs\Web\HTTPSig;
+use Zotlabs\Lib\PConfig;
+
+
+require_once('include/cli_startup.php');
+require_once('include/attach.php');
+require_once('include/import.php');
+
+class Content_importer {
+
+ static public function run($argc,$argv) {
+ cli_startup();
+
+ $page = $argv[1];
+ $since = $argv[2];
+ $until = $argv[3];
+ $channel_address = $argv[4];
+ $hz_server = urldecode($argv[5]);
+
+ $m = parse_url($hz_server);
+
+ $channel = channelx_by_nick($channel_address);
+ if(! $channel) {
+ logger('channel not found');
+ return;
+ }
+
+ $headers = [
+ 'X-API-Token' => random_string(),
+ 'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
+ 'Host' => $m['host'],
+ '(request-target)' => 'get /api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
+ ];
+
+ $headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
+
+ $x = z_fetch_url($hz_server . '/api/z/1.0/item/export_page?f=&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,false,$redirects,[ 'headers' => $headers ]);
+
+ // logger('item fetch: ' . print_r($x,true));
+
+ if(! $x['success']) {
+ logger('no API response',LOGGER_DEBUG);
+ killme();
+ }
+
+ $j = json_decode($x['body'],true);
+
+ if(! is_array($j['item']) || ! count($j['item'])) {
+ PConfig::Set($channel['channel_id'], 'import', 'content_completed', 1);
+ return;
+ }
+
+ $saved_notification_flags = notifications_off($channel['channel_id']);
+
+ import_items($channel,$j['item'],false,((array_key_exists('relocate',$j)) ? $j['relocate'] : null));
+
+ notifications_on($channel['channel_id'], $saved_notification_flags);
+
+ PConfig::Set($channel['channel_id'], 'import', 'content_progress', [
+ 'items_total' => $j['items_total'],
+ 'items_page' => $j['items_page'],
+ 'items_current_page' => count($j['item']),
+ 'last_page' => $page,
+ 'next_cmd' => ['Content_importer', sprintf('%d',$page + 1), $since, $until, $channel['channel_address'], urlencode($hz_server)]
+ ]);
+
+ $page++;
+
+ Master::Summon([ 'Content_importer', sprintf('%d',$page), $since, $until, $channel['channel_address'], urlencode($hz_server) ]);
+
+ return;
+ }
+}
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index 5c0330806..6629491de 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -36,7 +36,6 @@ class Cron {
// run queue delivery process in the background
Master::Summon(array('Queue'));
-
Master::Summon(array('Poller'));
/**
@@ -48,13 +47,6 @@ class Cron {
db_quoteinterval('3 MINUTE')
);
- // expire any expired mail
-
- q("delete from mail where expires > '%s' and expires < %s ",
- dbesc(NULL_DATE),
- db_utcnow()
- );
-
require_once('include/account.php');
remove_expired_registrations();
@@ -165,11 +157,6 @@ class Cron {
}
}
-
- // check if any connections transitioned to zot6 and upgrade the connections to zot6 at this hub if so.
- require_once('include/connections.php');
- z6trans_connections();
-
require_once('include/attach.php');
attach_upgrade();
@@ -218,10 +205,9 @@ class Cron {
// pull in some public posts
-/* $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
+ $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
if (!$disable_discover_tab)
- Master::Summon(array('Externals'));
-*/
+ Master::Summon(['Externals']);
$restart = false;
diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php
index bebccca9d..d1b74a032 100644
--- a/Zotlabs/Daemon/Cron_daily.php
+++ b/Zotlabs/Daemon/Cron_daily.php
@@ -95,8 +95,6 @@ class Cron_daily {
remove_obsolete_hublocs();
remove_duplicate_singleton_hublocs();
- z6_discover();
-
$date = datetime_convert();
call_hooks('cron_daily', $date);
diff --git a/Zotlabs/Daemon/Deliver.php b/Zotlabs/Daemon/Deliver.php
index f8149ee69..400ef697b 100644
--- a/Zotlabs/Daemon/Deliver.php
+++ b/Zotlabs/Daemon/Deliver.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Daemon;
-require_once('include/queue_fn.php');
+use Zotlabs\Lib\Queue;
class Deliver {
@@ -23,7 +23,7 @@ class Deliver {
);
if ($r) {
- queue_deliver($r[0], true);
+ Queue::deliver($r[0], true);
}
}
diff --git a/Zotlabs/Daemon/Delxitems.php b/Zotlabs/Daemon/Delxitems.php
new file mode 100644
index 000000000..264354ca0
--- /dev/null
+++ b/Zotlabs/Daemon/Delxitems.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Zotlabs\Daemon;
+
+require_once('include/connections.php');
+
+/*
+ * Daemon to remove 'item' resources in the background from a removed connection
+ */
+
+class Delxitems {
+
+ static public function run($argc, $argv) {
+
+ cli_startup();
+
+ if($argc != 3) {
+ return;
+ }
+
+ remove_abook_items($argv[1], $argv[2]);
+
+ return;
+ }
+}
diff --git a/Zotlabs/Daemon/Directory.php b/Zotlabs/Daemon/Directory.php
index 1f307b273..3996b8079 100644
--- a/Zotlabs/Daemon/Directory.php
+++ b/Zotlabs/Daemon/Directory.php
@@ -49,8 +49,9 @@ class Directory {
);
// Now update all the connections
- if ($pushall)
+ if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
+ }
return;
}
@@ -74,7 +75,7 @@ class Directory {
* the directory packet. That means we'll try again on the next poll run.
*/
- $hash = random_string();
+ $hash = new_uuid();
Queue::insert(array(
'hash' => $hash,
@@ -93,8 +94,8 @@ class Directory {
}
// Now update all the connections
- if ($pushall)
+ if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
-
+ }
}
}
diff --git a/Zotlabs/Daemon/Expire.php b/Zotlabs/Daemon/Expire.php
index c4ff8aec6..99fe68b6f 100644
--- a/Zotlabs/Daemon/Expire.php
+++ b/Zotlabs/Daemon/Expire.php
@@ -2,6 +2,7 @@
namespace Zotlabs\Daemon;
+require_once('include/items.php');
class Expire {
diff --git a/Zotlabs/Daemon/Externals.php b/Zotlabs/Daemon/Externals.php
index 064b3f71d..fb35a65c7 100644
--- a/Zotlabs/Daemon/Externals.php
+++ b/Zotlabs/Daemon/Externals.php
@@ -3,6 +3,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\ASCollection;
@@ -31,25 +32,55 @@ class Externals {
$url = $arr['url'];
}
else {
+ $networks = ['zot6'];
+
+ if (plugin_is_installed('pubcrawl')) {
+ $networks[] = 'activitypub';
+ }
+
+ stringify_array_elms($networks);
+ $networks_str = implode(',', $networks);
+
$randfunc = db_getfunc('RAND');
// fixme this query does not deal with directory realms.
-
- $r = q("select site_url, site_pull from site where site_url != '%s'
- and site_flags != %d and site_type = %d
- and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
+ //$r = q("select site_url, site_pull from site where site_url != '%s'
+ //and site_flags != %d and site_type = %d
+ //and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1",
+ //dbesc(z_root()),
+ //intval(DIRECTORY_MODE_STANDALONE),
+ //intval(SITE_TYPE_ZOT),
+ //dbesc('hubzilla%')
+ //);
+
+ $r = q("SELECT * FROM hubloc
+ LEFT JOIN abook ON abook_xchan = hubloc_hash
+ LEFT JOIN site ON site_url = hubloc_url WHERE
+ hubloc_network IN ( $networks_str ) AND
+ abook_xchan IS NULL AND
+ hubloc_url != '%s' AND
+ hubloc_updated > '%s' AND
+ hubloc_primary = 1 AND hubloc_deleted = 0 AND
+ site_dead = 0
+ ORDER BY $randfunc LIMIT 1",
dbesc(z_root()),
- intval(DIRECTORY_MODE_STANDALONE),
- intval(SITE_TYPE_ZOT),
- dbesc('hubzilla%')
+ datetime_convert('UTC', 'UTC', 'now - 30 days')
);
- if ($r)
- $url = $r[0]['site_url'];
+
+ $contact = $r[0];
+
+ if ($contact) {
+ $url = $contact['hubloc_id_url'];
+ }
+ }
+
+ if (!$url) {
+ continue;
}
$blacklisted = false;
- if (!check_siteallowed($url)) {
+ if (!check_siteallowed($contact['hubloc_url'])) {
logger('blacklisted site: ' . $url);
$blacklisted = true;
}
@@ -59,123 +90,67 @@ class Externals {
// make sure we can eventually break out if somebody blacklists all known sites
if ($blacklisted) {
- if ($attempts > 20)
+ if ($attempts > 5)
break;
$attempts--;
continue;
}
- if ($url) {
-
- $max = intval(get_config('system', 'max_imported_posts', 30));
- if (intval($max)) {
- logger('externals: fetching outbox');
-
- $feed_url = $url . '/zotfeed';
- $obj = new ASCollection($feed_url, $importer, 0, $max);
- $messages = $obj->get();
+ $cl = Activity::get_actor_collections($contact['hubloc_hash']);
+ if(empty($cl)) {
+ $cl = get_xconfig($contact['hubloc_hash'], 'activitypub', 'collections');
+ }
- if ($messages) {
- foreach ($messages as $message) {
- if (is_string($message)) {
- $message = Activity::fetch($message, $importer);
- }
- $AS = new ActivityStreams($message);
- if ($AS->is_valid() && is_array($AS->obj)) {
- $item = Activity::decode_note($AS);
- Activity::store($importer, $importer['xchan_hash'], $AS, $item, true);
- $total++;
- }
- }
- }
- logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
+ if (is_array($cl) && array_key_exists('outbox', $cl)) {
+ $url = $cl['outbox'];
+ }
+ else {
+ $url = str_replace('/channel/', '/outbox/', $contact['hubloc_id_url']);
+ if ($url) {
+ $url .= '?top=1';
}
}
- }
- return;
-
- /* $total = 0;
- $attempts = 0;
-
- logger('externals: startup', LOGGER_DEBUG);
- // pull in some public posts
-
- while ($total == 0 && $attempts < 3) {
- $arr = ['url' => ''];
- call_hooks('externals_url_select', $arr);
-
- if ($arr['url']) {
- $url = $arr['url'];
- }
- else {
- $randfunc = db_getfunc('RAND');
-
- // fixme this query does not deal with directory realms.
-
- $r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1",
- dbesc(z_root()),
- intval(DIRECTORY_MODE_STANDALONE),
- intval(SITE_TYPE_ZOT)
- );
- if ($r)
- $url = $r[0]['site_url'];
- }
+ if ($url) {
+ logger('fetching outbox: ' . $url);
- $blacklisted = false;
+ $obj = new ASCollection($url, $importer, 0, 10);
+ $messages = $obj->get();
- if (!check_siteallowed($url)) {
- logger('blacklisted site: ' . $url);
- $blacklisted = true;
- }
+ if ($messages) {
+ foreach ($messages as $message) {
+ if (is_string($message)) {
+ $message = Activity::fetch($message, $importer);
+ }
- $attempts++;
+ if ($message['type'] !== 'Create') {
+ continue;
+ }
- // make sure we can eventually break out if somebody blacklists all known sites
+ if ($contact['hubloc_network'] === 'zot6') {
+ // make sure we only fetch top level items
+ if (isset($message['object']['inReplyTo'])) {
+ continue;
+ }
- if ($blacklisted) {
- if ($attempts > 20)
- break;
- $attempts--;
- continue;
- }
+ $obj_id = isset($message['object']['id']) ?? $message['object'];
- if ($url) {
- if ($r[0]['site_pull'] > NULL_DATE)
- $mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day'));
- else {
- $days = get_config('externals', 'since_days');
- if ($days === false)
- $days = 15;
- $mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days'));
+ Libzot::fetch_conversation($importer, $obj_id);
+ $total++;
+ continue;
}
- $feedurl = $url . '/zotfeed?f=&mindate=' . $mindate;
-
- logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG);
-
- $x = z_fetch_url($feedurl);
- if (($x) && ($x['success'])) {
-
- q("update site set site_pull = '%s' where site_url = '%s'",
- dbesc(datetime_convert()),
- dbesc($url)
- );
-
- $j = json_decode($x['body'], true);
- if ($j['success'] && $j['messages']) {
- $sys = get_sys_channel();
- foreach ($j['messages'] as $message) {
- // on these posts, clear any route info.
- $message['route'] = '';
- process_delivery(['hash' => 'undefined'], get_item_elements($message),
- [['hash' => $sys['xchan_hash']]], false, true);
- $total++;
- }
- logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG);
- }
+ $AS = new ActivityStreams($message);
+ if ($AS->is_valid() && is_array($AS->obj)) {
+ $item = Activity::decode_note($AS);
+ Activity::store($importer, $contact['abook_xchan'], $AS, $item);
+ $total++;
}
}
- }*/
+ }
+ logger('fetched messages count: ' . $total);
+ }
+ }
+ return;
}
}
diff --git a/Zotlabs/Daemon/File_importer.php b/Zotlabs/Daemon/File_importer.php
new file mode 100644
index 000000000..7067e152d
--- /dev/null
+++ b/Zotlabs/Daemon/File_importer.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Zotlabs\Daemon;
+
+use Zotlabs\Web\HTTPSig;
+use Zotlabs\Lib\PConfig;
+
+
+require_once('include/cli_startup.php');
+require_once('include/attach.php');
+require_once('include/import.php');
+
+class File_importer {
+
+ static public function run($argc,$argv) {
+
+ cli_startup();
+
+ $page = $argv[1];
+ $channel_address = $argv[2];
+ $hz_server = urldecode($argv[3]);
+
+ $m = parse_url($hz_server);
+
+ $channel = channelx_by_nick($channel_address);
+ if(! $channel) {
+ logger('channel not found');
+ return;
+ }
+
+ $headers = [
+ 'X-API-Token' => random_string(),
+ 'X-API-Request' => $hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page,
+ 'Host' => $m['host'],
+ '(request-target)' => 'get /api/z/1.0/file/export_page?f=records=1&page=' . $page,
+ ];
+
+ $headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),true,'sha512');
+
+ // TODO: implement total count
+ $x = z_fetch_url($hz_server . '/api/z/1.0/file/export_page?f=records=1&page=' . $page, false, $redirects, [ 'headers' => $headers ]);
+ // logger('file fetch: ' . print_r($x,true));
+
+ if(! $x['success']) {
+ logger('no API response',LOGGER_DEBUG);
+ killme();
+ }
+
+ $j = json_decode($x['body'],true);
+
+ if(! is_array($j['results'][0]['attach']) || ! count($j['results'][0]['attach'])) {
+ PConfig::Set($channel['channel_id'], 'import', 'files_completed', 1);
+ return;
+ }
+
+ $r = sync_files($channel, $j['results']);
+
+ PConfig::Set($channel['channel_id'], 'import', 'files_progress', [
+ 'files_total' => $j['total'],
+ 'files_page' => 1, // export page atm returns just one file
+ 'last_page' => $page,
+ 'next_cmd' => ['File_importer',sprintf('%d',$page + 1), $channel['channel_address'], urlencode($hz_server)]
+ ]);
+
+ $page++;
+
+ Master::Summon([ 'File_importer',sprintf('%d',$page), $channel['channel_address'], urlencode($hz_server) ]);
+
+ return;
+ }
+}
diff --git a/Zotlabs/Daemon/Gprobe.php b/Zotlabs/Daemon/Gprobe.php
index 29efcf475..1124ead54 100644
--- a/Zotlabs/Daemon/Gprobe.php
+++ b/Zotlabs/Daemon/Gprobe.php
@@ -15,19 +15,31 @@ class Gprobe {
return;
$url = hex2bin($argv[1]);
+ $is_webbie = false;
+ $r = null;
- if (!strpos($url, '@'))
- return;
+ if (filter_var($url, FILTER_VALIDATE_EMAIL)) {
+ $is_webbie = true;
- $r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
- dbesc($url)
- );
+ $r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
+ dbesc($url)
+ );
+ }
+ elseif (filter_var($url, FILTER_VALIDATE_URL)) {
+ $r = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
+ dbesc($url)
+ );
+ }
if (!$r) {
- $href = Webfinger::zot_url(punify($url));
- if ($href) {
- $zf = Zotfinger::exec($href, null);
+ if ($is_webbie) {
+ $url = Webfinger::zot_url(punify($url));
}
+
+ if ($url) {
+ $zf = Zotfinger::exec($url, null);
+ }
+
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
}
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index 741078422..8aee08fe6 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -5,24 +5,16 @@ namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Queue;
+use Zotlabs\Lib\LDSignatures;
-require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once('include/conversation.php');
-require_once('include/zot.php');
require_once('include/items.php');
require_once('include/bbcode.php');
/*
- * This file was at one time responsible for doing all deliveries, but this caused
- * big problems on shared hosting systems, where the process might get killed by the
- * hosting provider and nothing would get delivered.
- * It now only delivers one message under certain cases, and invokes a queued
- * delivery mechanism (include/deliver.php) to deliver individual contacts at
- * controlled intervals.
- * This has a much better chance of surviving random processes getting killed
- * by the hosting provider.
+ * Notifier - message dispatch and preparation for delivery
*
* The basic flow is:
* Identify the type of message
@@ -53,7 +45,6 @@ require_once('include/bbcode.php');
* event (in events.php)
* expire (in items.php)
* like (in like.php, poke.php)
- * mail (in message.php)
* tag (in photos.php, poke.php, tagger.php)
* tgroup (in items.php)
* wall-new (in photos.php, item.php)
@@ -63,7 +54,6 @@ require_once('include/bbcode.php');
* ZOT
* permission_create abook_id
* permission_accept abook_id
- * permission_reject abook_id
* permission_update abook_id
* refresh_all channel_id
* purge channel_id xchan_hash
@@ -71,7 +61,6 @@ require_once('include/bbcode.php');
* expire channel_id
* relay item_id (item was relayed to owner, we will deliver it as owner)
* single_activity item_id (deliver to a singleton network from the appropriate clone)
- * single_mail mail_id (deliver to a singleton network from the appropriate clone)
* location channel_id
* request channel_id xchan_hash message_id
* rating xlink_id
@@ -82,164 +71,126 @@ require_once('include/bbcode.php');
class Notifier {
+ static public $deliveries = [];
+ static public $recipients = [];
+ static public $env_recips = [];
+ static public $packet_type = 'activity';
+ static public $encoding = 'activitystreams';
+ static public $encoded_item = null;
+ static public $channel = null;
+ static public $private = false;
+ // $fragment can contain additional info to omit de-duplication in the queueworker.
+ // E.g. if an item is updated many times in a row from different sources (multiple vote updates) the
+ // update source mid or a timestamp or random string can be added.
+ static public $fragment = null;
+
static public function run($argc, $argv) {
- if ($argc < 3)
+ if ($argc < 3) {
return;
+ }
logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG);
$cmd = $argv[1];
-
$item_id = $argv[2];
- if (!$item_id)
+ if (!$item_id) {
return;
-
- $sys = get_sys_channel();
-
- $deliveries = [];
-
- $request = false;
- $mail = false;
- $location = false;
- $recipients = [];
- $normal_mode = true;
- $packet_type = 'undefined';
-
- if ($cmd === 'mail' || $cmd === 'single_mail') {
- $normal_mode = false;
- $mail = true;
- $private = true;
- $message = q("SELECT * FROM mail WHERE id = %d LIMIT 1",
- intval($item_id)
- );
- if (!$message) {
- return;
- }
- xchan_mail_query($message[0]);
- $uid = $message[0]['channel_id'];
- $recipients[] = $message[0]['from_xchan']; // include clones
- $recipients[] = $message[0]['to_xchan'];
- $item = $message[0];
- $encoded_item = encode_mail($item);
-
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($uid)
- );
- if ($s)
- $channel = $s[0];
-
}
- elseif ($cmd === 'request') {
- $channel_id = $item_id;
- $xchan = $argv[3];
- $request_message_id = $argv[4];
-
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($channel_id)
- );
- if ($s)
- $channel = $s[0];
- $private = true;
- $recipients[] = $xchan;
- $packet_type = 'request';
- $normal_mode = false;
- }
- elseif ($cmd === 'keychange') {
- $channel = channelx_by_n($item_id);
-
- $r = q("select abook_xchan from abook where abook_channel = %d",
+ self::$deliveries = [];
+ self::$recipients = [];
+ self::$env_recips = [];
+ self::$packet_type = 'activity';
+ self::$encoding = 'activitystreams';
+ self::$encoded_item = null;
+ self::$channel = null;
+ self::$private = false;
+ self::$fragment = null;
+
+ $sys = get_sys_channel();
+ $normal_mode = true;
+
+ if ($cmd === 'keychange') {
+ self::$channel = channelx_by_n($item_id);
+ $r = q("select abook_xchan from abook where abook_channel = %d",
intval($item_id)
);
if ($r) {
foreach ($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
+ self::$recipients[] = $rr['abook_xchan'];
}
}
- $private = false;
- $packet_type = 'keychange';
- $normal_mode = false;
+ self::$private = false;
+ self::$packet_type = 'keychange';
+ self::$encoded_item = get_pconfig(self::$channel['channel_id'], 'system', 'keychange');
+ self::$encoding = 'zot';
+ $normal_mode = false;
}
- elseif (in_array($cmd, ['permission_update', 'permission_reject', 'permission_accept', 'permission_create'])) {
+ elseif (in_array($cmd, ['permission_update', 'permission_accept', 'permission_create'])) {
// Get the (single) recipient
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
intval($item_id)
);
if ($r) {
- $uid = $r[0]['abook_channel'];
+ $recip = $r[0];
+
// Get the sender
- $channel = channelx_by_n($uid);
- if ($channel) {
- $perm_update = ['sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''];
-
- if ($cmd === 'permission_create')
- call_hooks('permissions_create', $perm_update);
- elseif ($cmd === 'permission_accept')
- call_hooks('permissions_accept', $perm_update);
- elseif ($cmd === 'permission_reject')
- call_hooks('permissions_reject', $perm_update);
- else
- call_hooks('permissions_update', $perm_update);
+ self::$channel = channelx_by_n($recip['abook_channel']);
+ if (self::$channel) {
+ $perm_update = ['sender' => self::$channel, 'recipient' => $recip, 'success' => false, 'deliveries' => ''];
+
+ switch ($cmd) {
+ case 'permission_create':
+ call_hooks('permissions_create', $perm_update);
+ break;
+ case 'permission_accept':
+ call_hooks('permissions_accept', $perm_update);
+ break;
+ case 'permission_update':
+ call_hooks('permissions_update', $perm_update);
+ break;
+ default:
+ break;
+ }
if ($perm_update['success']) {
if ($perm_update['deliveries']) {
- $deliveries[] = $perm_update['deliveries'];
- do_delivery($deliveries);
+ self::$deliveries[] = $perm_update['deliveries'];
+ do_delivery(self::$deliveries);
}
return;
}
else {
- $recipients[] = $r[0]['abook_xchan'];
- $private = false;
- $packet_type = 'refresh';
- $packet_recips = [['guid' => $r[0]['xchan_guid'], 'guid_sig' => $r[0]['xchan_guid_sig'], 'hash' => $r[0]['xchan_hash']]];
+ self::$recipients[] = $recip['abook_xchan'];
+ self::$private = false;
+ self::$packet_type = 'refresh';
+ self::$env_recips = [$recip['xchan_hash']];
}
}
}
}
elseif ($cmd === 'refresh_all') {
logger('notifier: refresh_all: ' . $item_id);
- $uid = $item_id;
- $channel = channelx_by_n($item_id);
-
- $r = q("select abook_xchan from abook where abook_channel = %d",
- intval($uid)
- );
- if ($r) {
- foreach ($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
- }
- }
- $private = false;
- $packet_type = 'refresh';
- }
- elseif ($cmd === 'location') {
- logger('notifier: location: ' . $item_id);
- $s = q("select * from channel where channel_id = %d limit 1",
- intval($item_id)
- );
- if ($s)
- $channel = $s[0];
- $uid = $item_id;
- $recipients = [];
+ self::$channel = channelx_by_n($item_id, true);
- $r = q("select abook_xchan from abook where abook_channel = %d",
- intval($uid)
+ $r = q("select abook_xchan from abook where abook_channel = %d",
+ intval($item_id)
);
if ($r) {
foreach ($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
+ self::$recipients[] = $rr['abook_xchan'];
}
}
- $encoded_item = ['locations' => Libzot::encode_locations($channel), 'type' => 'location', 'encoding' => 'zot'];
- $target_item = ['aid' => $channel['channel_account_id'], 'uid' => $channel['channel_id']];
- $private = false;
- $packet_type = 'location';
- $location = true;
+ // In case we deleted the channel, our abook entry has already vanished.
+ // In order to be able to update our clones we need to add ourself here.
+ self::$recipients[] = self::$channel['channel_hash'];
+
+ self::$private = false;
+ self::$packet_type = 'refresh';
}
elseif ($cmd === 'purge') {
$xchan = $argv[3];
@@ -248,33 +199,27 @@ class Notifier {
return;
}
- $channel = channelx_by_n($item_id);
- $recipients[] = $xchan;
- $private = true;
- $packet_type = 'purge';
- $packet_recips[] = ['hash' => $xchan];
+ self::$channel = channelx_by_n($item_id, true);
+ self::$recipients = [$xchan];
+ self::$private = true;
+ self::$packet_type = 'purge';
}
elseif ($cmd === 'purge_all') {
-
logger('notifier: purge_all: ' . $item_id);
- $channel = channelx_by_n($item_id);
+ self::$channel = channelx_by_n($item_id, true);
+ self::$recipients = [];
+ self::$private = false;
+ self::$packet_type = 'purge';
- $recipients = [];
- $r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
+ $r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
intval($item_id)
);
if (!$r) {
return;
}
foreach ($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
- $packet_recips[] = ['hash' => $rr['abook_xchan']];
+ self::$recipients[] = $rr['abook_xchan'];
}
-
- $private = false;
- $packet_type = 'purge';
-
-
}
else {
@@ -282,20 +227,21 @@ class Notifier {
// Fetch the target item
- $r = q("SELECT * FROM item WHERE id = %d and parent != 0 LIMIT 1",
+ self::$fragment = $argv[3] ?? '';
+
+ $r = q("SELECT * FROM item WHERE id = %d AND parent != 0",
intval($item_id)
);
-
- if (!$r)
+ if (!$r) {
return;
+ }
xchan_query($r);
-
$r = fetch_post_tags($r);
$target_item = $r[0];
- if (in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
+ if (in_array($target_item['author']['xchan_network'], ['rss', 'anon', 'token'])) {
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
return;
}
@@ -345,11 +291,12 @@ class Notifier {
$s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($target_item['uid'])
);
- if ($s)
- $channel = $s[0];
+ if ($s) {
+ self::$channel = $s[0];
+ }
- if ($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) {
- logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
+ if (self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) {
+ logger("notifier: Sending channel " . self::$channel['channel_hash'] . " is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
return;
}
@@ -359,12 +306,13 @@ class Notifier {
}
else {
// fetch the parent item
- $r = q("SELECT * from item where id = %d order by id asc",
+ $r = q("SELECT * FROM item WHERE id = %d",
intval($target_item['parent'])
);
- if (!$r)
+ if (!$r) {
return;
+ }
if (strpos($r[0]['postopts'], 'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE);
@@ -379,29 +327,28 @@ class Notifier {
}
// avoid looping of discover items 12/4/2014
-
- if ($sys && $parent_item['uid'] == $sys['channel_id'])
+ if ($sys && $parent_item['uid'] == $sys['channel_id']) {
return;
+ }
- $encoded_item = encode_item($target_item);
-
+ $m = get_iconfig($target_item, 'activitypub', 'signed_data');
// Re-use existing signature unless the activity type changed to a Tombstone, which won't verify.
- $m = ((intval($target_item['item_deleted'])) ? '' : get_iconfig($target_item, 'activitypub', 'signed_data'));
-
- if ($m) {
- $activity = json_decode($m, true);
+ if ($m && (!intval($target_item['item_deleted']))) {
+ self::$encoded_item = json_decode($m, true);
}
else {
- $activity = array_merge(['@context' => [
+
+ self::$encoded_item = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_activity($target_item)
);
+ self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel);
}
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
- logger('encoded: ' . print_r($activity, true), LOGGER_DEBUG);
+ logger('encoded: ' . print_r(self::$encoded_item, true), LOGGER_DEBUG);
// Send comments to the owner to re-deliver to everybody in the conversation
// We only do this if the item in question originated on this site. This prevents looping.
@@ -412,9 +359,9 @@ class Notifier {
// flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
// the hostname in the message_id and provides a second (fallback) opinion.
- $relay_to_owner = (((!$top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
-
- $uplink = false;
+ $relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
+ $uplink = false;
+ $upstream = false;
// $cmd === 'relay' indicates the owner is sending it to the original recipients
// don't allow the item in the relay command to relay to owner under any circumstances, it will loop
@@ -426,27 +373,34 @@ class Notifier {
if (($cmd === 'uplink') && intval($parent_item['item_uplink']) && (!$top_level_post)) {
logger('notifier: uplink');
- $uplink = true;
+ $uplink = true;
+ self::$packet_type = 'response';
}
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
- $recipients = [($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']];
- $private = true;
- if (!$encoded_item['flags'])
- $encoded_item['flags'] = [];
- $encoded_item['flags'][] = 'relay';
- $upstream = true;
+ $sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
+ self::$recipients = [$sendto];
+ self::$private = true;
+ $upstream = true;
+ self::$packet_type = 'response';
}
else {
- logger('notifier: normal distribution', LOGGER_DEBUG);
- if ($cmd === 'relay')
- logger('notifier: owner relay');
- $upstream = false;
+ if ($cmd === 'relay') {
+ logger('owner relay (downstream delivery)');
+ }
+ else {
+ logger('normal (downstream) distribution', LOGGER_DEBUG);
+ }
+
+ if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
+ logger('conversation privacy mismatch - downstream delivery prevented');
+ return;
+ }
+
// if our parent is a tag_delivery recipient, uplink to the original author causing
// a delivery fork.
-
- if (($parent_item) && intval($parent_item['item_uplink']) && (!$top_level_post) && ($cmd !== 'uplink')) {
+ if ($parent_item && intval($parent_item['item_uplink']) && !$top_level_post && $cmd !== 'uplink') {
// don't uplink a relayed post to the relay owner
if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
logger('notifier: uplinking this item');
@@ -454,98 +408,87 @@ class Notifier {
}
}
- $private = false;
- $recipients = collect_recipients($parent_item, $private);
+ self::$private = false;
+ self::$recipients = collect_recipients($parent_item, self::$private);
+
+ // FIXME add any additional recipients such as mentions, etc.
if ($top_level_post) {
// remove clones who will receive the post via sync
- $recipients = array_diff($recipients, [$target_item['owner_xchan']]);
+ self::$recipients = array_values(array_diff(self::$recipients, [$target_item['owner_xchan']]));
}
- // FIXME add any additional recipients such as mentions, etc.
-
+ // don't send deletions onward for other people's stuff
+ if (intval($target_item['item_deleted']) && (!intval($target_item['item_wall']))) {
+ logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
+ return;
+ }
}
}
- $walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
-
// Generic delivery section, we have an encoded item and recipients
// Now start the delivery process
- $x = $encoded_item;
- $x['title'] = 'private';
- $x['body'] = 'private';
- logger('notifier: encoded item: ' . print_r($x, true), LOGGER_DATA, LOG_DEBUG);
+ logger('encoded item: ' . print_r(self::$encoded_item, true), LOGGER_DATA, LOG_DEBUG);
- //logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG);
-
- stringify_array_elms($recipients);
- if (!$recipients) {
+ stringify_array_elms(self::$recipients);
+ if (!self::$recipients) {
logger('no recipients');
return;
}
- // logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG);
-
- $env_recips = (($private) ? [] : null);
+ // logger('recipients: ' . print_r(self::$recipients,true), LOGGER_NORMAL, LOG_DEBUG);
- $details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',', $recipients)) . ")");
+ if (!count(self::$env_recips)) {
+ self::$env_recips = ((self::$private) ? [] : null);
+ }
$recip_list = [];
+ $details = dbq("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")");
+
if ($details) {
foreach ($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
- if ($private) {
- $env_recips[] = [
- 'guid' => $d['xchan_guid'],
- 'guid_sig' => $d['xchan_guid_sig'],
- 'hash' => $d['xchan_hash']
- ];
+ if (self::$private) {
+ self::$env_recips[] = $d['xchan_hash'];
}
}
}
-
$narr = [
- 'channel' => $channel,
+ 'channel' => self::$channel,
'upstream' => $upstream,
- 'env_recips' => $env_recips,
- 'packet_recips' => $packet_recips,
- 'recipients' => $recipients,
- 'item' => $item,
+ 'env_recips' => self::$env_recips,
+ 'recipients' => self::$recipients,
'target_item' => $target_item,
'parent_item' => $parent_item,
'top_level_post' => $top_level_post,
- 'private' => $private,
+ 'private' => self::$private,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
- 'mail' => $mail,
- 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
- 'location' => $location,
- 'request' => $request,
+ 'single' => ($cmd === 'single_activity'),
'normal_mode' => $normal_mode,
- 'packet_type' => $packet_type,
- 'walltowall' => $walltowall,
+ 'packet_type' => self::$packet_type,
'queued' => []
];
call_hooks('notifier_process', $narr);
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
- $deliveries[] = $pq;
+ self::$deliveries[] = $pq;
}
// notifier_process can alter the recipient list
- $recipients = $narr['recipients'];
- $env_recips = $narr['env_recips'];
- $packet_recips = $narr['packet_recips'];
+ self::$recipients = $narr['recipients'];
+ self::$env_recips = $narr['env_recips'];
- if (($private) && (!$env_recips)) {
+ if (self::$private && !self::$env_recips) {
// shouldn't happen
logger('notifier: private message with no envelope recipients.' . print_r($argv, true), LOGGER_NORMAL, LOG_NOTICE);
+ return;
}
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list, true), LOGGER_DEBUG);
@@ -554,15 +497,15 @@ class Notifier {
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs; checking that the site is not dead.
- $hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
- where hubloc_hash in (" . protect_sprintf(implode(',', $recipients)) . ")
+ $hubs = dbq("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
+ where hubloc_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")
and hubloc_error = 0 and hubloc_deleted = 0"
);
// public posts won't make it to the local public stream unless there's a recipient on this site.
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
- if (!$private) {
+ if (!self::$private) {
$found_localhost = false;
if ($hubs) {
foreach ($hubs as $h) {
@@ -573,12 +516,12 @@ class Notifier {
}
}
if (!$found_localhost) {
- $localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
- left join site on site_url = hubloc_url where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
+ $localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
+ where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
dbesc(z_root() . '/channel/sys')
);
if ($localhub) {
- $hubs = array_merge($hubs, $localhub);
+ $hubs = array_merge($localhub, $hubs);
}
}
}
@@ -595,41 +538,36 @@ class Notifier {
*/
- $hublist = []; // this provides an easily printable list for the logs
- $dhubs = []; // delivery hubs where we store our resulting unique array
- $keys = []; // array of keys to check uniquness for zot hubs
- $urls = []; // array of urls to check uniqueness of hubs from other networks
- $hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
- $dead = []; // known dead hubs - report them as undeliverable
+ $hublist = []; // this provides an easily printable list for the logs
+ $dhubs = []; // delivery hubs where we store our resulting unique array
+ $keys = []; // array of keys to check uniquness for zot hubs
+ $urls = []; // array of urls to check uniqueness of hubs from other networks
+ $hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
+ $dead_hosts = []; // known dead hubs - report them as undeliverable
foreach ($hubs as $hub) {
-
- if (intval($hub['site_dead'])) {
- $dead[] = $hub;
+ if (isset($hub['site_dead']) && intval($hub['site_dead'])) {
+ if(!in_array($hub['hubloc_host'], $dead_hosts)) {
+ $dead_hosts[] = $hub['hubloc_host'];
+ }
continue;
}
- if ($env_recips) {
- foreach ($env_recips as $er) {
- if ($hub['hubloc_hash'] === $er['hash']) {
- if (!array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) {
- $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = [];
+ if (self::$env_recips) {
+ foreach (self::$env_recips as $er) {
+ if ($hub['hubloc_hash'] === $er) {
+ if (!array_key_exists($hub['hubloc_site_id'], $hub_env)) {
+ $hub_env[$hub['hubloc_site_id']] = [];
+ }
+ if (!in_array($er, $hub_env[$hub['hubloc_site_id']])) {
+ $hub_env[$hub['hubloc_site_id']][] = $er;
}
- $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er;
}
}
}
-
- if ($hub['hubloc_network'] == 'zot') {
+ if ($hub['hubloc_network'] === 'zot6') {
if (!in_array($hub['hubloc_sitekey'], $keys)) {
- $hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
- $dhubs[] = $hub;
- $keys[] = $hub['hubloc_sitekey'];
- }
- }
- else {
- if (!in_array($hub['hubloc_url'], $urls)) {
if ($hub['hubloc_url'] === z_root()) {
//deliver to local hub first
array_unshift($hublist, $hub['hubloc_host'] . ' ' . $hub['hubloc_network']);
@@ -639,7 +577,14 @@ class Notifier {
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
$dhubs[] = $hub;
}
- $urls[] = $hub['hubloc_url'];
+ $keys[] = $hub['hubloc_sitekey'];
+ }
+ }
+ else {
+ if (!in_array($hub['hubloc_url'], $urls)) {
+ $hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
+ $dhubs[] = $hub;
+ $urls[] = $hub['hubloc_url'];
}
}
}
@@ -650,37 +595,30 @@ class Notifier {
logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
- if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
+ if ($hub['hubloc_network'] !== 'zot6') {
$narr = [
- 'channel' => $channel,
+ 'channel' => self::$channel,
'upstream' => $upstream,
- 'env_recips' => $env_recips,
- 'packet_recips' => $packet_recips,
- 'recipients' => $recipients,
- 'item' => $item,
+ 'env_recips' => self::$env_recips,
+ 'recipients' => self::$recipients,
'target_item' => $target_item,
'parent_item' => $parent_item,
'hub' => $hub,
'top_level_post' => $top_level_post,
- 'private' => $private,
+ 'private' => self::$private,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
- 'mail' => $mail,
- 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
- 'location' => $location,
- 'request' => $request,
+ 'single' => $cmd === 'single_activity',
'normal_mode' => $normal_mode,
- 'packet_type' => $packet_type,
- 'walltowall' => $walltowall,
+ 'packet_type' => self::$packet_type,
'queued' => []
];
-
call_hooks('notifier_hub', $narr);
if ($narr['queued']) {
foreach ($narr['queued'] as $pq)
- $deliveries[] = $pq;
+ self::$deliveries[] = $pq;
}
continue;
@@ -695,175 +633,95 @@ class Notifier {
// will invoke a delivery to those connections which are connected to just that
// hub instance.
- if ($cmd === 'single_mail' || $cmd === 'single_activity') {
- continue;
- }
-
- if (!in_array($hub['hubloc_network'], ['zot', 'zot6'])) {
+ if ($cmd === 'single_activity') {
continue;
}
- // Do not change this to a uuid as long as we have traditional zot servers
- // in the loop. The signature verification step can't handle dashes in the
- // hashes.
+ // default: zot protocol
- $hash = random_string(48);
+ // Prevent zot6 delivery of group comment boosts, which are not required for conversational platforms.
+ // ActivityPub conversational platforms may wish to filter these if they don't want or require them.
+ // We will assume here that if $target_item exists and has a verb that it is an actual item structure
+ // so we won't need to check the existence of the other item fields prior to evaluation.
- $packet = null;
- $pmsg = '';
-
- if ($packet_type === 'refresh' || $packet_type === 'purge') {
- if ($hub['hubloc_network'] === 'zot6') {
- $packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips, 'hash'));
- }
- else {
- $packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
- }
- }
- if ($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
- $pmsg = get_pconfig($channel['channel_id'], 'system', 'keychange');
- $packet = zot_build_packet($channel, $packet_type, (($packet_recips) ? $packet_recips : null));
- }
- elseif ($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
- $env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
- $packet = zot_build_packet($channel, $packet_type, $env, $hub['hubloc_sitekey'], $hub['site_crypto'],
- $hash, ['message_id' => $request_message_id]
- );
- }
+ // This shouldn't produce false positives on comment boosts that were generated on other platforms
+ // because we won't be delivering them.
- if ($packet) {
- Queue::insert(
- [
- 'hash' => $hash,
- 'account_id' => $channel['channel_account_id'],
- 'channel_id' => $channel['channel_id'],
- 'posturl' => $hub['hubloc_callback'],
- 'driver' => $hub['hubloc_network'],
- 'notify' => $packet,
- 'msg' => (($pmsg) ? json_encode($pmsg) : '')
- ]
- );
+ if (isset($target_item) && isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
+ continue;
}
- else {
- $env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
-
- if ($hub['hubloc_network'] === 'zot6') {
- $zenv = [];
- if ($env) {
- foreach ($env as $e) {
- $zenv[] = $e['hash'];
- }
- }
-
- $packet_type = (($upstream || $uplink) ? 'response' : 'activity');
-
- // block zot private reshares from zot6, as this could cause a number of privacy issues
- // due to parenting differences between the reshare implementations. In zot a reshare is
- // a standalone parent activity and in zot6 it is a followup/child of the original activity.
- // For public reshares, some comments to the reshare on the zot fork will not make it to zot6
- // due to these different message models. This cannot be prevented at this time.
- if ($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
- continue;
- }
-
- $packet = Libzot::build_packet($channel, $packet_type, $zenv, $activity, 'activitystreams', (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
- }
- else {
- // currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
- // Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
- // with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
- // to trigger dequeue'ing
-
- $z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (!array_key_exists('allow_cid', $encoded_item))) ? true : false);
- if ($z6) {
- $packet = zot6_build_packet($channel, 'notify', $env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
- }
- else {
- $packet = zot_build_packet($channel, 'notify', $env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'], $hash);
+ $hash = new_uuid();
- }
- }
+ $env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
+ if ((self::$private) && (!$env)) {
+ continue;
+ }
+ $packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding, ((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
- // remove this after most hubs have updated to version 5.0
- if (stripos($hub['site_project'], 'hubzilla') !== false && version_compare($hub['site_version'], '4.7.3', '<=')) {
- if ($encoded_item['type'] === 'mail') {
- $encoded_item['from']['network'] = 'zot';
- $encoded_item['from']['guid_sig'] = str_replace('sha256.', '', $encoded_item['from']['guid_sig']);
- }
- else {
- $encoded_item['owner']['network'] = 'zot';
- $encoded_item['owner']['guid_sig'] = str_replace('sha256.', '', $encoded_item['owner']['guid_sig']);
- if (strpos($encoded_item['author']['url'], z_root()) === 0) {
- $encoded_item['author']['network'] = 'zot';
- $encoded_item['author']['guid_sig'] = str_replace('sha256.', '', $encoded_item['author']['guid_sig']);
- }
- }
- }
+ Queue::insert(
+ [
+ 'hash' => $hash,
+ 'account_id' => self::$channel['channel_account_id'],
+ 'channel_id' => self::$channel['channel_id'],
+ 'posturl' => $hub['hubloc_callback'],
+ 'notify' => $packet,
+ 'msg' => EMPTY_STR
+ ]
+ );
- Queue::insert(
- [
- 'hash' => $hash,
- 'account_id' => $target_item['aid'],
- 'channel_id' => $target_item['uid'],
- 'posturl' => $hub['hubloc_callback'],
- 'driver' => $hub['hubloc_network'],
- 'notify' => $packet,
- 'msg' => json_encode($encoded_item)
- ]
+ // only create delivery reports for normal undeleted items
+ if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
+ q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
+ values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
+ dbesc($target_item['mid']),
+ dbesc($hub['hubloc_host']),
+ dbesc($hub['hubloc_host']),
+ dbesc($hub['hubloc_host']),
+ dbesc('queued'),
+ dbesc(datetime_convert()),
+ dbesc(self::$channel['channel_hash']),
+ dbesc($hash)
);
-
- // only create delivery reports for normal undeleted items
- if (is_array($target_item) && array_key_exists('postopts', $target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
- q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ",
- dbesc($target_item['mid']),
- dbesc($hub['hubloc_host']),
- dbesc($hub['hubloc_host']),
- dbesc('queued'),
- dbesc(datetime_convert()),
- dbesc($channel['channel_hash']),
- dbesc($hash)
- );
- }
}
- $deliveries[] = $hash;
+ self::$deliveries[] = $hash;
+
}
if ($normal_mode) {
+ // This wastes a process if there are no delivery hooks configured, so check this before launching the new process
$x = q("select * from hook where hook = 'notifier_normal'");
if ($x) {
- Master::Summon(['Deliver_hooks', $target_item['id']]);
+ Master::Summon(['Deliver_hooks', $target_item['id'], self::$fragment]);
}
}
- if ($deliveries)
- do_delivery($deliveries);
-
- logger('notifier: basic loop complete.', LOGGER_DEBUG);
-
- if ($dead) {
- foreach ($dead as $deceased) {
- if (is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
- q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
- values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
- dbesc($target_item['mid']),
- dbesc($deceased['hubloc_host']),
- dbesc($deceased['hubloc_host']),
- dbesc($deceased['hubloc_host']),
- dbesc('undeliverable/unresponsive site'),
- dbesc(datetime_convert()),
- dbesc($channel['channel_hash']),
- dbesc(random_string(48))
- );
- }
+ if (self::$deliveries) {
+ do_delivery(self::$deliveries);
+ }
+
+ if ($dead_hosts && is_array($target_item) && (!$target_item['item_deleted']) && (!get_config('system', 'disable_dreport'))) {
+ foreach ($dead_hosts as $deceased_host) {
+ $r = q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
+ values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
+ dbesc($target_item['mid']),
+ dbesc($deceased_host),
+ dbesc($deceased_host),
+ dbesc($deceased_host),
+ dbesc('undeliverable/unresponsive site'),
+ dbesc(datetime_convert()),
+ dbesc(self::$channel['channel_hash']),
+ dbesc(new_uuid())
+ );
}
}
call_hooks('notifier_end', $target_item);
logger('notifer: complete.');
+
return;
}
diff --git a/Zotlabs/Daemon/Onedirsync.php b/Zotlabs/Daemon/Onedirsync.php
index f29fbe5b8..ea995be9e 100644
--- a/Zotlabs/Daemon/Onedirsync.php
+++ b/Zotlabs/Daemon/Onedirsync.php
@@ -5,10 +5,6 @@ namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libzotdir;
-require_once('include/zot.php');
-require_once('include/dir_fns.php');
-
-
class Onedirsync {
static public function run($argc, $argv) {
@@ -29,6 +25,7 @@ class Onedirsync {
if (!$r)
return;
+
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
return;
@@ -54,25 +51,24 @@ class Onedirsync {
// ignore doing an update if this ud_addr refers to a known dead hubloc
$h = q("select * from hubloc where hubloc_addr = '%s'",
- dbesc($r[0]['ud_addr'])
+ dbesc($r[0]['ud_addr']),
);
$h = Libzot::zot_record_preferred($h);
- if (($h) && ($h['hubloc_status'] & HUBLOC_OFFLINE)) {
+ if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
- intval(UPDATE_FLAGS_UPDATED),
+ intval(UPDATE_FLAGS_DELETED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED)
);
-
return;
}
// we might have to pull this out some day, but for now update_directory_entry()
// runs zot_finger() and is kind of zot specific
- if ($h && !in_array($h['hubloc_network'], ['zot6', 'zot']))
+ if ($h && $h['hubloc_network'] !== 'zot6')
return;
Libzotdir::update_directory_entry($r[0]);
diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php
index d747e65f3..79fd06df9 100644
--- a/Zotlabs/Daemon/Onepoll.php
+++ b/Zotlabs/Daemon/Onepoll.php
@@ -8,6 +8,7 @@ use Zotlabs\Lib\ASCollection;
use Zotlabs\Lib\Libzot;
require_once('include/socgraph.php');
+require_once('include/feedutils.php');
class Onepoll {
@@ -44,18 +45,14 @@ class Onepoll {
return;
}
- $contact = array_shift($contacts);
+ $contact = $contacts[0];
$importer_uid = $contact['abook_channel'];
- $r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
- intval($importer_uid)
- );
+ $importer = channelx_by_n($importer_uid);
- if (!$r)
+ if (!$importer)
return;
- $importer = $r[0];
-
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
@@ -75,16 +72,12 @@ class Onepoll {
return;
}
- if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
+ if ($contact['xchan_network'] !== 'zot6')
return;
// update permissions
- if ($contact['xchan_network'] === 'zot6')
- $x = Libzot::refresh($contact, $importer);
-
- if ($contact['xchan_network'] === 'zot')
- $x = zot_refresh($contact, $importer);
+ $x = Libzot::refresh($contact, $importer);
$responded = false;
$updated = datetime_convert();
@@ -109,46 +102,63 @@ class Onepoll {
return;
$fetch_feed = true;
- $x = null;
// They haven't given us permission to see their stream
-
$can_view_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'their_perms', 'view_stream'));
- if (!$can_view_stream)
+ if (!$can_view_stream) {
$fetch_feed = false;
+ }
// we haven't given them permission to send us their stream
-
$can_send_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'my_perms', 'send_stream'));
- if (!$can_send_stream)
+ if (!$can_send_stream) {
$fetch_feed = false;
+ }
- if ($fetch_feed && $contact['xchan_network'] !== 'zot') {
+ if ($fetch_feed) {
$max = intval(get_config('system', 'max_imported_posts', 30));
if (intval($max)) {
- $cl = get_xconfig($contact['abook_xchan'], 'activitypub', 'collections');
+ $cl = Activity::get_actor_collections($contact['abook_xchan']);
+ if(empty($cl)) {
+ $cl = get_xconfig($contact['abook_xchan'], 'activitypub', 'collections');
+ }
- if (is_array($cl) && $cl) {
- $url = ((array_key_exists('outbox', $cl)) ? $cl['outbox'] : '');
+ if (is_array($cl) && array_key_exists('outbox', $cl)) {
+ $url = $cl['outbox'];
}
else {
- $url = str_replace('/poco/', '/zotfeed/', $contact['xchan_connurl']);
+ $url = str_replace('/poco/', '/outbox/', $contact['xchan_connurl']);
}
if ($url) {
logger('fetching outbox');
- $url = $url . '?date_begin=' . urlencode($last_update);
+ $url = $url . '?date_begin=' . urlencode($last_update);
+
+ if($contact['xchan_network'] === 'zot6') {
+ $url = $url . '&top=1';
+ }
+
$obj = new ASCollection($url, $importer, 0, $max);
$messages = $obj->get();
+
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $importer);
}
+
+ if ($contact['xchan_network'] === 'zot6') {
+ // make sure we only fetch top level items
+ if ($message['type'] === 'Create' && !isset($message['object']['inReplyTo'])) {
+ Libzot::fetch_conversation($importer, $message['object']['id']);
+ }
+ continue;
+ }
+
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
@@ -163,8 +173,10 @@ class Onepoll {
// update the poco details for this connection
$r = q("SELECT xlink_id from xlink where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
intval($contact['xchan_hash']),
- db_utcnow(), db_quoteinterval('1 DAY')
+ db_utcnow(),
+ db_quoteinterval('1 DAY')
);
+
if (!$r) {
poco_load($contact['xchan_hash'], $contact['xchan_connurl']);
}
diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php
index 762f1349c..88213a7c9 100644
--- a/Zotlabs/Daemon/Poller.php
+++ b/Zotlabs/Daemon/Poller.php
@@ -69,11 +69,11 @@ class Poller {
abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending,
abook.abook_ignored, abook.abook_blocked,
xchan.xchan_network,
- account.account_lastlog, account.account_flags
- FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
+ account.account_lastlog, account.account_flags
+ FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
where abook_self = 0
- $sql_extra
+ $sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED) // FIXME
@@ -102,8 +102,7 @@ class Poller {
continue;
}
-
- if (!in_array($contact['xchan_network'], ['zot', 'zot6']))
+ if ($contact['xchan_network'] !== 'zot6')
continue;
if ($c == $t) {
@@ -191,7 +190,7 @@ class Poller {
set_config('system', 'lastpoll', datetime_convert());
- //All done - clear the lockfile
+ //All done - clear the lockfile
@unlink($lockfile);
diff --git a/Zotlabs/Daemon/Queue.php b/Zotlabs/Daemon/Queue.php
index e1f4b73de..41aaf45ed 100644
--- a/Zotlabs/Daemon/Queue.php
+++ b/Zotlabs/Daemon/Queue.php
@@ -2,8 +2,7 @@
namespace Zotlabs\Daemon;
-require_once('include/queue_fn.php');
-require_once('include/zot.php');
+use Zotlabs\Lib\Queue as LibQueue;
class Queue {
@@ -48,17 +47,17 @@ class Queue {
else {
// For the first 12 hours we'll try to deliver every 15 minutes
- // After that, we'll only attempt delivery once per hour.
- // This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
+ // After that, we'll only attempt delivery once per hour.
+ // This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
// so that we don't start off a thousand deliveries for a couple of dead hubs.
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
// Other drivers will have to do something different here and may need their own query.
- // Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
+ // Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
- // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
- // or twice a day.
+ // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
+ // or twice a day.
$sqlrandfunc = db_getfunc('rand');
@@ -67,7 +66,7 @@ class Queue {
);
while ($r) {
foreach ($r as $rv) {
- queue_deliver($rv);
+ LibQueue::deliver($rv);
}
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
db_utcnow()
@@ -78,7 +77,7 @@ class Queue {
return;
foreach ($r as $rv) {
- queue_deliver($rv);
+ LibQueue::deliver($rv);
}
}
}
diff --git a/Zotlabs/Daemon/Ratenotif.php b/Zotlabs/Daemon/Ratenotif.php
deleted file mode 100644
index 8afde2c4c..000000000
--- a/Zotlabs/Daemon/Ratenotif.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-
-namespace Zotlabs\Daemon;
-
-require_once('include/zot.php');
-require_once('include/queue_fn.php');
-
-
-class Ratenotif {
-
- static public function run($argc,$argv) {
-
-
- // Deprecated
- return;
-
-
- require_once("datetime.php");
- require_once('include/items.php');
-
- if($argc < 3)
- return;
-
-
- logger('ratenotif: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
-
- $cmd = $argv[1];
-
- $item_id = $argv[2];
-
-
- if($cmd === 'rating') {
- $r = q("select * from xlink where xlink_id = %d and xlink_static = 1 limit 1",
- intval($item_id)
- );
- if(! $r) {
- logger('rating not found');
- return;
- }
-
- $encoded_item = array(
- 'type' => 'rating',
- 'encoding' => 'zot',
- 'target' => $r[0]['xlink_link'],
- 'rating' => intval($r[0]['xlink_rating']),
- 'rating_text' => $r[0]['xlink_rating_text'],
- 'signature' => $r[0]['xlink_sig'],
- 'edited' => $r[0]['xlink_updated']
- );
- }
-
- $channel = channelx_by_hash($r[0]['xlink_xchan']);
- if(! $channel) {
- logger('no channel');
- return;
- }
-
-
- $primary = get_directory_primary();
-
- if(! $primary)
- return;
-
-
- $interval = ((get_config('system','delivery_interval') !== false)
- ? intval(get_config('system','delivery_interval')) : 2 );
-
- $deliveries_per_process = intval(get_config('system','delivery_batch_count'));
-
- if($deliveries_per_process <= 0)
- $deliveries_per_process = 1;
-
- $deliver = array();
-
- $x = z_fetch_url($primary . '/regdir');
- if($x['success']) {
- $j = json_decode($x['body'],true);
- if($j && $j['success'] && is_array($j['directories'])) {
-
- foreach($j['directories'] as $h) {
- if($h == z_root())
- continue;
-
- $hash = random_string();
- $n = zot_build_packet($channel,'notify',null,null,'',$hash);
-
- queue_insert(array(
- 'hash' => $hash,
- 'account_id' => $channel['channel_account_id'],
- 'channel_id' => $channel['channel_id'],
- 'posturl' => $h . '/post',
- 'notify' => $n,
- 'msg' => json_encode($encoded_item)
- ));
-
-
- $x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
- if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) {
- logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
- update_queue_item($hash);
- continue;
- }
-
- $deliver[] = $hash;
-
- if(count($deliver) >= $deliveries_per_process) {
- Master::Summon(array('Deliver',$deliver));
- $deliver = array();
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
- }
- }
-
- // catch any stragglers
-
- if(count($deliver)) {
- Master::Summon(array('Deliver',$deliver));
- }
- }
- }
-
- logger('ratenotif: complete.');
- return;
-
- }
-}
diff --git a/Zotlabs/Daemon/Thumbnail.php b/Zotlabs/Daemon/Thumbnail.php
index 72034b870..3688e8ae5 100644
--- a/Zotlabs/Daemon/Thumbnail.php
+++ b/Zotlabs/Daemon/Thumbnail.php
@@ -45,7 +45,6 @@ class Thumbnail {
return;
}
-
$default_controller = null;
$files = glob('Zotlabs/Thumbs/*.php');
diff --git a/Zotlabs/Lib/AccessList.php b/Zotlabs/Lib/AccessList.php
index 3c008f8c7..f4b762eaa 100644
--- a/Zotlabs/Lib/AccessList.php
+++ b/Zotlabs/Lib/AccessList.php
@@ -1,38 +1,37 @@
-<?php
+<?php
namespace Zotlabs\Lib;
-use Zotlabs\Lib\Libsync;
-
-
class AccessList {
-
- static function add($uid,$name,$public = 0) {
- $ret = false;
+ static function add($uid, $name, $public = 0) {
+
+ $ret = false;
+ $hash = '';
if ($uid && $name) {
- $r = self::byname($uid,$name); // check for dups
+ $r = self::by_name($uid, $name); // check for dups
if ($r !== false) {
- // This could be a problem.
+ // This could be a problem.
// Let's assume we've just created a list which we once deleted
// all the old members are gone, but the list remains so we don't break any security
// access lists. What we're doing here is reviving the dead list, but old content which
- // was restricted to this list may now be seen by the new list members.
+ // was restricted to this list may now be seen by the new list members.
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
intval($r)
);
- if(($z) && $z[0]['deleted']) {
+ if (($z) && $z[0]['deleted']) {
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
- notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
+ notice(t('A deleted privacy group with this name was revived. Existing item permissions <strong>may</strong> apply to this privacy group and any future members. If this is not what you intended, please create another privacy group with a different name.') . EOL);
}
- return true;
+ $hash = self::by_id($uid, $r);
+ return $hash;
}
$hash = new_uuid();
- $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
+ $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -42,12 +41,12 @@ class AccessList {
$ret = $r;
}
- Libsync::build_sync_packet($uid,null,true);
- return $ret;
- }
+ Libsync::build_sync_packet($uid, null, true);
+ return (($ret) ? $hash : $ret);
+ }
- static function remove($uid,$name) {
+ static function remove($uid, $name) {
$ret = false;
if ($uid && $name) {
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
@@ -55,36 +54,36 @@ class AccessList {
dbesc($name)
);
if ($r) {
- $group_id = $r[0]['id'];
+ $group_id = $r[0]['id'];
$group_hash = $r[0]['hash'];
}
else {
return false;
}
-
+
// remove group from default posting lists
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
- intval($uid)
+ intval($uid)
);
if ($r) {
$user_info = array_shift($r);
- $change = false;
+ $change = false;
if ($user_info['channel_default_group'] == $group_hash) {
$user_info['channel_default_group'] = '';
- $change = true;
+ $change = true;
}
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
- $change = true;
+ $change = true;
}
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
- $change = true;
+ $change = true;
}
if ($change) {
- q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
+ q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
WHERE channel_id = %d",
intval($user_info['channel_default_group']),
dbesc($user_info['channel_allow_gid']),
@@ -110,16 +109,16 @@ class AccessList {
}
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $ret;
}
// returns the integer id of an access group owned by $uid and named $name
// or false.
-
- static function byname($uid,$name) {
- if (! ($uid && $name)) {
+
+ static function by_name($uid, $name) {
+ if (!($uid && $name)) {
return false;
}
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
@@ -132,11 +131,11 @@ class AccessList {
return false;
}
- static function by_id($uid,$id) {
- if (! ($uid && $id)) {
+ static function by_id($uid, $id) {
+ if (!($uid && $id)) {
return false;
}
-
+
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
intval($uid),
intval($id)
@@ -147,10 +146,8 @@ class AccessList {
return false;
}
-
-
- static function rec_byhash($uid,$hash) {
- if (! ( $uid && $hash)) {
+ static function by_hash($uid, $hash) {
+ if (!($uid && $hash)) {
return false;
}
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
@@ -163,46 +160,46 @@ class AccessList {
return false;
}
-
- static function member_remove($uid,$name,$member) {
- $gid = self::byname($uid,$name);
- if (! $gid) {
- return false;
+ static function member_remove($uid, $name, $member, $gid = 0) {
+ if (!$gid) {
+ $gid = self::by_name($uid, $name);
}
- if (! ($uid && $gid && $member)) {
+
+ if (!($uid && $gid && $member)) {
return false;
}
+
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
intval($uid),
intval($gid),
dbesc($member)
);
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $r;
}
-
- static function member_add($uid,$name,$member,$gid = 0) {
- if (! $gid) {
- $gid = self::byname($uid,$name);
+ static function member_add($uid, $name, $member, $gid = 0) {
+ if (!$gid) {
+ $gid = self::by_name($uid, $name);
}
- if (! ($gid && $uid && $member)) {
+ if (!($gid && $uid && $member)) {
return false;
}
- $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
+ $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
intval($uid),
intval($gid),
dbesc($member)
);
if ($r) {
- return true; // You might question this, but
- // we indicate success because the group member was in fact created
- // -- It was just created at another time
+ return true;
+ // You might question this, but
+ // we indicate success because the group member was in fact created
+ // -- It was just created at another time
}
- else {
+ else {
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($uid),
@@ -210,15 +207,14 @@ class AccessList {
dbesc($member)
);
}
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $r;
}
-
static function members($uid, $gid) {
$ret = [];
if (intval($gid)) {
- $r = q("SELECT * FROM pgrp_member
+ $r = q("SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
intval($gid),
@@ -232,7 +228,7 @@ class AccessList {
return $ret;
}
- static function members_xchan($uid,$gid) {
+ static function members_xchan($uid, $gid) {
$ret = [];
if (intval($gid)) {
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
@@ -248,99 +244,75 @@ class AccessList {
return $ret;
}
- static function members_profile_xchan($uid,$gid) {
+ static function profile_members_xchan($uid,$gid) {
$ret = [];
- if (intval($gid)) {
+
+ 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 $rv) {
- $ret[] = $rv['xchan'];
+ if($r) {
+ foreach($r as $rr) {
+ $ret[] = $rr['xchan'];
}
}
}
return $ret;
}
+ static function select($uid, $options) {
+ $selected = $options['selected'] ?? '';
+ $form_id = $options['form_id'] ?? 'accesslist_select';
+ $label = $options['label'] ?? t('Select a privacy group');
+ $before = $options['before'] ?? [];
+ $after = $options['after'] ?? [];
-
- static function select($uid,$group = '') {
-
$grps = [];
+ $o = '';
- $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($uid)
- );
- $grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
- if ($r) {
- foreach ($r as $rr) {
- $grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
- }
+ $grps[] = [
+ 'name' => '',
+ 'id' => '0',
+ 'selected' => false
+ ];
+ if ($before) {
+ $grps[] = $before;
}
-
- return replace_macros(get_markup_template('group_selection.tpl'), [
- '$label' => t('Add new connections to this access list'),
- '$groups' => $grps
- ]);
- }
-
-
- static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
-
- $o = '';
-
- $groups = [];
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($_SESSION['uid'])
+ intval($uid)
);
- $member_of = [];
- if ($cid) {
- $member_of = self::containing(local_channel(),$cid);
- }
- if ($r) {
- foreach ($r as $rr) {
- $selected = (($group_id == $rr['id']) ? ' group-selected' : '');
-
- if ($edit) {
- $groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
- }
- else {
- $groupedit = null;
- }
-
- $groups[] = [
- 'id' => $rr['id'],
- 'enc_cid' => base64url_encode($cid),
- 'cid' => $cid,
- 'text' => $rr['gname'],
- 'selected' => $selected,
- 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
- 'edit' => $groupedit,
- 'ismember' => in_array($rr['id'],$member_of),
+ if($r) {
+ foreach($r as $rr) {
+ $grps[] = [
+ 'name' => $rr['gname'],
+ 'id' => $rr['hash'],
+ 'selected' => ($selected == $rr['hash'])
];
}
}
-
- return replace_macros(get_markup_template('group_side.tpl'), [
- '$title' => t('Lists'),
- '$edittext' => t('Edit list'),
- '$createtext' => t('Create new list'),
- '$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
- '$groups' => $groups,
- '$add' => t('add'),
- ]);
- }
+ if ($after) {
+ $grps[] = $after;
+ }
+
+ logger('select: ' . print_r($grps,true), LOGGER_DATA);
+ $o = replace_macros(get_markup_template('group_selection.tpl'), array(
+ '$label' => $label,
+ '$form_id' => $form_id,
+ '$groups' => $grps
+ ));
+
+ return $o;
+ }
static function expand($g) {
- if (! (is_array($g) && count($g))) {
+ if (!(is_array($g) && count($g))) {
return [];
}
@@ -350,8 +322,8 @@ class AccessList {
// private profile linked virtual groups
foreach ($g as $gv) {
- if (substr($gv,0,3) === 'vp.') {
- $profile_hash = substr($gv,3);
+ 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)
@@ -366,10 +338,10 @@ class AccessList {
else {
$x[] = $gv;
}
- }
+ }
if ($x) {
- stringify_array_elms($x,true);
+ stringify_array_elms($x, true);
$groups = implode(',', $x);
if ($groups) {
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
@@ -383,9 +355,8 @@ class AccessList {
return $ret;
}
-
static function member_of($c) {
- $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
+ $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
dbesc($c)
);
@@ -393,7 +364,7 @@ class AccessList {
return $r;
}
- static function containing($uid,$c) {
+ static function containing($uid, $c) {
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
intval($uid),
@@ -405,7 +376,8 @@ class AccessList {
foreach ($r as $rv)
$ret[] = $rv['gid'];
}
-
+
return $ret;
}
-} \ No newline at end of file
+
+}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 6e8344def..0c25605e7 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -11,6 +11,7 @@ use Zotlabs\Web\HTTPSig;
require_once('include/event.php');
require_once('include/html2plain.php');
+require_once('include/items.php');
class Activity {
@@ -41,9 +42,6 @@ class Activity {
if ($x['type'] === ACTIVITY_OBJ_EVENT) {
return self::fetch_event($x);
}
- if ($x['type'] === ACTIVITY_OBJ_PHOTO) {
- return self::fetch_image($x);
- }
call_hooks('encode_object', $x);
}
@@ -104,7 +102,7 @@ class Activity {
if ($x['success']) {
$m = parse_url($url);
if ($m) {
- $y = [ 'scheme' => $m['scheme'], 'host' => $m['host'] ];
+ $y = ['scheme' => $m['scheme'], 'host' => $m['host']];
if (array_key_exists('port', $m))
$y['port'] = $m['port'];
$site_url = unparse_url($y);
@@ -118,6 +116,11 @@ class Activity {
$y = json_decode($x['body'], true);
logger('returned: ' . json_encode($y, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOGGER_DEBUG);
+
+ if (ActivityStreams::is_an_actor($y['type'])) {
+ XConfig::Set($y['id'], 'system', 'actor_record', $y);
+ }
+
return json_decode($x['body'], true);
}
else {
@@ -193,6 +196,7 @@ class Activity {
}
static function fetch_image($x) {
+
$ret = [
'type' => 'Image',
'id' => $x['id'],
@@ -287,21 +291,21 @@ class Activity {
'type' => $type . 'Page',
];
- $numpages = $total / App::$pager['itemspage'];
- $lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
+ $numpages = $total / App::$pager['itemspage'];
+ $lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$url_parts = parse_url($id);
$ret['partOf'] = z_root() . '/' . $url_parts['path'];
$extra_query_args = '';
- $query_args = null;
- if(isset($url_parts['query'])) {
+ $query_args = null;
+ if (isset($url_parts['query'])) {
parse_str($url_parts['query'], $query_args);
}
- if(is_array($query_args)) {
+ if (is_array($query_args)) {
unset($query_args['page']);
- foreach($query_args as $k => $v)
+ foreach ($query_args as $k => $v)
$extra_query_args .= '&' . urlencode($k) . '=' . urlencode($v);
}
@@ -375,11 +379,33 @@ class Activity {
return $ret;
}
- static function encode_item($i) {
+ static function encode_simple_collection($items, $id, $type, $total = 0, $extra = null) {
- $ret = [];
+ $ret = [
+ 'id' => z_root() . '/' . $id,
+ 'type' => $type,
+ 'totalItems' => $total,
+ ];
+
+ if ($extra) {
+ $ret = array_merge($ret, $extra);
+ }
+ if ($items) {
+ if ($type === 'OrderedCollection') {
+ $ret['orderedItems'] = $items;
+ }
+ else {
+ $ret['items'] = $items;
+ }
+ }
+
+ return $ret;
+ }
+
+ static function encode_item($i) {
+ $ret = [];
if ($i['verb'] === ACTIVITY_FRIEND) {
// Hubzilla 'make-friend' activity, no direct mapping from AS1 to AS2 - make it a note
@@ -475,7 +501,7 @@ class Activity {
$ret['attributedTo'] = $i['author']['xchan_url'];
- if ($i['id'] != $i['parent']) {
+ if ($i['mid'] !== $i['parent_mid']) {
$ret['inReplyTo'] = ((strpos($i['thr_parent'], 'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
}
@@ -508,6 +534,7 @@ class Activity {
$top_level = (($i['mid'] === $i['parent_mid']) ? true : false);
if ($public) {
+
$ret['to'] = [ACTIVITY_PUBLIC_INBOX];
$ret['cc'] = [z_root() . '/followers/' . substr($i['author']['xchan_addr'], 0, strpos($i['author']['xchan_addr'], '@'))];
}
@@ -581,23 +608,21 @@ class Activity {
$ptr = [$ptr];
}
foreach ($ptr as $t) {
- if (!array_key_exists('type', $t))
+ if (is_array($t) && !array_key_exists('type', $t))
$t['type'] = 'Hashtag';
- if (array_key_exists('href', $t) && array_key_exists('name', $t)) {
+ if (is_array($t) && array_key_exists('href', $t) && array_key_exists('name', $t)) {
switch ($t['type']) {
case 'Hashtag':
$ret[] = ['ttype' => TERM_HASHTAG, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '#') ? substr($t['name'], 1) : $t['name'])];
break;
case 'Mention':
- $mention_type = substr($t['name'], 0, 1);
- if ($mention_type === '!') {
- $ret[] = ['ttype' => TERM_FORUM, 'url' => $t['href'], 'term' => escape_tags(substr($t['name'], 1))];
- }
- else {
- $ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
- }
+ $ret[] = ['ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '@') ? substr($t['name'], 1) : $t['name'])];
+ break;
+
+ case 'Bookmark':
+ $ret[] = ['ttype' => TERM_BOOKMARK, 'url' => $t['href'], 'term' => escape_tags($t['name'])];
break;
default:
@@ -624,14 +649,14 @@ class Activity {
}
break;
- case TERM_FORUM:
- $ret[] = ['type' => 'Mention', 'href' => $t['url'], 'name' => '!' . $t['term']];
- break;
-
case TERM_MENTION:
$ret[] = ['type' => 'Mention', 'href' => $t['url'], 'name' => '@' . $t['term']];
break;
+ case TERM_BOOKMARK:
+ $ret[] = ['type' => 'Bookmark', 'href' => $t['url'], 'name' => $t['term']];
+ break;
+
default:
break;
}
@@ -641,15 +666,15 @@ class Activity {
return $ret;
}
- static function encode_attachment($item) {
+ static function encode_attachment($item, $iconfig = false) {
$ret = [];
- if (array_key_exists('attach', $item)) {
+ if (!$iconfig && array_key_exists('attach', $item)) {
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
if ($atts) {
foreach ($atts as $att) {
- if (strpos($att['type'], 'image')) {
+ if (isset($att['type']) && strpos($att['type'], 'image')) {
$ret[] = ['type' => 'Image', 'url' => $att['href']];
}
else {
@@ -658,7 +683,7 @@ class Activity {
}
}
}
- if (array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
+ if ($iconfig && array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
foreach ($item['iconfig'] as $att) {
if ($att['sharing']) {
$value = ((is_string($att['v']) && preg_match('|^a:[0-9]+:{.*}$|s', $att['v'])) ? unserialize($att['v']) : $att['v']);
@@ -758,7 +783,9 @@ class Activity {
if (array_path_exists('object/id', $obj)) {
$obj['object'] = $obj['object']['id'];
}
- unset($obj['cc']);
+ if (isset($obj['cc'])) {
+ unset($obj['cc']);
+ }
$obj['to'] = [ACTIVITY_PUBLIC_INBOX];
$ret['object'] = $obj;
}
@@ -848,7 +875,7 @@ class Activity {
}
}
- if ($i['id'] != $i['parent']) {
+ if ($i['mid'] !== $i['parent_mid']) {
$reply = true;
// inReplyTo needs to be set in the activity for followup actions (Like, Dislike, Announce, etc.),
@@ -865,10 +892,6 @@ class Activity {
else
return [];
- if (strpos($i['body'], '[/share]') !== false) {
- $i['obj'] = null;
- }
-
if ($i['obj']) {
if (!is_array($i['obj'])) {
$i['obj'] = json_decode($i['obj'], true);
@@ -878,8 +901,10 @@ class Activity {
}
$obj = self::encode_object($i['obj']);
- if ($obj)
+
+ if ($obj) {
$ret['object'] = $obj;
+ }
else
return [];
}
@@ -911,6 +936,11 @@ class Activity {
$ret['tag'] = $t;
}
+ $a = self::encode_attachment($i, true);
+ if ($a) {
+ $ret['attachment'] = $a;
+ }
+
// addressing madness
$public = (($i['item_private']) ? false : true);
@@ -1021,7 +1051,7 @@ class Activity {
$tmp = expand_acl($i['allow_cid']);
$list = stringify_array($tmp, true);
if ($list) {
- $details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != ''");
+ $details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != '' and hubloc_deleted = 0");
if ($details) {
foreach ($details as $d) {
$ret[] = $d['hubloc_id_url'];
@@ -1068,10 +1098,11 @@ class Activity {
$ret['type'] = 'Person';
if ($c) {
- $role = get_pconfig($c['channel_id'], 'system', 'permissions_role');
- if (strpos($role, 'forum') !== false) {
+ if (get_pconfig($c['channel_id'], 'system', 'group_actor')) {
$ret['type'] = 'Group';
}
+
+ $ret['manuallyApprovesFollowers'] = ((get_pconfig($c['channel_id'], 'system', 'autoperms')) ? false : true);
}
if ($c) {
@@ -1094,16 +1125,53 @@ class Activity {
'height' => 300,
'width' => 300,
];
- $ret['url'] = $p['xchan_url'];
+
+/* This could be used to distinguish actors by protocol instead of tags,
+ * array urls are not supported by some AP projects (pixelfed) though.
+ *
+ $ret['url'] = [
+ [
+ 'type' => 'Link',
+ 'rel' => 'alternate',
+ 'mediaType' => 'application/x-zot+json',
+ 'href' => $p['xchan_url']
+ ],
+ [
+ 'type' => 'Link',
+ 'rel' => 'alternate',
+ 'mediaType' => 'application/activity+json',
+ 'href' => $p['xchan_url']
+ ],
+ [
+ 'type' => 'Link',
+ 'rel' => 'alternate', // 'me'?
+ 'mediaType' => 'text/html',
+ 'href' => $p['xchan_url']
+ ]
+ ];
+*/
+
+ $ret['url'] = $p['xchan_url'];
$ret['publicKey'] = [
- 'id' => $p['xchan_url'],
- 'owner' => $p['xchan_url'],
- 'publicKeyPem' => $p['xchan_pubkey']
+ 'id' => $p['xchan_url'],
+ 'owner' => $p['xchan_url'],
+ 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ 'publicKeyPem' => $p['xchan_pubkey']
];
+ if ($c) {
+ $ret['tag'][] = [
+ 'type' => 'PropertyValue',
+ 'name' => 'Protocol',
+ 'value' => 'zot6'
+ ];
+
+ $ret['outbox'] = z_root() . '/outbox/' . $c['channel_address'];
+ }
+
$arr = [
- 'xchan' => $p,
+ 'xchan' => $p,
'encoded' => $ret
];
@@ -1117,8 +1185,8 @@ class Activity {
$ret = [];
if ($item[$elm]) {
- if (! is_array($item[$elm])) {
- $item[$elm] = json_decode($item[$elm],true);
+ if (!is_array($item[$elm])) {
+ $item[$elm] = json_decode($item[$elm], true);
}
if ($item[$elm]['type'] === ACTIVITY_OBJ_PHOTO) {
$item[$elm]['id'] = $item['mid'];
@@ -1148,22 +1216,22 @@ class Activity {
}
$acts = [
- 'http://activitystrea.ms/schema/1.0/post' => 'Create',
- 'http://activitystrea.ms/schema/1.0/share' => 'Announce',
- 'http://activitystrea.ms/schema/1.0/update' => 'Update',
- 'http://activitystrea.ms/schema/1.0/like' => 'Like',
- 'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
- 'http://purl.org/zot/activity/dislike' => 'Dislike',
- 'http://activitystrea.ms/schema/1.0/tag' => 'Add',
- 'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
- 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
+ 'http://activitystrea.ms/schema/1.0/post' => 'Create',
+ 'http://activitystrea.ms/schema/1.0/share' => 'Announce',
+ 'http://activitystrea.ms/schema/1.0/update' => 'Update',
+ 'http://activitystrea.ms/schema/1.0/like' => 'Like',
+ 'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
+ 'http://purl.org/zot/activity/dislike' => 'Dislike',
+ 'http://activitystrea.ms/schema/1.0/tag' => 'Add',
+ 'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
+ 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
- 'http://purl.org/zot/activity/attendyes' => 'Accept',
- 'http://purl.org/zot/activity/attendno' => 'Reject',
- 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
- 'Invite' => 'Invite',
- 'Delete' => 'Delete',
- 'Undo' => 'Undo'
+ 'http://purl.org/zot/activity/attendyes' => 'Accept',
+ 'http://purl.org/zot/activity/attendno' => 'Reject',
+ 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
+ 'Invite' => 'Invite',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_mapper', $acts);
@@ -1196,22 +1264,22 @@ class Activity {
static function activity_decode_mapper($verb) {
$acts = [
- 'http://activitystrea.ms/schema/1.0/post' => 'Create',
- 'http://activitystrea.ms/schema/1.0/share' => 'Announce',
- 'http://activitystrea.ms/schema/1.0/update' => 'Update',
- 'http://activitystrea.ms/schema/1.0/like' => 'Like',
- 'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
- 'http://purl.org/zot/activity/dislike' => 'Dislike',
- 'http://activitystrea.ms/schema/1.0/tag' => 'Add',
- 'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
- 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
+ 'http://activitystrea.ms/schema/1.0/post' => 'Create',
+ 'http://activitystrea.ms/schema/1.0/share' => 'Announce',
+ 'http://activitystrea.ms/schema/1.0/update' => 'Update',
+ 'http://activitystrea.ms/schema/1.0/like' => 'Like',
+ 'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
+ 'http://purl.org/zot/activity/dislike' => 'Dislike',
+ 'http://activitystrea.ms/schema/1.0/tag' => 'Add',
+ 'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
+ 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://activitystrea.ms/schema/1.0/stop-following' => 'Unfollow',
- 'http://purl.org/zot/activity/attendyes' => 'Accept',
- 'http://purl.org/zot/activity/attendno' => 'Reject',
- 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
- 'Invite' => 'Invite',
- 'Delete' => 'Delete',
- 'Undo' => 'Undo'
+ 'http://purl.org/zot/activity/attendyes' => 'Accept',
+ 'http://purl.org/zot/activity/attendno' => 'Reject',
+ 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
+ 'Invite' => 'Invite',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_decode_mapper', $acts);
@@ -1323,7 +1391,7 @@ class Activity {
*
*/
- if (in_array($act->type, [ 'Follow', 'Invite', 'Join'])) {
+ if (in_array($act->type, ['Follow', 'Invite', 'Join'])) {
$their_follow_id = $act->id;
}
@@ -1346,8 +1414,8 @@ class Activity {
}
}
- $x = \Zotlabs\Access\PermissionRoles::role_perms('social');
- $their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
+ $x = PermissionRoles::role_perms('personal');
+ $their_perms = Permissions::FilledPerms($x['perms_connect']);
if ($contact && $contact['abook_id']) {
@@ -1421,7 +1489,7 @@ class Activity {
}
$ret = $r[0];
- $p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
+ $p = Permissions::connect_perms($channel['channel_id']);
$my_perms = $p['perms'];
$automatic = $p['automatic'];
@@ -1442,13 +1510,13 @@ class Activity {
]
);
- if($my_perms)
- foreach($my_perms as $k => $v)
- set_abconfig($channel['channel_id'],$ret['xchan_hash'],'my_perms',$k,$v);
+ if ($my_perms)
+ foreach ($my_perms as $k => $v)
+ set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'my_perms', $k, $v);
- if($their_perms)
- foreach($their_perms as $k => $v)
- set_abconfig($channel['channel_id'],$ret['xchan_hash'],'their_perms',$k,$v);
+ if ($their_perms)
+ foreach ($their_perms as $k => $v)
+ set_abconfig($channel['channel_id'], $ret['xchan_hash'], 'their_perms', $k, $v);
if ($r) {
logger("New ActivityPub follower for {$channel['channel_name']}");
@@ -1463,7 +1531,7 @@ class Activity {
'type' => NOTIFY_INTRO,
'from_xchan' => $ret['xchan_hash'],
'to_xchan' => $channel['channel_hash'],
- 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
+ 'link' => z_root() . '/connections#' . $new_connection[0]['abook_id'],
]
);
@@ -1497,9 +1565,9 @@ class Activity {
/* If there is a default group for this channel and permissions are automatic, add this member to it */
if ($channel['channel_default_group'] && $automatic) {
- $g = Group::rec_byhash($channel['channel_id'], $channel['channel_default_group']);
+ $g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']);
if ($g)
- Group::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
+ AccessList::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
}
@@ -1532,34 +1600,128 @@ class Activity {
return;
}
- static function actor_store($url, $person_obj) {
+ public static function drop($channel, $observer, $act) {
+ $r = q(
+ "select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc((is_array($act->obj)) ? $act->obj['id'] : $act->obj),
+ intval($channel['channel_id'])
+ );
+
+ if (!$r) {
+ return;
+ }
+
+ if (in_array($observer, [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
+ drop_item($r[0]['id'], false);
+ } elseif (in_array($act->actor['id'], [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
+ drop_item($r[0]['id'], false);
+ }
+ }
+
- if (!is_array($person_obj))
+ static function actor_store($url, $person_obj, $force = false) {
+
+ if (!is_array($person_obj)) {
return;
+ }
- $inbox = $person_obj['inbox'];
+ /* not implemented
+ if (array_key_exists('movedTo',$person_obj) && $person_obj['movedTo'] && ! is_array($person_obj['movedTo'])) {
+ $tgt = self::fetch($person_obj['movedTo']);
+ if (is_array($tgt)) {
+ self::actor_store($person_obj['movedTo'],$tgt);
+ ActivityPub::move($person_obj['id'],$tgt);
+ }
+ return;
+ }
+ */
+ $ap_hubloc = null;
- // invalid identity
+ $hublocs = self::get_actor_hublocs($url);
+ $has_zot_hubloc = false;
+
+ if ($hublocs) {
+ foreach ($hublocs as $hub) {
+ if ($hub['hubloc_network'] === 'activitypub') {
+ $ap_hubloc = $hub;
+ }
+ if ($hub['hubloc_network'] === 'zot6') {
+ $has_zot_hubloc = true;
+ Libzot::update_cached_hubloc($hub);
+ }
+ }
+ }
+
+ if ($ap_hubloc) {
+ // we already have a stored record. Determine if it needs updating.
+ if ($ap_hubloc['hubloc_updated'] < datetime_convert('UTC', 'UTC', ' now - 3 days') || $force) {
+ $person_obj = self::fetch($url);
+ }
+ else {
+ return;
+ }
+ }
+
+ if (isset($person_obj['id'])) {
+ $url = $person_obj['id'];
+ }
+
+ if (!$url) {
+ return;
+ }
+
+ $inbox = $person_obj['inbox'] ?? null;
+
+ // invalid AP identity
if (!$inbox || strpos($inbox, z_root()) !== false) {
return;
}
+ // store the actor record in XConfig
+
+ // we already store this in Activity::fetch()
+ // XConfig::Set($url, 'system', 'actor_record', $person_obj);
+
$name = $person_obj['name'];
- if (!$name)
+ if (!$name) {
$name = $person_obj['preferredUsername'];
- if (!$name)
+ }
+ if (!$name) {
$name = t('Unknown');
+ }
+
+ $webfinger_addr = '';
+ $m = parse_url($url);
+ if ($m) {
+ $hostname = $m['host'];
+ $baseurl = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+ $site_url = $m['scheme'] . '://' . $m['host'];
+ }
+
+ if (!empty($person_obj['preferredUsername']) && isset($parsed_url['host'])) {
+ $webfinger_addr = escape_tags($person_obj['preferredUsername']) . '@' . $hostname;
+ }
+
+ $icon = z_root() . '/' . get_default_profile_photo(300);
if ($person_obj['icon']) {
if (is_array($person_obj['icon'])) {
- if (array_key_exists('url', $person_obj['icon']))
+ if (array_key_exists('url', $person_obj['icon'])) {
$icon = $person_obj['icon']['url'];
- else
- $icon = $person_obj['icon'][0]['url'];
+ }
+ else {
+ if (is_string($person_obj['icon'][0])) {
+ $icon = $person_obj['icon'][0];
+ }
+ elseif (array_key_exists('url', $person_obj['icon'][0])) {
+ $icon = $person_obj['icon'][0]['url'];
+ }
+ }
}
- else
+ else {
$icon = $person_obj['icon'];
+ }
}
$links = false;
@@ -1576,7 +1738,7 @@ class Activity {
if ($links) {
foreach ($links as $link) {
- if (array_key_exists('mediaType', $link) && $link['mediaType'] === 'text/html') {
+ if (is_array($link) && array_key_exists('mediaType', $link) && $link['mediaType'] === 'text/html') {
$profile = $link['href'];
}
}
@@ -1592,20 +1754,6 @@ class Activity {
$profile = $url;
}
- $collections = [];
-
- if ($inbox) {
- $collections['inbox'] = $inbox;
- if (array_key_exists('outbox', $person_obj))
- $collections['outbox'] = $person_obj['outbox'];
- if (array_key_exists('followers', $person_obj))
- $collections['followers'] = $person_obj['followers'];
- if (array_key_exists('following', $person_obj))
- $collections['following'] = $person_obj['following'];
- if (array_key_exists('endpoints', $person_obj) && array_key_exists('sharedInbox', $person_obj['endpoints']))
- $collections['sharedInbox'] = $person_obj['endpoints']['sharedInbox'];
- }
-
if (array_key_exists('publicKey', $person_obj) && array_key_exists('publicKeyPem', $person_obj['publicKey'])) {
if ($person_obj['id'] === $person_obj['publicKey']['owner']) {
$pubkey = $person_obj['publicKey']['publicKeyPem'];
@@ -1615,66 +1763,68 @@ class Activity {
}
}
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ $r = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where xchan_hash = '%s'",
dbesc($url)
);
- if (!$r) {
- // create a new record
-
- xchan_store_lowlevel(
- [
- 'xchan_hash' => $url,
- 'xchan_guid' => $url,
- 'xchan_pubkey' => $pubkey,
- 'xchan_addr' => '',
- 'xchan_url' => $profile,
- 'xchan_name' => $name,
- 'xchan_name_date' => datetime_convert(),
- 'xchan_network' => 'activitypub'
- ]
- );
- }
- else {
+ if ($r) {
// Record exists. Cache existing records for one week at most
// then refetch to catch updated profile photos, names, etc.
-
- $d = datetime_convert('UTC', 'UTC', 'now - 1 week');
- if ($r[0]['xchan_name_date'] > $d)
+ $d = datetime_convert('UTC', 'UTC', 'now - 3 days');
+ if ($r[0]['hubloc_updated'] > $d && !$force) {
return;
+ }
- // update existing record
- q("update xchan set xchan_name = '%s', xchan_pubkey = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
- dbesc($name),
- dbesc($pubkey),
- dbesc('activitypub'),
+ q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s'",
dbesc(datetime_convert()),
+ dbesc($site_url)
+ );
+
+ // update existing xchan record
+ q("update xchan set xchan_name = '%s', xchan_guid = '%s', xchan_pubkey = '%s', xchan_addr = '%s', xchan_network = 'activitypub', xchan_name_date = '%s' where xchan_hash = '%s'",
+ dbesc(escape_tags($name)),
+ dbesc($url),
+ dbesc(escape_tags($pubkey)),
+ dbesc(escape_tags($webfinger_addr)),
+ dbescdate(datetime_convert()),
dbesc($url)
);
- }
- if ($collections) {
- set_xconfig($url, 'activitypub', 'collections', $collections);
+ // update existing hubloc record
+ q("update hubloc set hubloc_guid = '%s', hubloc_addr = '%s', hubloc_network = 'activitypub', hubloc_url = '%s', hubloc_host = '%s', hubloc_callback = '%s', hubloc_updated = '%s', hubloc_id_url = '%s' where hubloc_hash = '%s'",
+ dbesc($url),
+ dbesc(escape_tags($webfinger_addr)),
+ dbesc($baseurl),
+ dbesc($hostname),
+ dbesc($inbox),
+ dbescdate(datetime_convert()),
+ dbesc($profile),
+ dbesc($url)
+ );
}
+ else {
+ // create a new record
- $r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
- dbesc($url)
- );
-
- $m = parse_url($url);
- if ($m) {
- $hostname = $m['host'];
- $site_url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
- }
+ xchan_store_lowlevel(
+ [
+ 'xchan_hash' => $url,
+ 'xchan_guid' => $url,
+ 'xchan_pubkey' => escape_tags($pubkey),
+ 'xchan_addr' => $webfinger_addr,
+ 'xchan_url' => escape_tags($profile),
+ 'xchan_name' => escape_tags($name),
+ 'xchan_name_date' => datetime_convert(),
+ 'xchan_network' => 'activitypub'
+ ]
+ );
- if (!$r) {
hubloc_store_lowlevel(
[
'hubloc_guid' => $url,
'hubloc_hash' => $url,
- 'hubloc_addr' => '',
+ 'hubloc_addr' => $webfinger_addr,
'hubloc_network' => 'activitypub',
- 'hubloc_url' => $site_url,
+ 'hubloc_url' => $baseurl,
'hubloc_host' => $hostname,
'hubloc_callback' => $inbox,
'hubloc_updated' => datetime_convert(),
@@ -1684,15 +1834,18 @@ class Activity {
);
}
- q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s' AND site_update < %s - INTERVAL %s",
- dbesc(datetime_convert()),
- dbesc($site_url),
- db_utcnow(),
- db_quoteinterval('1 DAY')
- );
+ // We store all ActivityPub actors we can resolve. Some of them may be able to communicate over Zot6. Find them.
+ // Adding zot discovery urls to the actor record will cause federation to fail with the 20-30 projects which don't accept arrays in the url field.
- if (!$icon)
- $icon = z_root() . '/' . get_default_profile_photo(300);
+ $actor_protocols = self::get_actor_protocols($person_obj);
+ if (!$has_zot_hubloc && in_array('zot6', $actor_protocols)) {
+ $zx = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6'",
+ dbesc($url)
+ );
+ if (!$zx) {
+ Master::Summon(['Gprobe', bin2hex($url)]);
+ }
+ }
$photos = import_xchan_photo($icon, $url);
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'",
@@ -1741,15 +1894,10 @@ class Activity {
static function create_note($channel, $observer_hash, $act) {
- $s = [];
-
- // Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
- // They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
- // This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
- $pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
+ $s = [];
$is_sys_channel = is_sys_channel($channel['channel_id']);
+ $parent = ((array_key_exists('inReplyTo', $act->obj)) ? urldecode($act->obj['inReplyTo']) : '');
- $parent = ((array_key_exists('inReplyTo', $act->obj)) ? urldecode($act->obj['inReplyTo']) : '');
if ($parent) {
$r = q("select * from item where uid = %d and ( mid = '%s' or mid = '%s' ) limit 1",
@@ -1764,7 +1912,7 @@ class Activity {
}
if ($r[0]['owner_xchan'] === $channel['channel_hash']) {
- if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
+ if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
logger('no comment permission.');
return;
}
@@ -1776,17 +1924,27 @@ class Activity {
}
else {
- if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
- logger('no permission');
+ if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
+ logger('no send_stream permission');
return;
}
$s['owner_xchan'] = $s['author_xchan'] = $observer_hash;
}
- $abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
- dbesc($observer_hash),
- intval($channel['channel_id'])
- );
+ if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips)))
+ $s['item_private'] = 1;
+
+
+ if (array_key_exists('directMessage', $act->obj) && intval($act->obj['directMessage'])) {
+ $s['item_private'] = 2;
+ }
+
+ if (intval($s['item_private']) === 2) {
+ if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'post_mail')) {
+ logger('no post_mail permission');
+ return;
+ }
+ }
$content = self::get_content($act->obj);
@@ -1865,15 +2023,23 @@ class Activity {
}
if ($channel['channel_system']) {
- if (!MessageFilter::evaluate($s, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
+ $incl = get_config('system','pubstream_incl');
+ $excl = get_config('system','pubstream_excl');
+
+ if(($incl || $excl) && !MessageFilter::evaluate($s, $incl, $excl)) {
logger('post is filtered');
return;
}
}
+ $abook = q("select * from abook where (abook_xchan = '%s' OR abook_xchan = '%s') and abook_channel = %d ",
+ dbesc($s['author_xchan']),
+ dbesc($s['owner_xchan']),
+ intval($channel['channel_id'])
+ );
if ($abook) {
- if (!post_is_importable($s, $abook[0])) {
+ if (!post_is_importable($channel['channel_id'], $s, $abook)) {
logger('post is filtered');
return;
}
@@ -1931,14 +2097,6 @@ class Activity {
}
}
- if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips)))
- $s['item_private'] = 1;
-
-
- if (array_key_exists('directMessage', $act->obj) && intval($act->obj['directMessage'])) {
- $s['item_private'] = 2;
- }
-
set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
if ($parent) {
set_iconfig($s, 'activitypub', 'rawmsg', $act->raw, 1);
@@ -1995,6 +2153,7 @@ class Activity {
}
static function update_poll($item, $post) {
+
$multi = false;
$mid = $post['mid'];
$content = $post['title'];
@@ -2079,7 +2238,8 @@ class Activity {
dbesc(datetime_convert()),
intval($item['id'])
);
- Master::Summon(['Notifier', 'wall-new', $item['id']]);
+
+ Master::Summon(['Notifier', 'wall-new', $item['id'], $post['mid'] /* trick queueworker de-duplication */ ]);
return true;
}
@@ -2088,38 +2248,64 @@ class Activity {
static function decode_note($act) {
+ $response_activity = false;
+
+ $s = [];
+
+ // These activities should have been handled separately in the Inbox module and should not be turned into posts
+
+ if (
+ in_array($act->type, ['Follow', 'Accept', 'Reject', 'Create', 'Update']) &&
+ is_array($act->obj) &&
+ array_key_exists('type', $act->obj) &&
+ ($act->obj['type'] === 'Follow' || ActivityStreams::is_an_actor($act->obj['type']))
+ ) {
+ return false;
+ }
+
// Within our family of projects, Follow/Unfollow of a thread is an internal activity which should not be transmitted,
// hence if we receive it - ignore or reject it.
// Unfollow is not defined by ActivityStreams, which prefers Undo->Follow.
// This may have to be revisited if AP projects start using Follow for objects other than actors.
- if (in_array($act->type, [ 'Follow', 'Unfollow' ])) {
+ if (in_array($act->type, ['Follow', 'Unfollow'])) {
return false;
}
- $response_activity = false;
+ if (!isset($act->actor['id'])) {
+ logger('No actor!');
+ return false;
+ }
- $s = [];
+ // ensure we store the original actor
+ self::actor_store($act->actor['id'], $act->actor);
+
+ $s['owner_xchan'] = $act->actor['id'];
+ $s['author_xchan'] = $act->actor['id'];
if (is_array($act->obj)) {
$content = self::get_content($act->obj);
}
- $s['owner_xchan'] = $act->actor['id'];
- $s['author_xchan'] = $act->actor['id'];
+ $s['mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
- // ensure we store the original actor
- self::actor_store($act->actor['id'], $act->actor);
+ if (!$s['mid']) {
+ return false;
+ }
+
+ // Friendica sends the diaspora guid in a nonstandard field via AP
+ // If no uuid is provided we will create an uuid v5 from the mid
+ $s['uuid'] = ((is_array($act->obj) && isset($act->obj['diaspora:guid'])) ? $act->obj['diaspora:guid'] : uuid_from_url($s['mid']));
- $s['mid'] = $act->obj['id'];
- $s['uuid'] = $act->obj['diaspora:guid'];
$s['parent_mid'] = $act->parent_id;
if (array_key_exists('published', $act->data)) {
- $s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
+ $s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
+ $s['commented'] = $s['created'];
}
elseif (array_key_exists('published', $act->obj)) {
- $s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
+ $s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
+ $s['commented'] = $s['created'];
}
if (array_key_exists('updated', $act->data)) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
@@ -2134,13 +2320,18 @@ class Activity {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
}
+ if ($act->type === 'Invite' && is_array($act->obj) && array_key_exists('type', $act->obj) && $act->obj['type'] === 'Event') {
+ $s['mid'] = $s['parent_mid'] = $act->id;
+ }
+
if (ActivityStreams::is_response_activity($act->type)) {
$response_activity = true;
$s['mid'] = $act->id;
- // $s['parent_mid'] = $act->obj['id'];
- $s['uuid'] = $act->data['diaspora:guid'];
+ $s['uuid'] = ((is_array($act->data) && isset($act->data['diaspora:guid'])) ? $act->data['diaspora:guid'] : uuid_from_url($s['mid']));
+
+ $s['parent_mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
// over-ride the object timestamp with the activity
@@ -2153,8 +2344,8 @@ class Activity {
}
$obj_actor = ((isset($act->obj['actor'])) ? $act->obj['actor'] : $act->get_actor('attributedTo', $act->obj));
- // ensure we store the original actor
+ // ensure we store the original actor
self::actor_store($obj_actor['id'], $obj_actor);
$mention = self::get_actor_bbmention($obj_actor['id']);
@@ -2183,23 +2374,61 @@ class Activity {
}
if ($act->type === 'Announce') {
- $content['content'] = sprintf(t('&#x1f501; Repeated %1$s\'s %2$s'), $mention, $act->obj['type']);
+ $s['author_xchan'] = $obj_actor['id'];
+ $s['mid'] = $act->obj['id'];
+ $s['parent_mid'] = $act->obj['id'];
}
if ($act->type === 'emojiReaction') {
$content['content'] = (($act->tgt && $act->tgt['type'] === 'Image') ? '[img=32x32]' . $act->tgt['url'] . '[/img]' : '&#x' . $act->tgt['name'] . ';');
}
}
- if (! array_key_exists('created', $s))
+ $s['item_thread_top'] = 0;
+ $s['comment_policy'] = 'authenticated';
+
+ if ($s['mid'] === $s['parent_mid']) {
+ $s['item_thread_top'] = 1;
+
+ // it is a parent node - decode the comment policy info if present
+ if (isset($act->obj['commentPolicy'])) {
+ $until = strpos($act->obj['commentPolicy'], 'until=');
+ if ($until !== false) {
+ $s['comments_closed'] = datetime_convert('UTC', 'UTC', substr($act->obj['commentPolicy'], $until + 6));
+ if ($s['comments_closed'] < datetime_convert()) {
+ $s['nocomment'] = true;
+ }
+ }
+
+ $remainder = substr($act->obj['commentPolicy'], 0, (($until) ? $until : strlen($act->obj['commentPolicy'])));
+ if ($remainder) {
+ $s['comment_policy'] = $remainder;
+ }
+ if (!(isset($item['comment_policy']) && strlen($item['comment_policy']))) {
+ $s['comment_policy'] = 'contacts';
+ }
+ }
+ }
+
+ if (!array_key_exists('created', $s))
$s['created'] = datetime_convert();
- if (! array_key_exists('edited', $s))
+ if (!array_key_exists('edited', $s))
$s['edited'] = $s['created'];
$s['title'] = (($response_activity) ? EMPTY_STR : self::bb_content($content, 'name'));
$s['summary'] = self::bb_content($content, 'summary');
$s['body'] = ((self::bb_content($content, 'bbcode') && (!$response_activity)) ? self::bb_content($content, 'bbcode') : self::bb_content($content, 'content'));
+ if (isset($act->obj['quoteUrl'])) {
+ $quote_bbcode = self::get_quote_bbcode($act->obj['quoteUrl']);
+
+ if ($s['body']) {
+ $s['body'] .= "\r\n\r\n";
+ }
+
+ $s['body'] .= $quote_bbcode;
+ }
+
$s['verb'] = self::activity_decode_mapper($act->type);
// Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
@@ -2216,6 +2445,12 @@ class Activity {
$s['obj_type'] = ACTIVITY_OBJ_COMMENT;
}
+ $s['obj'] = $act->obj;
+ if (is_array($s['obj']) && array_path_exists('actor/id', $s['obj'])) {
+ $s['obj']['actor'] = $s['obj']['actor']['id'];
+ }
+
+/*
$eventptr = null;
if ($act->obj['type'] === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event') {
@@ -2236,19 +2471,19 @@ class Activity {
$s['obj']['asld'] = $eventptr;
$s['obj']['type'] = ACTIVITY_OBJ_EVENT;
$s['obj']['id'] = $eventptr['id'];
- $s['obj']['title'] = $eventptr['name'];
+ $s['obj']['title'] = html2plain($eventptr['name']);
if (strpos($act->obj['startTime'], 'Z'))
$s['obj']['adjust'] = true;
else
- $s['obj']['adjust'] = false;
+ $s['obj']['adjust'] = true;
$s['obj']['dtstart'] = datetime_convert('UTC', 'UTC', $eventptr['startTime']);
if ($act->obj['endTime'])
$s['obj']['dtend'] = datetime_convert('UTC', 'UTC', $eventptr['endTime']);
else
$s['obj']['nofinish'] = true;
- $s['obj']['description'] = $eventptr['content'];
+ $s['obj']['description'] = html2bbcode($eventptr['content']);
if (array_path_exists('location/content', $eventptr))
$s['obj']['location'] = $eventptr['location']['content'];
@@ -2257,6 +2492,7 @@ class Activity {
else {
$s['obj'] = $act->obj;
}
+*/
$generator = $act->get_property_obj('generator');
if ((!$generator) && (!$response_activity)) {
@@ -2268,7 +2504,6 @@ class Activity {
$s['app'] = escape_tags($generator['name']);
}
-
if (!$response_activity) {
$a = self::decode_taxonomy($act->obj);
if ($a) {
@@ -2297,7 +2532,7 @@ class Activity {
if (array_key_exists('type', $act->obj)) {
if ($act->obj['type'] === 'Note' && $s['attach']) {
- $s['body'] .= self::bb_attach($s['attach'], $s['body']);
+ $s['body'] = self::bb_attach($s['attach'], $s['body']) . $s['body'];
}
if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
@@ -2325,31 +2560,57 @@ class Activity {
'video/webm'
];
- $mps = [];
+ $mps = [];
+ $poster = null;
+ $ptr = null;
+
+ // try to find a poster to display on the video element
+
+ if (array_key_exists('icon',$act->obj)) {
+ if (is_array($act->obj['icon'])) {
+ if (array_key_exists(0,$act->obj['icon'])) {
+ $ptr = $act->obj['icon'];
+ }
+ else {
+ $ptr = [ $act->obj['icon'] ];
+ }
+ }
+ if ($ptr) {
+ foreach ($ptr as $foo) {
+ if (is_array($foo) && array_key_exists('type',$foo) && $foo['type'] === 'Image' && is_string($foo['url'])) {
+ $poster = $foo['url'];
+ }
+ }
+ }
+ }
+
+ $tag = (($poster) ? '[video poster=&quot;' . $poster . '&quot;]' : '[video]' );
$ptr = null;
- if (array_key_exists('url', $act->obj)) {
+ if (array_key_exists('url',$act->obj)) {
if (is_array($act->obj['url'])) {
- if (array_key_exists(0, $act->obj['url'])) {
+ if (array_key_exists(0,$act->obj['url'])) {
$ptr = $act->obj['url'];
}
else {
- $ptr = [$act->obj['url']];
+ $ptr = [ $act->obj['url'] ];
}
- foreach ($ptr as $vurl) {
- // peertube uses the non-standard element name 'mimeType' here
- if (array_key_exists('mimeType', $vurl)) {
- if (in_array($vurl['mimeType'], $vtypes)) {
- if (!array_key_exists('width', $vurl)) {
- $vurl['width'] = 0;
- }
- $mps[] = $vurl;
+ // handle peertube's weird url link tree if we find it here
+ // 0 => html link, 1 => application/x-mpegURL with 'tag' set to an array of actual media links
+ foreach ($ptr as $idex) {
+ if (is_array($idex) && array_key_exists('mediaType',$idex)) {
+ if ($idex['mediaType'] === 'application/x-mpegURL' && isset($idex['tag']) && is_array($idex['tag'])) {
+ $ptr = $idex['tag'];
+ break;
}
}
- elseif (array_key_exists('mediaType', $vurl)) {
+ }
+
+ foreach ($ptr as $vurl) {
+ if (array_key_exists('mediaType',$vurl)) {
if (in_array($vurl['mediaType'], $vtypes)) {
- if (!array_key_exists('width', $vurl)) {
- $vurl['width'] = 0;
+ if (! array_key_exists('height',$vurl)) {
+ $vurl['height'] = 0;
}
$mps[] = $vurl;
}
@@ -2357,17 +2618,18 @@ class Activity {
}
}
if ($mps) {
- usort($mps, [__CLASS__, 'vid_sort']);
+ usort($mps,[ '\Zotlabs\Lib\Activity', 'vid_sort' ]);
foreach ($mps as $m) {
- if (intval($m['width']) < 500 && self::media_not_in_body($m['href'], $s['body'])) {
- $s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
+ if (intval($m['height']) < 500 && Activity::media_not_in_body($m['href'],$s['body'])) {
+ $s['body'] = $tag . $m['href'] . '[/video]' . "\n\n" . $s['body'];
break;
}
}
}
- elseif (is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'], $s['body'])) {
- $s['body'] .= "\n\n" . '[video]' . $act->obj['url'] . '[/video]';
+ elseif (is_string($act->obj['url']) && Activity::media_not_in_body($act->obj['url'],$s['body'])) {
+ $s['body'] = $tag . $act->obj['url'] . '[/video]' . "\n\n" . $s['body'];
}
+
}
}
@@ -2391,19 +2653,19 @@ class Activity {
}
foreach ($ptr as $vurl) {
if (in_array($vurl['mediaType'], $atypes) && self::media_not_in_body($vurl['href'], $s['body'])) {
- $s['body'] .= "\n\n" . '[audio]' . $vurl['href'] . '[/audio]';
+ $s['body'] = '[audio]' . $vurl['href'] . '[/audio]' . "\n\n" . $s['body'];
break;
}
}
}
elseif (is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'], $s['body'])) {
- $s['body'] .= "\n\n" . '[audio]' . $act->obj['url'] . '[/audio]';
+ $s['body'] = '[audio]' . $act->obj['url'] . '[/audio]' . "\n\n" . $s['body'];
}
}
}
- if ($act->obj['type'] === 'Image') {
+ if ($act->obj['type'] === 'Image' && strpos($s['body'], 'zrl=') === false) {
$ptr = null;
@@ -2472,7 +2734,6 @@ class Activity {
}
}
-
if (in_array($act->obj['type'], ['Note', 'Article', 'Page'])) {
$ptr = null;
@@ -2515,13 +2776,78 @@ class Activity {
}
}
- set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
+ $ap_rawmsg = '';
+ $diaspora_rawmsg = '';
+ $raw_arr = [];
- $parent = (($s['parent_mid'] && $s['parent_mid'] === $s['mid']) ? true : false);
- if ($parent) {
+ $raw_arr = json_decode($act->raw, true);
+
+ // This is a zot6 packet and the raw activitypub or diaspora message json
+ // is possibly available in the attachement.
+ if (array_key_exists('signed', $raw_arr) && is_array($act->data['attachment'])) {
+ foreach($act->data['attachment'] as $a) {
+ if (
+ isset($a['type']) && $a['type'] === 'PropertyValue' &&
+ isset($a['name']) && $a['name'] === 'zot.activitypub.rawmsg' &&
+ isset($a['value'])
+ ) {
+ $ap_rawmsg = $a['value'];
+ }
+ if (
+ isset($a['type']) && $a['type'] === 'PropertyValue' &&
+ isset($a['name']) && $a['name'] === 'zot.diaspora.fields' &&
+ isset($a['value'])
+ ) {
+ $diaspora_rawmsg = $a['value'];
+ }
+ }
+ }
+
+ // old style: can be removed after most hubs are on 7.0.2
+ elseif (array_key_exists('signed', $raw_arr) && is_array($act->obj) && is_array($act->obj['attachment'])) {
+ foreach($act->obj['attachment'] as $a) {
+ if (
+ isset($a['type']) && $a['type'] === 'PropertyValue' &&
+ isset($a['name']) && $a['name'] === 'zot.activitypub.rawmsg' &&
+ isset($a['value'])
+ ) {
+ $ap_rawmsg = $a['value'];
+ }
+
+ if (
+ isset($a['type']) && $a['type'] === 'PropertyValue' &&
+ isset($a['name']) && $a['name'] === 'zot.diaspora.fields' &&
+ isset($a['value'])
+ ) {
+ $diaspora_rawmsg = $a['value'];
+ }
+ }
+ }
+
+ // catch the likes
+ if (!$ap_rawmsg && $response_activity) {
+ $ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
+ }
+ // end old style
+
+ if (!$ap_rawmsg && array_key_exists('signed', $raw_arr)) {
+ // zap
+ $ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
+ }
+
+ if ($ap_rawmsg) {
+ set_iconfig($s, 'activitypub', 'rawmsg', $ap_rawmsg, 1);
+ }
+ elseif (!array_key_exists('signed', $raw_arr)) {
set_iconfig($s, 'activitypub', 'rawmsg', $act->raw, 1);
}
+ if ($diaspora_rawmsg) {
+ set_iconfig($s, 'diaspora', 'fields', $diaspora_rawmsg, 1);
+ }
+
+ set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
+
$hookinfo = [
'act' => $act,
's' => $s
@@ -2545,18 +2871,6 @@ class Activity {
return;
}*/
- // Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
- // They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
- // This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
-
- $pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
-
- // TODO: this his handled in pubcrawl atm.
- // very unpleasant and imperfect way of determining a Mastodon DM
- /*if ($act->raw_recips && array_key_exists('to',$act->raw_recips) && is_array($act->raw_recips['to']) && count($act->raw_recips['to']) === 1 && $act->raw_recips['to'][0] === channel_url($channel) && ! $act->raw_recips['cc']) {
- $item['item_private'] = 2;
- }*/
-
if ($item['parent_mid'] && $item['parent_mid'] !== $item['mid']) {
$is_child_node = true;
}
@@ -2576,6 +2890,17 @@ class Activity {
// set the owner to the owner of the parent
$item['owner_xchan'] = $p[0]['owner_xchan'];
+ // quietly reject group comment boosts by group owner
+ // (usually only sent via ActivityPub so groups will work on microblog platforms)
+ // This catches those activities if they slipped in via a conversation fetch
+
+ if ($p[0]['parent_mid'] !== $item['parent_mid']) {
+ if ($item['verb'] === 'Announce' && $item['author_xchan'] === $item['owner_xchan']) {
+ logger('group boost activity by group owner rejected');
+ return;
+ }
+ }
+
// check permissions against the author, not the sender
$allowed = perm_is_allowed($channel['channel_id'], $item['author_xchan'], 'post_comments');
if ((!$allowed)/* && $permit_mentions*/) {
@@ -2611,7 +2936,7 @@ class Activity {
$allowed = true;
// reject public stream comments that weren't sent by the conversation owner
- if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
+ if ($is_sys_channel && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
$allowed = false;
}
}
@@ -2626,7 +2951,7 @@ class Activity {
// The $item['item_fetched'] flag is set in fetch_and_store_parents().
// In this case we should check against author permissions because sender is not owner.
- if (perm_is_allowed($channel['channel_id'], (($item['item_fetched']) ? $item['author_xchan'] : $observer_hash), 'send_stream') || ($is_sys_channel && $pubstream)) {
+ if (perm_is_allowed($channel['channel_id'], (($item['item_fetched']) ? $item['author_xchan'] : $observer_hash), 'send_stream') || $is_sys_channel) {
$allowed = true;
}
// TODO: not implemented
@@ -2641,6 +2966,11 @@ class Activity {
$allowed = true;
}
+ if (intval($item['item_private']) === 2) {
+ if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'post_mail')) {
+ $allowed = false;
+ }
+ }
if ($is_sys_channel) {
@@ -2705,19 +3035,23 @@ class Activity {
return;
if ($channel['channel_system']) {
- if (!MessageFilter::evaluate($item, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
+ $incl = get_config('system','pubstream_incl');
+ $excl = get_config('system','pubstream_excl');
+
+ if(($incl || $excl) && !MessageFilter::evaluate($item, $incl, $excl)) {
logger('post is filtered');
return;
}
}
- $abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
- dbesc($observer_hash),
+ $abook = q("select * from abook where ( abook_xchan = '%s' OR abook_xchan = '%s') and abook_channel = %d ",
+ dbesc($item['author_xchan']),
+ dbesc($item['owner_xchan']),
intval($channel['channel_id'])
);
if ($abook) {
- if (!post_is_importable($item, $abook[0])) {
+ if (!post_is_importable($channel['channel_id'], $item, $abook)) {
logger('post is filtered');
return;
}
@@ -2764,7 +3098,7 @@ class Activity {
$fetch = false;
// TODO: debug
// if (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && (PConfig::Get($channel['channel_id'],'system','hyperdrive',true) || $act->type === 'Announce')) {
- if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || ($is_sys_channel && $pubstream)) {
+ if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) {
$fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false);
}
if ($fetch) {
@@ -2787,6 +3121,19 @@ class Activity {
$item['thr_parent'] = $parent[0]['parent_mid'];
}
$item['parent_mid'] = $parent[0]['parent_mid'];
+ //$item['item_private'] = $parent[0]['item_private'];
+
+ }
+
+ // An ugly and imperfect way to recognise a mastodon direct message
+ if (
+ $item['item_private'] === 1 &&
+ !isset($act->raw_recips['cc']) &&
+ is_array($act->raw_recips['to']) &&
+ in_array(channel_url($channel), $act->raw_recips['to']) &&
+ !in_array($act->actor['followers'], $act->raw_recips['to'])
+ ) {
+ $item['item_private'] = 2;
}
// TODO: not implemented
@@ -2797,6 +3144,12 @@ class Activity {
intval($item['uid'])
);
if ($r) {
+
+ // If we already have the item, dismiss its announce
+ if ($act->type === 'Announce') {
+ return;
+ }
+
if ($item['edited'] > $r[0]['edited']) {
$item['id'] = $r[0]['id'];
$x = item_store_update($item);
@@ -2813,12 +3166,12 @@ class Activity {
logger('topfetch', LOGGER_DEBUG);
// if the thread owner is a connnection, we will already receive any additional comments to their posts
// but if they are not we can try to fetch others in the background
- $x = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
+ $connected = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
intval($channel['channel_id']),
dbesc($parent[0]['owner_xchan'])
);
- if (!$x) {
+ if (!$connected) {
// determine if the top-level post provides a replies collection
if ($parent[0]['obj']) {
$parent[0]['obj'] = json_decode($parent[0]['obj'], true);
@@ -3070,18 +3423,13 @@ class Activity {
}
+/* this is deprecated and not used anymore
static function announce_note($channel, $observer_hash, $act) {
- $s = [];
-
+ $s = [];
$is_sys_channel = is_sys_channel($channel['channel_id']);
- // Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
- // They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
- // This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
- $pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
-
- if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream)) {
+ if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) {
logger('no permission');
return;
}
@@ -3206,6 +3554,7 @@ class Activity {
}
}
+*/
static function like_note($channel, $observer_hash, $act) {
@@ -3338,7 +3687,7 @@ class Activity {
$ret = false;
foreach ($attach as $a) {
- if (array_key_exists('type',$a) && stripos($a['type'], 'image') !== false) {
+ if (array_key_exists('type', $a) && stripos($a['type'], 'image') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
}
@@ -3426,7 +3775,49 @@ class Activity {
$event['nofinish'] = true;
}
}
+/*
+ $eventptr = null;
+
+ if ($act->obj['type'] === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event') {
+ $eventptr = $act->obj['object'];
+ $s['mid'] = $s['parent_mid'] = $act->obj['id'];
+ }
+
+ if ($act->obj['type'] === 'Event') {
+ if ($act->type === 'Invite') {
+ $s['mid'] = $s['parent_mid'] = $act->id;
+ }
+ $eventptr = $act->obj;
+ }
+
+ if ($eventptr) {
+ $s['obj'] = [];
+ $s['obj']['asld'] = $eventptr;
+ $s['obj']['type'] = ACTIVITY_OBJ_EVENT;
+ $s['obj']['id'] = $eventptr['id'];
+ $s['obj']['title'] = html2plain($eventptr['name']);
+
+ if (strpos($act->obj['startTime'], 'Z'))
+ $s['obj']['adjust'] = true;
+ else
+ $s['obj']['adjust'] = true;
+
+ $s['obj']['dtstart'] = datetime_convert('UTC', 'UTC', $eventptr['startTime']);
+ if ($act->obj['endTime'])
+ $s['obj']['dtend'] = datetime_convert('UTC', 'UTC', $eventptr['endTime']);
+ else
+ $s['obj']['nofinish'] = true;
+ $s['obj']['description'] = html2bbcode($eventptr['content']);
+
+ if (array_path_exists('location/content', $eventptr))
+ $s['obj']['location'] = $eventptr['location']['content'];
+
+ }
+ else {
+ $s['obj'] = $act->obj;
+ }
+*/
foreach (['name', 'summary', 'content'] as $a) {
if (($x = self::get_textfield($act, $a)) !== false) {
$content[$a] = $x;
@@ -3496,7 +3887,7 @@ class Activity {
static function find_best_identity($xchan) {
if (filter_var($xchan, FILTER_VALIDATE_URL)) {
- $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' and hubloc_network in ('zot6', 'zot') and hubloc_deleted = 0",
+ $r = q("SELECT hubloc_hash, hubloc_network FROM hubloc WHERE hubloc_id_url = '%s' AND hubloc_network IN ('zot6', 'activitypub') AND hubloc_deleted = 0",
dbesc($xchan)
);
if ($r) {
@@ -3510,4 +3901,116 @@ class Activity {
}
+ static function get_cached_actor($id) {
+
+ // remove any fragments like #main-key since these won't be present in our cached data
+ $cache_url = ((strpos($id, '#')) ? substr($id, 0, strpos($id, '#')) : $id);
+ $actor = XConfig::Get($cache_url, 'system', 'actor_record');
+
+ if ($actor) {
+ return $actor;
+ }
+
+ // try other get_cached_actor providers (e.g. diaspora)
+ $hookdata = [
+ 'id' => $id,
+ 'actor' => null
+ ];
+
+ call_hooks('get_cached_actor_provider', $hookdata);
+
+ return $hookdata['actor'];
+ }
+
+ static function get_actor_hublocs($url, $options = 'all') {
+
+ switch ($options) {
+ case 'activitypub':
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' and hubloc_deleted = 0 ",
+ dbesc($url)
+ );
+ break;
+ case 'zot6':
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_id_url = '%s' and hubloc_deleted = 0 ",
+ dbesc($url)
+ );
+ break;
+ case 'all':
+ default:
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where ( hubloc_id_url = '%s' OR hubloc_hash = '%s' ) and hubloc_deleted = 0 ",
+ dbesc($url),
+ dbesc($url)
+ );
+ break;
+ }
+
+ return $hublocs;
+ }
+
+ static function get_actor_collections($url) {
+ $ret = [];
+ $actor_record = XConfig::Get($url, 'system', 'actor_record');
+ if (!$actor_record) {
+ return $ret;
+ }
+
+ foreach (['inbox', 'outbox', 'followers', 'following'] as $collection) {
+ if (isset($actor_record[$collection]) && $actor_record[$collection]) {
+ $ret[$collection] = $actor_record[$collection];
+ }
+ }
+ if (array_path_exists('endpoints/sharedInbox', $actor_record) && $actor_record['endpoints']['sharedInbox']) {
+ $ret['sharedInbox'] = $actor_record['endpoints']['sharedInbox'];
+ }
+
+ return $ret;
+ }
+
+
+ static function get_actor_protocols($actor) {
+ $ret = [];
+
+ if (!array_key_exists('tag', $actor) || empty($actor['tag']) || !is_array($actor['tag'])) {
+ return $ret;
+ }
+
+ foreach ($actor['tag'] as $t) {
+ if ((isset($t['type']) && $t['type'] === 'PropertyValue') &&
+ (isset($t['name']) && $t['name'] === 'Protocol') &&
+ (isset($t['value']) && in_array($t['value'], ['zot6', 'activitypub', 'diaspora']))
+ ) {
+ $ret[] = $t['value'];
+ }
+ }
+
+ return $ret;
+ }
+
+ static function get_quote_bbcode($url) {
+
+ $ret = '';
+
+ $a = self::fetch($url);
+ if ($a) {
+ $act = new ActivityStreams($a);
+
+ if ($act->is_valid()) {
+ $content = self::get_content($act->obj);
+
+ $ret .= "[share author='" . urlencode($act->actor['name']) .
+ "' profile='" . $act->actor['id'] .
+ "' avatar='" . $act->actor['icon']['url'] .
+ "' link='" . $act->obj['id'] .
+ "' auth='" . ((is_matrix_url($act->actor['id'])) ? 'true' : 'false') .
+ "' posted='" . $act->obj['published'] .
+ "' message_id='" . $act->obj['id'] .
+ "']";
+ $ret .= self::bb_content($content, 'content');
+ $ret .= '[/share]';
+ }
+ }
+
+ return $ret;
+ }
+
}
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index a5fb4a756..1c278f2ee 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -11,6 +11,7 @@ class ActivityStreams {
public $raw = null;
public $data = null;
+ public $meta = null;
public $valid = false;
public $deleted = false;
public $id = '';
@@ -36,10 +37,14 @@ class ActivityStreams {
*/
function __construct($string) {
+ if(!$string)
+ return;
+
$this->raw = $string;
if (is_array($string)) {
$this->data = $string;
+ $this->raw = json_encode($string, JSON_UNESCAPED_SLASHES);
}
else {
$this->data = json_decode($string, true);
@@ -56,10 +61,10 @@ class ActivityStreams {
if ($ret['signer']) {
$saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
$this->data = $tmp;
- $this->data['signer'] = $ret['signer'];
- $this->data['signed_data'] = $saved;
+ $this->meta['signer'] = $ret['signer'];
+ $this->meta['signed_data'] = $saved;
if ($ret['hubloc']) {
- $this->data['hubloc'] = $ret['hubloc'];
+ $this->meta['hubloc'] = $ret['hubloc'];
}
}
}
@@ -87,7 +92,7 @@ class ActivityStreams {
$this->ldsig = $this->get_compound_property('signature');
if ($this->ldsig) {
- $this->signer = $this->get_compound_property('creator', $this->ldsig);
+ $this->signer = $this->get_actor('creator', $this->ldsig);
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
}
@@ -285,7 +290,7 @@ class ActivityStreams {
if (!$s) {
return false;
}
- return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
+ return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
}
/**
@@ -300,16 +305,8 @@ class ActivityStreams {
function get_actor($property, $base = '', $namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
if ($this->is_url($x)) {
-
- // SECURITY: If we have already stored the actor profile, re-generate it
- // from cached data - don't refetch it from the network
-
- $r = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where hubloc_network in ('zot6', 'activitypub') and hubloc_id_url = '%s'",
- dbesc($x)
- );
- if ($r) {
- $y = Activity::encode_person($r[0]);
- $y['cached'] = true;
+ $y = Activity::get_cached_actor($x);
+ if ($y) {
return $y;
}
}
@@ -351,10 +348,10 @@ class ActivityStreams {
if ($ret['signer']) {
$saved = json_encode($x, JSON_UNESCAPED_SLASHES);
$x = $tmp;
- $x['signer'] = $ret['signer'];
- $x['signed_data'] = $saved;
+ $x['meta']['signer'] = $ret['signer'];
+ $x['meta']['signed_data'] = $saved;
if ($ret['hubloc']) {
- $x['hubloc'] = $ret['hubloc'];
+ $x['meta']['hubloc'] = $ret['hubloc'];
}
}
}
@@ -425,15 +422,19 @@ class ActivityStreams {
static function get_accept_header_string($channel = null) {
+ $ret = '';
+
$hookdata = [];
if ($channel)
$hookdata['channel'] = $channel;
- $hookdata['data'] = 'application/x-zot-activity+json';
+ $hookdata['data'] = ['application/x-zot-activity+json'];
call_hooks('get_accept_header_string', $hookdata);
- return $hookdata['data'];
+ $ret = implode(', ', $hookdata['data']);
+
+ return $ret;
}
diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php
index 5ef4ecc8d..98ebc546a 100644
--- a/Zotlabs/Lib/Apps.php
+++ b/Zotlabs/Lib/Apps.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Lib;
-use Zotlabs\Lib\Libsync;
+use App;
require_once('include/plugin.php');
require_once('include/channel.php');
@@ -21,9 +21,10 @@ class Apps {
* @brief
*
* @param boolean $translate (optional) default true
+ * @param boolean $sync (optional) default false used if called from sync_sysapps()
* @return array
*/
- static public function get_system_apps($translate = true) {
+ static public function get_system_apps($translate = true, $sync = false) {
$ret = [];
if(is_dir('apps'))
@@ -33,7 +34,7 @@ class Apps {
if($files) {
foreach($files as $f) {
- $x = self::parse_app_description($f,$translate);
+ $x = self::parse_app_description($f, $translate, $sync);
if($x) {
$ret[] = $x;
}
@@ -45,7 +46,7 @@ class Apps {
$path = explode('/',$f);
$plugin = trim($path[1]);
if(plugin_is_installed($plugin)) {
- $x = self::parse_app_description($f,$translate);
+ $x = self::parse_app_description($f, $translate, $sync);
if($x) {
$x['plugin'] = $plugin;
$ret[] = $x;
@@ -66,17 +67,17 @@ class Apps {
static public function get_base_apps() {
$x = get_config('system','base_apps',[
'Connections',
+ 'Contact Roles',
'Network',
- 'Settings',
'Files',
- 'Channel Home',
- 'View Profile',
+ 'Channel',
'Photos',
'Calendar',
'Directory',
'Search',
'Help',
- 'Profile Photo'
+ 'HQ',
+ 'Post'
]);
/**
@@ -207,9 +208,10 @@ class Apps {
*
* @param string $f filename
* @param boolean $translate (optional) default true
+ * @param boolean $sync (optional) default false
* @return boolean|array
*/
- static public function parse_app_description($f, $translate = true) {
+ static public function parse_app_description($f, $translate = true, $sync = false) {
$ret = [];
$matches = [];
@@ -255,7 +257,7 @@ class Apps {
if(array_key_exists('categories',$ret))
$ret['categories'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['categories']);
- if(array_key_exists('requires',$ret)) {
+ if(array_key_exists('requires',$ret) && !$sync) {
$requires = explode(',',$ret['requires']);
foreach($requires as $require) {
$require = trim(strtolower($require));
@@ -307,14 +309,16 @@ class Apps {
}
}
}
- if(isset($ret)) {
- if($translate)
- self::translate_system_apps($ret);
- return $ret;
+ if(empty($ret)) {
+ return false;
}
- return false;
+ if($translate) {
+ self::translate_system_apps($ret);
+ }
+
+ return $ret;
}
@@ -340,7 +344,7 @@ class Apps {
'Files' => t('Files'),
'Webpages' => t('Webpages'),
'Wiki' => t('Wiki'),
- 'Channel Home' => t('Channel Home'),
+ 'Channel' => t('Channel'),
'View Profile' => t('View Profile'),
'Photos' => t('Photos'),
'Calendar' => t('Calendar'),
@@ -371,7 +375,7 @@ class Apps {
'OAuth Apps Manager' => t('OAuth Apps Manager'),
'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'),
'PDL Editor' => t('PDL Editor'),
- 'Permission Categories' => t('Permission Categories'),
+ 'Contact Roles' => t('Contact Roles'),
'Public Stream' => t('Public Stream'),
'My Chatrooms' => t('My Chatrooms'),
'Channel Export' => t('Channel Export')
@@ -422,7 +426,7 @@ class Apps {
self::translate_system_apps($papp);
- if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
+ if(isset($papp['plugin']) && trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
return '';
$papp['papp'] = self::papp_encode($papp);
@@ -524,7 +528,7 @@ class Apps {
}
elseif(remote_channel()) {
$observer = \App::get_observer();
- if($observer && in_array($observer['xchan_network'], ['zot6', 'zot'])) {
+ if($observer && $observer['xchan_network'] === 'zot6') {
// some folks might have xchan_url redirected offsite, use the connurl
$x = parse_url($observer['xchan_connurl']);
if($x) {
@@ -536,13 +540,47 @@ class Apps {
$install_action = (($installed) ? t('Update') : t('Install'));
$icon = ((strpos($papp['photo'],'icon:') === 0) ? substr($papp['photo'],5) : '');
+ if (!$installed && $mode === 'module') {
+ $_SESSION['return_url'] = App::$query_string;
+ return replace_macros(get_markup_template('app_install.tpl'), [
+ '$papp' => $papp,
+ '$install' => $install_action
+ ]);
+ }
+
if($mode === 'navbar') {
+ return replace_macros(get_markup_template('app_nav_pinned.tpl'),array(
+ '$app' => $papp,
+ '$icon' => $icon,
+ ));
+ }
+
+ if($mode === 'nav') {
return replace_macros(get_markup_template('app_nav.tpl'),array(
'$app' => $papp,
'$icon' => $icon,
));
}
+ if($mode === 'inline') {
+ return replace_macros(get_markup_template('app_inline.tpl'),array(
+ '$app' => $papp,
+ '$icon' => $icon,
+ '$installed' => $installed,
+ '$purchase' => ((isset($papp['page']) && (! $installed)) ? t('Purchase') : ''),
+ '$action_label' => $install_action
+ ));
+ }
+
+ if(in_array($mode, ['nav-order', 'nav-order-pinned'])) {
+ return replace_macros(get_markup_template('app_order.tpl'),array(
+ '$app' => $papp,
+ '$icon' => $icon,
+ '$hosturl' => $hosturl,
+ '$mode' => $mode
+ ));
+ }
+
if($mode === 'install') {
$papp['embed'] = true;
}
@@ -563,8 +601,6 @@ class Apps {
'$pin' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
- '$navapps' => (($mode == 'nav') ? true : false),
- '$order' => (($mode === 'nav-order' || $mode === 'nav-order-pinned') ? true : false),
'$mode' => $mode,
'$add' => t('Add to app-tray'),
'$remove' => t('Remove from app-tray'),
@@ -574,6 +610,7 @@ class Apps {
));
}
+
static public function app_install($uid,$app) {
if(! is_array($app)) {
@@ -588,10 +625,12 @@ class Apps {
$app['uid'] = $uid;
- if(self::app_installed($uid,$app,true))
+ if(self::app_installed($uid,$app,true)) {
$x = self::app_update($app);
- else
+ }
+ else {
$x = self::app_store($app);
+ }
if($x['success']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
@@ -599,13 +638,12 @@ class Apps {
intval($uid)
);
if($r) {
- if(($app['uid']) && (! $r[0]['app_system'])) {
+ if($app['uid']) {
if($app['categories'] && (! $app['term'])) {
$r[0]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
);
- Libsync::build_sync_packet($uid,array('app' => $r[0]));
}
}
}
@@ -634,6 +672,7 @@ class Apps {
}
}
}
+
return true;
}
@@ -645,38 +684,35 @@ class Apps {
dbesc($app['guid']),
intval($uid)
);
- if($x) {
- if(! intval($x[0]['app_deleted'])) {
- $x[0]['app_deleted'] = 1;
- if(self::can_delete($uid,$app)) {
- q("delete from app where app_id = '%s' and app_channel = %d",
- dbesc($app['guid']),
- intval($uid)
- );
- q("delete from term where otype = %d and oid = %d",
- intval(TERM_OBJ_APP),
- intval($x[0]['id'])
- );
- /**
- * @hooks app_destroy
- * Called after app entry got removed from database
- * and provide app array from database.
- */
- call_hooks('app_destroy', $x[0]);
- }
- else {
- q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
- dbesc($app['guid']),
- intval($uid)
- );
- }
- if(! intval($x[0]['app_system'])) {
- Libsync::build_sync_packet($uid,array('app' => $x));
- }
- }
- else {
- self::app_undestroy($uid,$app);
- }
+
+ if($x && intval($x[0]['app_deleted'])) {
+ self::app_undestroy($uid, $app);
+ return;
+ }
+
+ if(self::can_delete($uid,$app)) {
+ q("delete from app where app_id = '%s' and app_channel = %d",
+ dbesc($app['guid']),
+ intval($uid)
+ );
+
+ q("delete from term where otype = %d and oid = %d",
+ intval(TERM_OBJ_APP),
+ intval($x[0]['id'])
+ );
+
+ /**
+ * @hooks app_destroy
+ * Called after app entry got removed from database
+ * and provide app array from database.
+ */
+ call_hooks('app_destroy', $x[0]);
+ }
+ else {
+ q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d",
+ dbesc($app['guid']),
+ intval($uid)
+ );
}
}
}
@@ -693,13 +729,11 @@ class Apps {
dbesc($app['guid']),
intval($uid)
);
- if($x) {
- if($x[0]['app_system']) {
- q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
- dbesc($app['guid']),
- intval($uid)
- );
- }
+ if($x && intval($x[0]['app_deleted']) && $x[0]['app_system']) {
+ q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d",
+ dbesc($app['guid']),
+ intval($uid)
+ );
}
}
}
@@ -1158,9 +1192,9 @@ class Apps {
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {
- $t = trim($t);
+ $t = escape_tags(trim($t));
if($t) {
- store_item_tag($darray['app_channel'],$x[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,escape_tags($t),escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t)));
+ store_item_tag($darray['app_channel'], $x[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, $t, z_root() . '/apps/?f=&cat=' . $t);
}
}
}
@@ -1356,4 +1390,17 @@ class Apps {
return chunk_split(base64_encode(json_encode($papp)),72,"\n");
}
+ static public function get_papp($app) {
+
+ $r = q("select * from app where app_id = '%s' and app_channel = 0 limit 1",
+ dbesc(hash('whirlpool', $app))
+ );
+
+ if ($r) {
+ $papp = self::app_encode($r[0]);
+ return $papp;
+ }
+
+ return false;
+ }
}
diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php
index 21bec171b..0b9ff7089 100644
--- a/Zotlabs/Lib/Connect.php
+++ b/Zotlabs/Lib/Connect.php
@@ -146,7 +146,7 @@ class Connect {
}
- $allowed = ((in_array($xchan['xchan_network'],['rss','zot','zot6'])) ? 1 : 0);
+ $allowed = ((in_array($xchan['xchan_network'],['rss', 'zot6'])) ? 1 : 0);
$hookdata = ['channel_id' => $uid, 'follow_address' => $url, 'xchan' => $xchan, 'allowed' => $allowed, 'singleton' => 0];
call_hooks('follow_allow',$hookdata);
@@ -261,7 +261,8 @@ class Connect {
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
'abook_created' => datetime_convert(),
'abook_updated' => datetime_convert(),
- 'abook_instance' => (($singleton) ? z_root() : '')
+ 'abook_instance' => (($singleton) ? z_root() : ''),
+ 'abook_role' => get_pconfig($uid, 'system', 'default_permcat', 'default')
]
);
}
@@ -300,7 +301,7 @@ class Connect {
/** If there is a default group for this channel, add this connection to it */
if ($default_group) {
- $g = AccessList::rec_byhash($uid,$default_group);
+ $g = AccessList::by_hash($uid,$default_group);
if ($g) {
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
}
diff --git a/Zotlabs/Lib/Crypto.php b/Zotlabs/Lib/Crypto.php
index f1794ae64..188c6bd81 100644
--- a/Zotlabs/Lib/Crypto.php
+++ b/Zotlabs/Lib/Crypto.php
@@ -87,6 +87,10 @@ class Crypto {
return false;
}
+ if (!$alg) {
+ $alg = 'sha256';
+ }
+
try {
$verify = openssl_verify($data, $sig, $key, $alg);
} catch (Exception $e) {
diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php
index 7515d3292..2263529b2 100644
--- a/Zotlabs/Lib/DReport.php
+++ b/Zotlabs/Lib/DReport.php
@@ -87,8 +87,7 @@ class DReport {
// Is the sender one of our channels?
- $c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1",
- dbesc($dr['sender']),
+ $c = q("select channel_id from channel where channel_hash = '%s' limit 1",
dbesc($dr['sender'])
);
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index 7e33f09b8..1421c72ae 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -69,24 +69,24 @@ class Enotify {
$sender_name = $product;
$hostname = \App::get_hostname();
if(strpos($hostname,':'))
- $hostname = substr($hostname,0,strpos($hostname,':'));
+ $hostname = substr($hostname, 0, strpos($hostname,':'));
// Do not translate 'noreply' as it must be a legal 7-bit email address
- $reply_email = get_config('system','reply_address');
+ $reply_email = get_config('system', 'reply_address');
if(! $reply_email)
$reply_email = 'noreply' . '@' . $hostname;
- $sender_email = get_config('system','from_email');
+ $sender_email = get_config('system', 'from_email');
if(! $sender_email)
$sender_email = 'Administrator' . '@' . $hostname;
- $sender_name = get_config('system','from_email_name');
+ $sender_name = get_config('system', 'from_email_name');
if(! $sender_name)
$sender_name = \Zotlabs\Lib\System::get_site_name();
- $additional_mail_header = "";
+ $additional_mail_header = '';
if(array_key_exists('item', $params)) {
require_once('include/conversation.php');
@@ -114,27 +114,28 @@ class Enotify {
}
- $always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
- $vnotify = get_pconfig($recip['channel_id'],'system','vnotify');
+ $always_show_in_notices = get_pconfig($recip['channel_id'], 'system', 'always_show_in_notices');
+ $vnotify = get_pconfig($recip['channel_id'], 'system', 'vnotify');
$salutation = $recip['channel_name'];
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
+// @@TODO: consider using switch instead of those elseif
if ($params['type'] == NOTIFY_MAIL) {
logger('notification: mail');
- $subject = sprintf( t('[$Projectname:Notify] New mail received at %s'),$sitename);
-
- $preamble = sprintf( t('%1$s sent you a new private message at %2$s.'), $sender['xchan_name'],$sitename);
- $epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
- $sitelink = t('Please visit %s to view and/or reply to your private messages.');
- $tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
- $itemlink = $siteurl . '/mail/' . $params['item']['id'];
+ $subject = sprintf( t('[$Projectname:Notify] New direct message received at %s'), $sitename);
+
+ $preamble = sprintf( t('%1$s sent you a new direct message at %2$s'), $sender['xchan_name'], $sitename);
+ $epreamble = sprintf( t('%1$s sent you %2$s.'), '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a direct message') . '[/zrl]');
+ $sitelink = t('Please visit %s to view and/or reply to your direct messages.');
+ $tsitelink = sprintf( $sitelink, $siteurl . '/hq/' . gen_link_id($params['item']['mid']));
+ $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/hq/' . gen_link_id($params['item']['mid']) . '">' . $sitename . '</a>');
+ $itemlink = $siteurl . '/hq/' . gen_link_id($params['item']['mid']);
}
- if ($params['type'] == NOTIFY_COMMENT) {
+ elseif ($params['type'] === NOTIFY_COMMENT) {
//logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
@@ -171,7 +172,6 @@ class Enotify {
// Check to see if there was already a notify for this post.
// If so don't create a second notification
- $p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -196,6 +196,7 @@ class Enotify {
xchan_query($p);
+//@@FIXME $p can be null (line 188)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
@@ -237,7 +238,7 @@ class Enotify {
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
else
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
- $preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
+ $preamble = sprintf( t('%1$s commented on an item/conversation you have been following'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
@@ -250,12 +251,12 @@ class Enotify {
}
- if ($params['type'] == NOTIFY_LIKE) {
+ elseif ($params['type'] === NOTIFY_LIKE) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$itemlink = $params['link'];
- if (array_key_exists('item',$params) && (! activity_match($params['item']['verb'],ACTIVITY_LIKE))) {
+ if (array_key_exists('item',$params) && activity_match($params['item']['verb'],ACTIVITY_LIKE)) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
logger('notification: not a visible activity. Ignoring.');
pop_lang();
@@ -268,7 +269,6 @@ class Enotify {
// Check to see if there was already a notify for this post.
// If so don't create a second notification
- $p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -293,7 +293,7 @@ class Enotify {
xchan_query($p);
-
+//@@FIXME $p can be null (line 285)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
@@ -302,7 +302,7 @@ class Enotify {
// "your post"
- if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
+ if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
$dest_str = sprintf(t('%1$s liked [zrl=%2$s]your %3$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$itemlink,
@@ -318,7 +318,7 @@ class Enotify {
// differents subjects for messages on the same thread.
$subject = sprintf( t('[$Projectname:Notify] Like received to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
- $preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
+ $preamble = sprintf( t('%1$s liked an item/conversation you created'), $sender['xchan_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
@@ -328,7 +328,7 @@ class Enotify {
- if($params['type'] == NOTIFY_WALL) {
+ elseif($params['type'] === NOTIFY_WALL) {
$subject = sprintf( t('[$Projectname:Notify] %s posted to your profile wall') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $sender['xchan_name'], $sitename);
@@ -343,9 +343,8 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_TAGSELF) {
+ elseif ($params['type'] === NOTIFY_TAGSELF) {
- $p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
@@ -368,7 +367,7 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_POKE) {
+ elseif ($params['type'] === NOTIFY_POKE) {
$subject = sprintf( t('[$Projectname:Notify] %1$s poked you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
@@ -385,7 +384,7 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_TAGSHARE) {
+ elseif ($params['type'] === NOTIFY_TAGSHARE) {
$subject = sprintf( t('[$Projectname:Notify] %s tagged your post') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s tagged your post at %2$s'),$sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s tagged [zrl=%2$s]your post[/zrl]') ,
@@ -398,7 +397,7 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_INTRO) {
+ elseif ($params['type'] === NOTIFY_INTRO) {
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
@@ -412,7 +411,7 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_SUGGEST) {
+ elseif ($params['type'] === NOTIFY_SUGGEST) {
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a friend suggestion[/zrl] for %2$s from %3$s.'),
@@ -430,11 +429,11 @@ class Enotify {
$itemlink = $params['link'];
}
- if ($params['type'] == NOTIFY_CONFIRM) {
+ elseif ($params['type'] === NOTIFY_CONFIRM) {
// ?
}
- if ($params['type'] == NOTIFY_SYSTEM) {
+ elseif ($params['type'] === NOTIFY_SYSTEM) {
// ?
}
@@ -477,7 +476,7 @@ class Enotify {
} while ($dups === true);
- $datarray = array();
+ $datarray = [];
$datarray['hash'] = $hash;
$datarray['sender_hash'] = $sender['xchan_hash'];
$datarray['xname'] = $sender['xchan_name'];
@@ -514,7 +513,7 @@ class Enotify {
// (probably would be better that way)
if (!$always_show_in_notices) {
- if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
+ if (($params['type'] === NOTIFY_WALL) || ($params['type'] === NOTIFY_MAIL) || ($params['type'] === NOTIFY_INTRO)) {
$seen = 1;
}
}
@@ -550,12 +549,12 @@ class Enotify {
}
$itemlink = z_root() . '/notify/view/' . $notify_id;
- $msg = str_replace('$itemlink',$itemlink,$epreamble);
+ $msg = str_replace('$itemlink', $itemlink, $epreamble);
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
- $msg = substr($msg,strpos($msg,', ')+1);
+ $msg = substr($msg, strpos($msg,', ')+1);
$datarray['id'] = $notify_id;
$datarray['msg'] = $msg;
@@ -575,7 +574,7 @@ class Enotify {
logger('notification: sending notification email');
- $hn = get_pconfig($recip['channel_id'],'system','email_notify_host');
+ $hn = get_pconfig($recip['channel_id'], 'system', 'email_notify_host');
if($hn && (! stristr(\App::get_hostname(),$hn))) {
// this isn't the email notification host
pop_lang();
@@ -584,7 +583,7 @@ class Enotify {
$textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8'));
- $htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
+ $htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array('',"<br />\n"),$body)));
// use $_SESSION['zid_override'] to force zid() to use
@@ -601,7 +600,7 @@ class Enotify {
unset($_SESSION['zid_override']);
unset($_SESSION['zrl_override']);
- $datarray = array();
+ $datarray = [];
$datarray['banner'] = $banner;
$datarray['product'] = $product;
$datarray['preamble'] = $preamble;
@@ -758,9 +757,9 @@ class Enotify {
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
// generate a mime boundary
- $mimeBoundary = rand(0, 9) . "-"
- .rand(100000000, 999999999) . "-"
- .rand(100000000, 999999999) . "=:"
+ $mimeBoundary = rand(0, 9) . '-'
+ .rand(100000000, 999999999) . '-'
+ .rand(100000000, 999999999) . '=:'
.rand(10000, 99999);
// generate a multipart/alternative message header
@@ -768,7 +767,7 @@ class Enotify {
$params['additionalMailHeader'] .
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
- "MIME-Version: 1.0" . PHP_EOL .
+ 'MIME-Version: 1.0' . PHP_EOL .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
@@ -776,15 +775,15 @@ class Enotify {
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$multipartMessageBody =
- "--" . $mimeBoundary . PHP_EOL . // plain text section
- "Content-Type: text/plain; charset=UTF-8" . PHP_EOL .
- "Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
+ '--' . $mimeBoundary . PHP_EOL . // plain text section
+ 'Content-Type: text/plain; charset=UTF-8' . PHP_EOL .
+ 'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL .
$textBody . PHP_EOL .
- "--" . $mimeBoundary . PHP_EOL . // text/html section
- "Content-Type: text/html; charset=UTF-8" . PHP_EOL .
- "Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
+ '--' . $mimeBoundary . PHP_EOL . // text/html section
+ 'Content-Type: text/html; charset=UTF-8' . PHP_EOL .
+ 'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL .
$htmlBody . PHP_EOL .
- "--" . $mimeBoundary . "--" . PHP_EOL; // message ending
+ '--' . $mimeBoundary . '--' . PHP_EOL; // message ending
// send the message
$res = mail(
@@ -793,7 +792,7 @@ class Enotify {
$multipartMessageBody, // message body
$messageHeader // message headers
);
- logger("notification: enotify::send returns " . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
+ logger('notification: enotify::send returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
return $res;
}
@@ -833,13 +832,12 @@ class Enotify {
$edit = false;
if($item['edited'] > $item['created']) {
+ $edit = true;
if($item['item_thread_top']) {
$itemem_text = sprintf( t('edited a post dated %s'), relative_date($item['created']));
- $edit = true;
}
else {
$itemem_text = sprintf( t('edited a comment dated %s'), relative_date($item['created']));
- $edit = true;
}
}
@@ -847,6 +845,10 @@ class Enotify {
// convert this logic into a json array just like the system notifications
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
+ $body = html2plain(bbcode($item['body'], ['drop_media']), 75, true);
+ if ($body) {
+ $body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
+ }
$x = array(
'notify_link' => $item['llink'],
@@ -856,18 +858,18 @@ class Enotify {
'photo' => $item[$who]['xchan_photo_s'],
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
- 'b64mid' => (($item['mid']) ? 'b64.' . base64url_encode($item['mid']) : ''),
- //'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
+ 'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
+ //'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => bbcode(escape_tags($itemem_text)),
- 'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_QUOTES, 'UTF-8', false),
+ 'body' => $body,
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
'uid' => $item['uid'],
'display' => true
);
- call_hooks('enotify_format',$x);
+ call_hooks('enotify_format', $x);
if(! $x['display']) {
return [];
}
@@ -884,9 +886,9 @@ class Enotify {
$mid = basename($tt['link']);
- $b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
+ $b64mid = gen_link_id($mid);
$x = [
- 'notify_link' => z_root() . '/notify/view/' . $tt['id'],
+ 'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
'name' => $tt['xname'],
'url' => $tt['url'],
'photo' => $tt['photo'],
@@ -903,8 +905,8 @@ class Enotify {
static public function format_intros($rr) {
- $x = [
- 'notify_link' => z_root() . '/connections/ifpending',
+ return [
+ 'notify_link' => z_root() . '/connections#' . $rr['abook_id'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
@@ -914,13 +916,11 @@ class Enotify {
'message' => t('added your channel')
];
- return $x;
-
}
static public function format_files($rr) {
- $x = [
+ return [
'notify_link' => z_root() . '/sharedwithme',
'name' => $rr['author']['xchan_name'],
'addr' => $rr['author']['xchan_addr'],
@@ -931,13 +931,11 @@ class Enotify {
'message' => t('shared a file with you')
];
- return $x;
-
}
static public function format_mail($rr) {
- $x = [
+ return [
'notify_link' => z_root() . '/mail/' . $rr['id'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@@ -945,11 +943,9 @@ class Enotify {
'photo' => $rr['xchan_photo_s'],
'when' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']),
'hclass' => (intval($rr['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
- 'message' => t('sent you a private message'),
+ 'message' => t('sent you a direct message'),
];
- return $x;
-
}
static public function format_all_events($rr) {
@@ -959,7 +955,7 @@ class Enotify {
$today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
- $x = [
+ return [
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@@ -970,13 +966,12 @@ class Enotify {
'message' => t('created an event')
];
- return $x;
}
static public function format_register($rr) {
- $x = [
+ return [
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['reg_did2'],
//'addr' => '',
@@ -986,7 +981,5 @@ class Enotify {
'message' => t('status verified')
];
- return $x;
-
}
}
diff --git a/Zotlabs/Lib/Group.php b/Zotlabs/Lib/Group.php
deleted file mode 100644
index a4ff4fced..000000000
--- a/Zotlabs/Lib/Group.php
+++ /dev/null
@@ -1,405 +0,0 @@
-<?php
-
-namespace Zotlabs\Lib;
-
-use Zotlabs\Lib\Libsync;
-
-
-class Group {
-
- static function add($uid,$name,$public = 0) {
-
- $ret = false;
- if(x($uid) && x($name)) {
- $r = self::byname($uid,$name); // check for dups
- if($r !== false) {
-
- // This could be a problem.
- // Let's assume we've just created a group which we once deleted
- // all the old members are gone, but the group remains so we don't break any security
- // access lists. What we're doing here is reviving the dead group, but old content which
- // was restricted to this group may now be seen by the new group members.
-
- $z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
- intval($r)
- );
- if(($z) && $z[0]['deleted']) {
- q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
- notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
- }
- return true;
- }
-
- do {
- $dups = false;
- $hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
-
- $r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
- if($r)
- $dups = true;
- } while($dups == true);
-
-
- $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
- VALUES( '%s', %d, %d, '%s' ) ",
- dbesc($hash),
- intval($uid),
- intval($public),
- dbesc($name)
- );
- $ret = $r;
- }
-
- Libsync::build_sync_packet($uid,null,true);
- return $ret;
- }
-
-
- static function remove($uid,$name) {
- $ret = false;
- if(x($uid) && x($name)) {
- $r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
- intval($uid),
- dbesc($name)
- );
- if($r) {
- $group_id = $r[0]['id'];
- $group_hash = $r[0]['hash'];
- }
-
- if(! $group_id)
- return false;
-
- // remove group from default posting lists
- $r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
- intval($uid)
- );
- if($r) {
- $user_info = $r[0];
- $change = false;
-
- if($user_info['channel_default_group'] == $group_hash) {
- $user_info['channel_default_group'] = '';
- $change = true;
- }
- if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
- $user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
- $change = true;
- }
- if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
- $user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
- $change = true;
- }
-
- if($change) {
- q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
- WHERE channel_id = %d",
- intval($user_info['channel_default_group']),
- dbesc($user_info['channel_allow_gid']),
- dbesc($user_info['channel_deny_gid']),
- intval($uid)
- );
- }
- }
-
- // remove all members
- $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
- intval($uid),
- intval($group_id)
- );
-
- // remove group
- $r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
- intval($uid),
- dbesc($name)
- );
-
- $ret = $r;
-
- }
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $ret;
- }
-
-
- static function byname($uid,$name) {
- if((! $uid) || (! strlen($name)))
- return false;
- $r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
- intval($uid),
- dbesc($name)
- );
- if($r)
- return $r[0]['id'];
- return false;
- }
-
-
- static function rec_byhash($uid,$hash) {
- if((! $uid) || (! strlen($hash)))
- return false;
- $r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
- intval($uid),
- dbesc($hash)
- );
- if($r)
- return $r[0];
- return false;
- }
-
-
- static function member_remove($uid,$name,$member) {
- $gid = self::byname($uid,$name);
- if(! $gid)
- return false;
- if(! ( $uid && $gid && $member))
- return false;
- $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $r;
- }
-
-
- static function member_add($uid,$name,$member,$gid = 0) {
- if(! $gid)
- $gid = self::byname($uid,$name);
- if((! $gid) || (! $uid) || (! $member))
- return false;
-
- $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
- if($r)
- return true; // You might question this, but
- // we indicate success because the group member was in fact created
- // -- It was just created at another time
- if(! $r)
- $r = q("INSERT INTO pgrp_member (uid, gid, xchan)
- VALUES( %d, %d, '%s' ) ",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $r;
- }
-
-
- static function members($gid) {
- $ret = array();
- if(intval($gid)) {
- $r = q("SELECT * FROM pgrp_member
- LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
- WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
- intval($gid),
- intval(local_channel()),
- intval(local_channel())
- );
- if($r)
- $ret = $r;
- }
- return $ret;
- }
-
- static function members_xchan($gid) {
- $ret = [];
- if(intval($gid)) {
- $r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
- intval($gid),
- intval(local_channel())
- );
- if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['xchan'];
- }
- }
- }
- return $ret;
- }
-
- static function members_profile_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;
- }
-
-
-
-
- static function select($uid,$group = '') {
-
- $grps = [];
- $o = '';
-
- $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($uid)
- );
- $grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
- if($r) {
- foreach($r as $rr) {
- $grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
- }
-
- }
- logger('select: ' . print_r($grps,true), LOGGER_DATA);
-
- $o = replace_macros(get_markup_template('group_selection.tpl'), array(
- '$label' => t('Add new connections to this privacy group'),
- '$groups' => $grps
- ));
- return $o;
- }
-
-
-
-
- static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
-
- $o = '';
-
- if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
- return '';
- }
-
- $groups = array();
-
- $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($_SESSION['uid'])
- );
- $member_of = array();
- if($cid) {
- $member_of = self::containing(local_channel(),$cid);
- }
-
- if($r) {
- foreach($r as $rr) {
- $selected = (($group_id == $rr['id']) ? ' group-selected' : '');
-
- if ($edit) {
- $groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
- }
- else {
- $groupedit = null;
- }
-
- $groups[] = [
- 'id' => $rr['id'],
- 'enc_cid' => base64url_encode($cid),
- 'cid' => $cid,
- 'text' => $rr['gname'],
- 'selected' => $selected,
- 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
- 'edit' => $groupedit,
- 'ismember' => in_array($rr['id'],$member_of),
- ];
- }
- }
-
-
- $tpl = get_markup_template("group_side.tpl");
- $o = replace_macros($tpl, array(
- '$title' => t('Privacy Groups'),
- '$edittext' => t('Edit group'),
- '$createtext' => t('Add privacy group'),
- '$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
- '$groups' => $groups,
- '$add' => t('add'),
- ));
-
-
- return $o;
- }
-
-
- static function expand($g) {
- if(! (is_array($g) && count($g)))
- return array();
-
- $ret = [];
- $x = [];
-
- // 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 pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
- if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['xchan'];
- }
- }
- }
- }
- return $ret;
- }
-
-
- static function member_of($c) {
- $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
- dbesc($c)
- );
-
- return $r;
-
- }
-
- static function containing($uid,$c) {
-
- $r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
- intval($uid),
- dbesc($c)
- );
-
- $ret = array();
- if($r) {
- foreach($r as $rr)
- $ret[] = $rr['gid'];
- }
-
- return $ret;
- }
-} \ No newline at end of file
diff --git a/Zotlabs/Lib/LDSignatures.php b/Zotlabs/Lib/LDSignatures.php
index 1c2095f10..00042bc7a 100644
--- a/Zotlabs/Lib/LDSignatures.php
+++ b/Zotlabs/Lib/LDSignatures.php
@@ -75,22 +75,23 @@ class LDSignatures {
}
static function hash($obj) {
-
- return hash('sha256',self::normalise($obj));
+ return hash('sha256', self::normalise($obj));
}
static function normalise($data) {
+ $ret = '';
+
if(is_string($data)) {
$data = json_decode($data);
}
if(! is_object($data))
- return '';
+ return $ret;
jsonld_set_document_loader('jsonld_document_loader');
try {
- $d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
+ $ret = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
}
catch (\Exception $e) {
// Don't log the exception - this can exhaust memory
@@ -98,7 +99,7 @@ class LDSignatures {
logger('normalise error: ' . print_r($data,true));
}
- return $d;
+ return $ret;
}
static function salmon_sign($data,$channel) {
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index 5455aa2ea..36a0a044c 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -141,7 +141,6 @@ class Libsync {
logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG);
$total = count($synchubs);
-
foreach ($synchubs as $hub) {
$hash = random_string();
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
@@ -186,7 +185,6 @@ class Libsync {
require_once('include/import.php');
$result = [];
-
$keychange = ((array_key_exists('keychange', $arr)) ? true : false);
foreach ($deliveries as $d) {
@@ -232,8 +230,35 @@ class Libsync {
if (array_key_exists('config', $arr) && is_array($arr['config']) && count($arr['config'])) {
foreach ($arr['config'] as $cat => $k) {
- foreach ($arr['config'][$cat] as $k => $v)
- set_pconfig($channel['channel_id'], $cat, $k, $v);
+ $pconfig_updated = [];
+
+ foreach($arr['config'][$cat] as $k => $v) {
+ if ($cat === 'hz_delpconfig' && strpos($k, 'b64.') === 0) {
+ $delpconfig = explode(':', unpack_link_id($k));
+
+ // delete the provided pconfig
+ del_pconfig($channel['channel_id'], $delpconfig[0], $delpconfig[1], $v);
+
+ // delete the messenger pconfig
+ del_pconfig($channel['channel_id'], 'hz_delpconfig', $k);
+ }
+
+ if (strpos($k,'pcfgud:') === 0) {
+ $realk = substr($k,7);
+ $pconfig_updated[$realk] = $v;
+ unset($arr['config'][$cat][$k]);
+ }
+ }
+
+ foreach($arr['config'][$cat] as $k => $v) {
+ if (!isset($pconfig_updated[$k])) {
+ $pconfig_updated[$k] = NULL;
+ }
+
+ if ($cat !== 'hz_delpconfig') {
+ set_pconfig($channel['channel_id'],$cat,$k,$v,$pconfig_updated[$k]);
+ }
+ }
}
}
@@ -246,6 +271,10 @@ class Libsync {
if (array_key_exists('app', $arr) && $arr['app'])
sync_apps($channel, $arr['app']);
+ if (array_key_exists('sysapp',$arr) && $arr['sysapp']) {
+ sync_sysapps($channel, $arr['sysapp']);
+ }
+
if (array_key_exists('addressbook', $arr) && $arr['addressbook'])
sync_addressbook($channel, $arr['addressbook']);
@@ -255,11 +284,8 @@ class Libsync {
if (array_key_exists('chatroom', $arr) && $arr['chatroom'])
sync_chatrooms($channel, $arr['chatroom']);
- if (array_key_exists('conv', $arr) && $arr['conv'])
- import_conv($channel, $arr['conv']);
-
- if (array_key_exists('mail', $arr) && $arr['mail'])
- sync_mail($channel, $arr['mail']);
+ //if (array_key_exists('mail', $arr) && $arr['mail'])
+ // sync_mail($channel, $arr['mail']);
if (array_key_exists('event', $arr) && $arr['event'])
sync_events($channel, $arr['event']);
@@ -273,8 +299,8 @@ class Libsync {
// deprecated, maintaining for a few months for upward compatibility
// this should sync webpages, but the logic is a bit subtle
- if (array_key_exists('item_id', $arr) && $arr['item_id'])
- sync_items($channel, $arr['item_id']);
+ //if (array_key_exists('item_id', $arr) && $arr['item_id'])
+ // sync_items($channel, $arr['item_id']);
if (array_key_exists('menu', $arr) && $arr['menu'])
sync_menus($channel, $arr['menu']);
@@ -385,19 +411,42 @@ class Libsync {
// This relies on the undocumented behaviour that red sites send xchan info with the abook
// and import_author_xchan will look them up on all federated networks
- if ($abook['abook_xchan'] && $abook['xchan_addr']) {
+ $found = false;
+ if ($abook['abook_xchan'] && $abook['xchan_addr'] && (! in_array($abook['xchan_network'], [ 'token', 'unknown' ]))) {
$h = Libzot::get_hublocs($abook['abook_xchan']);
- if (!$h) {
+ if ($h) {
+ $found = true;
+ }
+ else {
$xhash = import_author_xchan(encode_item_xchan($abook));
- if (!$xhash) {
+ if ($xhash) {
+ $found = true;
+ }
+ else {
logger('Import of ' . $abook['xchan_addr'] . ' failed.');
- continue;
}
}
}
+ if (!$found && !in_array($abook['xchan_network'], ['zot6', 'activitypub', 'diaspora'])) {
+ // just import the record.
+ $xc = [];
+ foreach ($abook as $k => $v) {
+ if (strpos($k,'xchan_') === 0) {
+ $xc[$k] = $v;
+ }
+ }
+ $r = q("select * from xchan where xchan_hash = '%s'",
+ dbesc($xc['xchan_hash'])
+ );
+ if (! $r) {
+ xchan_store_lowlevel($xc);
+ }
+ }
+
+
foreach ($abook as $k => $v) {
- if (in_array($k, $disallowed) || (strpos($k, 'abook') !== 0)) {
+ if (in_array($k, $disallowed) || (strpos($k, 'abook_') !== 0)) {
continue;
}
if (!in_array($k, $fields)) {
@@ -411,6 +460,13 @@ class Libsync {
if (array_key_exists('abook_instance', $clean) && $clean['abook_instance'] && strpos($clean['abook_instance'], z_root()) === false) {
$clean['abook_not_here'] = 1;
+
+ // guest pass or access token - don't try to probe since it is one-way
+ // we are relying on the undocumented behaviour that the abook record also contains the xchan
+ if ($abook['xchan_network'] === 'token') {
+ $clean['abook_instance'] .= ',';
+ $clean['abook_instance'] .= z_root();
+ }
}
@@ -707,6 +763,15 @@ class Libsync {
$ret = [];
+ // If a sender reports that the channel has been deleted, delete its hubloc
+ if (isset($arr['deleted_locally']) && intval($arr['deleted_locally'])) {
+ q("UPDATE hubloc SET hubloc_deleted = 1, hubloc_updated = '%s' WHERE hubloc_hash = '%s' AND hubloc_url = '%s'",
+ dbesc(datetime_convert()),
+ dbesc($sender['hash']),
+ dbesc($sender['site']['url'])
+ );
+ }
+
if ($arr['locations']) {
if ($absolute)
@@ -760,14 +825,13 @@ class Libsync {
// match as many fields as possible in case anything at all changed.
- $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
+ $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
dbesc($sender['hash']),
dbesc($sender['id']),
dbesc($sender['id_sig']),
dbesc($location['id_url']),
dbesc($location['url']),
dbesc($location['url_sig']),
- dbesc($location['site_id']),
dbesc($location['host']),
dbesc($location['address']),
dbesc($location['callback']),
@@ -776,6 +840,15 @@ class Libsync {
if ($r) {
logger('Hub exists: ' . $location['url'], LOGGER_DEBUG);
+ // generate a new hubloc_site_id if it's wrong due to historical bugs 2021-11-30
+
+ if ($r[0]['hubloc_site_id'] !== $location['site_id']) {
+ q("update hubloc set hubloc_site_id = '%s' where hubloc_id = %d",
+ dbesc(Libzot::make_xchan_hash($location['url'], $location['sitekey'])),
+ intval($r[0]['hubloc_id'])
+ );
+ }
+
// update connection timestamp if this is the site we're talking to
// This only happens when called from import_xchan
@@ -864,6 +937,7 @@ class Libsync {
$what .= 'delete_hub ';
$changed = true;
}
+
continue;
}
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index c7d001d21..2ed18d10b 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -266,7 +266,7 @@ class Libzot {
dbesc($them['xchan_addr'])
);
}
- if (!$r) {
+ if (!$r && array_key_exists('xchan_hash', $them) && $them['xchan_hash']) {
$r = q("select hubloc_id_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc",
dbesc($them['xchan_hash'])
);
@@ -275,8 +275,8 @@ class Libzot {
if ($r) {
foreach ($r as $rr) {
if (intval($rr['hubloc_primary'])) {
- $url = $rr['hubloc_id_url'];
- $record = $rr;
+ $url = $rr['hubloc_id_url'];
+ break;
}
}
if (!$url) {
@@ -284,13 +284,17 @@ class Libzot {
}
}
}
+
if (!$url) {
logger('zot_refresh: no url');
return false;
}
+ $m = parse_url($url);
+ $site_url = unparse_url([ 'scheme' => $m['scheme'], 'host' => $m['host'] ]);
+
$s = q("select site_dead from site where site_url = '%s' limit 1",
- dbesc($url)
+ dbesc($site_url)
);
if ($s && intval($s[0]['site_dead']) && (!$force)) {
@@ -299,25 +303,25 @@ class Libzot {
}
$record = Zotfinger::exec($url, $channel);
- // Check the HTTP signature
+ // Check the HTTP signature
$hsig = $record['signature'];
- if ($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
+ if ($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true) {
$hsig_valid = true;
+ }
if (!$hsig_valid) {
logger('http signature not valid: ' . print_r($hsig, true));
return false;
}
-
logger('zot-info: ' . print_r($record, true), LOGGER_DATA, LOG_DEBUG);
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
-
- if (!$x['success'])
+ if (!$x['success']) {
return false;
+ }
if ($channel && $record['data']['permissions']) {
$permissions = explode(',', $record['data']['permissions']);
@@ -357,8 +361,9 @@ class Libzot {
// we have as we may have updated the year after sending a notification; and resetting
// to the one we just received would cause us to create duplicated events.
- if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5))
+ if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5)) {
$next_birthday = $r[0]['abook_dob'];
+ }
$y = q("update abook set abook_dob = '%s'
where abook_xchan = '%s' and abook_channel = %d
@@ -368,20 +373,23 @@ class Libzot {
intval($channel['channel_id'])
);
- if (!$y)
+ if (!$y) {
logger('abook update failed');
+ }
else {
// if we were just granted read stream permission and didn't have it before, try to pull in some posts
- if ((!$old_read_stream_perm) && (intval($permissions['view_stream'])))
+ if (!$old_read_stream_perm && intval($permissions['view_stream'])) {
Master::Summon(['Onepoll', $r[0]['abook_id']]);
+ }
}
}
else {
- $p = Permissions::connect_perms($channel['channel_id']);
- $my_perms = $p['perms'];
+ $p = Permissions::connect_perms($channel['channel_id']);
+ $my_perms = $p['perms'];
$automatic = $p['automatic'];
+ $role = (($automatic) ? $p['role'] : '');
// new connection
@@ -403,7 +411,8 @@ class Libzot {
'abook_created' => datetime_convert(),
'abook_updated' => datetime_convert(),
'abook_dob' => $next_birthday,
- 'abook_pending' => intval(($automatic) ? 0 : 1)
+ 'abook_pending' => intval(($automatic) ? 0 : 1),
+ 'abook_role' => $role
]
);
@@ -419,53 +428,62 @@ class Libzot {
);
if ($new_connection) {
- if (!Permissions::PermsCompare($new_perms, $previous_perms))
+ if (!Permissions::PermsCompare($new_perms, $previous_perms)) {
Master::Summon(['Notifier', 'permission_create', $new_connection[0]['abook_id']]);
+ }
+
Enotify::submit(
[
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
- 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
+ 'link' => z_root() . '/connections#' . $new_connection[0]['abook_id']
]
);
if (intval($permissions['view_stream'])) {
if (intval(get_pconfig($channel['channel_id'], 'perm_limits', 'send_stream') & PERMS_PENDING)
- || (!intval($new_connection[0]['abook_pending'])))
+ || (!intval($new_connection[0]['abook_pending']))) {
Master::Summon(['Onepoll', $new_connection[0]['abook_id']]);
+ }
}
-
// If there is a default group for this channel, add this connection to it
- // for pending connections this will happens at acceptance time.
+ // for pending connections this will happen at acceptance time.
if (!intval($new_connection[0]['abook_pending'])) {
$default_group = $channel['channel_default_group'];
+
if ($default_group) {
- $g = Group::rec_byhash($channel['channel_id'], $default_group);
- if ($g)
- Group::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
+ $g = AccessList::by_hash($channel['channel_id'], $default_group);
+
+ if ($g) {
+ AccessList::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
+ }
}
}
unset($new_connection[0]['abook_id']);
unset($new_connection[0]['abook_account']);
unset($new_connection[0]['abook_channel']);
+
$abconfig = load_abconfig($channel['channel_id'], $new_connection['abook_xchan']);
- if ($abconfig)
+
+ if ($abconfig) {
$new_connection['abconfig'] = $abconfig;
+ }
Libsync::build_sync_packet($channel['channel_id'], ['abook' => $new_connection]);
+
}
}
-
}
return true;
}
return false;
}
+
/**
* @brief Look up if channel is known and previously verified.
*
@@ -479,6 +497,7 @@ class Libzot {
* * \e string \b id_sig => id signed with conversant's private key
* * \e string \b location => URL of the origination hub of this communication
* * \e string \b location_sig => URL signed with conversant's private key
+ * * \e string \b site_id => URL signed with conversant's private key
* @param boolean $multiple (optional) default false
*
* @return array|null
@@ -488,7 +507,7 @@ class Libzot {
static function gethub($arr, $multiple = false) {
- if ($arr['id'] && $arr['id_sig'] && $arr['location'] && $arr['location_sig']) {
+ if ($arr['id'] && $arr['id_sig'] && $arr['location'] && $arr['location_sig'] && $arr['site_id']) {
if (!check_siteallowed($arr['location'])) {
logger('blacklisted site: ' . $arr['location']);
@@ -512,9 +531,9 @@ class Libzot {
logger('Found', LOGGER_DEBUG);
return (($multiple) ? $r : $r[0]);
}
+ logger('Not found: ' . print_r($arr, true), LOGGER_DEBUG);
}
- logger('Not found: ' . print_r($arr, true), LOGGER_DEBUG);
-
+ logger('Incomplete array: ' . print_r($arr, true), LOGGER_DEBUG);
return false;
}
@@ -616,7 +635,6 @@ class Libzot {
*/
static function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
-
/**
* @hooks import_xchan
* Called when processing the result of zot_finger() to store the result
@@ -658,6 +676,10 @@ class Libzot {
logger('import_xchan: ' . $xchan_hash, LOGGER_DEBUG);
+ if (isset($arr['signing_algorithm']) && $arr['signing_algorithm']) {
+ set_xconfig($xchan_hash, 'system', 'signing_algorithm', $arr['signing_algorithm']);
+ }
+
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan_hash)
);
@@ -666,6 +688,7 @@ class Libzot {
$arr['connect_url'] = '';
if ($r) {
+
if ($arr['photo'] && array_key_exists('updated', $arr['photo']) && $arr['photo']['updated'] > $r[0]['xchan_photo_date'])
$import_photos = true;
@@ -984,7 +1007,7 @@ class Libzot {
$x = Crypto::unencapsulate($x, get_config('system', 'prvkey'));
- if (!is_array($x)) {
+ if ($x && !is_array($x)) {
$x = json_decode($x, true);
}
@@ -1126,6 +1149,7 @@ class Libzot {
if ($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data);
+
if (!$AS->is_valid()) {
logger('Activity rejected: ' . print_r($data, true));
return;
@@ -1141,7 +1165,6 @@ class Libzot {
}
-
$deliveries = null;
if (array_key_exists('recipients', $env) && count($env['recipients'])) {
@@ -1199,31 +1222,51 @@ class Libzot {
if (in_array($env['type'], ['activity', 'response'])) {
- $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ",
+ if(empty($AS->actor['id'])) {
+ logger('No actor id!');
+ return;
+ }
+
+ $r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
+ if (! $r) {
+ // Author is unknown to this site. Perform channel discovery and try again.
+ $z = discover_by_webbie($AS->actor['id']);
+ if ($z) {
+ $r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s'",
+ dbesc($AS->actor['id'])
+ );
+ }
+ }
+
if ($r) {
- // selects a zot6 hash if available, otherwise use whatever we have
- $r = self::zot_record_preferred($r);
+ $r = self::zot_record_preferred($r);
$arr['author_xchan'] = $r['hubloc_hash'];
}
- if (!$arr['author_xchan']) {
+ if (! $arr['author_xchan']) {
logger('No author!');
return;
}
- $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
- dbesc($env['sender'])
- );
+ $arr['owner_xchan'] = $env['sender'];
+
+ if(filter_var($env['sender'], FILTER_VALIDATE_URL)) {
+ // in individual delivery, change owner if needed
+ $s = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
+ dbesc($env['sender'])
+ );
- // in individual delivery, change owner if needed
- if ($s) {
- $arr['owner_xchan'] = $s[0]['hubloc_hash'];
+ if ($s) {
+ $arr['owner_xchan'] = $s[0]['hubloc_hash'];
+ }
}
- else {
- $arr['owner_xchan'] = $env['sender'];
+
+ if (! $arr['owner_xchan']) {
+ logger('No owner!');
+ return;
}
if ($private && (!intval($arr['item_private']))) {
@@ -1251,29 +1294,14 @@ class Libzot {
if ($AS->data['hubloc']) {
$arr['item_verified'] = true;
+ }
- if (!array_key_exists('comment_policy', $arr)) {
- // set comment policy depending on source hub. Unknown or osada is ActivityPub.
- // Anything else we'll say is zot - which could have a range of project names
- $s = q("select site_project from site where site_url = '%s' limit 1",
- dbesc($r[0]['hubloc_url'])
- );
-
- if ((!$s) || (in_array($s[0]['site_project'], ['', 'osada']))) {
- $arr['comment_policy'] = 'authenticated';
- }
- else {
- $arr['comment_policy'] = 'contacts';
- }
- }
+ if (!array_key_exists('comment_policy', $arr)) {
+ $arr['comment_policy'] = 'authenticated';
}
- if ($AS->data['signed_data']) {
- IConfig::Set($arr, 'activitypub', 'signed_data', $AS->data['signed_data'], false);
- $j = json_decode($AS->data['signed_data'], true);
- if ($j) {
- IConfig::Set($arr, 'activitypub', 'rawmsg', json_encode(JSalmon::unpack($j['data'])), true);
- }
+ if ($AS->meta['signed_data']) {
+ IConfig::Set($arr, 'activitypub', 'signed_data', $AS->meta['signed_data'], false);
}
logger('Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
@@ -1332,7 +1360,7 @@ class Libzot {
static function find_parent($env, $act) {
if ($act) {
- if (in_array($act->type, ['Like', 'Dislike'])) {
+ if (in_array($act->type, ['Like', 'Dislike']) && is_array($act->obj)) {
return $act->obj['id'];
}
if ($act->parent_id) {
@@ -1377,8 +1405,6 @@ class Libzot {
$check_mentions = true;
}
}
- elseif ($msg['type'] === 'mail')
- $perm = 'post_mail';
$r = [];
@@ -1464,10 +1490,11 @@ class Libzot {
* @param boolean $relay
* @param boolean $public (optional) default false
* @param boolean $request (optional) default false
+ * @param boolean $force (optional) default false - should only be set for manual fetch
* @return array
*/
- static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false) {
+ static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) {
$result = [];
@@ -1545,7 +1572,11 @@ class Libzot {
$local_public = false;
continue;
}
- if (!MessageFilter::evaluate($arr, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
+
+ $incl = get_config('system','pubstream_incl');
+ $excl = get_config('system','pubstream_excl');
+
+ if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
$local_public = false;
continue;
}
@@ -1569,7 +1600,8 @@ class Libzot {
if ((!$tag_delivery) && (!$local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
- if (!$allowed) {
+
+ if ((!$allowed) && $perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
@@ -1595,7 +1627,7 @@ class Libzot {
// doesn't exist.
if ($perm === 'send_stream') {
- if (get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false) || $arr['verb'] === ACTIVITY_SHARE) {
+ if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false) || $arr['verb'] === ACTIVITY_SHARE) {
$allowed = true;
}
}
@@ -1606,6 +1638,12 @@ class Libzot {
$friendofriend = true;
}
+ if (intval($arr['item_private']) === 2) {
+ if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
+ $allowed = false;
+ }
+ }
+
if (!$allowed) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
@@ -1713,11 +1751,13 @@ class Libzot {
}
}
- $ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
+ // This is used to fetch allow/deny rules if either the sender
+ // or owner is a connection. post_is_importable() evaluates all of them
+ $abook = q("select * from abook where abook_channel = %d and ( abook_xchan = '%s' OR abook_xchan = '%s' )",
intval($channel['channel_id']),
- dbesc($arr['owner_xchan'])
+ dbesc($arr['owner_xchan']),
+ dbesc($arr['author_xchan'])
);
- $abook = (($ab) ? $ab[0] : null);
if (intval($arr['item_deleted'])) {
@@ -1768,17 +1808,18 @@ class Libzot {
elseif ($arr['edited'] > $r[0]['edited']) {
$arr['id'] = $r[0]['id'];
$arr['uid'] = $channel['channel_id'];
- if (($arr['mid'] == $arr['parent_mid']) && (!post_is_importable($arr, $abook))) {
- $DR->update('update ignored');
- $result[] = $DR->get();
- }
- else {
- $item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
- $DR->update('updated');
- $result[] = $DR->get();
- if (!$relay)
- add_source_route($item_id, $sender);
- }
+
+ if (post_is_importable($channel['channel_id'], $arr, $abook)) {
+ $item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
+ $DR->update('updated');
+ $result[] = $DR->get();
+ if (!$relay) {
+ add_source_route($item_id, $sender);
+ }
+ } else {
+ $DR->update('update ignored');
+ $result[] = $DR->get();
+ }
}
else {
$DR->update('update ignored');
@@ -1808,20 +1849,29 @@ class Libzot {
$item_id = 0;
- if (($arr['mid'] == $arr['parent_mid']) && (!post_is_importable($arr, $abook))) {
- $DR->update('post ignored');
- $result[] = $DR->get();
+ $maxlen = get_max_import_size();
+
+ if ($maxlen && mb_strlen($arr['body']) > $maxlen) {
+ $arr['body'] = mb_substr($arr['body'], 0, $maxlen, 'UTF-8');
+ logger('message length exceeds max_import_size: truncated');
}
- else {
+
+ if ($maxlen && mb_strlen($arr['summary']) > $maxlen) {
+ $arr['summary'] = mb_substr($arr['summary'], 0, $maxlen, 'UTF-8');
+ logger('message summary length exceeds max_import_size: truncated');
+ }
+
+ if (post_is_importable($arr['uid'], $arr, $abook)) {
$item_result = item_store($arr);
if ($item_result['success']) {
$item_id = $item_result['item_id'];
- $parr = [
+ $parr = [
'item_id' => $item_id,
- 'item' => $arr,
- 'sender' => $sender,
+ 'item' => $arr,
+ 'sender' => $sender,
'channel' => $channel
];
+
/**
* @hooks activity_received
* Called when an activity (post, comment, like, etc.) has been received from a zot source.
@@ -1831,13 +1881,19 @@ class Libzot {
* * \e array \b channel
*/
call_hooks('activity_received', $parr);
+
// don't add a source route if it's a relay or later recipients will get a route mismatch
- if (!$relay)
+ if (!$relay) {
add_source_route($item_id, $sender);
+ }
}
$DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']);
$result[] = $DR->get();
+ } else {
+ $DR->update('post ignored');
+ $result[] = $DR->get();
}
+
}
// preserve conversations with which you are involved from expiration
@@ -1864,7 +1920,7 @@ class Libzot {
return $result;
}
- static public function fetch_conversation($channel, $mid) {
+ static public function fetch_conversation($channel, $mid, $force = false) {
// Use Zotfinger to create a signed request
@@ -1896,6 +1952,7 @@ class Libzot {
dbesc($a['signature']['signer'])
);
+
foreach ($items as $activity) {
$AS = new ActivityStreams($activity);
@@ -1915,16 +1972,18 @@ class Libzot {
// logger($AS->debug());
- $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
+ $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
+ $r = self::zot_record_preferred($r);
if (!$r) {
$y = import_author_xchan(['url' => $AS->actor['id']]);
if ($y) {
- $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
+ $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
+ $r = self::zot_record_preferred($r);
}
if (!$r) {
logger('FOF Activity: no actor');
@@ -1940,9 +1999,8 @@ class Libzot {
}
}
-
if ($r) {
- $arr['author_xchan'] = $r[0]['hubloc_hash'];
+ $arr['author_xchan'] = $r['hubloc_hash'];
}
if ($signer) {
@@ -1956,9 +2014,9 @@ class Libzot {
$arr['item_verified'] = true;
}
- if ($AS->data['signed_data']) {
- IConfig::Set($arr, 'activitypub', 'signed_data', $AS->data['signed_data'], false);
- $j = json_decode($AS->data['signed_data'], true);
+ if ($AS->meta['signed_data']) {
+ IConfig::Set($arr, 'activitypub', 'signed_data', $AS->meta['signed_data'], false);
+ $j = json_decode($AS->meta['signed_data'], true);
if ($j) {
IConfig::Set($arr, 'activitypub', 'rawmsg', json_encode(JSalmon::unpack($j['data'])), true);
}
@@ -1967,7 +2025,7 @@ class Libzot {
logger('FOF Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
- $result = self::process_delivery($arr['owner_xchan'], $AS, $arr, [$channel['channel_hash']], false, false, true);
+ $result = self::process_delivery($arr['owner_xchan'], $AS, $arr, [$channel['channel_hash']], false, false, true, $force);
if ($result) {
$ret = array_merge($ret, $result);
}
@@ -2210,90 +2268,6 @@ class Libzot {
return $post_id;
}
- static function process_mail_delivery($sender, $arr, $deliveries) {
-
- $result = [];
-
- if ($sender != $arr['from_xchan']) {
- logger('process_mail_delivery: sender is not mail author');
- return;
- }
-
- foreach ($deliveries as $d) {
-
- $DR = new DReport(z_root(), $sender, $d, $arr['mid']);
-
- $r = q("select * from channel where channel_hash = '%s' limit 1",
- dbesc($d['hash'])
- );
-
- if (!$r) {
- $DR->update('recipient not found');
- $result[] = $DR->get();
- continue;
- }
-
- $channel = $r[0];
- $DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
-
-
- if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
-
- /*
- * Always allow somebody to reply if you initiated the conversation. It's anti-social
- * and a bit rude to send a private message to somebody and block their ability to respond.
- * If you are being harrassed and want to put an end to it, delete the conversation.
- */
-
- $return = false;
- if ($arr['parent_mid']) {
- $return = q("select * from mail where mid = '%s' and channel_id = %d limit 1",
- dbesc($arr['parent_mid']),
- intval($channel['channel_id'])
- );
- }
- if (!$return) {
- logger("permission denied for mail delivery {$channel['channel_id']}");
- $DR->update('permission denied');
- $result[] = $DR->get();
- continue;
- }
- }
-
-
- $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
- dbesc($arr['mid']),
- intval($channel['channel_id'])
- );
- if ($r) {
- if (intval($arr['mail_recalled'])) {
- $x = q("delete from mail where id = %d and channel_id = %d",
- intval($r[0]['id']),
- intval($channel['channel_id'])
- );
- $DR->update('mail recalled');
- $result[] = $DR->get();
- logger('mail_recalled');
- }
- else {
- $DR->update('duplicate mail received');
- $result[] = $DR->get();
- logger('duplicate mail received');
- }
- continue;
- }
- else {
- $arr['account_id'] = $channel['channel_account_id'];
- $arr['channel_id'] = $channel['channel_id'];
- $item_id = mail_store($arr);
- $DR->update('mail delivered');
- $result[] = $DR->get();
- }
- }
-
- return $result;
- }
-
/**
* @brief Processes delivery of profile.
@@ -2534,14 +2508,14 @@ class Libzot {
$access_policy = ACCESS_PRIVATE;
}
- $directory_url = htmlspecialchars($arr['directory_url'], ENT_COMPAT, 'UTF-8', false);
- $url = htmlspecialchars(strtolower($arr['url']), ENT_COMPAT, 'UTF-8', false);
- $sellpage = htmlspecialchars($arr['sellpage'], ENT_COMPAT, 'UTF-8', false);
- $site_location = htmlspecialchars($arr['location'], ENT_COMPAT, 'UTF-8', false);
- $site_realm = htmlspecialchars($arr['realm'], ENT_COMPAT, 'UTF-8', false);
- $site_project = htmlspecialchars($arr['project'], ENT_COMPAT, 'UTF-8', false);
- $site_crypto = ((array_key_exists('encryption', $arr) && is_array($arr['encryption'])) ? htmlspecialchars(implode(',', $arr['encryption']), ENT_COMPAT, 'UTF-8', false) : '');
- $site_version = ((array_key_exists('version', $arr)) ? htmlspecialchars($arr['version'], ENT_COMPAT, 'UTF-8', false) : '');
+ $directory_url = htmlspecialchars((string)$arr['directory_url'], ENT_COMPAT, 'UTF-8', false);
+ $url = htmlspecialchars((string)strtolower($arr['url']), ENT_COMPAT, 'UTF-8', false);
+ $sellpage = htmlspecialchars((string)$arr['sellpage'], ENT_COMPAT, 'UTF-8', false);
+ $site_location = htmlspecialchars((string)$arr['location'], ENT_COMPAT, 'UTF-8', false);
+ $site_realm = htmlspecialchars((string)$arr['realm'], ENT_COMPAT, 'UTF-8', false);
+ $site_project = htmlspecialchars((string)$arr['project'], ENT_COMPAT, 'UTF-8', false);
+ $site_crypto = ((array_key_exists('encryption', $arr) && is_array($arr['encryption'])) ? htmlspecialchars((string)implode(',', $arr['encryption']), ENT_COMPAT, 'UTF-8', false) : '');
+ $site_version = ((array_key_exists('version', $arr)) ? htmlspecialchars((string)$arr['version'], ENT_COMPAT, 'UTF-8', false) : '');
// You can have one and only one primary directory per realm.
// Downgrade any others claiming to be primary. As they have
@@ -2664,29 +2638,34 @@ class Libzot {
// we may only end up with one; which results in posts with no author name or photo and are a bit
// of a hassle to repair. If either or both are missing, do a full discovery probe.
- //if (!array_key_exists('id', $x)) {
- //return import_author_activitypub($x);
- //}
+ if(!isset($x['id']) && !isset($x['key']) && !isset($x['id_sig'])) {
+ return false;
+ }
$hash = self::make_xchan_hash($x['id'], $x['key']);
$desturl = $x['url'];
+ $found_primary = false;
+
$r1 = q("select hubloc_url, hubloc_updated, site_dead from hubloc left join site on
hubloc_url = site_url where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_primary = 1 limit 1",
dbesc($x['id']),
dbesc($x['id_sig'])
);
+ if ($r1) {
+ $found_primary = true;
+ }
$r2 = q("select xchan_hash from xchan where xchan_guid = '%s' and xchan_guid_sig = '%s' limit 1",
dbesc($x['id']),
dbesc($x['id_sig'])
);
- $site_dead = false;
+ $primary_dead = false;
if ($r1 && intval($r1[0]['site_dead'])) {
- $site_dead = true;
+ $primary_dead = true;
}
// We have valid and somewhat fresh information. Always true if it is our own site.
@@ -2704,16 +2683,17 @@ class Libzot {
// cached entry and the identity is valid. It's just unreachable until they bring back their
// server from the grave or create another clone elsewhere.
- if ($site_dead) {
- logger('dead site - ignoring', LOGGER_DEBUG, LOG_INFO);
+ if ($primary_dead || ! $found_primary) {
+ logger('dead or unknown primary site - ignoring', LOGGER_DEBUG, LOG_INFO);
$r = q("select hubloc_id_url from hubloc left join site on hubloc_url = site_url
where hubloc_hash = '%s' and site_dead = 0",
dbesc($hash)
);
+
if ($r) {
- logger('found another site that is not dead: ' . $r[0]['hubloc_url'], LOGGER_DEBUG, LOG_INFO);
- $desturl = $r[0]['hubloc_url'];
+ logger('found another site that is not dead: ' . $r[0]['hubloc_id_url'], LOGGER_DEBUG, LOG_INFO);
+ $desturl = $r[0]['hubloc_id_url'];
}
else {
return $hash;
@@ -2821,7 +2801,6 @@ class Libzot {
}
$e = $r[0];
-
$id = $e['channel_id'];
$sys_channel = (intval($e['channel_system']) ? true : false);
@@ -2834,28 +2813,6 @@ class Libzot {
if ($deleted || $censored || $sys_channel)
$searchable = false;
- $public_forum = false;
-
- $role = get_pconfig($e['channel_id'], 'system', 'permissions_role');
- if ($role === 'forum' || $role === 'repository') {
- $public_forum = true;
- }
- else {
- // check if it has characteristics of a public forum based on custom permissions.
- $m = Permissions::FilledAutoperms($e['channel_id']);
- if ($m) {
- foreach ($m as $k => $v) {
- if ($k == 'tag_deliver' && intval($v) == 1)
- $ch++;
- if ($k == 'send_stream' && intval($v) == 0)
- $ch++;
- }
- if ($ch == 2)
- $public_forum = true;
- }
- }
-
-
// This is for birthdays and keywords, but must check access permissions
$p = q("select * from profile where uid = %d and is_default = 1",
intval($e['channel_id'])
@@ -2914,6 +2871,7 @@ class Libzot {
];
$ret['public_key'] = $e['xchan_pubkey'];
+ $ret['signing_algorithm'] = 'rsa-sha256';
$ret['username'] = $e['channel_address'];
$ret['name'] = $e['xchan_name'];
$ret['name_updated'] = $e['xchan_name_date'];
@@ -2924,10 +2882,11 @@ class Libzot {
];
$ret['channel_role'] = get_pconfig($e['channel_id'], 'system', 'permissions_role', 'custom');
+ $ret['channel_type'] = ((get_pconfig($e['channel_id'], 'system', 'group_actor')) ? 'group' : 'normal');
$hookinfo = [
'channel_id' => $id,
- 'protocols' => ['zot6', 'zot']
+ 'protocols' => ['zot6']
];
/**
* @hooks channel_protocols
@@ -2939,16 +2898,19 @@ class Libzot {
$ret['protocols'] = $hookinfo['protocols'];
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
- $ret['public_forum'] = $public_forum;
+ // now all forums (public, restricted, and private) set the public_forum flag. So it really means "is a group"
+ // and has nothing to do with accessibility.
+ $ret['public_forum'] = get_pconfig($e['channel_id'], 'system', 'group_actor');
$ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_comments'));
$ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_mail'));
if ($deleted)
$ret['deleted'] = $deleted;
- if (intval($e['channel_removed']))
+ if (intval($e['channel_removed'])) {
$ret['deleted_locally'] = true;
+ }
// premium or other channel desiring some contact with potential followers before connecting.
// This is a template - %s will be replaced with the follow_url we discover for the return channel.
@@ -3231,14 +3193,15 @@ class Libzot {
return $v;
}
}
- foreach ($arr as $v) {
- if ($v[$check] === 'zot') {
- return $v;
- }
- }
return $arr[0];
}
+ static function update_cached_hubloc($hubloc) {
+ if ($hubloc['hubloc_updated'] > datetime_convert('UTC','UTC','now - 3 days') || $hubloc['hubloc_url'] === z_root()) {
+ return;
+ }
+ self::refresh( [ 'hubloc_id_url' => $hubloc['hubloc_id_url'] ] );
+ }
}
diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php
index 41c0a54e9..4f35a1b80 100644
--- a/Zotlabs/Lib/Libzotdir.php
+++ b/Zotlabs/Lib/Libzotdir.php
@@ -207,8 +207,6 @@ class Libzotdir {
);
}
-
-
// If there are no directory servers, setup the fallback master
/** @FIXME What to do if we're in a different realm? */
@@ -249,11 +247,12 @@ class Libzotdir {
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
+
if (! $x['success'])
continue;
$j = json_decode($x['body'],true);
- if (!($j['transactions']) || ($j['ratings']))
+ if (!$j['transactions'])
continue;
q("update site set site_sync = '%s' where site_url = '%s'",
@@ -265,6 +264,11 @@ class Libzotdir {
if (is_array($j['transactions']) && count($j['transactions'])) {
foreach ($j['transactions'] as $t) {
+
+ if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
+ continue;
+ }
+
$r = q("select * from updates where ud_guid = '%s' limit 1",
dbesc($t['transaction_id'])
);
@@ -319,6 +323,14 @@ class Libzotdir {
}
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
+ // This is a workaround for a missing xchan_updated column
+ // TODO: implement xchan_updated in the xchan table and update this column instead
+ if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
+ q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
+ dbesc(datetime_convert()),
+ dbesc($zf['data']['primary_location']['url'])
+ );
+ }
}
else {
q("update updates set ud_last = '%s' where ud_addr = '%s'",
@@ -345,7 +357,7 @@ class Libzotdir {
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
- $p = q("select channel.channel_hash, channel_address, channel_timezone, channel_portable_id, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
+ $p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
intval($uid)
);
@@ -354,7 +366,6 @@ class Libzotdir {
if ($p) {
$hash = $p[0]['channel_hash'];
- $legacy_hash = $p[0]['channel_portable_id'];
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
@@ -393,10 +404,9 @@ class Libzotdir {
);
if(intval($r[0]['xchan_hidden']) != $hidden) {
- $r = q("update xchan set xchan_hidden = %d where xchan_hash in ('%s', '%s')",
+ $r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
intval($hidden),
- dbesc($hash),
- dbesc($legacy_hash)
+ dbesc($hash)
);
}
@@ -410,13 +420,11 @@ class Libzotdir {
}
else {
// they may have made it private
- q("delete from xprof where xprof_hash in ('%s', '%s')",
- dbesc($hash),
- dbesc($legacy_hash)
+ q("delete from xprof where xprof_hash = '%s'",
+ dbesc($hash)
);
- q("delete from xtag where xtag_hash in ('%s', '%s')",
- dbesc($hash),
- dbesc($legacy_hash)
+ q("delete from xtag where xtag_hash = '%s'",
+ dbesc($hash)
);
}
@@ -635,8 +643,13 @@ class Libzotdir {
$dirmode = intval(get_config('system', 'directory_mode'));
- if($dirmode == DIRECTORY_MODE_NORMAL)
+ if($dirmode == DIRECTORY_MODE_NORMAL) {
return;
+ }
+
+ if (empty($hash) || empty($guid) || empty($addr)) {
+ return;
+ }
if($flags) {
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
@@ -656,9 +669,4 @@ class Libzotdir {
}
}
-
-
-
-
-
}
diff --git a/Zotlabs/Lib/MessageFilter.php b/Zotlabs/Lib/MessageFilter.php
index 750d6d424..95721e7c7 100644
--- a/Zotlabs/Lib/MessageFilter.php
+++ b/Zotlabs/Lib/MessageFilter.php
@@ -2,87 +2,104 @@
namespace Zotlabs\Lib;
-
+require_once('include/html2plain.php');
class MessageFilter {
+ public static function evaluate($item, $incl, $excl) {
- static public function evaluate($item,$incl,$excl) {
-
- require_once('include/html2plain.php');
-
- unobscure($item);
-
- $text = prepare_text($item['body'],$item['mimetype']);
+ $text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/x-multicode'));
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
-
$lang = null;
- if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
+ if ((strpos($incl, 'lang=') !== false) || (strpos($excl, 'lang=') !== false) || (strpos($incl, 'lang!=') !== false) || (strpos($excl, 'lang!=') !== false)) {
$lang = detect_language($text);
}
- $tags = ((is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
+ $tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
// exclude always has priority
- $exclude = (($excl) ? explode("\n",$excl) : null);
+ $exclude = (($excl) ? explode("\n", $excl) : null);
- if($exclude) {
- foreach($exclude as $word) {
+ if ($exclude) {
+ foreach ($exclude as $word) {
$word = trim($word);
- if(! $word)
+ if (! $word) {
continue;
- if(substr($word,0,1) === '#' && $tags) {
- foreach($tags as $t)
- if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
- return false;
}
- elseif(substr($word,0,1) === '$' && $tags) {
- foreach($tags as $t)
- if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ if (substr($word, 0, 1) === '#' && $tags) {
+ foreach ($tags as $t) {
+ if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
return false;
- }
- elseif((strpos($word,'/') === 0) && preg_match($word,$text))
+ }
+ }
+ } elseif (substr($word, 0, 1) === '$' && $tags) {
+ foreach ($tags as $t) {
+ if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
+ return false;
+ }
+ }
+ } elseif (substr($word, 0, 2) === '?+') {
+ if (self::test_condition(substr($word, 2), $item['obj'])) {
+ return false;
+ }
+ } elseif (substr($word, 0, 1) === '?') {
+ if (self::test_condition(substr($word, 1), $item)) {
+ return false;
+ }
+ } elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
return false;
- elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
+ } elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
return false;
- elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
+ } elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
return false;
- elseif(stristr($text,$word) !== false)
+ } elseif (stristr($text, $word) !== false) {
return false;
+ }
}
}
- $include = (($incl) ? explode("\n",$incl) : null);
+ $include = (($incl) ? explode("\n", $incl) : null);
- if($include) {
- foreach($include as $word) {
+ if ($include) {
+ foreach ($include as $word) {
$word = trim($word);
- if(! $word)
+ if (! $word) {
continue;
- if(substr($word,0,1) === '#' && $tags) {
- foreach($tags as $t)
- if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
- return true;
}
- elseif(substr($word,0,1) === '$' && $tags) {
- foreach($tags as $t)
- if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ if (substr($word, 0, 1) === '#' && $tags) {
+ foreach ($tags as $t) {
+ if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
return true;
- }
- elseif((strpos($word,'/') === 0) && preg_match($word,$text))
+ }
+ }
+ } elseif (substr($word, 0, 1) === '$' && $tags) {
+ foreach ($tags as $t) {
+ if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
+ return true;
+ }
+ }
+ } elseif (substr($word, 0, 2) === '?+') {
+ if (self::test_condition(substr($word, 2), $item['obj'])) {
+ return true;
+ }
+ } elseif (substr($word, 0, 1) === '?') {
+ if (self::test_condition(substr($word, 1), $item)) {
+ return true;
+ }
+ } elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
return true;
- elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
+ } elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
return true;
- elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
+ } elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
return true;
- elseif(stristr($text,$word) !== false)
+ } elseif (stristr($text, $word) !== false) {
return true;
+ }
}
- }
- else {
+ } else {
return true;
}
@@ -90,4 +107,113 @@ class MessageFilter {
}
+ /**
+ * @brief Test for Conditional Execution conditions. Shamelessly ripped off from Code/Render/Comanche
+ *
+ * This is extensible. The first version of variable testing supports tests of the forms:
+ *
+ * - ?foo ~= baz which will check if item.foo contains the string 'baz';
+ * - ?foo == baz which will check if item.foo is the string 'baz';
+ * - ?foo != baz which will check if item.foo is not the string 'baz';
+ * - ?foo >= 3 which will check if item.foo is greater than or equal to 3;
+ * - ?foo > 3 which will check if item.foo is greater than 3;
+ * - ?foo <= 3 which will check if item.foo is less than or equal to 3;
+ * - ?foo < 3 which will check if item.foo is less than 3;
+ *
+ * - ?foo {} baz which will check if 'baz' is an array element in item.foo
+ * - ?foo {*} baz which will check if 'baz' is an array key in item.foo
+ * - ?foo which will check for a return of a true condition for item.foo;
+ *
+ * The values 0, '', an empty array, and an unset value will all evaluate to false.
+ *
+ * @param string $s
+ * @param array $item
+ * @return bool
+ */
+
+ public static function test_condition($s,$item) {
+
+ if (preg_match('/(.*?)\s\~\=\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if (stripos($x, trim($matches[2])) !== false) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\=\=\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x == trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\!\=\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x != trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\>\=\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x >= trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\<\=\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x <= trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x > trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x < trim($matches[2])) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/[\$](.*?)\s\{\}\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if (is_array($x) && in_array(trim($matches[2]), $x)) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)\s\{\*\}\s(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if (is_array($x) && array_key_exists(trim($matches[2]), $x)) {
+ return true;
+ }
+ return false;
+ }
+
+ if (preg_match('/(.*?)$/', $s, $matches)) {
+ $x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
+ if ($x) {
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+ }
+
}
diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php
index 9e6a3ac85..bf4ac8e87 100644
--- a/Zotlabs/Lib/NativeWiki.php
+++ b/Zotlabs/Lib/NativeWiki.php
@@ -12,8 +12,8 @@ class NativeWiki {
public static function listwikis($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",
+ $wikis = q("SELECT * FROM item
+ WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
@@ -49,7 +49,7 @@ class NativeWiki {
$mid = z_root() . '/item/' . $uuid;
$arr = array(); // Initialize the array of parameters for the post
- $item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
+ $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['uuid'] = $uuid;
@@ -61,8 +61,8 @@ class NativeWiki {
$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=' . urlencode($arr['mid']);
- $arr['llink'] = $arr['plink'];
+ $arr['plink'] = $mid;
+ $arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['title'] = $wiki['htmlName']; // name of new wiki;
$arr['allow_cid'] = $ac['allow_cid'];
$arr['allow_gid'] = $ac['allow_gid'];
@@ -133,13 +133,13 @@ class NativeWiki {
// update acl for any existing wiki pages
q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d where resource_type = 'nwikipage' and resource_id = '%s'",
- dbesc($item['allow_cid']),
- dbesc($item['allow_gid']),
- dbesc($item['deny_cid']),
- dbesc($item['deny_gid']),
- dbesc($item['item_private']),
+ dbesc($item['allow_cid']),
+ dbesc($item['allow_gid']),
+ dbesc($item['deny_cid']),
+ dbesc($item['deny_gid']),
+ dbesc($item['item_private']),
dbesc($arr['resource_id'])
- );
+ );
if($update['item_id']) {
@@ -211,12 +211,12 @@ class NativeWiki {
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
-
+
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
- $item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
+ $item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
$sql_extra ORDER BY id LIMIT 1",
- intval($channel_id),
+ intval($channel_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
@@ -224,7 +224,7 @@ class NativeWiki {
return [ 'wiki' => null ];
}
else {
-
+
$w = $item[0]; // wiki item table record
// Get wiki metadata
$rawName = get_iconfig($w, 'wiki', 'rawName');
@@ -246,20 +246,20 @@ class NativeWiki {
public static function exists_by_name($uid, $urlName) {
- $sql_extra = item_permissions_sql($uid);
+ $sql_extra = item_permissions_sql($uid);
- $item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
- WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
- AND item_deleted = 0 $sql_extra limit 1",
- dbesc(NWIKI_ITEM_RESOURCE_TYPE),
- //dbesc(urldecode($urlName)),
+ $item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
+ WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
+ AND item_deleted = 0 $sql_extra limit 1",
+ dbesc(NWIKI_ITEM_RESOURCE_TYPE),
+ //dbesc(urldecode($urlName)),
dbesc(self::name_decode($urlName)),
intval($uid)
);
if($item) {
return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
- }
+ }
else {
return array('id' => null, 'resource_id' => null);
}
@@ -277,7 +277,7 @@ class NativeWiki {
$r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
intval($owner_id),
- dbesc(NWIKI_ITEM_RESOURCE_TYPE),
+ dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
@@ -285,8 +285,6 @@ class NativeWiki {
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_wiki');
return array('read' => true, 'write' => $write, 'success' => true);
}
diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php
index 3c61ea800..1e944f7ac 100644
--- a/Zotlabs/Lib/NativeWikiPage.php
+++ b/Zotlabs/Lib/NativeWikiPage.php
@@ -2,14 +2,15 @@
namespace Zotlabs\Lib;
-use \Zotlabs\Lib as Zlib;
+use App;
+use Zotlabs\Access\PermissionLimits;
class NativeWikiPage {
- static public function page_list($channel_id,$observer_hash, $resource_id) {
+ static public function page_list($channel_id, $observer_hash, $resource_id) {
// TODO: Create item table records for pages so that metadata like title can be applied
- $w = Zlib\NativeWiki::get_wiki($channel_id,$observer_hash,$resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$pages[] = [
'resource_id' => '',
@@ -18,134 +19,149 @@ class NativeWikiPage {
'link_id' => 'id_wiki_home_0'
];
- $sql_extra = item_permissions_sql($channel_id,$observer_hash);
+ $sql_extra = item_permissions_sql($channel_id, $observer_hash);
- $r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
+ $r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$sql_extra order by title asc",
dbesc($resource_id),
intval($channel_id)
);
- if($r) {
+ if ($r) {
$x = [];
$y = [];
- foreach($r as $rv) {
- if(! in_array($rv['mid'],$x)) {
+ foreach ($r as $rv) {
+ if (!in_array($rv['mid'], $x)) {
$y[] = $rv;
$x[] = $rv['mid'];
}
}
- $items = fetch_post_tags($y,true);
+ $items = fetch_post_tags($y, true);
- foreach($items as $page_item) {
- $title = get_iconfig($page_item['id'],'nwikipage','pagetitle',t('(No Title)'));
- if(urldecode($title) !== 'Home') {
+ foreach ($items as $page_item) {
+ $title = get_iconfig($page_item['id'], 'nwikipage', 'pagetitle', t('(No Title)'));
+ if (urldecode($title) !== 'Home') {
$pages[] = [
'resource_id' => $resource_id,
'title' => escape_tags($title),
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
- 'url' => Zlib\NativeWiki::name_encode($title),
+ 'url' => NativeWiki::name_encode($title),
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
];
}
}
}
- return array('pages' => $pages, 'wiki' => $w);
+ return ['pages' => $pages, 'wiki' => $w];
}
- static public function create_page($channel_id, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
+ static public function create_page($channel, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
logger('mimetype: ' . $mimetype);
- if(! in_array($mimetype,[ 'text/markdown','text/bbcode','text/plain','text/html' ]))
+ if (!in_array($mimetype, ['text/markdown', 'text/bbcode', 'text/plain', 'text/html']))
$mimetype = 'text/markdown';
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel['channel_id'], $observer_hash, $resource_id);
- if (! $w['wiki']) {
- return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ if (!$w['wiki']) {
+ return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
// backslashes won't work well in the javascript functions
- $name = str_replace('\\','',$name);
-
- // create an empty activity
+ $name = str_replace('\\', '', $name);
- $arr = [];
- $arr['uid'] = $channel_id;
- $arr['author_xchan'] = $observer_hash;
- $arr['mimetype'] = $mimetype;
- $arr['title'] = $name;
- $arr['resource_type'] = 'nwikipage';
- $arr['resource_id'] = $resource_id;
- $arr['allow_cid'] = $w['wiki']['allow_cid'];
- $arr['allow_gid'] = $w['wiki']['allow_gid'];
- $arr['deny_cid'] = $w['wiki']['deny_cid'];
- $arr['deny_gid'] = $w['wiki']['deny_gid'];
+ $uuid = new_uuid();
+ $mid = z_root() . '/item/' . $uuid;
- $arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel_id,'view_wiki'),true);
+ // create an empty activity
+ $arr = [];
+ $arr['aid'] = $channel['channel_account_id'];
+ $arr['uid'] = $channel['channel_id'];
+ $arr['mid'] = $mid;
+ $arr['parent_mid'] = $w['wiki']['mid'];
+ $arr['parent'] = $w['wiki']['parent'];
+ $arr['uuid'] = $uuid;
+ $arr['item_hidden'] = $w['wiki']['item_hidden'];
+ $arr['plink'] = $mid;
+ $arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
+ $arr['author_xchan'] = $observer_hash;
+ $arr['mimetype'] = $mimetype;
+ $arr['title'] = $name;
+ $arr['resource_type'] = 'nwikipage';
+ $arr['resource_id'] = $resource_id;
+ $arr['allow_cid'] = $w['wiki']['allow_cid'];
+ $arr['allow_gid'] = $w['wiki']['allow_gid'];
+ $arr['deny_cid'] = $w['wiki']['deny_cid'];
+ $arr['deny_gid'] = $w['wiki']['deny_gid'];
+ $arr['item_private'] = $w['wiki']['item_private'];
+ $arr['item_wall'] = 1;
+ $arr['item_origin'] = 1;
+ $arr['item_thread_top'] = 1;
+ $arr['verb'] = ACTIVITY_CREATE;
+ $arr['obj_type'] = 'Document';
+ // TODO: add an object?
+ $arr['public_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'], 'view_wiki'), true);
// We may wish to change this some day.
$arr['item_unpublished'] = 1;
- set_iconfig($arr,'nwikipage','pagetitle',(($name) ? $name : t('(No Title)')),true);
-
- $p = post_activity_item($arr, false, false);
+ set_iconfig($arr, 'nwikipage', 'pagetitle', (($name) ? $name : t('(No Title)')), true);
+ $p = item_store($arr, false, false);
- if($p['item_id']) {
- $page = [
+ if ($p['item_id']) {
+ $page = [
'rawName' => $name,
'htmlName' => escape_tags($name),
- //'urlName' => urlencode($name),
- 'urlName' => Zlib\NativeWiki::name_encode($name)
+ //'urlName' => urlencode($name),
+ 'urlName' => NativeWiki::name_encode($name)
];
- return array('page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true);
+ return ['page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true];
}
- return [ 'success' => false, 'message' => t('Wiki page create failed.') ];
+ return ['success' => false, 'message' => t('Wiki page create failed.')];
}
static public function 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'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
+ $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'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if(! $w['wiki']) {
- return array('message' => t('Wiki not found.'), 'success' => false);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ if (!$w['wiki']) {
+ return ['message' => t('Wiki not found.'), 'success' => false];
}
- $ic = q("select * from iconfig left join item on iconfig.iid = item.id
+ $ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageNewName)
);
- if($ic) {
- return [ 'success' => false, 'message' => t('Destination name already exists') ];
+ if ($ic) {
+ return ['success' => false, 'message' => t('Destination name already exists')];
}
$ids = [];
- $ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
+ $ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
- if($ic) {
- foreach($ic as $c) {
- set_iconfig($c['item_id'],'nwikipage','pagetitle',$pageNewName);
+ if ($ic) {
+ foreach ($ic as $c) {
+ set_iconfig($c['item_id'], 'nwikipage', 'pagetitle', $pageNewName);
$ids[] = $c['item_id'];
}
@@ -154,105 +170,101 @@ class NativeWikiPage {
dbesc($pageNewName)
);
- $page = [
- 'rawName' => $pageNewName,
- 'htmlName' => escape_tags($pageNewName),
+ $page = [
+ 'rawName' => $pageNewName,
+ 'htmlName' => escape_tags($pageNewName),
//'urlName' => urlencode(escape_tags($pageNewName))
- 'urlName' => Zlib\NativeWiki::name_encode($pageNewName)
+ 'urlName' => NativeWiki::name_encode($pageNewName)
];
- return [ 'success' => true, 'page' => $page ];
+ return ['success' => true, 'page' => $page];
}
- return [ 'success' => false, 'message' => t('Page not found') ];
-
+ return ['success' => false, 'message' => t('Page not found')];
+
}
static public function get_page_content($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? intval($arr['channel_id']) : 0);
- $revision = ((array_key_exists('revision',$arr)) ? intval($arr['revision']) : (-1));
-
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? intval($arr['channel_id']) : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if (! $w['wiki']) {
- return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ if (!$w['wiki']) {
+ return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$item = self::load_page($arr);
- if($item) {
+ if ($item) {
$content = $item['body'];
- return [
+ return [
'content' => $content,
'mimeType' => $w['mimeType'],
- 'pageMimeType' => $item['mimetype'],
- 'message' => '',
+ 'pageMimeType' => $item['mimetype'],
+ 'message' => '',
'success' => true
];
}
-
- return array('content' => null, 'message' => t('Error reading page content'), 'success' => false);
+
+ return ['content' => null, 'message' => t('Error reading page content'), 'success' => false];
}
static public function page_history($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
- return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
+ return ['history' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$items = self::load_page_history($arr);
$history = [];
- if($items) {
+ if ($items) {
$processed = 0;
- foreach($items as $item) {
- if($processed > 1000)
+ foreach ($items as $item) {
+ if ($processed > 1000)
break;
- $processed ++;
- $history[] = [
+ $processed++;
+ $history[] = [
'revision' => $item['revision'],
- 'date' => datetime_convert('UTC',date_default_timezone_get(),$item['edited']),
- 'name' => $item['author']['xchan_name'],
- 'title' => get_iconfig($item,'nwikipage','commit_msg')
+ 'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited']),
+ 'name' => $item['author']['xchan_name'],
+ 'title' => get_iconfig($item, 'nwikipage', 'commit_msg')
];
}
- return [ 'success' => true, 'history' => $history ];
+ return ['success' => true, 'history' => $history];
}
- return [ 'success' => false ];
+ return ['success' => false];
}
-
+
static public function load_page($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
- $revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
+ $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
+ $revision = ((array_key_exists('revision', $arr)) ? $arr['revision'] : (-1));
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if (! $w['wiki']) {
- return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ if (!$w['wiki']) {
+ return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
@@ -262,32 +274,32 @@ class NativeWikiPage {
dbesc($pageUrlName)
);
- if($ic) {
- foreach($ic as $c) {
- if($ids)
+ if ($ic) {
+ foreach ($ic as $c) {
+ if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
- $sql_extra = item_permissions_sql($channel_id,$observer_hash);
+ $sql_extra = item_permissions_sql($channel_id, $observer_hash);
- if($revision == (-1))
+ if ($revision == (-1))
$sql_extra .= " order by revision desc ";
- elseif($revision)
+ elseif ($revision)
$sql_extra .= " and revision = " . intval($revision) . " ";
$r = null;
- if($ids) {
+ if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) $sql_extra limit 1",
dbesc($resource_id),
intval($channel_id)
);
- if($r) {
- $items = fetch_post_tags($r,true);
+ if ($r) {
+ $items = fetch_post_tags($r, true);
return $items[0];
}
}
@@ -298,15 +310,14 @@ class NativeWikiPage {
static public function load_page_history($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
- $revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : (-1));
+ $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if (! $w['wiki']) {
- return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ if (!$w['wiki']) {
+ return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
@@ -315,28 +326,28 @@ class NativeWikiPage {
intval($channel_id),
dbesc($pageUrlName)
);
-
- if($ic) {
- foreach($ic as $c) {
- if($ids)
+
+ if ($ic) {
+ foreach ($ic as $c) {
+ if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
- $sql_extra = item_permissions_sql($channel_id,$observer_hash);
+ $sql_extra = item_permissions_sql($channel_id, $observer_hash);
$sql_extra .= " order by revision desc ";
$r = null;
- if($ids) {
+ if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) and item_deleted = 0 $sql_extra",
dbesc($resource_id),
intval($channel_id)
);
- if($r) {
+ if ($r) {
xchan_query($r);
- $items = fetch_post_tags($r,true);
+ $items = fetch_post_tags($r, true);
return $items;
}
}
@@ -346,31 +357,30 @@ class NativeWikiPage {
static public function save_page($arr) {
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
- $content = ((array_key_exists('content',$arr)) ? $arr['content'] : '');
- $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
- $revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0);
+ $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
+ $content = ((array_key_exists('content', $arr)) ? $arr['content'] : '');
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
- return array('message' => t('Error reading wiki'), 'success' => false);
+ return ['message' => t('Error reading wiki'), 'success' => false];
}
-
- // fetch the most recently saved revision.
+
+ // fetch the most recently saved revision.
$item = self::load_page($arr);
- if(! $item) {
- return array('message' => t('Page not found'), 'success' => false);
+ if (!$item) {
+ return ['message' => t('Page not found'), 'success' => false];
}
$mimetype = $item['mimetype'];
- // change just the fields we need to change to create a revision;
+ // change just the fields we need to change to create a revision;
unset($item['id']);
unset($item['author']);
@@ -381,8 +391,8 @@ class NativeWikiPage {
$item['edited'] = datetime_convert();
$item['mimetype'] = $mimetype;
- if($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
- for($x = 0; $x < count($item['iconfig']); $x ++) {
+ if ($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
+ for ($x = 0; $x < count($item['iconfig']); $x++) {
unset($item['iconfig'][$x]['id']);
unset($item['iconfig'][$x]['iid']);
}
@@ -390,168 +400,164 @@ class NativeWikiPage {
$ret = item_store($item, false, false);
- if($ret['item_id'])
- return array('message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true);
+ if ($ret['item_id'])
+ return ['message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true];
else
- return array('message' => t('Page update failed.'), 'success' => false);
- }
+ return ['message' => t('Page update failed.'), 'success' => false];
+ }
static public function delete_page($arr) {
- $pageUrlName = (array_key_exists('pageUrlName',$arr) ? $arr['pageUrlName'] : '');
- $resource_id = (array_key_exists('resource_id',$arr) ? $arr['resource_id'] : '');
- $observer_hash = (array_key_exists('observer_hash',$arr) ? $arr['observer_hash'] : '');
- $channel_id = (array_key_exists('channel_id',$arr) ? $arr['channel_id'] : 0);
+ $pageUrlName = (array_key_exists('pageUrlName', $arr) ? $arr['pageUrlName'] : '');
+ $resource_id = (array_key_exists('resource_id', $arr) ? $arr['resource_id'] : '');
+ $observer_hash = (array_key_exists('observer_hash', $arr) ? $arr['observer_hash'] : '');
+ $channel_id = (array_key_exists('channel_id', $arr) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if(! $w['wiki']) {
- return [ 'success' => false, 'message' => t('Error reading wiki') ];
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ if (!$w['wiki']) {
+ return ['success' => false, 'message' => t('Error reading wiki')];
}
$ids = [];
- $ic = q("select * from iconfig left join item on iconfig.iid = item.id
+ $ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
- if($ic) {
- foreach($ic as $c) {
+ if ($ic) {
+ foreach ($ic as $c) {
$ids[] = intval($c['iid']);
}
}
- if($ids) {
+ if ($ids) {
drop_items($ids, true, DROPITEM_PHASE1);
- return [ 'success' => true ];
+ return ['success' => true];
}
- return [ 'success' => false, 'message' => t('Nothing deleted') ];
+ return ['success' => false, 'message' => t('Nothing deleted')];
}
-
+
static public function 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);
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $commitHash = ((array_key_exists('commitHash', $arr)) ? $arr['commitHash'] : null);
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- if (! $commitHash) {
- return array('message' => 'No commit was provided', 'success' => false);
+ if (!$commitHash) {
+ return ['message' => 'No commit was provided', 'success' => false];
}
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
- return array('message' => 'Error reading wiki', 'success' => false);
+ return ['message' => 'Error reading wiki', 'success' => false];
}
$x = $arr;
- if(intval($commitHash) > 0) {
+ if (intval($commitHash) > 0) {
unset($x['commitHash']);
$x['revision'] = intval($commitHash) - 1;
- $loaded = self::load_page($x);
+ $loaded = self::load_page($x);
- if($loaded) {
+ if ($loaded) {
$content = $loaded['body'];
- return [ 'content' => $content, 'success' => true ];
+ return ['content' => $content, 'success' => true];
}
- return [ 'success' => false ];
+ return ['success' => false];
}
}
-
+
static public function 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'] : (-1));
- $compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : 0);
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
+ $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
+ $compareCommit = ((array_key_exists('compareCommit', $arr)) ? $arr['compareCommit'] : 0);
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
- return array('message' => t('Error reading wiki'), 'success' => false);
+ return ['message' => t('Error reading wiki'), 'success' => false];
}
- $x = $arr;
+ $x = $arr;
$x['revision'] = (-1);
$currpage = self::load_page($x);
- if($currpage)
+ if ($currpage)
$currentContent = $currpage['body'];
$x['revision'] = $compareCommit;
- $comppage = self::load_page($x);
- if($comppage)
+ $comppage = self::load_page($x);
+ if ($comppage)
$compareContent = $comppage['body'];
- if($currpage && $comppage) {
+ if ($currpage && $comppage) {
require_once('library/class.Diff.php');
$diff = \Diff::toTable(\Diff::compare($currentContent, $compareContent));
- return [ 'success' => true, 'diff' => $diff ];
+ return ['success' => true, 'diff' => $diff];
}
- return [ 'success' => false, 'message' => t('Compare: object not found.') ];
+ return ['success' => false, 'message' => t('Compare: object not found.')];
}
-
+
static public function commit($arr) {
- $commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
- $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : '');
- $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0);
- $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : t('Untitled'));
+ $commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
+ $observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
+ $channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
- if(array_key_exists('resource_id', $arr)) {
+ if (array_key_exists('resource_id', $arr)) {
$resource_id = $arr['resource_id'];
}
else {
- return array('message' => t('Wiki resource_id required for git commit'), 'success' => false);
+ return ['message' => t('Wiki resource_id required for git commit'), 'success' => false];
}
- $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
- if (! $w['wiki']) {
- return array('message' => t('Error reading wiki'), 'success' => false);
+ $w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
+ if (!$w['wiki']) {
+ return ['message' => t('Error reading wiki'), 'success' => false];
}
$page = self::load_page($arr);
- if($page) {
- set_iconfig($page['id'],'nwikipage','commit_msg',escape_tags($commit_msg),true);
- return [ 'success' => true, 'item_id' => $page['id'], 'page' => $page ];
+ if ($page) {
+ set_iconfig($page['id'], 'nwikipage', 'commit_msg', escape_tags($commit_msg), true);
+ return ['success' => true, 'item_id' => $page['id'], 'page' => $page];
}
- return [ 'success' => false, 'message' => t('Page not found.') ];
+ return ['success' => false, 'message' => t('Page not found.')];
}
-
+
static public function convert_links($s, $wikiURL) {
-
- if (strpos($s,'[[') !== false) {
+
+ if (strpos($s, '[[') !== false) {
preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
- $pages = $pageURLs = array();
+ $pages = $pageURLs = [];
foreach ($match[1] as $m) {
// TODO: Why do we need to double urlencode for this to work?
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
- $titleUri = explode('|',$m);
- $page = $titleUri[0] ?? '';
- $title = $titleUri[1] ?? $page;
- $pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($page));
- $pages[] = $title;
+ $titleUri = explode('|', $m);
+ $page = $titleUri[0] ?? '';
+ $title = $titleUri[1] ?? $page;
+ $pageURLs[] = NativeWiki::name_encode(escape_tags($page));
+ $pages[] = $title;
}
$idx = 0;
- while(strpos($s,'[[') !== false) {
- $replace = '<a href="'.$wikiURL.'/'.$pageURLs[$idx].'">'.$pages[$idx].'</a>';
- $s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
+ while (strpos($s, '[[') !== false) {
+ $replace = '<a href="' . $wikiURL . '/' . $pageURLs[$idx] . '">' . $pages[$idx] . '</a>';
+ $s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
$idx++;
}
}
@@ -564,21 +570,21 @@ class NativeWikiPage {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = self::page_history([
- 'channel_id' => \App::$profile_uid,
+ '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(
+ return replace_macros(get_markup_template('nwiki_page_history.tpl'), [
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
- '$msg_label' => t('Message','wiki_history'),
+ '$msg_label' => t('Message', 'wiki_history'),
'$date_lbl' => t('Date'),
'$revert_btn' => t('Revert'),
'$compare_btn' => t('Compare')
- ));
+ ]);
}
@@ -590,14 +596,14 @@ class NativeWikiPage {
* @return string
*/
static public function generate_toc($s) {
- if (strpos($s,'[toc]') !== false) {
+ 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);
+ $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
@@ -605,27 +611,27 @@ class NativeWikiPage {
* @return string
*/
static public function bbcode($s) {
-
- $s = str_replace(array('[baseurl]', '[sitename]'), array(z_root(), get_config('system', 'sitename')), $s);
-
- $s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_callback', $s);
- $s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism",'oblanguage_necallback', $s);
+ $s = str_replace(['[baseurl]', '[sitename]'], [z_root(), get_config('system', 'sitename')], $s);
+
+ $s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_callback', $s);
+ $s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_necallback', $s);
- $observer = \App::get_observer();
+
+ $observer = App::get_observer();
if ($observer) {
- $s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
- $s2 = '</span>';
+ $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);
- }
+ $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);
@@ -637,62 +643,63 @@ class NativeWikiPage {
return $s;
}
-
+
static public function get_file_ext($arr) {
- if($arr['mimetype'] === 'text/bbcode')
+ if ($arr['mimetype'] === 'text/bbcode')
return '.bb';
- elseif($arr['mimetype'] === 'text/markdown')
+ elseif ($arr['mimetype'] === 'text/markdown')
return '.md';
- elseif($arr['mimetype'] === 'text/plain')
+ elseif ($arr['mimetype'] === 'text/plain')
return '.txt';
}
-
- // This function is derived from
+
+ // This function is derived from
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
static public function 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)];
- }
+ // 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) {
+ foreach ($raw_toc as $t) {
$level = intval($t['level']);
- $text = $t['text'];
+ $text = $t['text'];
switch ($level) {
case 1:
$li = '* ';
@@ -712,7 +719,7 @@ class NativeWikiPage {
}
$o .= $li . $text . "\n";
}
- return $o;
+ return $o;
}
}
diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php
index 765131f0d..80340f501 100644
--- a/Zotlabs/Lib/PConfig.php
+++ b/Zotlabs/Lib/PConfig.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Lib;
+use App;
+
/**
* @brief Class for handling channel specific configurations.
*
@@ -32,15 +34,15 @@ class PConfig {
if(is_null($uid) || $uid === false)
return false;
- if(! is_array(\App::$config)) {
+ if(! is_array(App::$config)) {
btlogger('App::$config not an array');
}
- if(! array_key_exists($uid, \App::$config)) {
- \App::$config[$uid] = array();
+ if(! array_key_exists($uid, App::$config)) {
+ App::$config[$uid] = array();
}
- if(! is_array(\App::$config[$uid])) {
+ if(! is_array(App::$config[$uid])) {
btlogger('App::$config[$uid] not an array: ' . $uid);
}
@@ -52,12 +54,12 @@ class PConfig {
foreach($r as $rr) {
$k = $rr['k'];
$c = $rr['cat'];
- if(! array_key_exists($c, \App::$config[$uid])) {
- \App::$config[$uid][$c] = array();
- \App::$config[$uid][$c]['config_loaded'] = true;
+ if(! array_key_exists($c, App::$config[$uid])) {
+ App::$config[$uid][$c] = array();
+ App::$config[$uid][$c]['config_loaded'] = true;
}
- \App::$config[$uid][$c][$k] = $rr['v'];
- \App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
+ App::$config[$uid][$c][$k] = $rr['v'];
+ App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
}
}
}
@@ -86,15 +88,15 @@ class PConfig {
if(is_null($uid) || $uid === false)
return $default;
- if(! array_key_exists($uid, \App::$config))
+ if(! array_key_exists($uid, App::$config))
self::Load($uid);
- if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
+ if((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family])))
return $default;
- return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
- ? unserialize(\App::$config[$uid][$family][$key])
- : \App::$config[$uid][$family][$key]
+ return ((! is_array(App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$uid][$family][$key]))
+ ? unserialize(App::$config[$uid][$family][$key])
+ : App::$config[$uid][$family][$key]
);
}
@@ -133,6 +135,7 @@ class PConfig {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
$new = false;
+ $update = false;
$now = datetime_convert();
if (! $updated) {
@@ -143,23 +146,22 @@ class PConfig {
$updated = datetime_convert('UTC','UTC','-2 seconds');
}
- $hash = hash('sha256',$family.':'.$key);
+ $hash = gen_link_id($family.':'.$key);
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
if (self::Get($uid, 'hz_delpconfig', $hash) > $now) {
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
return self::Get($uid,$family,$key);
} else {
- self::Delete($uid,'hz_delpconfig',$hash);
+ self::Delete($uid, 'hz_delpconfig', $hash);
}
}
if(self::Get($uid, $family, $key) === false) {
- if(! array_key_exists($uid, \App::$config))
- \App::$config[$uid] = array();
- if(! array_key_exists($family, \App::$config[$uid]))
- \App::$config[$uid][$family] = array();
-
+ if(! array_key_exists($uid, App::$config))
+ App::$config[$uid] = array();
+ if(! array_key_exists($family, App::$config[$uid]))
+ App::$config[$uid][$family] = array();
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
intval($uid),
@@ -177,13 +179,14 @@ class PConfig {
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
}
- \App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
+ $new = true;
+ App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
}
else {
- $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
+ $update = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
- if ($new) {
+ if ($update) {
// @NOTE There is still a possible race condition under limited circumstances
// where a value will be updated by another thread with more current data than
@@ -198,7 +201,7 @@ class PConfig {
dbesc($key)
);
- \App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
+ App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
} else {
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
@@ -211,16 +214,16 @@ class PConfig {
// set in the life of this page. We need this to
// synchronise channel clones.
- if(! array_key_exists('transient', \App::$config[$uid]))
- \App::$config[$uid]['transient'] = array();
- if(! array_key_exists($family, \App::$config[$uid]['transient']))
- \App::$config[$uid]['transient'][$family] = array();
+ if(! array_key_exists('transient', App::$config[$uid]))
+ App::$config[$uid]['transient'] = array();
+ if(! array_key_exists($family, App::$config[$uid]['transient']))
+ App::$config[$uid]['transient'][$family] = array();
- \App::$config[$uid][$family][$key] = $value;
+ App::$config[$uid][$family][$key] = $value;
- if ($new) {
- \App::$config[$uid]['transient'][$family][$key] = $value;
- \App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
+ if ($new || $update) {
+ App::$config[$uid]['transient'][$family][$key] = $value;
+ App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
}
if($ret)
@@ -253,7 +256,7 @@ class PConfig {
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
$now = datetime_convert();
- $newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
+ $newer = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
if (! $newer) {
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
@@ -262,12 +265,12 @@ class PConfig {
$ret = false;
- if (isset(\App::$config[$uid][$family][$key])) {
- unset(\App::$config[$uid][$family][$key]);
+ if (isset(App::$config[$uid][$family][$key])) {
+ unset(App::$config[$uid][$family][$key]);
}
- if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
- unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
+ if (isset(App::$config[$uid][$family]['pcfgud:'.$key])) {
+ unset(App::$config[$uid][$family]['pcfgud:'.$key]);
}
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
@@ -278,9 +281,9 @@ class PConfig {
// Synchronize delete with clones.
- if ($family != 'hz_delpconfig') {
- $hash = hash('sha256',$family.':'.$key);
- set_pconfig($uid,'hz_delpconfig',$hash,$updated);
+ if ($family !== 'hz_delpconfig') {
+ $hash = gen_link_id($family.':'.$key);
+ set_pconfig($uid, 'hz_delpconfig', $hash, $updated);
}
return $ret;
diff --git a/Zotlabs/Lib/Permcat.php b/Zotlabs/Lib/Permcat.php
index ca4aed9ed..0a38ca324 100644
--- a/Zotlabs/Lib/Permcat.php
+++ b/Zotlabs/Lib/Permcat.php
@@ -4,6 +4,7 @@ namespace Zotlabs\Lib;
use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\Permissions;
+use Zotlabs\Daemon\Master;
/**
* @brief Permission Categories. Permission rules for various classes of connections.
@@ -38,33 +39,33 @@ class Permcat {
// first check role perms for a perms_connect setting
- $role = get_pconfig($channel_id,'system','permissions_role');
- if($role) {
+ $role = get_pconfig($channel_id, 'system', 'permissions_role');
+ if ($role) {
$x = PermissionRoles::role_perms($role);
- if($x['perms_connect']) {
+ if ($x['perms_connect']) {
$perms = Permissions::FilledPerms($x['perms_connect']);
}
}
// if no role perms it may be a custom role, see if there any autoperms
- if(! $perms) {
+ if (!$perms) {
$perms = Permissions::FilledAutoPerms($channel_id);
}
// if no autoperms it may be a custom role with manual perms
- if(! $perms) {
+ if (!$perms) {
$r = q("select channel_hash from channel where channel_id = %d",
intval($channel_id)
);
- if($r) {
+ if ($r) {
$x = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'my_perms'",
intval($channel_id),
dbesc($r[0]['channel_hash'])
);
- if($x) {
- foreach($x as $xv) {
+ if ($x) {
+ foreach ($x as $xv) {
$perms[$xv['k']] = intval($xv['v']);
}
}
@@ -73,25 +74,27 @@ class Permcat {
// nothing was found - create a filled permission array where all permissions are 0
- if(! $perms) {
+ if (!$perms) {
$perms = Permissions::FilledPerms([]);
}
$this->permcats[] = [
'name' => 'default',
- 'localname' => t('default','permcat'),
+ 'localname' => t('Default', 'permcat'),
'perms' => Permissions::Operms($perms),
+ 'raw_perms' => $perms,
'system' => 1
];
$p = $this->load_permcats($channel_id);
- if($p) {
- for($x = 0; $x < count($p); $x++) {
+ if ($p) {
+ for ($x = 0; $x < count($p); $x++) {
$this->permcats[] = [
'name' => $p[$x][0],
'localname' => $p[$x][1],
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
+ 'raw_perms' => Permissions::FilledPerms($p[$x][2]),
'system' => intval($p[$x][3])
];
}
@@ -116,9 +119,9 @@ class Permcat {
* * \e bool \b error if $name not found in permcats true
*/
public function fetch($name) {
- if($name && $this->permcats) {
- foreach($this->permcats as $permcat) {
- if(strcasecmp($permcat['name'], $name) === 0) {
+ if ($name && $this->permcats) {
+ foreach ($this->permcats as $permcat) {
+ if (strcasecmp($permcat['name'], $name) === 0) {
return $permcat;
}
}
@@ -128,31 +131,28 @@ class Permcat {
}
public function load_permcats($uid) {
-
+ /*
$permcats = [
- [ 'follower', t('follower','permcat'),
- [ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
- 'post_like' ], 1
+ [ 'contributor', t('Contributor','permcat'),
+ [ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
+ 'write_storage','post_wall','write_pages','write_wiki','post_comments', 'post_mail', 'post_like',
+ 'chat' ], 1
],
- [ 'contributor', t('contributor','permcat'),
+ [ 'muted', t('Muted','permcat'),
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
- 'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
+ 'post_comments','write_wiki','post_like' ], 1
],
- [ 'publisher', t('publisher','permcat'),
- [ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
- 'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
- 'chat', 'republish' ], 1
- ]
];
-
- if($uid) {
+ */
+ if ($uid) {
$x = q("select * from pconfig where uid = %d and cat = 'permcat'",
intval($uid)
);
- if($x) {
- foreach($x as $xv) {
- $value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
- $permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
+
+ if ($x) {
+ foreach ($x as $xv) {
+ $value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
+ $permcats[] = [$xv['k'], $xv['k'], $value, 0];
}
}
}
@@ -167,11 +167,11 @@ class Permcat {
}
static public function find_permcat($arr, $name) {
- if((! $arr) || (! $name))
+ if ((!$arr) || (!$name))
return false;
- foreach($arr as $p)
- if($p['name'] == $name)
+ foreach ($arr as $p)
+ if ($p['name'] == $name)
return $p['value'];
}
@@ -183,4 +183,105 @@ class Permcat {
PConfig::Delete($channel_id, 'permcat', $name);
}
-} \ No newline at end of file
+ /**
+ * @brief assign a contact role to contacts
+ *
+ * @param array $channel
+ * @param string $role the name of the role
+ * @param array $contacts an array of contact hashes
+ */
+ public static function assign($channel, $role, $contacts) {
+
+ if (!isset($channel['channel_id'])) {
+ return;
+ }
+
+ if (!is_array($contacts) || empty($contacts)) {
+ return;
+ }
+
+ if (!$role) {
+ // lookup the default
+ $role = get_pconfig($channel['channel_id'], 'system', 'default_permcat', 'default');
+ }
+
+
+ // Doublecheck that we do not assign a role to ourself.
+ // It does not make a difference but could be confusing.
+ if (in_array($channel['channel_hash'], $contacts)) {
+ $contacts = array_diff($contacts, [$channel['channel_hash']]);
+ }
+
+ $all_perms = Permissions::Perms();
+ $permcats = new Permcat($channel['channel_id']);
+ $role_perms = $permcats->fetch($role);
+
+ if (isset($role_perms['error'])) {
+ return false;
+ }
+
+ $perms = $role_perms['raw_perms'];
+
+ $values_sql = '';
+ stringify_array_elms($contacts, true);
+
+ if ($all_perms && $perms) {
+
+ foreach ($contacts as $contact) {
+ foreach ($all_perms as $perm => $desc) {
+ if (array_key_exists($perm, $perms)) {
+ $values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', " . intval($perms[$perm]) . "),";
+ }
+ else {
+ $values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', 0), ";
+ }
+ }
+ }
+ }
+
+ $values_sql = rtrim($values_sql, ',');
+
+ dbq("DELETE FROM abconfig WHERE chan = " . intval($channel['channel_id']) . " AND cat = 'my_perms' AND xchan IN (" . protect_sprintf(implode(',', $contacts)) . ")");
+
+ dbq("INSERT INTO abconfig ( chan, xchan, cat, k, v ) VALUES $values_sql");
+
+ q("UPDATE abook SET abook_role = '%s'
+ WHERE abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook_channel = %d",
+ dbesc($role),
+ intval($channel['channel_id'])
+ );
+
+ $r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook.abook_xchan = xchan.xchan_hash WHERE abook.abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook.abook_channel = %d AND abook_self = 0",
+ intval($channel['channel_id'])
+ );
+
+ foreach ($r as $rr) {
+
+ if (intval($rr['abook_self'])) {
+ continue;
+ }
+
+ Master::Summon([
+ 'Notifier',
+ 'permission_update',
+ $rr['abook_id']
+ ]);
+
+ $clone = $rr;
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
+
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
+
+ }
+
+ return true;
+ }
+
+}
diff --git a/Zotlabs/Lib/Queue.php b/Zotlabs/Lib/Queue.php
index 373a7d304..e03816f05 100644
--- a/Zotlabs/Lib/Queue.php
+++ b/Zotlabs/Lib/Queue.php
@@ -2,6 +2,9 @@
namespace Zotlabs\Lib;
+use Zotlabs\Zot6\Receiver;
+use Zotlabs\Zot6\Zot6Handler;
+
class Queue {
static function update($id, $add_priority = 0) {
@@ -28,19 +31,19 @@ class Queue {
$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.
+ // 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
+ // 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.
+ // minutes.
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'))) {
@@ -50,9 +53,9 @@ class Queue {
$next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes');
}
- q("UPDATE outq SET outq_updated = '%s',
- outq_priority = outq_priority + %d,
- outq_scheduled = '%s'
+ q("UPDATE outq SET outq_updated = '%s',
+ outq_priority = outq_priority + %d,
+ outq_scheduled = '%s'
WHERE outq_hash = '%s'",
dbesc(datetime_convert()),
@@ -66,7 +69,7 @@ class Queue {
static function remove($id,$channel_id = 0) {
logger('queue: remove queue item ' . $id,LOGGER_DEBUG);
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
-
+
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
dbesc($id)
);
@@ -75,7 +78,7 @@ class Queue {
static function remove_by_posturl($posturl) {
logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG);
-
+
q("DELETE FROM outq WHERE outq_posturl = '%s' ",
dbesc($posturl)
);
@@ -88,7 +91,7 @@ class Queue {
$sql_extra = (($channel['channel_id']) ? " and outq_channel = " . intval($channel['channel_id']) . " " : '');
// 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.
+ // 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()),
@@ -108,7 +111,7 @@ class Queue {
}
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
- outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
+ 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']),
@@ -133,7 +136,7 @@ class Queue {
$base = null;
$h = parse_url($outq['outq_posturl']);
- if($h !== false)
+ if($h !== false)
$base = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
if(($base) && ($base !== z_root()) && ($immediate)) {
@@ -147,7 +150,7 @@ class Queue {
return;
}
if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
- self::update($outq['outq_hash'],10);
+ self::update($outq['outq_hash'], 10);
logger('immediate delivery deferred for site ' . $base);
return;
}
@@ -158,12 +161,12 @@ class Queue {
// your site has existed. Since we don't know for sure what these sites are,
// call them unknown
- site_store_lowlevel(
+ site_store_lowlevel(
[
'site_url' => $base,
'site_update' => datetime_convert(),
'site_dead' => 0,
- 'site_type' => intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
+ 'site_type' => SITE_TYPE_UNKNOWN,
'site_crypto' => ''
]
);
@@ -171,65 +174,17 @@ class Queue {
}
$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
- call_hooks('queue_deliver',$arr);
+ call_hooks('queue_deliver', $arr);
if($arr['handled'])
return;
- // "post" queue driver - used for diaspora and friendica-over-diaspora communications.
-
- if($outq['outq_driver'] === 'post') {
- $result = z_post_url($outq['outq_posturl'],$outq['outq_msg']);
- if($result['success'] && $result['return_code'] < 300) {
- logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
- if($base) {
- q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
- dbesc(datetime_convert()),
- dbesc($base)
- );
- }
- q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
- dbesc('accepted for delivery'),
- dbesc(datetime_convert()),
- dbesc($outq['outq_hash'])
- );
- self::remove($outq['outq_hash']);
-
- // server is responding - see if anything else is going to this destination and is piled up
- // and try to send some more. We're relying on the fact that do_delivery() results in an
- // immediate delivery otherwise we could get into a queue loop.
-
- if(! $immediate) {
- $x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
- dbesc($outq['outq_posturl'])
- );
-
- $piled_up = array();
- if($x) {
- foreach($x as $xx) {
- $piled_up[] = $xx['outq_hash'];
- }
- }
- if($piled_up) {
- // call do_delivery() with the force flag
- do_delivery($piled_up, true);
- }
- }
- }
- else {
- logger('deliver: queue post returned ' . $result['return_code']
- . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
- self::update($outq['outq_hash'],10);
- }
- return;
- }
-
// normal zot delivery
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
if($outq['outq_posturl'] === z_root() . '/zot') {
// local delivery
- $zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
+ $zot = new Receiver(new Zot6Handler(), $outq['outq_notify']);
$result = $zot->run();
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
@@ -240,13 +195,14 @@ class Queue {
$channel = null;
if($outq['outq_channel']) {
- $channel = channelx_by_n($outq['outq_channel']);
+ $channel = channelx_by_n($outq['outq_channel'], true);
}
$host_crypto = null;
if($channel && $base) {
- $h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_sitekey != '' order by hubloc_id desc limit 1",
+ $h = q("SELECT hubloc_sitekey, site_crypto FROM hubloc LEFT JOIN site ON hubloc_url = site_url
+ WHERE site_url = '%s' AND hubloc_network = 'zot6' ORDER BY hubloc_id DESC LIMIT 1",
dbesc($base)
);
if($h) {
@@ -256,7 +212,7 @@ class Queue {
$msg = $outq['outq_notify'];
- $result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
+ $result = Libzot::zot($outq['outq_posturl'], $msg, $channel, $host_crypto);
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
@@ -265,7 +221,7 @@ class Queue {
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
- self::update($outq['outq_hash'],10);
+ self::update($outq['outq_hash'], 10);
}
}
return;
diff --git a/Zotlabs/Lib/Share.php b/Zotlabs/Lib/Share.php
index b4cd5a194..81f378d0d 100644
--- a/Zotlabs/Lib/Share.php
+++ b/Zotlabs/Lib/Share.php
@@ -8,13 +8,13 @@ class Share {
public function __construct($post_id) {
-
+
if(! $post_id)
return;
-
+
if(! (local_channel() || remote_channel()))
return;
-
+
$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
intval($post_id)
);
@@ -23,26 +23,26 @@ class Share {
if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
return;
-
+
$sql_extra = item_permissions_sql($r[0]['uid']);
-
+
$r = q("select * from item where id = %d $sql_extra",
intval($post_id)
);
if(! $r)
return;
-
+
if($r[0]['mimetype'] !== 'text/bbcode')
return;
-
+
/** @FIXME eventually we want to post remotely via rpost on your home site */
// When that works remove this next bit:
-
+
if(! local_channel())
return;
xchan_query($r);
-
+
$this->item = $r[0];
return;
}
@@ -66,14 +66,14 @@ class Share {
'address' => $this->item['author']['xchan_addr'],
'network' => $this->item['author']['xchan_network'],
'link' => [
- [
- 'rel' => 'alternate',
- 'type' => 'text/html',
+ [
+ 'rel' => 'alternate',
+ 'type' => 'text/html',
'href' => $this->item['author']['xchan_url']
],
[
- 'rel' => 'photo',
- 'type' => $this->item['author']['xchan_photo_mimetype'],
+ 'rel' => 'photo',
+ 'type' => $this->item['author']['xchan_photo_mimetype'],
'href' => $this->item['author']['xchan_photo_m']
]
]
@@ -84,14 +84,14 @@ class Share {
'address' => $this->item['owner']['xchan_addr'],
'network' => $this->item['owner']['xchan_network'],
'link' => [
- [
- 'rel' => 'alternate',
- 'type' => 'text/html',
+ [
+ 'rel' => 'alternate',
+ 'type' => 'text/html',
'href' => $this->item['owner']['xchan_url']
],
[
- 'rel' => 'photo',
- 'type' => $this->item['owner']['xchan_photo_mimetype'],
+ 'rel' => 'photo',
+ 'type' => $this->item['owner']['xchan_photo_mimetype'],
'href' => $this->item['owner']['xchan_photo_m']
]
]
@@ -117,7 +117,7 @@ class Share {
$object = json_decode($this->item['obj'],true);
$photo_bb = $object['body'];
}
-
+
if (strpos($this->item['body'], "[/share]") !== false) {
$pos = strpos($this->item['body'], "[share");
$bb = substr($this->item['body'], $pos);
@@ -126,7 +126,7 @@ class Share {
"' profile='" . $this->item['author']['xchan_url'] .
"' avatar='" . $this->item['author']['xchan_photo_s'] .
"' link='" . $this->item['plink'] .
- "' auth='" . ((in_array($this->item['author']['xchan_network'], ['zot6', 'zot'])) ? 'true' : 'false') .
+ "' auth='" . (($this->item['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='" . $this->item['created'] .
"' message_id='" . $this->item['mid'] .
"']";
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index c0d5c001b..8d20935a1 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -2,7 +2,9 @@
namespace Zotlabs\Lib;
+use App;
use Zotlabs\Lib\Apps;
+use Zotlabs\Access\AccessList;
require_once('include/text.php');
@@ -58,6 +60,9 @@ class ThreadItem {
$child = new ThreadItem($item);
$this->add_child($child);
}
+
+ // performance: we have already added the children
+ unset($this->data['children']);
}
// allow a site to configure the order and content of the reaction emoji list
@@ -98,11 +103,25 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
- $lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
- || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
- ? t('Private Message')
+ $acl = new AccessList(false);
+ $acl->set($item);
+
+ $lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
+ ? t('Restricted message')
: false);
- $locktype = $item['item_private'];
+
+ // 1 = restricted message, 2 = direct message
+ $locktype = intval($item['item_private']);
+
+ if ($locktype === 2) {
+ $lock = t('Direct message');
+ }
+
+ // 0 = limited based on public policy
+ if ($item['uid'] == local_channel() && intval($item['item_private']) && !$acl->is_private() && strlen($item['public_policy'])) {
+ $lock = t('Public Policy');
+ $locktype = 0;
+ }
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
@@ -110,6 +129,16 @@ class ThreadItem {
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
+ // @fixme
+ // Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
+ // Sharing a poll using a regular embedded share is harder because the poll will need to fork. This is due to comment permissions.
+ // The original poll author may not accept responses from strangers. Forking the poll will receive responses from the sharer's
+ // followers, but there's no elegant way to merge these two sets of results together. For now, we'll disable sharing polls.
+
+ if ($item['obj_type'] === 'Question') {
+ $shareable = false;
+ }
+
$privacy_warning = false;
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
@@ -299,7 +328,7 @@ class ThreadItem {
);
*/
- $settings = t('Conversation Tools');
+ $settings = t('Conversation Features');
}
$has_bookmarks = false;
@@ -367,7 +396,7 @@ class ThreadItem {
call_hooks('dropdown_extras',$dropdown_extras_arr);
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
- $midb64 = 'b64.' . base64url_encode($item['mid']);
+ $midb64 = gen_link_id($item['mid']);
$mids = [ $midb64 ];
$response_mids = [];
foreach($response_verbs as $v) {
@@ -384,6 +413,12 @@ class ThreadItem {
$pinned_items = ($allowed_type ? get_pconfig($item['uid'], 'pinned', $item['item_type'], []) : []);
$pinned = ((!empty($pinned_items) && in_array($midb64, $pinned_items)) ? true : false);
+ $contact = [];
+
+ if(App::$contacts && array_key_exists($item['author_xchan'], App::$contacts)) {
+ $contact = App::$contacts[$item['author_xchan']];
+ }
+
$tmp_item = array(
'template' => $this->get_template(),
'mode' => $mode,
@@ -401,6 +436,7 @@ class ThreadItem {
'mids' => $json_mids,
'parent' => $item['parent'],
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
+ 'author_is_group_actor' => (($item['author']['xchan_pubforum']) ? t('Forum') : ''),
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
@@ -503,7 +539,9 @@ class ThreadItem {
'wait' => t('Please wait'),
'thread_level' => $thread_level,
'settings' => $settings,
- 'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? 'b64.' . base64url_encode($item['thr_parent']) : '')
+ 'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : ''),
+ 'contact_id' => (($contact) ? $contact['abook_id'] : '')
+
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -842,7 +880,7 @@ class ThreadItem {
'$cipher' => $conv->get_cipher(),
'$sourceapp' => \App::$sourcename,
'$observer' => get_observer_hash(),
- '$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
+ '$anoncomments' => ((in_array($conv->get_mode(), ['channel', 'display', 'cards', 'articles']) && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
'$anonname' => [ 'anonname', t('Your full name (required)') ],
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ]
diff --git a/Zotlabs/Lib/ThreadStream.php b/Zotlabs/Lib/ThreadStream.php
index 68b2c70dd..7fe8fcc2e 100644
--- a/Zotlabs/Lib/ThreadStream.php
+++ b/Zotlabs/Lib/ThreadStream.php
@@ -77,7 +77,7 @@ class ThreadStream {
$this->reload = $_SESSION['return_url'];
break;
case 'display':
- // in this mode we set profile_owner after initialisation (from conversation()) and then
+ // in this mode we set profile_owner after initialisation (from conversation()) and then
// pull some trickery which allows us to re-invoke this function afterward
// it's an ugly hack so @FIXME
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
@@ -170,14 +170,14 @@ class ThreadStream {
* Only add things that will be displayed
*/
-
+
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
return false;
}
$item->set_commentable(false);
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
-
+
if(! comments_are_now_closed($item->get_data())) {
if(($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash))
$item->set_commentable(true);
@@ -194,7 +194,7 @@ class ThreadStream {
}
if($this->mode === 'pubstream' && (! local_channel())) {
$item->set_commentable(false);
- }
+ }
$item->set_conversation($this);
diff --git a/Zotlabs/Lib/ZotURL.php b/Zotlabs/Lib/ZotURL.php
index 6bb01fd7a..db0071f72 100644
--- a/Zotlabs/Lib/ZotURL.php
+++ b/Zotlabs/Lib/ZotURL.php
@@ -87,4 +87,4 @@ class ZotURL {
return ids_to_array($r,'hubloc_url');
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Lib/Zotfinger.php b/Zotlabs/Lib/Zotfinger.php
index 840d91403..fa57ab56d 100644
--- a/Zotlabs/Lib/Zotfinger.php
+++ b/Zotlabs/Lib/Zotfinger.php
@@ -6,7 +6,7 @@ use Zotlabs\Web\HTTPSig;
class Zotfinger {
- static function exec($resource,$channel = null, $verify = true) {
+ static function exec($resource, $channel = null, $verify = true, $recurse = true) {
if(! $resource) {
return false;
@@ -39,6 +39,30 @@ class Zotfinger {
logger('fetch: ' . print_r($x,true));
+ if (in_array(intval($x['return_code']), [ 404, 410 ]) && $recurse) {
+
+ // The resource has been deleted or doesn't exist at this location.
+ // Try to find another nomadic resource for this channel and return that.
+
+ // First, see if there's a hubloc for this site. Fetch that record to
+ // obtain the nomadic identity hash. Then use that to find any additional
+ // nomadic locations.
+
+ $h = Activity::get_actor_hublocs($resource, 'zot6');
+ if ($h) {
+ // mark this location deleted
+ hubloc_delete($h[0]);
+ $hubs = Activity::get_actor_hublocs($h[0]['hubloc_hash']);
+ if ($hubs) {
+ foreach ($hubs as $hub) {
+ if ($hub['hubloc_id_url'] !== $resource && !$hub['hubloc_deleted']) {
+ return self::exec($hub['hubloc_id_url'], $channel, $verify);
+ }
+ }
+ }
+ }
+ }
+
if($x['success']) {
if ($verify) {
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php
index fb95b0504..5b37f2707 100644
--- a/Zotlabs/Module/Acl.php
+++ b/Zotlabs/Module/Acl.php
@@ -3,9 +3,9 @@
namespace Zotlabs\Module;
use Zotlabs\Lib\Libzotdir;
+use Zotlabs\Lib\AccessList;
require_once 'include/acl_selectors.php';
-require_once 'include/group.php';
/**
* @brief ACL selector json backend.
@@ -123,7 +123,7 @@ class Acl extends \Zotlabs\Web\Controller {
"name" => t('Profile','acl') . ' ' . $rv['profile_name'],
"id" => 'vp' . $rv['id'],
"xid" => 'vp.' . $rv['profile_guid'],
- "uids" => group_get_profile_members_xchan(local_channel(), $rv['id']),
+ "uids" => AccessList::profile_members_xchan(local_channel(), $rv['id']),
"link" => ''
);
}
@@ -146,14 +146,14 @@ class Acl extends \Zotlabs\Web\Controller {
if($r) {
foreach($r as $g){
- // logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
+ // logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(), $g['id']));
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['gname'],
"id" => $g['id'],
"xid" => $g['hash'],
- "uids" => group_get_members_xchan($g['id']),
+ "uids" => AccessList::members_xchan(local_channel(), $g['id']),
"link" => ''
);
}
@@ -222,6 +222,7 @@ class Acl extends \Zotlabs\Web\Controller {
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
intval(local_channel())
);
+
if($r2)
$r = array_merge($r2,$r);
@@ -282,13 +283,12 @@ class Acl extends \Zotlabs\Web\Controller {
}
}
elseif($type == 'm') {
-
$r = array();
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
and xchan_deleted = 0
- and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora')
+ and not xchan_network IN ('rss', 'anon', 'unknown')
$sql_extra3
ORDER BY xchan_name ASC ",
intval(local_channel())
@@ -371,7 +371,7 @@ class Acl extends \Zotlabs\Web\Controller {
);
}
if($type !== 'f') {
- if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && ($g['net'] == 'zot6' || $g['net'] == 'zot'))) {
+ if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && $g['net'] == 'zot6')) {
$contacts[$x[$lkey]] = array(
"type" => "c",
"photo" => $g['micro'],
@@ -438,7 +438,6 @@ class Acl extends \Zotlabs\Web\Controller {
}
if(! $url) {
- require_once("include/dir_fns.php");
$directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch';
}
diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php
index 44c10b339..59a9e22b2 100644
--- a/Zotlabs/Module/Admin.php
+++ b/Zotlabs/Module/Admin.php
@@ -8,7 +8,6 @@
namespace Zotlabs\Module;
-require_once('include/queue_fn.php');
require_once('include/account.php');
/**
diff --git a/Zotlabs/Module/Admin/Queue.php b/Zotlabs/Module/Admin/Queue.php
index 5a47413ee..8a843083b 100644
--- a/Zotlabs/Module/Admin/Queue.php
+++ b/Zotlabs/Module/Admin/Queue.php
@@ -2,52 +2,64 @@
namespace Zotlabs\Module\Admin;
-
+use Zotlabs\Lib\Queue as LibQueue;
class Queue {
-
+
function get() {
$o = '';
-
+
$expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0);
-
+
if($_REQUEST['drophub']) {
hubloc_mark_as_down($_REQUEST['drophub']);
- remove_queue_by_posturl($_REQUEST['drophub']);
+ LibQueue::remove_by_posturl($_REQUEST['drophub']);
}
-
+
if($_REQUEST['emptyhub']) {
- remove_queue_by_posturl($_REQUEST['emptyhub']);
+ LibQueue::remove_by_posturl($_REQUEST['emptyhub']);
+ }
+
+ if($_REQUEST['deliverhub']) {
+
+ $hubq = q("SELECT * FROM outq WHERE outq_posturl = '%s'",
+ dbesc($_REQUEST['deliverhub'])
+ );
+
+ foreach ($hubq as $q) {
+ LibQueue::deliver($q, true);
+ }
}
-
- $r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
+
+ $r = dbq("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
where outq_delivered = 0 group by outq_posturl order by total desc");
-
+
for($x = 0; $x < count($r); $x ++) {
$r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']);
$r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d');
}
-
+
$o = replace_macros(get_markup_template('admin_queue.tpl'), array(
'$banner' => t('Queue Statistics'),
'$numentries' => t('Total Entries'),
'$priority' => t('Priority'),
'$desturl' => t('Destination URL'),
'$nukehub' => t('Mark hub permanently offline'),
+ '$deliverhub' => t('Retry delivery to this hub'),
'$empty' => t('Empty queue for this hub'),
'$lastconn' => t('Last known contact'),
'$hasentries' => ((count($r)) ? true : false),
'$entries' => $r,
'$expert' => $expert
));
-
+
return $o;
}
-
-} \ No newline at end of file
+
+}
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 3b2632411..f6e3ab12b 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -339,11 +339,14 @@ class Site {
// now invert the logic for the setting.
$discover_tab = (1 - $discover_tab);
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
- $default_role = get_config('system','default_permissions_role','social');
+ $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
+ $default_role = get_config('system', 'default_permissions_role', 'personal');
- $role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles);
+ if (!in_array($default_role, array_keys($perm_roles))) {
+ $default_role = 'personal';
+ }
+ $role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles);
$homelogin = get_config('system','login_on_homepage');
$enable_context_help = get_config('system','enable_context_help');
@@ -480,12 +483,12 @@ class Site {
'$invitation_only' => [
'invitation_only',
t("Require invite code"),
- $invitation_only
+ get_config('system', 'invitation_only', 0)
],
'$invitation_also' => [
'invitation_also',
t("Allow invite code"),
- $invitation_also
+ get_config('system', 'invitation_also', 0)
],
'$verify_email' => [
'verify_email',
diff --git a/Zotlabs/Module/Affinity.php b/Zotlabs/Module/Affinity.php
index f0d99f1e7..0e163b89a 100644
--- a/Zotlabs/Module/Affinity.php
+++ b/Zotlabs/Module/Affinity.php
@@ -44,17 +44,14 @@ class Affinity extends \Zotlabs\Web\Controller {
if(! local_channel())
return;
- $desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.');
- if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) {
+ if(! Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= $desc;
- return $o;
+ $papp = Apps::get_papp('Affinity Tool');
+ return Apps::app_render($papp, 'module');
}
- $text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
+ $text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
$content = '<div class="section-content-info-wrapper">' . $text . '</div>';
diff --git a/Zotlabs/Module/Album.php b/Zotlabs/Module/Album.php
new file mode 100644
index 000000000..f80880184
--- /dev/null
+++ b/Zotlabs/Module/Album.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\Config;
+use Zotlabs\Web\HTTPSig;
+
+require_once('include/security.php');
+require_once('include/attach.php');
+require_once('include/photo/photo_driver.php');
+require_once('include/photos.php');
+
+
+class Album extends Controller {
+
+ function init() {
+
+ if (ActivityStreams::is_as_request()) {
+ $sigdata = HTTPSig::verify(EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ if (!check_channelallowed($portable_id)) {
+ http_status_exit(403, 'Permission denied');
+ }
+ if (!check_siteallowed($sigdata['signer'])) {
+ http_status_exit(403, 'Permission denied');
+ }
+ observer_auth($portable_id);
+ }
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
+ }
+
+ $observer_xchan = get_observer_hash();
+ $allowed = false;
+
+ $bear = Activity::token_from_request();
+ if ($bear) {
+ logger('bear: ' . $bear, LOGGER_DEBUG);
+ }
+
+ $channel = null;
+
+ if (argc() > 1) {
+ $channel = channelx_by_nick(argv(1));
+ }
+ if (!$channel) {
+ http_status_exit(404, 'Not found.');
+ }
+
+ $sql_extra = permissions_sql($channel['channel_id'], $observer_xchan);
+
+ if (argc() > 2) {
+ $folder = argv(2);
+ $r = q("select * from attach where is_dir = 1 and hash = '%s' and uid = %d $sql_extra limit 1",
+ dbesc($folder),
+ intval($channel['channel_id'])
+ );
+ $allowed = (($r) ? attach_can_view($channel['channel_id'], $observer_xchan, $r[0]['hash'] /*,$bear */) : false);
+ }
+ else {
+ $folder = EMPTY_STR;
+ $allowed = perm_is_allowed($channel['channel_id'], $observer_xchan, 'view_storage');
+ }
+
+ if (!$allowed) {
+ http_status_exit(403, 'Permission denied.');
+ }
+
+ $x = q("select * from attach where folder = '%s' and uid = %d $sql_extra",
+ dbesc($folder),
+ intval($channel['channel_id'])
+ );
+
+ $contents = [];
+
+ if ($x) {
+ foreach ($x as $xv) {
+ if (intval($xv['is_dir'])) {
+ continue;
+ }
+ if (!attach_can_view($channel['channel_id'], $observer_xchan, $xv['hash'] /*,$bear*/)) {
+ continue;
+ }
+ if (intval($xv['is_photo'])) {
+ $contents[] = z_root() . '/photo/' . $xv['hash'];
+ }
+ }
+ }
+
+ $obj = Activity::encode_simple_collection($contents, App::$query_string, 'OrderedCollection', count($contents));
+ as_return_and_die($obj, $channel);
+
+ }
+
+ }
+
+}
+
diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php
index 39689665e..d287115d4 100644
--- a/Zotlabs/Module/Appman.php
+++ b/Zotlabs/Module/Appman.php
@@ -1,18 +1,18 @@
<?php /** @file */
-namespace Zotlabs\Module;
+namespace Zotlabs\Module;
-//require_once('include/apps.php');
-
-use \Zotlabs\Lib as Zlib;
+use App;
+use Zotlabs\Lib\Apps;
+use Zotlabs\Lib\Libsync;
class Appman extends \Zotlabs\Web\Controller {
function post() {
-
+
if(! local_channel())
return;
-
+
if($_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
@@ -32,32 +32,70 @@ class Appman extends \Zotlabs\Web\Controller {
'sig' => escape_tags($_REQUEST['sig']),
'categories' => escape_tags($_REQUEST['categories'])
);
-
- $_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr);
-
- if(Zlib\Apps::app_installed(local_channel(),$arr))
+
+ $_REQUEST['appid'] = Apps::app_install(local_channel(),$arr);
+
+ if(Apps::app_installed(local_channel(),$arr))
info( t('App installed.') . EOL);
goaway(z_root() . '/apps');
return; //not reached
}
-
-
- $papp = Zlib\Apps::app_decode($_POST['papp']);
-
+
+
+ $papp = Apps::app_decode($_POST['papp']);
+
if(! is_array($papp)) {
notice( t('Malformed app.') . EOL);
return;
}
-
+
if($_POST['install']) {
- Zlib\Apps::app_install(local_channel(),$papp);
- if(Zlib\Apps::app_installed(local_channel(),$papp))
+ Apps::app_install(local_channel(),$papp);
+ if(Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
+
+ $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($papp['guid'])
+ );
+
+ if (!$sync) {
+ return;
+ }
+
+ if (intval($sync[0]['app_system'])) {
+ Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
+ }
+ else {
+ Libsync::build_sync_packet($uid, ['app' => $sync]);
+ }
+
}
-
+
if($_POST['delete']) {
- Zlib\Apps::app_destroy(local_channel(),$papp);
+
+ // Fetch the app for sync before it is deleted (if it is deletable))
+ $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($papp['guid'])
+ );
+
+ if (!$sync) {
+ return;
+ }
+
+ Apps::app_destroy(local_channel(), $papp);
+
+ // Now flag it deleted
+ $sync[0]['app_deleted'] = 1;
+
+ if (intval($sync[0]['app_system'])) {
+ Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
+ }
+ else {
+ Libsync::build_sync_packet($uid, ['app' => $sync]);
+ }
}
if($_POST['edit']) {
@@ -65,37 +103,65 @@ class Appman extends \Zotlabs\Web\Controller {
}
if($_POST['feature']) {
- Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']);
+ Apps::app_feature(local_channel(), $papp, $_POST['feature']);
+
+ $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($papp['guid'])
+ );
+
+ if (intval($sync[0]['app_system'])) {
+ Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
+ }
+ else {
+ Libsync::build_sync_packet($uid, ['app' => $sync]);
+ }
}
if($_POST['pin']) {
- Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']);
+ Apps::app_feature(local_channel(), $papp, $_POST['pin']);
+
+ $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($papp['guid'])
+ );
+
+ if (intval($sync[0]['app_system'])) {
+ Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
+ }
+ else {
+ Libsync::build_sync_packet($uid, ['app' => $sync]);
+ }
}
- if($_SESSION['return_url'])
+ if($_POST['aj']) {
+ killme();
+ }
+
+ if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/apps');
-
-
+
+
}
-
-
+
+
function get() {
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
- $channel = \App::get_channel();
+ $channel = App::get_channel();
if(argc() > 3) {
if(argv(2) === 'moveup') {
- Zlib\Apps::moveup(local_channel(),argv(1),argv(3));
+ Apps::moveup(local_channel(),argv(1),argv(3));
}
if(argv(2) === 'movedown') {
- Zlib\Apps::movedown(local_channel(),argv(1),argv(3));
+ Apps::movedown(local_channel(),argv(1),argv(3));
}
goaway(z_root() . '/apporder');
}
@@ -129,12 +195,12 @@ class Appman extends \Zotlabs\Web\Controller {
}
}
- $embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"');
-
+ $embed = array('embed', t('Embed code'), Apps::app_encode($app,true),'', 'onclick="this.select();"');
+
}
-
+
return replace_macros(get_markup_template('app_create.tpl'), array(
-
+
'$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''),
@@ -154,7 +220,7 @@ class Appman extends \Zotlabs\Web\Controller {
'$embed' => $embed,
'$submit' => t('Submit')
));
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php
index 05b4495fc..77d1f2aec 100644
--- a/Zotlabs/Module/Apps.php
+++ b/Zotlabs/Module/Apps.php
@@ -9,7 +9,7 @@ class Apps extends \Zotlabs\Web\Controller {
function get() {
nav_set_selected('Apps');
-
+
if(argc() == 2 && argv(1) == 'edit')
$mode = 'edit';
else
@@ -18,9 +18,9 @@ class Apps extends \Zotlabs\Web\Controller {
$available = ((argc() == 2 && argv(1) === 'available') ? true : false);
$_SESSION['return_url'] = \App::$query_string;
-
+
$apps = array();
-
+
if(local_channel()) {
Zlib\Apps::import_system_apps();
$syslist = array();
@@ -37,9 +37,9 @@ class Apps extends \Zotlabs\Web\Controller {
$syslist = Zlib\Apps::get_system_apps(true);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
-
+
// logger('apps: ' . print_r($syslist,true));
-
+
foreach($syslist as $app) {
$apps[] = Zlib\Apps::app_render($app,(($available) ? 'install' : $mode));
}
@@ -53,7 +53,7 @@ class Apps extends \Zotlabs\Web\Controller {
'$manage' => (($available) ? '' : t('Manage Apps')),
'$create' => (($mode == 'edit') ? t('Create Custom App') : '')
));
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Apschema.php b/Zotlabs/Module/Apschema.php
index 6b0325d44..e8d45c522 100644
--- a/Zotlabs/Module/Apschema.php
+++ b/Zotlabs/Module/Apschema.php
@@ -14,7 +14,7 @@ class Apschema extends \Zotlabs\Web\Controller {
'zot' => z_root() . '/apschema#',
'id' => '@id',
'type' => '@type',
- 'commentPolicy' => 'as:commentPolicy',
+ 'commentPolicy' => 'zot:commentPolicy',
'meData' => 'zot:meData',
'meDataType' => 'zot:meDataType',
'meEncoding' => 'zot:meEncoding',
@@ -33,6 +33,9 @@ class Apschema extends \Zotlabs\Web\Controller {
'PropertyValue' => 'schema:PropertyValue',
'value' => 'schema:value',
+ 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
+
+
'magicEnv' => [
'@id' => 'zot:magicEnv',
'@type' => '@id'
@@ -50,7 +53,7 @@ class Apschema extends \Zotlabs\Web\Controller {
'guid' => 'diaspora:guid',
'Hashtag' => 'as:Hashtag'
-
+
]
];
diff --git a/Zotlabs/Module/Article_edit.php b/Zotlabs/Module/Article_edit.php
index efa02e1c1..97c87f2ba 100644
--- a/Zotlabs/Module/Article_edit.php
+++ b/Zotlabs/Module/Article_edit.php
@@ -85,7 +85,6 @@ class Article_edit extends \Zotlabs\Web\Controller {
$mimetype = $itm[0]['mimetype'];
- $summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : '');
$content = $itm[0]['body'];
$rp = 'articles/' . $channel['channel_address'];
@@ -109,7 +108,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
- 'body' => $summary . undo_post_tagging($content),
+ 'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php
index 9152f0e0e..0db098a31 100644
--- a/Zotlabs/Module/Articles.php
+++ b/Zotlabs/Module/Articles.php
@@ -48,10 +48,8 @@ class Articles extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Articles App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Create interactive articles');
- return $o;
+ $papp = Apps::get_papp('Articles');
+ return Apps::app_render($papp, 'module');
}
nav_set_selected('Articles');
diff --git a/Zotlabs/Module/Authtest.php b/Zotlabs/Module/Authtest.php
index 239ae3bdb..d85af09dc 100644
--- a/Zotlabs/Module/Authtest.php
+++ b/Zotlabs/Module/Authtest.php
@@ -1,41 +1,38 @@
<?php
namespace Zotlabs\Module;
-require_once('include/zot.php');
-
-
class Authtest extends \Zotlabs\Web\Controller {
function get() {
-
-
+
+
$auth_success = false;
$o .= '<h3>Magic-Auth Diagnostic</h3>';
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return $o;
}
-
+
$o .= '<form action="authtest" method="get">';
$o .= 'Target URL: <input type="text" style="width: 250px;" name="dest" value="' . $_GET['dest'] .'" />';
- $o .= '<input type="submit" name="submit" value="Submit" /></form>';
-
+ $o .= '<input type="submit" name="submit" value="Submit" /></form>';
+
$o .= '<br /><br />';
-
+
if(x($_GET,'dest')) {
if(strpos($_GET['dest'],'@')) {
$_GET['dest'] = $_REQUEST['dest'] = 'https://' . substr($_GET['dest'],strpos($_GET['dest'],'@')+1) . '/channel/' . substr($_GET['dest'],0,strpos($_GET['dest'],'@'));
}
-
+
$_REQUEST['test'] = 1;
$mod = new Magic();
$x = $mod->init($a);
$o .= 'Local Setup returns: ' . print_r($x,true);
-
-
-
+
+
+
if($x['url']) {
$z = z_fetch_url($x['url'] . '&test=1');
if($z['success']) {
@@ -50,12 +47,12 @@ class Authtest extends \Zotlabs\Web\Controller {
$o .= 'fetch url failure.' . print_r($z,true);
}
}
-
+
if(! $auth_success)
$o .= 'Authentication Failed!' . EOL;
}
-
+
return str_replace("\n",'<br />',$o);
}
-
+
}
diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php
index 822b18308..659884fed 100644
--- a/Zotlabs/Module/Bookmarks.php
+++ b/Zotlabs/Module/Bookmarks.php
@@ -18,31 +18,31 @@ class Bookmarks extends \Zotlabs\Web\Controller {
$item_id = (isset($_REQUEST['item']) ? $_REQUEST['item'] : false);
$burl = (isset($_REQUEST['burl']) ? trim($_REQUEST['burl']) : '');
-
+
if(! $item_id)
return;
-
+
$u = \App::get_channel();
-
+
$item_normal = item_normal();
-
+
$i = q("select * from item where id = %d and uid = %d $item_normal limit 1",
intval($item_id),
intval(local_channel())
);
-
+
if(! $i)
return;
-
+
$i = fetch_post_tags($i);
-
+
$item = $i[0];
-
+
$terms = (x($item, 'term') ? get_terms_oftype($item['term'],TERM_BOOKMARK) : false);
-
+
if($terms) {
require_once('include/bookmarks.php');
-
+
$s = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
@@ -58,13 +58,13 @@ class Bookmarks extends \Zotlabs\Web\Controller {
}
else
bookmark_add($u,$s[0],$t,$item['item_private']);
-
+
info( t('Bookmark added') . EOL);
}
}
killme();
}
-
+
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@@ -74,49 +74,47 @@ class Bookmarks extends \Zotlabs\Web\Controller {
if(! Apps::system_app_installed(local_channel(), 'Bookmarks')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Bookmarks App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Bookmark links from posts and manage them');
- return $o;
+ $papp = Apps::get_papp('Bookmarks');
+ return Apps::app_render($papp, 'module');
}
-
+
require_once('include/menu.php');
require_once('include/conversation.php');
-
+
$channel = \App::get_channel();
-
+
$o = '';
-
+
$o .= '<div class="generic-content-wrapper-styled">';
-
- $o .= '<h3>' . t('My Bookmarks') . '</h3>';
-
+
+ $o .= '<h3>' . t('Bookmarks') . '</h3>';
+
$x = menu_list(local_channel(),'',MENU_BOOKMARK);
-
+
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
-
+
$o .= '<h3>' . t('My Connections Bookmarks') . '</h3>';
-
-
+
+
$x = menu_list(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
-
+
if($x) {
foreach($x as $xx) {
$y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash());
$o .= menu_render($y,'',true);
}
}
-
+
$o .= '</div>';
-
+
return $o;
-
+
}
-
-
+
+
}
diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php
index 8f47208ce..b71af6044 100644
--- a/Zotlabs/Module/Cards.php
+++ b/Zotlabs/Module/Cards.php
@@ -47,10 +47,8 @@ class Cards extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Cards App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Create personal planning cards');
- return $o;
+ $papp = Apps::get_papp('Cards');
+ return Apps::app_render($papp, 'module');
}
nav_set_selected('Cards');
diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php
index e26cdd072..599552545 100644
--- a/Zotlabs/Module/Cdav.php
+++ b/Zotlabs/Module/Cdav.php
@@ -873,10 +873,8 @@ class Cdav extends Controller {
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('CardDAV App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('CalDAV capable addressbook');
- return $o;
+ $papp = Apps::get_papp('CardDAV');
+ return Apps::app_render($papp, 'module');
}
App::$profile_uid = local_channel();
@@ -1059,6 +1057,7 @@ class Cdav extends Controller {
'$cancel' => t('Cancel'),
'$create' => t('Create'),
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'),
+ '$disabled_warning' => t('Could not fetch calendar resource. The selected calendar might be disabled.'),
'$channel_hash' => $channel['channel_hash'],
'$acl' => $acl,
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index a7deb4f6b..aebc70c15 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -46,14 +46,15 @@ class Channel extends Controller {
}
$profile = 0;
- $channel = App::get_channel();
if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
+ $channel = App::get_channel();
$which = $channel['channel_address'];
$profile = argv(1);
}
- $channel = channelx_by_nick($which);
+ $channel = channelx_by_nick($which, true);
+
if (!$channel) {
http_status_exit(404, 'Not found');
}
@@ -65,8 +66,8 @@ class Channel extends Controller {
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
- $data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']]));
- $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
+ $data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash'], 'target_url' => $sigdata['signer']]));
+ $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($sigdata['signer'])
);
@@ -83,24 +84,31 @@ class Channel extends Controller {
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
];
- $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
+
+ $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
HTTPSig::set_headers($h);
echo $data;
killme();
}
+ if ($channel['channel_removed']) {
+ http_status_exit(410, 'Gone');
+ }
+
+ if (get_pconfig($channel['channel_id'], 'system', 'index_opt_out')) {
+ App::$meta->set('robots', 'noindex, noarchive');
+ }
+
if (ActivityStreams::is_as_request($channel)) {
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
// Make it do the right thing.
- $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
- if ($mid && strpos($mid, 'b64.') === 0) {
- $decoded = @base64url_decode(substr($mid, 4));
- if ($decoded) {
- $mid = $decoded;
- }
+ $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
+ if ($mid === false) {
+ http_status_exit(404, 'Not found');
}
+
if ($mid) {
$obj = null;
if (strpos($mid, z_root() . '/item/') === 0) {
@@ -145,15 +153,19 @@ class Channel extends Controller {
profile_load($which, $profile);
// Add Opengraph markup
- $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
- if (strpos($mid, 'b64.') === 0)
- $mid = @base64url_decode(substr($mid, 4));
+ $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
- if ($mid)
+ if ($mid === false) {
+ notice(t('Malformed message id.') . EOL);
+ return;
+ }
+
+ if ($mid) {
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc($mid),
intval($channel['channel_id'])
);
+ }
opengraph_add_meta((isset($r) && count($r) ? $r[0] : []), $channel);
}
@@ -164,12 +176,11 @@ class Channel extends Controller {
$category = $datequery = $datequery2 = '';
- $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : '');
-
- if (strpos($mid, 'b64.') === 0)
- $decoded = @base64url_decode(substr($mid, 4));
- if (isset($decoded))
- $mid = $decoded;
+ $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
+ if ($mid === false) {
+ notice(t('Malformed message id.') . EOL);
+ return;
+ }
$datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
@@ -213,7 +224,7 @@ class Channel extends Controller {
if (!$update) {
- nav_set_selected('Channel Home');
+ nav_set_selected('Channel');
// search terms header
if ($search) {
@@ -420,8 +431,8 @@ class Channel extends Controller {
if ((!$update) && (!$load)) {
- if (isset($decoded))
- $mid = 'b64.' . base64url_encode($mid);
+ //if we got a decoded hash we must encode it again before handing to javascript
+ $mid = gen_link_id($mid);
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php
index 8ae4841b4..fc1146023 100644
--- a/Zotlabs/Module/Chanview.php
+++ b/Zotlabs/Module/Chanview.php
@@ -10,49 +10,49 @@ use Zotlabs\Lib\Zotfinger;
class Chanview extends \Zotlabs\Web\Controller {
function get() {
-
+
$observer = App::get_observer();
$xchan = null;
-
+
$r = null;
-
+
if($_REQUEST['hash']) {
- $r = q("select * from xchan where xchan_hash = '%s'",
+ $r = q("select * from xchan where xchan_hash = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['hash'])
);
}
if($_REQUEST['address']) {
- $r = q("select * from xchan where xchan_addr = '%s'",
+ $r = q("select * from xchan where xchan_addr = '%s' and xchan_deleted = 0",
dbesc(punify($_REQUEST['address']))
);
}
elseif(local_channel() && intval($_REQUEST['cid'])) {
- $r = q("SELECT abook.*, xchan.*
+ $r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
- WHERE abook_channel = %d and abook_id = %d",
+ WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0",
intval(local_channel()),
intval($_REQUEST['cid'])
);
- }
+ }
elseif($_REQUEST['url']) {
-
+
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
- // the most useful consistently ascending table item we have.
-
- $r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc",
+ // the most useful consistently ascending table item we have.
+
+ $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0 order by xchan_name_date desc",
dbesc($_REQUEST['url'])
);
}
if($r) {
App::$poi = Libzot::zot_record_preferred($r, 'xchan_network');
}
-
-
+
+
// Here, let's see if we have an xchan. If we don't, how we proceed is determined by what
- // info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
- // address, we can and should try to import it. If it's just a hash, we can't continue, but we
+ // info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or
+ // address, we can and should try to import it. If it's just a hash, we can't continue, but we
// probably wouldn't have a hash if we don't already have an xchan for this channel.
-
+
if(! App::$poi) {
logger('mod_chanview: fallback');
@@ -71,7 +71,7 @@ class Chanview extends \Zotlabs\Web\Controller {
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
- $r = q("select * from xchan where xchan_url = '%s'",
+ $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['url'])
);
if($r) {
@@ -80,7 +80,7 @@ class Chanview extends \Zotlabs\Web\Controller {
}
if(! $r) {
if(discover_by_webbie($_REQUEST['url'])) {
- $r = q("select * from xchan where xchan_url = '%s'",
+ $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['url'])
);
if($r) {
@@ -90,7 +90,7 @@ class Chanview extends \Zotlabs\Web\Controller {
}
}
}
-
+
if(! App::$poi) {
notice( t('Channel not found.') . EOL);
return;
@@ -98,9 +98,9 @@ class Chanview extends \Zotlabs\Web\Controller {
$is_zot = false;
$connected = false;
-
+
$url = App::$poi['xchan_url'];
- if(in_array(App::$poi['xchan_network'], ['zot', 'zot6'])) {
+ if(App::$poi['xchan_network'] === 'zot6') {
$is_zot = true;
}
if(local_channel()) {
@@ -111,29 +111,29 @@ class Chanview extends \Zotlabs\Web\Controller {
if($c)
$connected = true;
}
-
- // We will load the chanview template if it's a foreign network,
+
+ // We will load the chanview template if it's a foreign network,
// just so that we can provide a connect button along with a profile
// photo. Chances are we can't load the remote profile into an iframe
// because of cross-domain security headers. So provide a link to
- // the remote profile.
+ // the remote profile.
// If we are already connected, just go to the profile.
// Zot channels will usually have a connect link.
-
+
if($is_zot || $connected) {
if($is_zot && $observer) {
$url = zid($url);
}
goaway($url);
}
- else {
+ else {
$o = replace_macros(get_markup_template('chanview.tpl'),array(
'$url' => $url,
'$full' => t('toggle full screen mode')
));
-
+
return $o;
}
}
-
+
}
diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php
index 28e775f9d..323471161 100644
--- a/Zotlabs/Module/Chat.php
+++ b/Zotlabs/Module/Chat.php
@@ -14,7 +14,7 @@ require_once('include/bookmarks.php');
class Chat extends Controller {
function init() {
-
+
$which = null;
if(argc() > 1)
$which = argv(1);
@@ -29,79 +29,77 @@ class Chat extends Controller {
notice( t('You must be logged in to see this page.') . EOL );
return;
}
-
+
$profile = 0;
$channel = App::get_channel();
-
+
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
- $profile = argv(1);
+ $profile = argv(1);
}
-
+
// Run profile_load() here to make sure the theme is set before
// we start loading content
-
+
profile_load($which,$profile);
-
+
}
-
+
function post() {
-
+
if($_POST['room_name'])
- $room = strip_tags(trim($_POST['room_name']));
-
+ $room = strip_tags(trim($_POST['room_name']));
+
if((! $room) || (! local_channel()))
return;
-
+
$channel = App::get_channel();
-
-
+
+
if($_POST['action'] === 'drop') {
logger('delete chatroom');
Chatroom::destroy($channel,array('cr_name' => $room));
goaway(z_root() . '/chat/' . $channel['channel_address']);
}
-
+
$acl = new AccessList($channel);
$acl->set_from_array($_REQUEST);
-
+
$arr = $acl->get();
$arr['name'] = $room;
$arr['expire'] = intval($_POST['chat_expire']);
if(intval($arr['expire']) < 0)
$arr['expire'] = 0;
-
+
Chatroom::create($channel,$arr);
-
+
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
dbesc($room),
intval(local_channel())
);
-
+
Libsync::build_sync_packet(0, array('chatroom' => $x));
-
+
if($x)
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']);
-
+
// that failed. Try again perhaps?
-
+
goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new');
-
-
+
+
}
-
-
+
+
function get() {
if(! Apps::system_app_installed(App::$profile_uid, 'Chatrooms')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Chatrooms App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Access Controlled Chatrooms');
- return $o;
+ $papp = Apps::get_papp('Chatrooms');
+ return Apps::app_render($papp, 'module');
}
-
+
if(local_channel()) {
$channel = App::get_channel();
nav_set_selected('Chatrooms');
@@ -113,24 +111,24 @@ class Chat extends Controller {
notice( t('Permission denied.') . EOL);
return;
}
-
+
if(! perm_is_allowed(App::$profile['profile_uid'],$observer,'chat')) {
notice( t('Permission denied.') . EOL);
return;
}
-
+
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
goaway(z_root() . '/channel/' . argv(1));
}
-
-
+
+
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'status')) {
$ret = array('success' => false);
$room_id = intval(argv(2));
if(! $room_id || ! $observer)
return;
-
+
$r = q("select * from chatroom where cr_id = %d limit 1",
intval($room_id)
);
@@ -139,7 +137,7 @@ class Chat extends Controller {
}
require_once('include/security.php');
$sql_extra = permissions_sql($r[0]['cr_uid']);
-
+
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
intval($room_id),
intval($r[0]['cr_uid'])
@@ -155,9 +153,9 @@ class Chat extends Controller {
$ret['chatroom'] = $r[0]['cr_name'];
$ret['inroom'] = $y[0]['total'];
}
-
+
// figure out how to present a timestamp of the last activity, since we don't know the observer's timezone.
-
+
$z = q("select created from chat where chat_room = %d order by created desc limit 1",
intval($room_id)
);
@@ -166,13 +164,13 @@ class Chat extends Controller {
}
json_return_and_die($ret);
}
-
-
+
+
if(argc() > 2 && intval(argv(2))) {
-
+
$room_id = intval(argv(2));
$bookmark_link = get_bookmark_link($ob);
-
+
$x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
@@ -180,26 +178,26 @@ class Chat extends Controller {
intval($room_id),
intval(App::$profile['profile_uid'])
);
-
+
if($x) {
$acl = new AccessList(false);
$acl->set($x[0]);
-
+
$private = $acl->is_private();
$room_name = $x[0]['cr_name'];
if($bookmark_link)
- $bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
+ $bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1';
}
else {
notice( t('Room not found') . EOL);
return;
}
-
+
$cipher = get_pconfig(local_channel(),'system','default_cipher');
if(! $cipher)
$cipher = 'AES-128-CCM';
-
-
+
+
$o = replace_macros(get_markup_template('chat.tpl'),array(
'$is_owner' => ((local_channel() && local_channel() == $x[0]['cr_uid']) ? true : false),
'$room_name' => $room_name,
@@ -223,7 +221,7 @@ class Chat extends Controller {
}
require_once('include/conversation.php');
-
+
$o = '';
$acl = new AccessList($channel);
@@ -246,12 +244,12 @@ class Chat extends Controller {
'$deny_gid' => acl2json($channel_acl['deny_gid']),
'$lockstate' => $lockstate,
'$submit' => t('Submit')
-
+
));
}
$rooms = Chatroom::roomlist(App::$profile['profile_uid']);
-
+
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
'$header' => sprintf( t('%1$s\'s Chatrooms'), App::$profile['fullname']),
'$name' => t('Name'),
@@ -259,15 +257,15 @@ class Chat extends Controller {
'$nickname' => App::$profile['channel_address'],
'$rooms' => $rooms,
'$norooms' => t('No chatrooms available'),
- '$newroom' => t('Create New'),
+ '$newroom' => t('Add Room'),
'$is_owner' => ((local_channel() && local_channel() == App::$profile['profile_uid']) ? 1 : 0),
'$chatroom_new' => $chatroom_new,
'$expire' => t('Expiration'),
'$expire_unit' => t('min') //minutes
));
-
+
return $o;
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php
index 5025f4e22..0f674965d 100644
--- a/Zotlabs/Module/Connections.php
+++ b/Zotlabs/Module/Connections.php
@@ -2,32 +2,32 @@
namespace Zotlabs\Module;
use App;
+use Zotlabs\Lib\Permcat;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
class Connections extends \Zotlabs\Web\Controller {
function init() {
-
+
if(! local_channel())
return;
App::$profile_uid = local_channel();
-
+
$channel = App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
-
+
}
-
+
function get() {
-
+
$sort_type = 0;
$o = '';
-
-
+
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
@@ -44,13 +44,13 @@ class Connections extends \Zotlabs\Web\Controller {
$pending = false;
$unconnected = false;
$all = false;
-
+
if(! $_REQUEST['aj'])
$_SESSION['return_url'] = App::$query_string;
-
+
$search_flags = "";
$head = '';
-
+
if(argc() == 2) {
switch(argv(1)) {
case 'active':
@@ -106,7 +106,7 @@ class Connections extends \Zotlabs\Web\Controller {
// $head = t('Unconnected');
// $unconnected = true;
// break;
-
+
case 'all':
$head = t('All');
break;
@@ -115,19 +115,19 @@ class Connections extends \Zotlabs\Web\Controller {
$active = true;
$head = t('Active');
break;
-
+
}
-
+
$sql_extra = $search_flags;
if(argv(1) === 'pending')
$sql_extra .= " and abook_ignored = 0 ";
-
+
}
else {
$sql_extra = " and abook_blocked = 0 ";
$unblocked = true;
}
-
+
switch($_REQUEST['order']) {
case 'name_desc':
$sql_order = 'xchan_name DESC';
@@ -143,32 +143,32 @@ class Connections extends \Zotlabs\Web\Controller {
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
-
+
$tabs = array(
/*
array(
'label' => t('Suggestions'),
- 'url' => z_root() . '/suggest',
+ 'url' => z_root() . '/suggest',
'sel' => '',
'title' => t('Suggest new connections'),
),
*/
-
+
'active' => array(
'label' => t('Active Connections'),
- 'url' => z_root() . '/connections/active',
+ 'url' => z_root() . '/connections/active',
'sel' => ($active) ? 'active' : '',
'title' => t('Show active connections'),
),
'pending' => array(
'label' => t('New Connections'),
- 'url' => z_root() . '/connections/pending',
+ 'url' => z_root() . '/connections/pending',
'sel' => ($pending) ? 'active' : '',
'title' => t('Show pending (new) connections'),
),
-
-
+
+
/*
array(
'label' => t('Unblocked'),
@@ -177,55 +177,55 @@ class Connections extends \Zotlabs\Web\Controller {
'title' => t('Only show unblocked connections'),
),
*/
-
+
'blocked' => array(
'label' => t('Blocked'),
'url' => z_root() . '/connections/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked connections'),
),
-
+
'ignored' => array(
'label' => t('Ignored'),
'url' => z_root() . '/connections/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored connections'),
),
-
+
'archived' => array(
'label' => t('Archived/Unreachable'),
'url' => z_root() . '/connections/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived/unreachable connections'),
),
-
+
'hidden' => array(
'label' => t('Hidden'),
'url' => z_root() . '/connections/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden connections'),
),
-
+
// array(
// 'label' => t('Unconnected'),
// 'url' => z_root() . '/connections/unconnected',
// 'sel' => ($unconnected) ? 'active' : '',
// 'title' => t('Only show one-way connections'),
// ),
-
+
'all' => array(
'label' => t('All Connections'),
- 'url' => z_root() . '/connections',
+ 'url' => z_root() . '/connections',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all connections'),
),
-
+
);
-
+
//$tab_tpl = get_markup_template('common_tabs.tpl');
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
-
+
$searching = false;
if($search) {
$search_hdr = $search;
@@ -233,12 +233,12 @@ class Connections extends \Zotlabs\Web\Controller {
$searching = true;
}
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
-
+
if($_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
}
-
- $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
+
+ $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ",
intval(local_channel())
);
@@ -246,19 +246,27 @@ class Connections extends \Zotlabs\Web\Controller {
App::set_pager_total($r[0]['total']);
$total = $r[0]['total'];
}
-
+
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ORDER BY $sql_order LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(App::$pager['itemspage']),
intval(App::$pager['start'])
);
-
+
+ $roles = new Permcat(local_channel());
+ $roles_list = $roles->listing();
+ $roles_dict = [];
+
+ foreach ($roles_list as $role) {
+ $roles_dict[$role['name']] = $role['localname'];
+ }
+
$contacts = array();
-
+
if($r) {
- vcard_query($r);
+ //vcard_query($r);
foreach($r as $rr) {
@@ -268,7 +276,7 @@ class Connections extends \Zotlabs\Web\Controller {
$phone = $rr['vcard']['tels'][0]['nr'];
else
$phone = '';
-
+
$status_str = '';
$status = array(
((intval($rr['abook_active'])) ? t('Active') : ''),
@@ -306,7 +314,7 @@ class Connections extends \Zotlabs\Web\Controller {
$perminfo['connperms'] .= t('Nothing');
}
-
+
foreach($status as $str) {
if(!$str)
continue;
@@ -314,19 +322,16 @@ class Connections extends \Zotlabs\Web\Controller {
$status_str .= ', ';
}
$status_str = rtrim($status_str, ', ');
-
+
$contacts[] = array(
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
'edit_hover' => t('Edit connection'),
'edit' => t('Edit'),
'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'],
- 'thumb' => $rr['xchan_photo_m'],
+ 'thumb' => $rr['xchan_photo_m'],
'name' => $rr['xchan_name'],
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
- 'link' => z_root() . '/connedit/' . $rr['abook_id'],
- 'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
- 'delete' => t('Delete'),
'url' => chanlink_hash($rr['xchan_hash']),
'webbie_label' => t('Channel address'),
'webbie' => $rr['xchan_addr'],
@@ -337,6 +342,7 @@ class Connections extends \Zotlabs\Web\Controller {
'phone' => $phone,
'status_label' => t('Status'),
'status' => $status_str,
+ 'states' => $status,
'connected_label' => t('Connected'),
'connected' => datetime_convert('UTC',date_default_timezone_get(),$rr['abook_created'], 'c'),
'approve_hover' => t('Approve connection'),
@@ -349,13 +355,22 @@ class Connections extends \Zotlabs\Web\Controller {
'perminfo' => $perminfo,
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
- 'connect_hover' => t('Connect at this location')
+ 'connect_hover' => t('Connect at this location'),
+ 'role' => $roles_dict[$rr['abook_role']],
+ 'pending' => intval($rr['abook_pending'])
);
}
}
}
-
-
+
+ $limit = service_class_fetch(local_channel(),'total_channels');
+ if($limit !== false) {
+ $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $$total, $limit);
+ }
+ else {
+ $abook_usage_message = '';
+ }
+
if($_REQUEST['aj']) {
if($contacts) {
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
@@ -371,27 +386,30 @@ class Connections extends \Zotlabs\Web\Controller {
}
else {
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
- $o .= replace_macros(get_markup_template('connections.tpl'),array(
+ $o .= replace_macros(get_markup_template('connections.tpl'), [
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
'$total' => $total,
'$search' => $search_hdr,
'$label' => t('Search'),
+ '$role_label' => t('Contact role'),
'$desc' => t('Search your connections'),
- '$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
+ '$finding' => (($searching) ? t('Contact search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
+ '$approve' => t('Approve'),
'$cmd' => App::$cmd,
'$contacts' => $contacts,
'$paginate' => paginate($a),
-
- ));
+ '$abook_usage_message' => $abook_usage_message,
+ '$group_label' => t('This is a group/forum channel')
+ ]);
}
-
+
if(! $contacts)
$o .= '<div id="content-complete"></div>';
-
+
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php
index 44211c8b9..6bebef026 100644
--- a/Zotlabs/Module/Connedit.php
+++ b/Zotlabs/Module/Connedit.php
@@ -1,4 +1,5 @@
<?php
+
namespace Zotlabs\Module;
/* @file connedit.php
@@ -8,8 +9,8 @@ namespace Zotlabs\Module;
*/
use App;
+use Sabre\VObject\Reader;
use Zotlabs\Lib\Apps;
-use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libsync;
use Zotlabs\Daemon\Master;
@@ -18,13 +19,12 @@ use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Web\HTTPHeaders;
use Zotlabs\Lib\Permcat;
+use Zotlabs\Lib\AccessList;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
require_once('include/photos.php');
-
class Connedit extends Controller {
/* @brief Initialize the connection-editor
@@ -34,26 +34,25 @@ class Connedit extends Controller {
function init() {
- if(! local_channel())
+ if (!local_channel())
return;
- if((argc() >= 2) && intval(argv(1))) {
+ if ((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
- WHERE abook_channel = %d and abook_id = %d LIMIT 1",
+ WHERE abook_channel = %d and abook_id = %d and abook_self = 0 and xchan_deleted = 0 LIMIT 1",
intval(local_channel()),
intval(argv(1))
);
- if($r) {
- App::$poi = array_shift($r);
+ if ($r) {
+ App::$poi = $r[0];
}
}
-
$channel = App::get_channel();
- if($channel)
+ if ($channel) {
head_set_icon($channel['xchan_photo_s']);
-
+ }
}
@@ -63,191 +62,98 @@ class Connedit extends Controller {
function post() {
- if(! local_channel())
+ if (!local_channel())
return;
$contact_id = intval(argv(1));
- if(! $contact_id)
+ if (!$contact_id)
return;
$channel = App::get_channel();
- // TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
- // connection enable is toggled to a special autopost url and set permissions immediately, leaving
- // the other form elements alone pending a manual submit of the form. The downside is that there
- // will be a window of opportunity when the permissions have been set but before you've had a chance
- // to review and possibly restrict them. The upside is we won't have to warn you that your connection
- // can't do anything until you save the bloody form.
-
- $autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
-
- $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
+ $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
- if(! $orig_record) {
- notice( t('Could not access contact record.') . EOL);
+ if (!$orig_record) {
+ notice(t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
call_hooks('contact_edit_post', $_POST);
- $vc = get_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard');
- $vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
- $serialised_vcard = update_vcard($_REQUEST,$vcard);
- if($serialised_vcard)
- set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$serialised_vcard);
-
- if(intval($orig_record[0]['abook_self'])) {
- $autoperms = intval($_POST['autoperms']);
- $is_self = true;
- }
- else {
- $autoperms = null;
- $is_self = false;
- }
+ $vc = get_abconfig(local_channel(), $orig_record['abook_xchan'], 'system', 'vcard');
+ $vcard = (($vc) ? Reader::read($vc) : null);
+ $serialised_vcard = update_vcard($_REQUEST, $vcard);
+ if ($serialised_vcard)
+ set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $serialised_vcard);
+ $profile_id = ((array_key_exists('profile_assign', $_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
- $profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
-
- if($profile_id) {
+ if ($profile_id) {
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
dbesc($profile_id),
intval(local_channel())
);
- if(! count($r)) {
- notice( t('Could not locate selected profile.') . EOL);
+ if (!count($r)) {
+ notice(t('Could not locate selected profile.') . EOL);
return;
}
}
- $abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
- $abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
-
-
- $hidden = intval($_POST['hidden']);
+ $abook_incl = ((array_key_exists('abook_incl', $_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
+ $abook_excl = ((array_key_exists('abook_excl', $_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
+ $abook_role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : $orig_record[0]['abook_role']);
- $priority = intval($_POST['poll']);
- if($priority > 5 || $priority < 0)
- $priority = 0;
-
- if(! array_key_exists('closeness',$_POST)) {
+ if (!array_key_exists('closeness', $_POST)) {
$_POST['closeness'] = 80;
}
$closeness = intval($_POST['closeness']);
- if($closeness < 0 || $closeness > 99) {
+ if ($closeness < 0 || $closeness > 99) {
$closeness = 80;
}
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
+ $new_friend = ((intval($orig_record[0]['abook_pending'])) ? true : false);
- $all_perms = Permissions::Perms();
+/*
+ $perms = [];
+ $permcats = new Permcat(local_channel());
+ $role_perms = $permcats->fetch($abook_role);
+ $all_perms = Permissions::Perms();
- if($all_perms) {
- foreach($all_perms as $perm => $desc) {
- if(array_key_exists('perms_' . $perm, $_POST)) {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,
- intval($_POST['perms_' . $perm]));
- if($autoperms) {
- set_pconfig($channel['channel_id'],'autoperms',$perm,intval($_POST['perms_' . $perm]));
- }
- }
- else {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,0);
- if($autoperms) {
- set_pconfig($channel['channel_id'],'autoperms',$perm,0);
- }
- }
- }
+ // if we got a valid role use the role (default behaviour because a role is mandatory since version 7.0)
+ if (!isset($role_perms['error'])) {
+ $perms = $role_perms['raw_perms'];
+ if (intval($orig_record[0]['abook_pending']))
+ $new_friend = true;
}
- if(! is_null($autoperms))
- set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
-
- $new_friend = false;
-
- // only store a record and notify the directory if the rating changed
-
- if(! $is_self) {
-
- $signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
- $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey']));
-
- $rated = ((intval($rating) || strlen($rating_text)) ? true : false);
-
- $record = 0;
-
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan'])
- );
-
- if($z) {
- if(($z[0]['xlink_rating'] != $rating) || ($z[0]['xlink_rating_text'] != $rating_text)) {
- $record = $z[0]['xlink_id'];
- $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
- where xlink_id = %d",
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert()),
- intval($record)
- );
- }
- }
- elseif($rated) {
- // only create a record if there's something to save
- $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan']),
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert())
- );
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan'])
- );
- if($z)
- $record = $z[0]['xlink_id'];
- }
- if($record) {
- Master::Summon(array('Ratenotif','rating',$record));
- }
- }
-
- if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
-
+ // approve shortcut (no role provided)
+ if (!$perms && intval($orig_record[0]['abook_pending'])) {
+ $connect_perms = Permissions::connect_perms(local_channel());
+ $perms = $connect_perms['perms'];
+ // set the role from $connect_perms
+ $abook_role = $connect_perms['role'];
$new_friend = true;
+ }
- // @fixme it won't be common, but when you accept a new connection request
- // the permissions will now be that of your permissions role and ignore
- // any you may have set manually on the form. We'll probably see a bug if somebody
- // tries to set the permissions *and* approve the connection in the same
- // request. The workaround is to approve the connection, then go back and
- // adjust permissions as desired.
-
- $p = Permissions::connect_perms(local_channel());
- $my_perms = $p['perms'];
- if($my_perms) {
- foreach($my_perms as $k => $v) {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$k,$v);
+ if ($all_perms && $perms) {
+ foreach ($all_perms as $perm => $desc) {
+ if (array_key_exists($perm, $perms)) {
+ set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, intval($perms[$perm]));
+ }
+ else {
+ set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, 0);
}
}
}
+*/
- $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
-
+ \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$orig_record[0]['abook_xchan']]);
+ $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
@@ -261,30 +167,29 @@ class Connedit extends Controller {
intval(local_channel())
);
- if($r)
- info( t('Connection updated.') . EOL);
+ if ($r)
+ info(t('Connection updated.') . EOL);
else
- notice( t('Failed to update connection record.') . EOL);
+ notice(t('Failed to update connection record.') . EOL);
- if(! intval(App::$poi['abook_self'])) {
- if($new_friend) {
- Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
+ if (!intval(App::$poi['abook_self'])) {
+ if ($new_friend) {
+ Master::Summon(['Notifier', 'permission_accept', $contact_id]);
}
- Master::Summon( [
+ Master::Summon([
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
$contact_id
]);
}
- if($new_friend) {
+ if ($new_friend) {
$default_group = $channel['channel_default_group'];
- if($default_group) {
- require_once('include/group.php');
- $g = group_rec_byhash(local_channel(),$default_group);
- if($g)
- group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']);
+ if ($default_group) {
+ $g = AccessList::by_hash(local_channel(), $default_group);
+ if ($g)
+ AccessList::member_add(local_channel(), '', App::$poi['abook_xchan'], $g['id']);
}
// Check if settings permit ("post new friend activity" is allowed, and
@@ -294,18 +199,18 @@ class Connedit extends Controller {
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
intval($channel['channel_id'])
);
- if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
+ if (($pr) && (!intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
$xarr = [];
- $xarr['item_wall'] = 1;
- $xarr['item_origin'] = 1;
+ $xarr['item_wall'] = 1;
+ $xarr['item_origin'] = 1;
$xarr['item_thread_top'] = 1;
- $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
- $xarr['allow_cid'] = $channel['channel_allow_cid'];
- $xarr['allow_gid'] = $channel['channel_allow_gid'];
- $xarr['deny_cid'] = $channel['channel_deny_cid'];
- $xarr['deny_gid'] = $channel['channel_deny_gid'];
- $xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
+ $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
+ $xarr['allow_cid'] = $channel['channel_allow_cid'];
+ $xarr['allow_gid'] = $channel['channel_allow_gid'];
+ $xarr['deny_cid'] = $channel['channel_deny_cid'];
+ $xarr['deny_gid'] = $channel['channel_deny_gid'];
+ $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]';
@@ -315,9 +220,8 @@ class Connedit extends Controller {
}
-
// pull in a bit of content if there is any to pull in
- Master::Summon(array('Onepoll',$contact_id));
+ Master::Summon(['Onepoll', $contact_id]);
}
@@ -329,18 +233,18 @@ class Connedit extends Controller {
intval(local_channel()),
intval($contact_id)
);
- if($r) {
+ if ($r) {
App::$poi = $r[0];
}
- if($new_friend) {
- $arr = array('channel_id' => local_channel(), 'abook' => App::$poi);
+ if ($new_friend) {
+ $arr = ['channel_id' => local_channel(), 'abook' => App::$poi];
call_hooks('accept_follow', $arr);
}
- $this->connedit_clone($a);
+ $this->connedit_clone();
- if(($_REQUEST['pending']) && (!$_REQUEST['done']))
+ if (($_REQUEST['pending']) && (!$_REQUEST['done']))
goaway(z_root() . '/connections/ifpending');
return;
@@ -352,35 +256,34 @@ class Connedit extends Controller {
*
*/
- function connedit_clone(&$a) {
-
- if(! App::$poi)
- return;
+ function connedit_clone() {
+ if (!App::$poi)
+ return;
- $channel = App::get_channel();
+ $channel = App::get_channel();
- $r = q("SELECT abook.*, xchan.*
+ $r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
- intval(local_channel()),
- intval(App::$poi['abook_id'])
- );
- if($r) {
- App::$poi = array_shift($r);
- }
+ intval(local_channel()),
+ intval(App::$poi['abook_id'])
+ );
+ if ($r) {
+ App::$poi = $r[0];
+ }
- $clone = App::$poi;
+ $clone = App::$poi;
- unset($clone['abook_id']);
- unset($clone['abook_account']);
- unset($clone['abook_channel']);
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
- $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
- if($abconfig)
- $clone['abconfig'] = $abconfig;
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
- Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
}
/* @brief Generate content of connection edit page
@@ -390,76 +293,58 @@ class Connedit extends Controller {
function get() {
- $sort_type = 0;
$o = '';
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
+ if (!local_channel()) {
+ notice(t('Permission denied.') . EOL);
return login();
}
- $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
- $channel = App::get_channel();
-
- $yes_no = array(t('No'),t('Yes'));
-
- $connect_perms = Permissions::connect_perms(local_channel());
-
- $o .= "<script>function connectDefaultShare() {
- \$('.abook-edit-me').each(function() {
- if(! $(this).is(':disabled'))
- $(this).prop('checked', false);
- });\n\n";
- foreach($connect_perms['perms'] as $p => $v) {
- if($v) {
- $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
- }
- }
- $o .= " }\n</script>\n";
+ $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : '');
- if(argc() == 3) {
+ if (argc() == 3) {
$contact_id = intval(argv(1));
- if(! $contact_id)
+ if (!$contact_id)
return;
$cmd = argv(2);
$orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
- WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
+ WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 and xchan_deleted = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
- if(! count($orig_record)) {
- notice( t('Could not access address book record.') . EOL);
+ if (!count($orig_record)) {
+ notice(t('Could not access address book record.') . EOL);
goaway(z_root() . '/connections');
}
- if($cmd === 'update') {
+ if ($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
- Master::Summon(array('Poller',$contact_id));
+ Master::Summon(['Poller', $contact_id]);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'fetchvc') {
- $url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard';
+ if ($cmd === 'fetchvc') {
+ $url = str_replace('/channel/', '/profile/', $orig_record[0]['xchan_url']) . '/vcard';
$recurse = 0;
- $x = z_fetch_url(zid($url),false,$recurse,['session' => true]);
- if($x['success']) {
- $h = new HTTPHeaders($x['header']);
+ $x = z_fetch_url(zid($url), false, $recurse, ['session' => true]);
+ if ($x['success']) {
+ $h = new HTTPHeaders($x['header']);
$fields = $h->fetch();
- if($fields) {
- foreach($fields as $y) {
- if(array_key_exists('content-type',$y)) {
- $type = explode(';',trim($y['content-type']));
- if($type && $type[0] === 'text/vcard' && $x['body']) {
- $vc = \Sabre\VObject\Reader::read($x['body']);
+ if ($fields) {
+ foreach ($fields as $y) {
+ if (array_key_exists('content-type', $y)) {
+ $type = explode(';', trim($y['content-type']));
+ if ($type && $type[0] === 'text/vcard' && $x['body']) {
+ $vc = Reader::read($x['body']);
$vcard = $vc->serialize();
- if($vcard) {
- set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard);
- $this->connedit_clone($a);
+ if ($vcard) {
+ set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $vcard);
+ $this->connedit_clone();
}
}
}
@@ -470,60 +355,55 @@ class Connedit extends Controller {
}
- if($cmd === 'resetphoto') {
+ if ($cmd === 'resetphoto') {
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
dbesc($orig_record[0]['xchan_hash'])
);
$cmd = 'refresh';
}
- if($cmd === 'refresh') {
- if($orig_record[0]['xchan_network'] === 'zot') {
- if(! zot_refresh($orig_record[0],App::get_channel()))
- notice( t('Refresh failed - channel is currently unavailable.') );
- }
- elseif($orig_record[0]['xchan_network'] === 'zot6') {
- if(! Libzot::refresh($orig_record[0],App::get_channel()))
- notice( t('Refresh failed - channel is currently unavailable.') );
+ if ($cmd === 'refresh') {
+ if ($orig_record[0]['xchan_network'] === 'zot6') {
+ if (!Libzot::refresh($orig_record[0], App::get_channel()))
+ notice(t('Refresh failed - channel is currently unavailable.'));
}
else {
-
// if you are on a different network we'll force a refresh of the connection basic info
- Master::Summon(array('Notifier','permission_update',$contact_id));
+ Master::Summon(['Notifier', 'permission_update', $contact_id]);
}
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'block') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'block') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_BLOCKED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'ignore') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'ignore') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_IGNORED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'archive') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'archive') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_ARCHIVED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'hide') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) {
- $this->connedit_clone($a);
+ if ($cmd === 'hide') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_HIDDEN)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
@@ -533,10 +413,10 @@ class Connedit extends Controller {
// We'll prevent somebody from unapproving an already approved contact.
// Though maybe somebody will want this eventually (??)
- if($cmd === 'approve') {
- if(intval($orig_record[0]['abook_pending'])) {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) {
- $this->connedit_clone($a);
+ if ($cmd === 'approve') {
+ if (intval($orig_record[0]['abook_pending'])) {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_PENDING)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
@@ -545,132 +425,130 @@ class Connedit extends Controller {
}
- if($cmd === 'drop') {
+ if ($cmd === 'drop') {
contact_remove(local_channel(), $orig_record[0]['abook_id']);
- Master::Summon( [ 'Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash'] ] );
+ Master::Summon(['Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash']]);
Libsync::build_sync_packet(0 /* use the current local_channel */,
- array('abook' => array(array(
- 'abook_xchan' => $orig_record[0]['abook_xchan'],
- 'entry_deleted' => true))
- )
+ ['abook' => [[
+ 'abook_xchan' => $orig_record[0]['abook_xchan'],
+ 'entry_deleted' => true]]
+ ]
);
- info( t('Connection has been removed.') . EOL );
- if(x($_SESSION,'return_url'))
+ info(t('Connection has been removed.') . EOL);
+ if (x($_SESSION, 'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/contacts');
}
}
- if(App::$poi) {
+ if (App::$poi) {
$abook_prev = 0;
$abook_next = 0;
-
$contact_id = App::$poi['abook_id'];
- $contact = App::$poi;
+ $contact = App::$poi;
$cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name",
intval(local_channel())
);
- if($cn) {
+ if ($cn) {
$pntotal = count($cn);
- for($x = 0; $x < $pntotal; $x ++) {
- if($cn[$x]['abook_id'] == $contact_id) {
- if($x === 0)
+ for ($x = 0; $x < $pntotal; $x++) {
+ if ($cn[$x]['abook_id'] == $contact_id) {
+ if ($x === 0)
$abook_prev = 0;
else
$abook_prev = $cn[$x - 1]['abook_id'];
- if($x === $pntotal)
+ if ($x === $pntotal)
$abook_next = 0;
else
- $abook_next = $cn[$x +1]['abook_id'];
+ $abook_next = $cn[$x + 1]['abook_id'];
}
}
- }
+ }
- $tools = array(
+ $tools = [
- 'view' => array(
+ 'view' => [
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
- 'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']),
- ),
+ 'title' => sprintf(t('View %s\'s profile'), $contact['xchan_name']),
+ ],
- 'refresh' => array(
+ 'refresh' => [
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
'sel' => '',
'title' => t('Fetch updated permissions'),
- ),
+ ],
- 'rephoto' => array(
+ 'rephoto' => [
'label' => t('Refresh Photo'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto',
'sel' => '',
'title' => t('Fetch updated photo'),
- ),
+ ],
- 'recent' => array(
+ 'recent' => [
'label' => t('Recent Activity'),
'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
- ),
+ ],
- 'block' => array(
+ 'block' => [
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
- 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
- ),
+ 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
+ ],
- 'ignore' => array(
+ 'ignore' => [
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
- 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
- ),
+ 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
+ ],
- 'archive' => array(
+ 'archive' => [
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
- 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
- ),
+ 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
+ ],
- 'hide' => array(
+ 'hide' => [
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
- 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
- ),
+ 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
+ ],
- 'delete' => array(
+ 'delete' => [
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
- ),
-
- );
+ ],
+ ];
- if(in_array($contact['xchan_network'], ['zot6', 'zot'])) {
+ if ($contact['xchan_network'] === 'zot6') {
$tools['fetchvc'] = [
'label' => t('Fetch Vcard'),
- 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
+ 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
'sel' => '',
'title' => t('Fetch electronic calling card for this connection')
];
@@ -679,31 +557,16 @@ class Connedit extends Controller {
$sections = [];
- $sections['perms'] = [
- 'label' => t('Permissions'),
- 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=perms',
- 'sel' => '',
- 'title' => t('Open Individual Permissions section by default'),
- ];
-
- $self = false;
-
- if(intval($contact['abook_self'])) {
- $self = true;
- $abook_prev = $abook_next = 0;
- }
-
- $vc = get_abconfig(local_channel(),$contact['abook_xchan'],'system','vcard');
+ $vc = get_abconfig(local_channel(), $contact['abook_xchan'], 'system', 'vcard');
- $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
- $vcard = (($vctmp) ? get_vcard_array($vctmp,$contact['abook_id']) : [] );
- if(! $vcard)
+ $vctmp = (($vc) ? Reader::read($vc) : null);
+ $vcard = (($vctmp) ? get_vcard_array($vctmp, $contact['abook_id']) : []);
+ if (!$vcard['fn'])
$vcard['fn'] = $contact['xchan_name'];
-
$tpl = get_markup_template("abook_edit.tpl");
- if(Apps::system_app_installed(local_channel(),'Affinity Tool')) {
+ if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
$sections['affinity'] = [
'label' => t('Affinity'),
@@ -719,12 +582,12 @@ class Connedit extends Controller {
t('Acquaintances'),
t('All')
];
- call_hooks('affinity_labels',$labels);
+ call_hooks('affinity_labels', $labels);
$label_str = '';
- if($labels) {
- foreach($labels as $l) {
- if($label_str) {
+ if ($labels) {
+ foreach ($labels as $l) {
+ if ($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
@@ -737,14 +600,14 @@ class Connedit extends Controller {
$slideval = intval($contact['abook_closeness']);
- $slide = replace_macros($slider_tpl,array(
- '$min' => 1,
- '$val' => $slideval,
+ $slide = replace_macros($slider_tpl, [
+ '$min' => 1,
+ '$val' => $slideval,
'$labels' => $label_str,
- ));
+ ]);
}
- if(feature_enabled(local_channel(),'connfilter')) {
+ if (feature_enabled(local_channel(), 'connfilter')) {
$sections['filter'] = [
'label' => t('Filter'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=filter',
@@ -753,195 +616,148 @@ class Connedit extends Controller {
];
}
- $rating_val = 0;
- $rating_text = '';
-
- $xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc($contact['xchan_hash'])
- );
-
- if($xl) {
- $rating_val = intval($xl[0]['xlink_rating']);
- $rating_text = $xl[0]['xlink_rating_text'];
- }
-
- $rating_enabled = get_config('system','rating_enabled');
-
- if($rating_enabled) {
- $rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
- '$min' => -10,
- '$val' => $rating_val
- ));
- }
- else {
- $rating = false;
- }
-
-
- $perms = array();
- $channel = App::get_channel();
-
+ $perms = [];
$global_perms = Permissions::Perms();
+ $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
+ $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]];
+ $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false);
- $existing = get_all_perms(local_channel(),$contact['abook_xchan'],false);
-
- $unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
-
- $multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
-
- if($slide && !$multiprofs)
+ if ($slide && !$multiprofs)
$affinity = t('Set Affinity');
- if(!$slide && $multiprofs)
+ if (!$slide && $multiprofs)
$affinity = t('Set Profile');
- if($slide && $multiprofs)
+ if ($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
- intval(local_channel()),
- dbesc($contact['abook_xchan'])
+ intval(local_channel()),
+ dbesc($contact['abook_xchan'])
);
- $their_perms = array();
- if($theirs) {
- foreach($theirs as $t) {
+
+ $their_perms = [];
+ if ($theirs) {
+ foreach ($theirs as $t) {
$their_perms[$t['k']] = $t['v'];
}
}
- foreach($global_perms as $k => $v) {
- $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
-//fixme
-
- $checkinherited = PermissionLimits::Get(local_channel(),$k);
-
- // For auto permissions (when $self is true) we don't want to look at existing
- // permissions because they are enabled for the channel owner
- if((! $self) && ($existing[$k]))
- $thisperm = "1";
-
-
+ foreach ($global_perms as $k => $v) {
+ $thisperm = $existing[$k];
+ $checkinherited = PermissionLimits::Get(local_channel(), $k);
+ $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited];
+ }
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
+ $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']);
- $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
+ if (!$current_permcat) {
+ notice(t('Please select a role for this contact!') . EOL);
+ $permcats[] = '';
}
- $pcat = new Permcat(local_channel());
- $pcatlist = $pcat->listing();
- $permcats = [];
- if($pcatlist) {
- foreach($pcatlist as $pc) {
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
$permcats[$pc['name']] = $pc['localname'];
}
}
$locstr = locations_by_netid($contact['xchan_hash']);
- if(! $locstr)
+ if (!$locstr) {
$locstr = unpunify($contact['xchan_url']);
+ }
$clone_warn = '';
- $clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
- if(! $clonable) {
+ $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
+ if (!$clonable) {
$clone_warn = '<strong>';
$clone_warn .= ((intval($contact['abook_not_here']))
- ? t('This connection is unreachable from this location.')
- : t('This connection may be unreachable from other channel locations.')
+ ? t('This contact is unreachable from this location.')
+ : t('This contact may be unreachable from other channel locations.')
);
$clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
}
-
-
- if(intval($contact['abook_not_here']) && $unclonable)
- $not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.');
-
$o .= replace_macros($tpl, [
- '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
- '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
- '$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
- '$permcat_new' => t('Add permission role'),
- '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
- '$addr' => unpunify($contact['xchan_addr']),
- '$primeurl' => unpunify($contact['xchan_url']),
- '$section' => $section,
- '$sections' => $sections,
- '$vcard' => $vcard,
- '$addr_text' => t('This connection\'s primary address is'),
- '$loc_text' => t('Available locations:'),
- '$locstr' => $locstr,
- '$unclonable' => $clone_warn,
- '$notself' => (($self) ? '' : '1'),
- '$self' => (($self) ? '1' : ''),
- '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
- '$tools_label' => t('Connection Tools'),
- '$tools' => (($self) ? '' : $tools),
- '$lbl_slider' => t('Slide to adjust your degree of friendship'),
- '$lbl_rating' => t('Rating'),
- '$lbl_rating_label' => t('Slide to adjust your rating'),
- '$lbl_rating_txt' => t('Optionally explain your rating'),
- '$connfilter' => feature_enabled(local_channel(),'connfilter'),
+ '$header' => sprintf(t('Contact: %s'), $contact['xchan_name']),
+ '$permcat' => ['permcat', t('Contact role'), $current_permcat, '', $permcats],
+ '$permcat_new' => t('Manage contact roles'),
+ '$permcat_value' => bin2hex($current_permcat),
+ '$addr' => unpunify($contact['xchan_addr']),
+ '$primeurl' => unpunify($contact['xchan_url']),
+ '$section' => $section,
+ '$sections' => $sections,
+ '$vcard' => $vcard,
+ '$addr_text' => t('This contacts\'s primary address is'),
+ '$loc_text' => t('Available locations:'),
+ '$locstr' => $locstr,
+ '$unclonable' => $clone_warn,
+ '$notself' => '1',
+ '$self' => '',
+ '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $tools,
+ '$lbl_slider' => t('Slide to adjust your degree of friendship'),
+ '$connfilter' => feature_enabled(local_channel(), 'connfilter'),
'$connfilter_label' => t('Custom Filter'),
- '$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
- '$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
- '$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''),
- '$rating_info' => t('This information is public!'),
- '$rating' => $rating,
- '$rating_val' => $rating_val,
- '$slide' => $slide,
- '$affinity' => $affinity,
- '$pending_label' => t('Connection Pending Approval'),
- '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
- '$unapproved' => $unapproved,
- '$inherited' => t('inherited'),
- '$submit' => t('Submit'),
- '$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
- '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
- '$them' => t('Their Settings'),
- '$me' => t('My Settings'),
- '$perms' => $perms,
- '$permlbl' => t('Individual Permissions'),
- '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
- '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
- '$lastupdtext' => t('Last update:'),
- '$last_update' => relative_date($contact['abook_connected']),
- '$profile_select' => contact_profile_assign($contact['abook_profile']),
- '$multiprofs' => $multiprofs,
- '$contact_id' => $contact['abook_id'],
- '$name' => $contact['xchan_name'],
- '$abook_prev' => $abook_prev,
- '$abook_next' => $abook_next,
- '$vcard_label' => t('Details'),
- '$displayname' => $displayname,
- '$name_label' => t('Name'),
- '$org_label' => t('Organisation'),
- '$title_label' => t('Title'),
- '$tel_label' => t('Phone'),
- '$email_label' => t('Email'),
- '$impp_label' => t('Instant messenger'),
- '$url_label' => t('Website'),
- '$adr_label' => t('Address'),
- '$note_label' => t('Note'),
- '$mobile' => t('Mobile'),
- '$home' => t('Home'),
- '$work' => t('Work'),
- '$other' => t('Other'),
- '$add_card' => t('Add Contact'),
- '$add_field' => t('Add Field'),
- '$create' => t('Create'),
- '$update' => t('Update'),
- '$delete' => t('Delete'),
- '$cancel' => t('Cancel'),
- '$po_box' => t('P.O. Box'),
- '$extra' => t('Additional'),
- '$street' => t('Street'),
- '$locality' => t('Locality'),
- '$region' => t('Region'),
- '$zip_code' => t('ZIP Code'),
- '$country' => t('Country')
+ '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$slide' => $slide,
+ '$affinity' => $affinity,
+ '$pending_label' => t('Contact Pending Approval'),
+ '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
+ '$unapproved' => $unapproved,
+ '$inherited' => t('inherited'),
+ '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')),
+ '$lbl_vis2' => sprintf(t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
+ '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
+ '$them' => t('Their'),
+ '$me' => t('My'),
+ '$perms' => $perms,
+ '$permlbl' => t('Individual Permissions'),
+ '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
+ '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
+ '$lastupdtext' => t('Last update:'),
+ '$last_update' => relative_date($contact['abook_connected']),
+ '$profile_select' => contact_profile_assign($contact['abook_profile']),
+ '$multiprofs' => $multiprofs,
+ '$contact_id' => $contact['abook_id'],
+ '$name' => $contact['xchan_name'],
+ '$abook_prev' => $abook_prev,
+ '$abook_next' => $abook_next,
+ '$vcard_label' => t('Details'),
+ '$name_label' => t('Name'),
+ '$org_label' => t('Organisation'),
+ '$title_label' => t('Title'),
+ '$tel_label' => t('Phone'),
+ '$email_label' => t('Email'),
+ '$impp_label' => t('Instant messenger'),
+ '$url_label' => t('Website'),
+ '$adr_label' => t('Address'),
+ '$note_label' => t('Note'),
+ '$mobile' => t('Mobile'),
+ '$home' => t('Home'),
+ '$work' => t('Work'),
+ '$other' => t('Other'),
+ '$add_card' => t('Add Contact'),
+ '$add_field' => t('Add Field'),
+ '$create' => t('Create'),
+ '$update' => t('Update'),
+ '$delete' => t('Delete'),
+ '$cancel' => t('Cancel'),
+ '$po_box' => t('P.O. Box'),
+ '$extra' => t('Additional'),
+ '$street' => t('Street'),
+ '$locality' => t('Locality'),
+ '$region' => t('Region'),
+ '$zip_code' => t('ZIP Code'),
+ '$country' => t('Country')
]);
- $arr = array('contact' => $contact,'output' => $o);
+ $arr = ['contact' => $contact, 'output' => $o];
call_hooks('contact_edit', $arr);
diff --git a/Zotlabs/Module/Contactedit.php b/Zotlabs/Module/Contactedit.php
new file mode 100644
index 000000000..d306039d2
--- /dev/null
+++ b/Zotlabs/Module/Contactedit.php
@@ -0,0 +1,675 @@
+<?php
+
+namespace Zotlabs\Module;
+
+/* @file Cobtactedit.php
+ * @brief In this file the connection-editor form is generated and evaluated.
+ *
+ *
+ */
+
+use App;
+use Sabre\VObject\Reader;
+use Zotlabs\Lib\Apps;
+use Zotlabs\Lib\Libzot;
+use Zotlabs\Lib\Libsync;
+use Zotlabs\Daemon\Master;
+use Zotlabs\Web\Controller;
+use Zotlabs\Access\Permissions;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Web\HTTPHeaders;
+use Zotlabs\Lib\Permcat;
+use Zotlabs\Lib\AccessList;
+
+require_once('include/socgraph.php');
+require_once('include/selectors.php');
+require_once('include/group.php');
+require_once('include/photos.php');
+
+class Contactedit extends Controller {
+
+ /* @brief Initialize the connection-editor
+ *
+ *
+ */
+
+ function init() {
+
+ if (!local_channel())
+ return;
+
+ if ((argc() >= 2) && intval(argv(1))) {
+ $r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash
+ WHERE abook_channel = %d AND abook_id = %d AND abook_self = 0 AND xchan_deleted = 0",
+ intval(local_channel()),
+ intval(argv(1))
+ );
+ if (!$r) {
+ json_return_and_die([
+ 'success' => false,
+ 'message' => t('Invalid abook_id')
+ ]);
+ }
+
+ App::$poi = $r[0];
+
+ }
+ }
+
+
+ /* @brief Evaluate posted values and set changes
+ *
+ */
+
+ function post() {
+
+ if (!local_channel())
+ return;
+
+ $contact_id = intval(argv(1));
+ if (!$contact_id)
+ return;
+
+ $channel = App::get_channel();
+
+ $contact = App::$poi;
+
+ if (!$contact) {
+ notice(t('Could not access contact record.') . EOL);
+ killme();
+ }
+
+ call_hooks('contact_edit_post', $_REQUEST);
+
+ if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
+ $pgrp_ids = q("SELECT id FROM pgrp WHERE deleted = 0 AND uid = %d",
+ intval(local_channel())
+ );
+
+ foreach($pgrp_ids as $pgrp) {
+ if (array_key_exists('pgrp_id_' . $pgrp['id'], $_REQUEST)) {
+ AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
+ }
+ else {
+ AccessList::member_remove(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
+ }
+ }
+ }
+
+ $profile_id = ((array_key_exists('profile_assign', $_REQUEST)) ? $_REQUEST['profile_assign'] : $contact['abook_profile']);
+
+ if ($profile_id) {
+ $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
+ dbesc($profile_id),
+ intval(local_channel())
+ );
+ if (!count($r)) {
+ notice(t('Could not locate selected profile.') . EOL);
+ return;
+ }
+ }
+
+ $abook_incl = ((array_key_exists('abook_incl', $_REQUEST)) ? escape_tags($_REQUEST['abook_incl']) : $contact['abook_incl']);
+ $abook_excl = ((array_key_exists('abook_excl', $_REQUEST)) ? escape_tags($_REQUEST['abook_excl']) : $contact['abook_excl']);
+ $abook_role = ((array_key_exists('permcat', $_REQUEST)) ? escape_tags($_REQUEST['permcat']) : $contact['abook_role']);
+
+ if (!array_key_exists('closeness', $_REQUEST)) {
+ $_REQUEST['closeness'] = 80;
+ }
+
+ $closeness = intval($_REQUEST['closeness']);
+
+ if ($closeness < 0 || $closeness > 99) {
+ $closeness = 80;
+ }
+
+ $new_friend = ((intval($contact['abook_pending'])) ? true : false);
+
+ \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$contact['abook_xchan']]);
+
+ $abook_pending = (($new_friend) ? 0 : $contact['abook_pending']);
+
+ $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
+ abook_incl = '%s', abook_excl = '%s'
+ where abook_id = %d AND abook_channel = %d",
+ dbesc($profile_id),
+ intval($closeness),
+ intval($abook_pending),
+ dbesc($abook_incl),
+ dbesc($abook_excl),
+ intval($contact_id),
+ intval(local_channel())
+ );
+
+ $_REQUEST['success'] = false;
+
+ if ($r) {
+ $_REQUEST['success'] = true;
+ }
+
+
+ if (!intval($contact['abook_self'])) {
+ if ($new_friend) {
+ Master::Summon(['Notifier', 'permission_accept', $contact_id]);
+ }
+
+ Master::Summon([
+ 'Notifier',
+ (($new_friend) ? 'permission_create' : 'permission_update'),
+ $contact_id
+ ]);
+ }
+
+ if ($new_friend) {
+ $default_group = $channel['channel_default_group'];
+ if ($default_group) {
+ $g = AccessList::by_hash(local_channel(), $default_group);
+ if ($g) {
+ AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $g['id']);
+ }
+ }
+
+ // Check if settings permit ("post new friend activity" is allowed, and
+ // friends in general or this friend in particular aren't hidden)
+ // and send out a new friend activity
+
+ $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
+ intval($channel['channel_id'])
+ );
+ if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
+ $xarr = [];
+
+ $xarr['item_wall'] = 1;
+ $xarr['item_origin'] = 1;
+ $xarr['item_thread_top'] = 1;
+ $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
+ $xarr['allow_cid'] = $channel['channel_allow_cid'];
+ $xarr['allow_gid'] = $channel['channel_allow_gid'];
+ $xarr['deny_cid'] = $channel['channel_deny_cid'];
+ $xarr['deny_gid'] = $channel['channel_deny_gid'];
+ $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
+
+ $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]';
+
+ $xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]';
+
+ post_activity_item($xarr);
+
+ }
+
+ // pull in a bit of content if there is any to pull in
+ Master::Summon(['Onepoll', $contact_id]);
+
+ }
+
+ // Refresh the structure in memory with the new data
+ $this->init();
+
+ if ($new_friend) {
+ $arr = ['channel_id' => local_channel(), 'abook' => App::$poi];
+ call_hooks('accept_follow', $arr);
+ }
+
+ $this->contactedit_clone();
+ $this->get();
+
+ killme();
+
+ return;
+
+ }
+
+
+ /* @brief Generate content of contact edit page
+ *
+ *
+ */
+
+ function get() {
+
+ if (!local_channel()) {
+ killme();
+ }
+
+ if (!App::$poi) {
+ killme();
+ }
+
+
+ $channel = App::get_channel();
+ $contact_id = App::$poi['abook_id'];
+ $contact = App::$poi;
+ $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : 'roles');
+ $sub_section = ((array_key_exists('sub_section', $_REQUEST)) ? $_REQUEST['sub_section'] : '');
+
+
+ if (argc() == 3) {
+ $cmd = argv(2);
+ $ret = $this->do_action($contact, $cmd);
+ $contact = App::$poi;
+
+ $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $this->get_tools($contact),
+ ]);
+
+ $ret['tools'] = $tools_html;
+
+ json_return_and_die($ret);
+ }
+
+ $groups = [];
+
+ if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
+
+ $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ intval(local_channel())
+ );
+
+ $member_of = AccessList::containing(local_channel(), $contact['xchan_hash']);
+
+ if ($r) {
+ foreach ($r as $rr) {
+ $default_group = false;
+ if ($rr['hash'] === $channel['channel_default_group']) {
+ $default_group = true;
+ }
+
+ $groups[] = [
+ 'pgrp_id_' . $rr['id'],
+ $rr['gname'],
+ // if it's a new contact preset the default group if we have one
+ (($default_group && $contact['abook_pending']) ? 1 : in_array($rr['id'], $member_of)),
+ '',
+ [t('No'), t('Yes')]
+ ];
+ }
+ }
+ }
+
+ $slide = '';
+
+ if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
+
+ $labels = [
+ t('Me'),
+ t('Family'),
+ t('Friends'),
+ t('Acquaintances'),
+ t('All')
+ ];
+ call_hooks('affinity_labels', $labels);
+ $label_str = '';
+
+ if ($labels) {
+ foreach ($labels as $l) {
+ if ($label_str) {
+ $label_str .= ", '|'";
+ $label_str .= ", '" . $l . "'";
+ }
+ else
+ $label_str .= "'" . $l . "'";
+ }
+ }
+
+ $slider_tpl = get_markup_template('contact_slider.tpl');
+
+ $slideval = intval($contact['abook_closeness']);
+
+ $slide = replace_macros($slider_tpl, [
+ '$min' => 1,
+ '$val' => $slideval,
+ '$labels' => $label_str,
+ ]);
+ }
+
+ $perms = [];
+ $global_perms = Permissions::Perms();
+ $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
+ $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]];
+ $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false);
+
+ $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
+ intval(local_channel()),
+ dbesc($contact['abook_xchan'])
+ );
+
+ $their_perms = [];
+ if ($theirs) {
+ foreach ($theirs as $t) {
+ $their_perms[$t['k']] = $t['v'];
+ }
+ }
+
+ foreach ($global_perms as $k => $v) {
+ $thisperm = $existing[$k];
+ $checkinherited = PermissionLimits::Get(local_channel(), $k);
+ $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited];
+ }
+
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
+ $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']);
+
+ $roles_dict = [];
+ foreach ($pcatlist as $role) {
+ $roles_dict[$role['name']] = $role['localname'];
+ }
+
+
+ if (!$current_permcat) {
+ notice(t('Please select a role for this contact!') . EOL);
+ $permcats[] = '';
+ }
+
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
+ $permcats[$pc['name']] = $pc['localname'];
+ }
+ }
+
+ $locstr = locations_by_netid($contact['xchan_hash']);
+ if (!$locstr) {
+ $locstr = unpunify($contact['xchan_url']);
+ }
+
+ $clone_warn = '';
+ $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
+ if (!$clonable) {
+ $clone_warn = '<strong>';
+ $clone_warn .= ((intval($contact['abook_not_here']))
+ ? t('This contact is unreachable from this location.')
+ : t('This contact may be unreachable from other channel locations.')
+ );
+ $clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
+ }
+
+ $header_card = '<img src="' . $contact['xchan_photo_s'] . '" class="rounded" style="width: 3rem; height: 3rem;">&nbsp; ' . $contact['xchan_name'];
+
+ $header_html = replace_macros(get_markup_template("contact_edit_header.tpl"), [
+ '$img_src' => $contact['xchan_photo_s'],
+ '$name' => $contact['xchan_name'],
+ '$addr' => (($contact['xchan_addr']) ? $contact['xchan_addr'] : $contact['xchan_url']),
+ '$href' => ((is_matrix_url($contact['xchan_url'])) ? zid($contact['xchan_url']) : $contact['xchan_url']),
+ '$link_label' => t('View profile'),
+ '$is_group' => $contact['xchan_pubforum'],
+ '$group_label' => t('This is a group/forum channel')
+ ]);
+
+ $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $this->get_tools($contact),
+ ]);
+
+ $tpl = get_markup_template("contact_edit.tpl");
+
+ $o = replace_macros($tpl, [
+ '$permcat' => ['permcat', t('Select a role for this contact'), $current_permcat, '', $permcats],
+ '$permcat_new' => t('Contact roles'),
+ '$permcat_value' => bin2hex($current_permcat),
+// '$addr' => unpunify($contact['xchan_addr']),
+// '$primeurl' => unpunify($contact['xchan_url']),
+ '$section' => $section,
+ '$sub_section' => $sub_section,
+ '$groups' => $groups,
+// '$addr_text' => t('This contacts\'s primary address is'),
+// '$loc_text' => t('Available locations:'),
+// '$locstr' => $locstr,
+// '$unclonable' => $clone_warn,
+ '$lbl_slider' => t('Slide to adjust your degree of friendship'),
+ '$connfilter' => feature_enabled(local_channel(), 'connfilter'),
+ '$connfilter_label' => t('Custom Filter'),
+ '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$slide' => $slide,
+// '$pending_label' => t('Contact Pending Approval'),
+// '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
+// '$unapproved' => $unapproved,
+ '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')),
+ '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
+ '$them' => t('Their'),
+ '$me' => t('My'),
+ '$perms' => $perms,
+// '$lastupdtext' => t('Last update:'),
+// '$last_update' => relative_date($contact['abook_connected']),
+ '$profile_select' => contact_profile_assign($contact['abook_profile']),
+ '$multiprofs' => $multiprofs,
+ '$contact_id' => $contact['abook_id'],
+// '$name' => $contact['xchan_name'],
+ '$roles_label' => t('Roles'),
+ '$compare_label' => t('Compare permissions'),
+ '$permission_label' => t('Permission'),
+ '$pgroups_label' => t('Privacy groups'),
+ '$profiles_label' => t('Profiles'),
+ '$affinity_label' => t('Affinity'),
+ '$filter_label' => t('Content filter')
+ ]);
+
+ $arr = ['contact' => $contact, 'output' => $o];
+
+ call_hooks('contact_edit', $arr);
+
+ if (is_ajax()) {
+ json_return_and_die([
+ 'success' => ((intval($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1),
+ 'message' => (($_REQUEST['success']) ? t('Contact updated') : t('Contact update failed')),
+ 'id' => $contact_id,
+ 'title' => $header_html,
+ 'role' => ((intval($contact['abook_pending'])) ? '' : $roles_dict[$current_permcat]),
+ 'body' => $arr['output'],
+ 'tools' => $tools_html,
+ 'submit' => ((intval($contact['abook_pending'])) ? t('Approve connection') : t('Submit')),
+ 'pending' => intval($contact['abook_pending'])
+ ]);
+ }
+
+ return $arr['output'];
+
+ }
+
+ function contactedit_clone() {
+
+ if (!App::$poi)
+ return;
+
+ $channel = App::get_channel();
+
+ $clone = App::$poi;
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
+
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
+ }
+
+ function do_action($contact, $cmd) {
+ $ret = [
+ 'sucess' => false,
+ 'message' => ''
+ ];
+
+ if ($cmd === 'resetphoto') {
+ q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
+ dbesc($contact['xchan_hash'])
+ );
+ $cmd = 'refresh';
+ }
+
+ if ($cmd === 'refresh') {
+ if ($contact['xchan_network'] === 'zot6') {
+ if (Libzot::refresh($contact, App::get_channel())) {
+ $ret['success'] = true;
+ $ret['message'] = t('Refresh succeeded');
+ }
+ else {
+ $ret['message'] = t('Refresh failed - channel is currently unavailable');
+ }
+ }
+ else {
+ // if you are on a different network we'll force a refresh of the connection basic info
+ Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]);
+ $ret['success'] = true;
+ $ret['message'] = t('Refresh succeeded');
+ }
+
+ return $ret;
+ }
+
+ if ($cmd === 'block') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_BLOCKED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Block status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Block failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'ignore') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_IGNORED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Ignore status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Ignore failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'archive') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_ARCHIVED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Archive status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Archive failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'hide') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_HIDDEN)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Hide status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Hide failed');
+ }
+ return $ret;
+ }
+
+ // We'll prevent somebody from unapproving an already approved contact.
+ // Though maybe somebody will want this eventually (??)
+
+ //if ($cmd === 'approve') {
+ //if (intval($contact['abook_pending'])) {
+ //if (abook_toggle_flag($contact, ABOOK_FLAG_PENDING)) {
+ //$this->contactedit_clone();
+ //}
+ //else
+ //notice(t('Unable to set address book parameters.') . EOL);
+ //}
+ //goaway(z_root() . '/connedit/' . $contact_id);
+ //}
+
+
+ if ($cmd === 'drop') {
+
+ if (contact_remove(local_channel(), $contact['abook_id'])) {
+
+ Master::Summon(['Notifier', 'purge', local_channel(), $contact['xchan_hash']]);
+ Libsync::build_sync_packet(0 /* use the current local_channel */,
+ ['abook' => [
+ [
+ 'abook_xchan' => $contact['abook_xchan'],
+ 'entry_deleted' => true
+ ]
+ ]
+ ]);
+
+ $ret['success'] = true;
+ $ret['message'] = t('Contact removed');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Delete failed');
+ }
+ return $ret;
+ }
+ }
+
+ function get_tools($contact) {
+ return [
+
+ 'refresh' => [
+ 'label' => t('Refresh Permissions'),
+ 'title' => t('Fetch updated permissions'),
+ ],
+
+ 'rephoto' => [
+ 'label' => t('Refresh Photo'),
+ 'title' => t('Fetch updated photo'),
+ ],
+
+
+ 'block' => [
+ 'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
+ 'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
+ 'title' => t('Block (or Unblock) all communications with this connection'),
+ 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
+ ],
+
+ 'ignore' => [
+ 'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
+ 'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
+ 'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
+ 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
+ ],
+
+ 'archive' => [
+ 'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
+ 'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
+ 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
+ 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
+ ],
+
+ 'hide' => [
+ 'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
+ 'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
+ 'title' => t('Hide or Unhide this connection from your other connections'),
+ 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
+ ],
+
+ 'delete' => [
+ 'label' => t('Delete'),
+ 'sel' => '',
+ 'title' => t('Delete this connection'),
+ ],
+
+ ];
+ }
+
+}
diff --git a/Zotlabs/Module/Contactgroup.php b/Zotlabs/Module/Contactgroup.php
index 36aaf7da0..3e88179fb 100644
--- a/Zotlabs/Module/Contactgroup.php
+++ b/Zotlabs/Module/Contactgroup.php
@@ -1,17 +1,17 @@
<?php
namespace Zotlabs\Module;
-require_once('include/group.php');
+use Zotlabs\Lib\AccessList;
+use Zotlabs\Web\Controller;
-
-class Contactgroup extends \Zotlabs\Web\Controller {
+class Contactgroup extends Controller {
function get() {
-
+
if(! local_channel()) {
killme();
}
-
+
if((argc() > 2) && (intval(argv(1))) && (argv(2))) {
$r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc(base64url_decode(argv(2))),
@@ -20,9 +20,9 @@ class Contactgroup extends \Zotlabs\Web\Controller {
if($r)
$change = $r[0]['abook_xchan'];
}
-
+
if((argc() > 1) && (intval(argv(1)))) {
-
+
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
@@ -30,25 +30,25 @@ class Contactgroup extends \Zotlabs\Web\Controller {
if(! $r) {
killme();
}
-
+
$group = $r[0];
- $members = group_get_members($group['id']);
+ $members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
-
+
if($change) {
if(in_array($change,$preselected)) {
- group_rmv_member(local_channel(),$group['gname'],$change);
+ AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
- group_add_member(local_channel(),$group['gname'],$change);
+ AccessList::member_add(local_channel(),$group['gname'],$change);
}
}
}
-
+
killme();
}
}
diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php
index f2f7c10e5..70270d36b 100644
--- a/Zotlabs/Module/Defperms.php
+++ b/Zotlabs/Module/Defperms.php
@@ -8,7 +8,6 @@ use Zotlabs\Lib\Libsync;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
require_once('include/photos.php');
class Defperms extends Controller {
@@ -19,13 +18,13 @@ class Defperms extends Controller {
*/
function init() {
-
+
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
- return;
-
+ //if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
+ // return;
+
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_self = 1 and abook_channel = %d LIMIT 1",
@@ -37,39 +36,39 @@ class Defperms extends Controller {
$channel = App::get_channel();
if($channel)
- head_set_icon($channel['xchan_photo_s']);
+ head_set_icon($channel['xchan_photo_s']);
}
-
+
/* @brief Evaluate posted values and set changes
*
*/
-
+
function post() {
-
+
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
- return;
-
+ //if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
+ // return;
+
$contact_id = intval(argv(1));
if(! $contact_id)
return;
-
+
$channel = App::get_channel();
-
+
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id),
intval(local_channel())
);
-
+
if(! $orig_record) {
notice( t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
-
+
if(intval($orig_record[0]['abook_self'])) {
$autoperms = intval($_POST['autoperms']);
@@ -79,8 +78,8 @@ class Defperms extends Controller {
$autoperms = null;
$is_self = false;
}
-
-
+
+
$all_perms = \Zotlabs\Access\Permissions::Perms();
if($all_perms) {
@@ -105,15 +104,15 @@ class Defperms extends Controller {
}
}
- if(! is_null($autoperms))
+ if(! is_null($autoperms))
set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
-
-
+
+
notice( t('Settings updated.') . EOL);
-
+
// Refresh the structure in memory with the new data
-
+
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -123,28 +122,28 @@ class Defperms extends Controller {
if($r) {
App::$poi = $r[0];
}
-
-
+
+
$this->defperms_clone($a);
-
+
goaway(z_root() . '/defperms');
-
+
return;
-
+
}
-
+
/* @brief Clone connection
*
*
*/
-
+
function defperms_clone(&$a) {
-
+
if(! App::$poi)
return;
-
+
$channel = App::get_channel();
-
+
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
@@ -154,49 +153,47 @@ class Defperms extends Controller {
if($r) {
App::$poi = array_shift($r);
}
-
+
$clone = App::$poi;
-
+
unset($clone['abook_id']);
unset($clone['abook_account']);
unset($clone['abook_channel']);
-
+
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig)
$clone['abconfig'] = $abconfig;
-
+
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
}
-
+
/* @brief Generate content of connection default permissions page
*
*
*/
-
+
function get() {
-
+
$sort_type = 0;
$o = '';
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
}
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
+ //~ if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
+ //~ //Do not display any associated widgets at this point
+ //~ App::$pdl = '';
+ //~ $papp = Apps::get_papp('Default Permissions');
+ //~ return Apps::app_render($papp, 'module');
+ //~ }
- $o = '<b>' . t('Default Permissions App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Set custom default permissions for new connections');
- return $o;
- }
-
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
$channel = App::get_channel();
-
+
$yes_no = array(t('No'),t('Yes'));
-
+
$connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel());
$o .= "<script>function connectDefaultShare() {
@@ -210,28 +207,28 @@ class Defperms extends Controller {
}
}
$o .= " }\n</script>\n";
-
+
if(App::$poi) {
-
+
$sections = [];
$self = false;
-
+
$tpl = get_markup_template('defperms.tpl');
-
-
+
+
$perms = array();
$channel = App::get_channel();
$contact = App::$poi;
-
+
$global_perms = \Zotlabs\Access\Permissions::Perms();
$hidden_perms = [];
-
+
foreach($global_perms as $k => $v) {
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
-
+
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
$inherited = (($checkinherited & PERMS_SPECIFIC) ? false : true);
@@ -241,7 +238,7 @@ class Defperms extends Controller {
$hidden_perms[] = [ 'perms_' . $k, intval($thisperm) ];
}
}
-
+
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
$pcatlist = $pcat->listing();
$permcats = [];
@@ -272,13 +269,13 @@ class Defperms extends Controller {
'$contact_id' => $contact['abook_id'],
'$name' => $contact['xchan_name'],
]);
-
+
$arr = array('contact' => $contact,'output' => $o);
-
+
call_hooks('contact_edit', $arr);
-
+
return $arr['output'];
-
- }
+
+ }
}
}
diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php
index e1555fc2d..da37c582f 100644
--- a/Zotlabs/Module/Directory.php
+++ b/Zotlabs/Module/Directory.php
@@ -8,7 +8,6 @@ use Zotlabs\Lib\Libzotdir;
require_once('include/socgraph.php');
-require_once('include/dir_fns.php');
require_once('include/bbcode.php');
require_once('include/html2plain.php');
@@ -255,21 +254,21 @@ class Directory extends Controller {
$connect_link = '';
$location = '';
- if(strlen($rr['locale']))
+ if(isset($rr['locale']))
$location .= $rr['locale'];
- if(strlen($rr['region'])) {
- if(strlen($rr['locale']))
+ if(isset($rr['region'])) {
+ if($location)
$location .= ', ';
$location .= $rr['region'];
}
- if(strlen($rr['country'])) {
- if(strlen($location))
+ if(isset($rr['country'])) {
+ if($location)
$location .= ', ';
$location .= $rr['country'];
}
$age = '';
- if(strlen($rr['birthday'])) {
+ if(isset($rr['birthday'])) {
if(($years = age($rr['birthday'],'UTC','')) > 0)
$age = $years;
}
diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php
index 804d7af5c..78205a9fc 100644
--- a/Zotlabs/Module/Dirsearch.php
+++ b/Zotlabs/Module/Dirsearch.php
@@ -4,26 +4,22 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
-require_once('include/dir_fns.php');
-
-
-
class Dirsearch extends Controller {
function init() {
App::set_pager_itemspage(30);
-
+
}
-
+
function get() {
-
+
$ret = array('success' => false);
-
+
// logger('request: ' . print_r($_REQUEST,true));
-
-
+
+
$dirmode = intval(get_config('system','directory_mode'));
-
+
if($dirmode == DIRECTORY_MODE_NORMAL) {
$ret['message'] = t('This site is not a directory server');
json_return_and_die($ret);
@@ -31,24 +27,24 @@ class Dirsearch extends Controller {
$access_token = $_REQUEST['t'];
-
+
$token = get_config('system','realm_token');
if($token && $access_token != $token) {
$ret['message'] = t('This directory server requires an access token');
json_return_and_die($ret);
}
-
-
+
+
if(argc() > 1 && argv(1) === 'sites') {
$ret = $this->list_public_sites();
json_return_and_die($ret);
}
-
+
$sql_extra = '';
-
-
+
+
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
-
+
if($_REQUEST['query']) {
$advanced = $this->dir_parse_query($_REQUEST['query']);
if($advanced) {
@@ -64,9 +60,9 @@ class Dirsearch extends Controller {
}
}
}
-
+
$hash = ((x($_REQUEST['hash'])) ? $_REQUEST['hash'] : '');
-
+
$name = ((x($_REQUEST,'name')) ? $_REQUEST['name'] : '');
$hub = ((x($_REQUEST,'hub')) ? $_REQUEST['hub'] : '');
$address = ((x($_REQUEST,'address')) ? $_REQUEST['address'] : '');
@@ -82,16 +78,16 @@ class Dirsearch extends Controller {
$agele = ((x($_REQUEST,'agele')) ? intval($_REQUEST['agele']) : 0 );
$kw = ((x($_REQUEST,'kw')) ? intval($_REQUEST['kw']) : 0 );
$forums = ((array_key_exists('pubforums',$_REQUEST)) ? intval($_REQUEST['pubforums']) : 0);
-
+
if(get_config('system','disable_directory_keywords'))
$kw = 0;
-
-
+
+
// by default use a safe search
$safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
if ($safe === false)
$safe = 1;
-
+
if(array_key_exists('sync',$_REQUEST)) {
if($_REQUEST['sync'])
$sync = datetime_convert('UTC','UTC',$_REQUEST['sync']);
@@ -100,7 +96,7 @@ class Dirsearch extends Controller {
}
else
$sync = false;
-
+
if(($dirmode == DIRECTORY_MODE_STANDALONE) && (! $hub)) {
$hub = \App::get_hostname();
}
@@ -109,13 +105,13 @@ class Dirsearch extends Controller {
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
else
$hub_query = '';
-
+
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
-
+
$joiner = ' OR ';
if($_REQUEST['and'])
$joiner = ' AND ';
-
+
if($name)
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
if($address)
@@ -136,58 +132,58 @@ class Dirsearch extends Controller {
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
if($keywords)
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
-
-
- // we only support an age range currently. You must set both agege
- // (greater than or equal) and agele (less than or equal)
-
+
+
+ // we only support an age range currently. You must set both agege
+ // (greater than or equal) and agele (less than or equal)
+
if($agele && $agege) {
$sql_extra .= " $joiner ( xprof_age <= " . intval($agele) . " ";
$sql_extra .= " AND xprof_age >= " . intval($agege) . ") ";
}
-
-
+
+
if($hash) {
$sql_extra = " AND xchan_hash like '" . dbesc($hash) . protect_sprintf('%') . "' ";
}
-
-
+
+
$perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 60);
$page = (($_REQUEST['p']) ? intval($_REQUEST['p'] - 1) : 0);
$startrec = (($page+1) * $perpage) - $perpage;
$limit = (($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 0);
$return_total = ((x($_REQUEST,'return_total')) ? intval($_REQUEST['return_total']) : 0);
-
+
// mtime is not currently working
-
+
$mtime = ((x($_REQUEST,'mtime')) ? datetime_convert('UTC','UTC',$_REQUEST['mtime']) : '');
-
- // ok a separate tag table won't work.
+
+ // ok a separate tag table won't work.
// merge them into xprof
-
+
$ret['success'] = true;
-
+
// If &limit=n, return at most n entries
// If &return_total=1, we count matching entries and return that as 'total_items' for use in pagination.
// By default we return one page (default 80 items maximum) and do not count total entries
-
+
$logic = ((strlen($sql_extra)) ? 'false' : 'true');
-
+
if($hash)
$logic = 'true';
-
+
if($dirmode == DIRECTORY_MODE_STANDALONE) {
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
}
-
+
$safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
if($safe < 0)
$safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
-
+
if($forums)
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
-
- if($limit)
+
+ if($limit)
$qlimit = " LIMIT $limit ";
else {
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
@@ -198,27 +194,27 @@ class Dirsearch extends Controller {
}
}
}
-
+
if($sort_order == 'normal') {
$order = " order by xchan_name asc ";
-
- // Start the alphabetic search at 'A'
+
+ // Start the alphabetic search at 'A'
// This will make a handful of channels whose names begin with
// punctuation un-searchable in this mode
-
+
$safesql .= " and ascii(substring(xchan_name FROM 1 FOR 1)) > 64 ";
}
elseif($sort_order == 'reverse')
$order = " order by xchan_name desc ";
elseif($sort_order == 'reversedate')
$order = " order by xchan_name_date asc ";
- else
+ else
$order = " order by xchan_name_date desc ";
-
-
+
+
if($sync) {
$spkt = array('transactions' => array());
- $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' order by ud_date desc",
+ $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc",
dbesc($sync)
);
if($r) {
@@ -228,7 +224,7 @@ class Dirsearch extends Controller {
$flags[] = 'deleted';
if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
$flags[] = 'forced';
-
+
$spkt['transactions'][] = array(
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
@@ -238,87 +234,48 @@ class Dirsearch extends Controller {
);
}
}
- $r = q("select * from xlink where xlink_static = 1 and xlink_updated >= '%s' ",
- dbesc($sync)
- );
- if($r) {
- $spkt['ratings'] = array();
- foreach($r as $rr) {
- $spkt['ratings'][] = array(
- 'type' => 'rating',
- 'encoding' => 'zot',
- 'channel' => $rr['xlink_xchan'],
- 'target' => $rr['xlink_link'],
- 'rating' => intval($rr['xlink_rating']),
- 'rating_text' => $rr['xlink_rating_text'],
- 'signature' => $rr['xlink_sig'],
- 'edited' => $rr['xlink_updated']
- );
- }
- }
json_return_and_die($spkt);
}
else {
-
- $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
- where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
- $safesql $order $qlimit "
+
+ $r = q("SELECT
+ xchan.xchan_name as name,
+ xchan.xchan_hash as hash,
+ xchan.xchan_censored as censored,
+ xchan.xchan_selfcensored as selfcensored,
+ xchan.xchan_pubforum as public_forum,
+ xchan.xchan_url as url,
+ xchan.xchan_photo_l as photo_l,
+ xchan.xchan_photo_m as photo,
+ xchan.xchan_addr as address,
+ xprof.xprof_desc as description,
+ xprof.xprof_locale as locale,
+ xprof.xprof_region as region,
+ xprof.xprof_postcode as postcode,
+ xprof.xprof_country as country,
+ xprof.xprof_dob as birthday,
+ xprof.xprof_age as age,
+ xprof.xprof_gender as gender,
+ xprof.xprof_marital as marital,
+ xprof.xprof_sexual as sexual,
+ xprof.xprof_about as about,
+ xprof.xprof_homepage as homepage,
+ xprof.xprof_hometown as hometown,
+ xprof.xprof_keywords as keywords
+ from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on hubloc_hash = xchan_hash
+ where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
+ $safesql $order $qlimit",
+ db_utcnow(),
+ db_quoteinterval('30 DAY')
);
-
-
-
- $ret['page'] = $page + 1;
- $ret['records'] = count($r);
+
}
-
-
-
+
if($r) {
-
- $entries = array();
-
- foreach($r as $rr) {
-
- $entry = array();
-
- $pc = q("select count(xlink_rating) as total_ratings from xlink where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 group by xlink_rating",
- dbesc($rr['xchan_hash'])
- );
-
- if($pc)
- $entry['total_ratings'] = intval($pc[0]['total_ratings']);
- else
- $entry['total_ratings'] = 0;
-
- $entry['name'] = $rr['xchan_name'];
- $entry['hash'] = $rr['xchan_hash'];
- $entry['censored'] = $rr['xchan_censored'];
- $entry['selfcensored'] = $rr['xchan_selfcensored'];
- $entry['public_forum'] = (intval($rr['xchan_pubforum']) ? true : false);
- $entry['url'] = $rr['xchan_url'];
- $entry['photo_l'] = $rr['xchan_photo_l'];
- $entry['photo'] = $rr['xchan_photo_m'];
- $entry['address'] = $rr['xchan_addr'];
- $entry['description'] = $rr['xprof_desc'];
- $entry['locale'] = $rr['xprof_locale'];
- $entry['region'] = $rr['xprof_region'];
- $entry['postcode'] = $rr['xprof_postcode'];
- $entry['country'] = $rr['xprof_country'];
- $entry['birthday'] = $rr['xprof_dob'];
- $entry['age'] = $rr['xprof_age'];
- $entry['gender'] = $rr['xprof_gender'];
- $entry['marital'] = $rr['xprof_marital'];
- $entry['sexual'] = $rr['xprof_sexual'];
- $entry['about'] = $rr['xprof_about'];
- $entry['homepage'] = $rr['xprof_homepage'];
- $entry['hometown'] = $rr['xprof_hometown'];
- $entry['keywords'] = $rr['xprof_keywords'];
-
- $entries[] = $entry;
-
- }
-
- $ret['results'] = $entries;
+ $ret['results'] = $r;
+ $ret['page'] = $page + 1;
+ $ret['records'] = count($r);
+
if($kw) {
$k = dir_tagadelic($kw, $hub);
if($k) {
@@ -328,30 +285,30 @@ class Dirsearch extends Controller {
}
}
}
- }
-
+ }
+
json_return_and_die($ret);
}
-
+
function dir_query_build($joiner,$field,$s) {
$ret = '';
if(trim($s))
$ret .= dbesc($joiner) . " " . dbesc($field) . " like '" . protect_sprintf( '%' . dbesc($s) . '%' ) . "' ";
return $ret;
}
-
+
function dir_flag_build($joiner,$field,$bit,$s) {
return dbesc($joiner) . " ( " . dbesc($field) . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 ";
}
-
-
+
+
function dir_parse_query($s) {
-
+
$ret = array();
$curr = array();
$all = explode(' ',$s);
$quoted_string = false;
-
+
if($all) {
foreach($all as $q) {
if($quoted_string === false) {
@@ -382,7 +339,7 @@ class Dirsearch extends Controller {
$ret[] = $curr;
$curr = array();
continue;
- }
+ }
else {
$ret[] = $curr;
$curr = array();
@@ -405,15 +362,15 @@ class Dirsearch extends Controller {
logger('dir_parse_query:' . print_r($ret,true),LOGGER_DATA);
return $ret;
}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
function list_public_sites() {
-
+
$rand = db_getfunc('rand');
$realm = get_directory_realm();
if($realm == DIRECTORY_REALM) {
@@ -428,16 +385,16 @@ class Dirsearch extends Controller {
intval(SITE_TYPE_ZOT)
);
}
-
+
$ret = array('success' => false);
-
+
if($r) {
$ret['success'] = true;
$ret['sites'] = array();
$insecure = array();
-
+
foreach($r as $rr) {
-
+
if($rr['site_access'] == ACCESS_FREE)
$access = 'free';
elseif($rr['site_access'] == ACCESS_PAID)
@@ -446,14 +403,14 @@ class Dirsearch extends Controller {
$access = 'tiered';
else
$access = 'private';
-
+
if($rr['site_register'] == REGISTER_OPEN)
$register = 'open';
elseif($rr['site_register'] == REGISTER_APPROVE)
$register = 'approve';
else
$register = 'closed';
-
+
if(strpos($rr['site_url'],'https://') !== false)
$ret['sites'][] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']);
else
diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php
index e6caa9906..02a79f854 100644
--- a/Zotlabs/Module/Display.php
+++ b/Zotlabs/Module/Display.php
@@ -1,6 +1,8 @@
<?php
namespace Zotlabs\Module;
+use App;
+
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
@@ -34,11 +36,20 @@ class Display extends \Zotlabs\Web\Controller {
}
}
- if($_REQUEST['mid'])
+ if($_REQUEST['mid']) {
$item_hash = $_REQUEST['mid'];
+ }
- if(! $item_hash) {
- \App::$error = 404;
+ $item_hash = unpack_link_id($item_hash);
+
+ if ($item_hash === false) {
+ App::$error = 400;
+ notice(t('Malformed message id.') . EOL);
+ return;
+ }
+
+ if(!$item_hash) {
+ App::$error = 404;
notice( t('Item not found.') . EOL);
return;
}
@@ -47,7 +58,7 @@ class Display extends \Zotlabs\Web\Controller {
if(local_channel() && (! $update)) {
- $channel = \App::get_channel();
+ $channel = App::get_channel();
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
@@ -92,11 +103,6 @@ class Display extends \Zotlabs\Web\Controller {
$target_item = null;
- if(strpos($item_hash,'b64.') === 0)
- $decoded = @base64url_decode(substr($item_hash,4));
- if($decoded)
- $item_hash = $decoded;
-
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1",
dbesc($item_hash)
);
@@ -110,7 +116,7 @@ class Display extends \Zotlabs\Web\Controller {
);
if($x) {
// not yet ready for prime time
-// \App::$poi = $x[0];
+// App::$poi = $x[0];
}
//if the item is to be moderated redirect to /moderate
@@ -189,17 +195,15 @@ class Display extends \Zotlabs\Web\Controller {
// if the target item is not a post (eg a like) we want to address its thread parent
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
- $mid = $target_item['mid'];
// if we got a decoded hash we must encode it again before handing to javascript
- if($decoded)
- $mid = 'b64.' . base64url_encode($mid);
+ $mid = gen_link_id($target_item['mid']);
$o .= '<div id="live-display"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
- . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n";
+ . "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
- \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
+ App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'display',
'$uid' => '0',
@@ -215,7 +219,7 @@ class Display extends \Zotlabs\Web\Controller {
'$dm' => '0',
'$nouveau' => '0',
'$wall' => '0',
- '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
+ '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$search' => '',
'$xchan' => '',
@@ -233,7 +237,7 @@ class Display extends \Zotlabs\Web\Controller {
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
- 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
+ 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
@@ -355,7 +359,7 @@ class Display extends \Zotlabs\Web\Controller {
}
$o .= '</noscript>';
- \App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
+ App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . App::$page['title'] : App::$page['title']);
$o .= conversation($items, 'display', $update, 'client');
}
@@ -368,12 +372,12 @@ class Display extends \Zotlabs\Web\Controller {
'$version' => xmlify(\Zotlabs\Lib\System::get_project_version()),
'$generator' => xmlify(\Zotlabs\Lib\System::get_platform_name()),
'$generator_uri' => 'https://hubzilla.org',
- '$feed_id' => xmlify(\App::$cmd),
+ '$feed_id' => xmlify(App::$cmd),
'$feed_title' => xmlify(t('Article')),
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now', ATOM_TIME)),
'$author' => '',
'$owner' => '',
- '$profile_page' => xmlify(z_root() . '/display/' . $target_item['mid']),
+ '$profile_page' => xmlify(z_root() . '/display/' . gen_link_id($target_item['mid'])),
));
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php
index 0fc36dc29..d6f4e5979 100644
--- a/Zotlabs/Module/Dreport.php
+++ b/Zotlabs/Module/Dreport.php
@@ -5,33 +5,21 @@ namespace Zotlabs\Module;
class Dreport extends \Zotlabs\Web\Controller {
function get() {
-
+
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
-
+
$table = 'item';
-
$channel = \App::get_channel();
-
- $mid = ((argc() > 1) ? argv(1) : '');
- $encoded_mid = '';
+ $mid = ((argc() > 1) ? unpack_link_id(argv(1)) : '');
- if(strpos($mid,'b64.') === 0) {
- $encoded_mid = $mid;
- $mid = @base64url_decode(substr($mid,4));
- }
if($mid === 'push') {
$table = 'push';
- $mid = ((argc() > 2) ? argv(2) : '');
-
- if(strpos($mid,'b64.') === 0) {
- $encoded_mid = $mid;
- $mid = @base64url_decode(substr($mid,4));
- }
+ $mid = ((argc() > 2) ? unpack_link_id(argv(2)) : '');
- if($mid) {
+ if($mid) {
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
dbesc($mid),
intval($channel['channel_id']),
@@ -43,23 +31,14 @@ class Dreport extends \Zotlabs\Web\Controller {
}
}
sleep(3);
- goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid));
+ goaway(z_root() . '/dreport/' . gen_link_id($mid));
}
- if($mid === 'mail') {
- $table = 'mail';
- $mid = ((argc() > 2) ? argv(2) : '');
- if(strpos($mid,'b64.') === 0)
- $mid = @base64url_decode(substr($mid,4));
-
- }
-
-
if(! $mid) {
notice( t('Invalid message') . EOL);
return;
}
-
+
switch($table) {
case 'item':
$i = q("select id from item where mid = '%s' and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
@@ -68,39 +47,33 @@ class Dreport extends \Zotlabs\Web\Controller {
dbesc($channel['channel_hash'])
);
break;
- case 'mail':
- $i = q("select id from mail where mid = '%s' and from_xchan = '%s'",
- dbesc($mid),
- dbesc($channel['channel_hash'])
- );
- break;
default:
break;
}
-
+
if(! $i) {
notice( t('Permission denied') . EOL);
return;
}
-
- $r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'",
+
+ $r = q("select * from dreport where dreport_xchan = '%s' and (dreport_mid = '%s' or dreport_mid = '%s')",
dbesc($channel['channel_hash']),
- dbesc($channel['channel_portable_id']),
- dbesc($mid)
+ dbesc($mid),
+ dbesc(str_replace('/item/', '/activity/', $mid))
);
-
+
if(! $r) {
notice( t('no results') . EOL);
// return;
}
-
+
for($x = 0; $x < count($r); $x++ ) {
-
+
// This has two purposes: 1. make the delivery report strings translateable, and
// 2. assign an ordering to item delivery results so we can group them and provide
// a readable report with more interesting events listed toward the top and lesser
// interesting items towards the bottom
-
+
switch($r[$x]['dreport_result']) {
case 'channel sync processed':
$r[$x]['gravity'] = 0;
@@ -132,27 +105,18 @@ class Dreport extends \Zotlabs\Web\Controller {
case 'recipient not found':
$r[$x]['dreport_result'] = t('recipient not found');
break;
- case 'mail recalled':
- $r[$x]['dreport_result'] = t('mail recalled');
- break;
- case 'duplicate mail received':
- $r[$x]['dreport_result'] = t('duplicate mail received');
- break;
- case 'mail delivered':
- $r[$x]['dreport_result'] = t('mail delivered');
- break;
default:
$r[$x]['gravity'] = 1;
break;
}
}
-
+
usort($r,'self::dreport_gravity_sort');
$entries = array();
foreach($r as $rr) {
- $entries[] = [
- 'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
+ $entries[] = [
+ 'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
'result' => escape_tags($rr['dreport_result']),
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
];
@@ -167,14 +131,14 @@ class Dreport extends \Zotlabs\Web\Controller {
'$push' => t('Redeliver'),
'$entries' => $entries
));
-
-
+
+
return $o;
-
-
-
+
+
+
}
-
+
private static function dreport_gravity_sort($a,$b) {
if($a['gravity'] == $b['gravity']) {
if($a['dreport_name'] === $b['dreport_name'])
@@ -183,5 +147,5 @@ class Dreport extends \Zotlabs\Web\Controller {
}
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
}
-
+
}
diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php
deleted file mode 100644
index 681d6887d..000000000
--- a/Zotlabs/Module/Events.php
+++ /dev/null
@@ -1,750 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-require_once('include/conversation.php');
-require_once('include/bbcode.php');
-require_once('include/datetime.php');
-require_once('include/event.php');
-require_once('include/items.php');
-require_once('include/html2plain.php');
-
-class Events extends \Zotlabs\Web\Controller {
-
- function post() {
-
- // this module is deprecated
- return;
-
- logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
-
- if(! local_channel())
- return;
-
- if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) {
- $src = $_FILES['userfile']['tmp_name'];
- if($src) {
- $result = parse_ical_file($src,local_channel());
- if($result)
- info( t('Calendar entries imported.') . EOL);
- else
- notice( t('No calendar entries found.') . EOL);
- @unlink($src);
- }
- goaway(z_root() . '/events');
- }
-
-
- $event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
- $event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
-
- $xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
- $uid = local_channel();
-
- $start_text = escape_tags($_REQUEST['start_text']);
- $finish_text = escape_tags($_REQUEST['finish_text']);
-
- $adjust = intval($_POST['adjust']);
- $nofinish = intval($_POST['nofinish']);
-
- $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
-
- $tz = (($timezone) ? $timezone : date_default_timezone_get());
-
- $categories = escape_tags(trim($_POST['category']));
-
- // only allow editing your own events.
-
- if(($xchan) && ($xchan !== get_observer_hash()))
- return;
-
- if($start_text) {
- $start = $start_text;
- }
- else {
- $start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute);
- }
-
-
- if($finish_text) {
- $finish = $finish_text;
- }
- else {
- $finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute);
- }
-
- if($nofinish) {
- $finish = NULL_DATE;
- }
-
-
- if($adjust) {
- $start = datetime_convert($tz,'UTC',$start);
- if(! $nofinish)
- $finish = datetime_convert($tz,'UTC',$finish);
- }
- else {
- $start = datetime_convert('UTC','UTC',$start);
- if(! $nofinish)
- $finish = datetime_convert('UTC','UTC',$finish);
- }
-
- // Don't allow the event to finish before it begins.
- // It won't hurt anything, but somebody will file a bug report
- // and we'll waste a bunch of time responding to it. Time that
- // could've been spent doing something else.
-
-
- $summary = escape_tags(trim($_POST['summary']));
- $desc = escape_tags(trim($_POST['desc']));
- $location = escape_tags(trim($_POST['location']));
- $type = escape_tags(trim($_POST['type']));
-
- require_once('include/text.php');
- linkify_tags($desc, local_channel());
- linkify_tags($location, local_channel());
-
- //$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
-
- //fixme: this url gives a wsod if there is a linebreak detected in one of the variables ($desc or $location)
- //$onerror_url = z_root() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish&type=$type";
- $onerror_url = z_root() . "/events";
-
- if(strcmp($finish,$start) < 0 && !$nofinish) {
- notice( t('Event can not end before it has started.') . EOL);
- if(intval($_REQUEST['preview'])) {
- echo( t('Unable to generate preview.'));
- killme();
- }
- goaway($onerror_url);
- }
-
- if((! $summary) || (! $start)) {
- notice( t('Event title and start time are required.') . EOL);
- if(intval($_REQUEST['preview'])) {
- echo( t('Unable to generate preview.'));
- killme();
- }
- goaway($onerror_url);
- }
-
- // $share = ((intval($_POST['distr'])) ? intval($_POST['distr']) : 0);
-
- $share = 1;
-
- $channel = \App::get_channel();
-
- $acl = new \Zotlabs\Access\AccessList(false);
-
- if($event_id) {
- $x = q("select * from event where id = %d and uid = %d limit 1",
- intval($event_id),
- intval(local_channel())
- );
- if(! $x) {
- notice( t('Event not found.') . EOL);
- if(intval($_REQUEST['preview'])) {
- echo( t('Unable to generate preview.'));
- killme();
- }
- return;
- }
-
- $acl->set($x[0]);
-
- $created = $x[0]['created'];
- $edited = datetime_convert();
-
- if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>'
- && $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') {
- $share = false;
- }
- else {
- $share = true;
- }
- }
- else {
- $created = $edited = datetime_convert();
- if($share) {
- $acl->set_from_array($_POST);
- }
- else {
- $acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
- }
- }
-
- $post_tags = array();
- $channel = \App::get_channel();
- $ac = $acl->get();
-
- if(strlen($categories)) {
- $cats = explode(',',$categories);
- foreach($cats as $cat) {
- $post_tags[] = array(
- 'uid' => $profile_uid,
- 'ttype' => TERM_CATEGORY,
- 'otype' => TERM_OBJ_POST,
- 'term' => trim($cat),
- 'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
- );
- }
- }
-
- $datarray = array();
- $datarray['dtstart'] = $start;
- $datarray['dtend'] = $finish;
- $datarray['summary'] = $summary;
- $datarray['description'] = $desc;
- $datarray['location'] = $location;
- $datarray['etype'] = $type;
- $datarray['adjust'] = $adjust;
- $datarray['nofinish'] = $nofinish;
- $datarray['uid'] = local_channel();
- $datarray['account'] = get_account_id();
- $datarray['event_xchan'] = $channel['channel_hash'];
- $datarray['allow_cid'] = $ac['allow_cid'];
- $datarray['allow_gid'] = $ac['allow_gid'];
- $datarray['deny_cid'] = $ac['deny_cid'];
- $datarray['deny_gid'] = $ac['deny_gid'];
- $datarray['private'] = (($acl->is_private()) ? 1 : 0);
- $datarray['id'] = $event_id;
- $datarray['created'] = $created;
- $datarray['edited'] = $edited;
-
- if(intval($_REQUEST['preview'])) {
- $html = format_event_html($datarray);
- echo $html;
- killme();
- }
-
- $event = event_store_event($datarray);
-
- if($post_tags)
- $datarray['term'] = $post_tags;
-
- $item_id = event_store_item($datarray,$event);
-
- if($item_id) {
- $r = q("select * from item where id = %d",
- intval($item_id)
- );
- if($r) {
- xchan_query($r);
- $sync_item = fetch_post_tags($r);
- $z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
- dbesc($r[0]['resource_id']),
- intval($channel['channel_id'])
- );
- if($z) {
- build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
- }
- }
- }
-
- if($share)
- \Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
-
- }
-
-
-
- function get() {
-
- // this module is deprecated
- return;
-
- if(argc() > 2 && argv(1) == 'ical') {
- $event_id = argv(2);
-
- require_once('include/security.php');
- $sql_extra = permissions_sql(local_channel());
-
- $r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
- dbesc($event_id)
- );
- if($r) {
- header('Content-type: text/calendar');
- header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
- echo ical_wrapper($r);
- killme();
- }
- else {
- notice( t('Event not found.') . EOL );
- return;
- }
- }
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- \App::$profile_uid = local_channel();
- nav_set_selected('Events');
-
-
- if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
- $r = q("update event set dismissed = 1 where id = %d and uid = %d",
- intval(argv(2)),
- intval(local_channel())
- );
- }
-
- if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
- $r = q("update event set dismissed = 0 where id = %d and uid = %d",
- intval(argv(2)),
- intval(local_channel())
- );
- }
-
- $first_day = feature_enabled(local_channel(), 'events_cal_first_day');
- $first_day = (($first_day) ? $first_day : 0);
-
- $htpl = get_markup_template('event_head.tpl');
- \App::$page['htmlhead'] .= replace_macros($htpl,array(
- '$baseurl' => z_root(),
- '$module_url' => '/events',
- '$modparams' => 1,
- '$lang' => \App::$language,
- '$first_day' => $first_day
- ));
-
- $o = '';
-
- $channel = \App::get_channel();
-
- $mode = 'view';
- $y = 0;
- $m = 0;
- $ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
-
-
- // logger('args: ' . print_r(\App::$argv,true));
-
-
-
- if(argc() > 1) {
- if(argc() > 2 && argv(1) === 'add') {
- $mode = 'add';
- $item_id = intval(argv(2));
- }
- if(argc() > 2 && argv(1) === 'drop') {
- $mode = 'drop';
- $event_id = argv(2);
- }
- if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
- $mode = 'view';
- $y = intval(argv(1));
- $m = intval(argv(2));
- }
- if(argc() <= 2) {
- $mode = 'view';
- $event_id = argv(1);
- }
- }
-
- if($mode === 'add') {
- event_addtocal($item_id,local_channel());
- killme();
- }
-
- if($mode == 'view') {
-
- /* edit/create form */
- if($event_id) {
- $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
- dbesc($event_id),
- intval(local_channel())
- );
- if(count($r))
- $orig_event = $r[0];
- }
-
- $channel = \App::get_channel();
-
- // Passed parameters overrides anything found in the DB
- if(!x($orig_event))
- $orig_event = array();
-
- // In case of an error the browser is redirected back here, with these parameters filled in with the previous values
- /*
- if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish'];
- if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust'];
- if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary'];
- if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description'];
- if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location'];
- if(x($_REQUEST,'start')) $orig_event['dtstart'] = $_REQUEST['start'];
- if(x($_REQUEST,'finish')) $orig_event['dtend'] = $_REQUEST['finish'];
- if(x($_REQUEST,'type')) $orig_event['etype'] = $_REQUEST['type'];
- */
-
- $n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
- $a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
- $t_orig = ((x($orig_event)) ? $orig_event['summary'] : '');
- $d_orig = ((x($orig_event)) ? $orig_event['description'] : '');
- $l_orig = ((x($orig_event)) ? $orig_event['location'] : '');
- $eid = ((x($orig_event)) ? $orig_event['id'] : 0);
- $event_xchan = ((x($orig_event)) ? $orig_event['event_xchan'] : $channel['channel_hash']);
- $mid = ((x($orig_event)) ? $orig_event['mid'] : '');
-
- if(! x($orig_event)) {
- $sh_checked = '';
- $a_checked = ' checked="checked" ';
- }
- else {
- $sh_checked = ((($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' || (! $orig_event['allow_cid'])) && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' );
- }
-
- if($orig_event['event_xchan'])
- $sh_checked .= ' disabled="disabled" ';
-
- $sdt = ((x($orig_event)) ? $orig_event['dtstart'] : 'now');
-
- $fdt = ((x($orig_event)) ? $orig_event['dtend'] : '+1 hour');
-
- $tz = date_default_timezone_get();
- if(x($orig_event))
- $tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
-
- $syear = datetime_convert('UTC', $tz, $sdt, 'Y');
- $smonth = datetime_convert('UTC', $tz, $sdt, 'm');
- $sday = datetime_convert('UTC', $tz, $sdt, 'd');
- $shour = datetime_convert('UTC', $tz, $sdt, 'H');
- $sminute = datetime_convert('UTC', $tz, $sdt, 'i');
-
- $stext = datetime_convert('UTC',$tz,$sdt);
- $stext = substr($stext,0,14) . "00:00";
-
- $fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
- $fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
- $fday = datetime_convert('UTC', $tz, $fdt, 'd');
- $fhour = datetime_convert('UTC', $tz, $fdt, 'H');
- $fminute = datetime_convert('UTC', $tz, $fdt, 'i');
-
- $ftext = datetime_convert('UTC',$tz,$fdt);
- $ftext = substr($ftext,0,14) . "00:00";
-
- $type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
-
- $f = get_config('system','event_input_format');
- if(! $f)
- $f = 'ymd';
-
- $catsenabled = feature_enabled(local_channel(),'categories');
-
- $category = '';
-
- if($catsenabled && x($orig_event)){
- $itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1",
- dbesc($orig_event['event_hash']),
- intval(local_channel())
- );
- $itm = fetch_post_tags($itm);
- if($itm) {
- $cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
- foreach ($cats as $cat) {
- if(strlen($category))
- $category .= ', ';
- $category .= $cat['term'];
- }
- }
- }
-
- require_once('include/acl_selectors.php');
-
- $acl = new \Zotlabs\Access\AccessList($channel);
- $perm_defaults = $acl->get();
-
- $permissions = ((x($orig_event)) ? $orig_event : $perm_defaults);
-
- $tpl = get_markup_template('event_form.tpl');
-
- $form = replace_macros($tpl,array(
- '$post' => z_root() . '/events',
- '$eid' => $eid,
- '$type' => $type,
- '$xchan' => $event_xchan,
- '$mid' => $mid,
- '$event_hash' => $event_id,
- '$summary' => array('summary', (($event_id) ? t('Edit event title') : t('Event title')), $t_orig, t('Required'), '*'),
- '$catsenabled' => $catsenabled,
- '$placeholdercategory' => t('Categories (comma-separated list)'),
- '$c_text' => (($event_id) ? t('Edit Category') : t('Category')),
- '$category' => $category,
- '$required' => '<span class="required" title="' . t('Required') . '">*</span>',
- '$s_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$syear+5),\DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"), (($event_id) ? t('Edit start date and time') : t('Start date and time')), 'start_text',true,true,'','',true,$first_day),
- '$n_text' => t('Finish date and time are not known or not relevant'),
- '$n_checked' => $n_checked,
- '$f_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$fyear+5),\DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"), (($event_id) ? t('Edit finish date and time') : t('Finish date and time')),'finish_text',true,true,'start_text','',false,$first_day),
- '$nofinish' => array('nofinish', t('Finish date and time are not known or not relevant'), $n_checked, '', array(t('No'),t('Yes')), 'onclick="enableDisableFinishDate();"'),
- '$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked, t('Important for events that happen in a particular place. Not practical for global holidays.'), array(t('No'),t('Yes'))),
- '$a_text' => t('Adjust for viewer timezone'),
- '$d_text' => (($event_id) ? t('Edit Description') : t('Description')),
- '$d_orig' => $d_orig,
- '$l_text' => (($event_id) ? t('Edit Location') : t('Location')),
- '$l_orig' => $l_orig,
- '$t_orig' => $t_orig,
- '$preview' => t('Preview'),
- '$perms_label' => t('Permission settings'),
- // populating the acl dialog was a permission description from view_stream because Cal.php, which
- // displays events, says "since we don't currently have an event permission - use the stream permission"
- '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'))),
-
- '$allow_cid' => acl2json($permissions['allow_cid']),
- '$allow_gid' => acl2json($permissions['allow_gid']),
- '$deny_cid' => acl2json($permissions['deny_cid']),
- '$deny_gid' => acl2json($permissions['deny_gid']),
- '$tz_choose' => feature_enabled(local_channel(),'event_tz_select'),
- '$timezone' => array('timezone_select' , t('Timezone:'), date_default_timezone_get(), '', get_timezones()),
-
- '$lockstate' => (($acl->is_private()) ? 'lock' : 'unlock'),
-
- '$submit' => t('Submit'),
- '$advanced' => t('Advanced Options')
-
- ));
- /* end edit/create form */
-
- $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
- $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
- if(! $y)
- $y = intval($thisyear);
- if(! $m)
- $m = intval($thismonth);
-
- $export = false;
- if(argc() === 4 && argv(3) === 'export')
- $export = true;
-
- // Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
- // An upper limit was chosen to keep search engines from exploring links millions of years in the future.
-
- if($y < 1901)
- $y = 1900;
- if($y > 2099)
- $y = 2100;
-
- $nextyear = $y;
- $nextmonth = $m + 1;
- if($nextmonth > 12) {
- $nextmonth = 1;
- $nextyear ++;
- }
-
- $prevyear = $y;
- if($m > 1)
- $prevmonth = $m - 1;
- else {
- $prevmonth = 12;
- $prevyear --;
- }
-
- $dim = get_dim($y,$m);
- $start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
- $finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
-
-
- if (argv(1) === 'json'){
- if (x($_GET,'start')) $start = $_GET['start'];
- if (x($_GET,'end')) $finish = $_GET['end'];
- }
-
- $start = datetime_convert('UTC','UTC',$start);
- $finish = datetime_convert('UTC','UTC',$finish);
-
- $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
- $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
-
- if (x($_GET,'id')){
- $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
- from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
- intval(local_channel()),
- intval($_GET['id'])
- );
- } elseif($export) {
- $r = q("SELECT * from event where uid = %d
- AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
- OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ",
- intval(local_channel()),
- dbesc($start),
- dbesc($finish),
- dbesc($adjust_start),
- dbesc($adjust_finish)
- );
- }
- else {
- // fixed an issue with "nofinish" events not showing up in the calendar.
- // There's still an issue if the finish date crosses the end of month.
- // Noting this for now - it will need to be fixed here and in Friendica.
- // Ultimately the finish date shouldn't be involved in the query.
-
- $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
- from event left join item on event_hash = resource_id
- where resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
- AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
- OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ",
- intval(local_channel()),
- dbesc($start),
- dbesc($finish),
- dbesc($adjust_start),
- dbesc($adjust_finish)
- );
- }
-
- $links = array();
-
- if($r && ! $export) {
- xchan_query($r);
- $r = fetch_post_tags($r,true);
-
- $r = sort_by_date($r);
- }
-
- if($r) {
- foreach($r as $rr) {
- $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
- if(! x($links,$j))
- $links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
- }
- }
-
- $events=array();
-
- $last_date = '';
- $fmt = t('l, F j');
-
- if($r) {
-
- foreach($r as $rr) {
-
- $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
- $d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
- $d = day_translate($d);
-
- $start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
- if ($rr['nofinish']){
- $end = null;
- } else {
- $end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
-
- // give a fake end to birthdays so they get crammed into a
- // single day on the calendar
-
- if($rr['etype'] === 'birthday')
- $end = null;
- }
-
-
- $is_first = ($d !== $last_date);
-
- $last_date = $d;
-
- $edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
-
- $drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
-
- $title = strip_tags(html_entity_decode(zidify_links(bbcode($rr['summary'])),ENT_QUOTES,'UTF-8'));
- if(! $title) {
- list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
- $title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
- }
- $html = format_event_html($rr);
- $rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
- $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false);
- $rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
- $events[] = array(
- 'id'=>$rr['id'],
- 'hash' => $rr['event_hash'],
- 'start'=> $start,
- 'end' => $end,
- 'drop' => $drop,
- 'allDay' => false,
- 'title' => $title,
-
- 'j' => $j,
- 'd' => $d,
- 'edit' => $edit,
- 'is_first'=>$is_first,
- 'item'=>$rr,
- 'html'=>$html,
- 'plink' => array($rr['plink'],t('Link to Source'),'',''),
- );
-
- }
- }
-
- if($export) {
- header('Content-type: text/calendar');
- header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
- echo ical_wrapper($r);
- killme();
- }
-
- if (\App::$argv[1] === 'json'){
- echo json_encode($events); killme();
- }
-
- // links: array('href', 'text', 'extra css classes', 'title')
- if (x($_GET,'id')){
- $tpl = get_markup_template("event.tpl");
- }
- else {
- $tpl = get_markup_template("events-js.tpl");
- }
-
- $o = replace_macros($tpl, array(
- '$baseurl' => z_root(),
- '$new_event' => array(z_root().'/events',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
- '$previus' => array(z_root()."/events/$prevyear/$prevmonth",t('Previous'),'',''),
- '$next' => array(z_root()."/events/$nextyear/$nextmonth",t('Next'),'',''),
- '$export' => array(z_root()."/events/$y/$m/export",t('Export'),'',''),
- '$calendar' => cal($y,$m,$links, ' eventcal'),
- '$events' => $events,
- '$view_label' => t('View'),
- '$month' => t('Month'),
- '$week' => t('Week'),
- '$day' => t('Day'),
- '$prev' => t('Previous'),
- '$next' => t('Next'),
- '$today' => t('Today'),
- '$form' => $form,
- '$expandform' => ((x($_GET,'expandform')) ? true : false),
- ));
-
- if (x($_GET,'id')){ echo $o; killme(); }
-
- return $o;
- }
-
- if($mode === 'drop' && $event_id) {
- $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
- dbesc($event_id),
- intval(local_channel())
- );
-
- $sync_event = $r[0];
-
- if($r) {
- $r = q("delete from event where event_hash = '%s' and uid = %d",
- dbesc($event_id),
- intval(local_channel())
- );
- if($r) {
- $r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d",
- dbesc($event_id),
- intval(local_channel())
- );
- $sync_event['event_deleted'] = 1;
- build_sync_packet(0,array('event' => array($sync_event)));
-
- info( t('Event removed') . EOL);
- }
- else {
- notice( t('Failed to remove event' ) . EOL);
- }
- goaway(z_root() . '/events');
- }
- }
-
- }
-
-}
diff --git a/Zotlabs/Module/Fhublocs.php b/Zotlabs/Module/Fhublocs.php
index 42dac5b12..9dcece715 100644
--- a/Zotlabs/Module/Fhublocs.php
+++ b/Zotlabs/Module/Fhublocs.php
@@ -3,7 +3,6 @@ namespace Zotlabs\Module;
use Zotlabs\Lib\Libzot;
-require_once('include/zot.php');
require_once('include/crypto.php');
/* fix missing or damaged hublocs */
@@ -59,23 +58,6 @@ class Fhublocs extends \Zotlabs\Web\Controller {
// Create a verified hub location pointing to this site.
-/*
- $h = hubloc_store_lowlevel(
- [
- 'hubloc_guid' => $rr['channel_guid'],
- 'hubloc_guid_sig' => $rr['channel_guid_sig'],
- 'hubloc_hash' => $rr['channel_hash'],
- 'hubloc_addr' => channel_reddress($rr),
- 'hubloc_network' => 'zot',
- 'hubloc_primary' => $primary,
- 'hubloc_url' => z_root(),
- 'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$rr['channel_prvkey'])),
- 'hubloc_host' => \App::get_hostname(),
- 'hubloc_callback' => z_root() . '/post',
- 'hubloc_sitekey' => $sitekey
- ]
- );
-*/
$h = hubloc_store_lowlevel(
[
'hubloc_guid' => $rr['channel_guid'],
diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php
index e18067e20..d4c9ad59a 100644
--- a/Zotlabs/Module/File_upload.php
+++ b/Zotlabs/Module/File_upload.php
@@ -99,6 +99,9 @@ class File_upload extends \Zotlabs\Web\Controller {
}
}
+ if(is_ajax())
+ killme();
+
goaway(z_root() . '/' . $_REQUEST['return_url']);
}
diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php
index 4fe20f56b..94daa4c70 100644
--- a/Zotlabs/Module/Follow.php
+++ b/Zotlabs/Module/Follow.php
@@ -108,7 +108,7 @@ class Follow extends Controller {
}
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
- $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
+ $can_view_stream = intval(get_abconfig($channel['channel_id'], $clone['abook_xchan'], 'their_perms', 'view_stream'));
// If we can view their stream, pull in some posts
@@ -117,7 +117,7 @@ class Follow extends Controller {
}
if ($interactive) {
- goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');
+ goaway(z_root() . '/connections#' . $result['abook']['abook_id']);
}
else {
json_return_and_die([ 'success' => true ]);
diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php
index 993d428f5..1dce08757 100644
--- a/Zotlabs/Module/Group.php
+++ b/Zotlabs/Module/Group.php
@@ -5,8 +5,7 @@ use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
-
-require_once('include/group.php');
+use Zotlabs\Lib\AccessList;
class Group extends Controller {
@@ -26,7 +25,7 @@ class Group extends Controller {
}
function post() {
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -35,25 +34,26 @@ class Group extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
return;
}
-
+
if((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
-
+
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
- $r = group_add(local_channel(),$name,$public);
+ $r = AccessList::add(local_channel(),$name,$public);
+ $group_hash = $r;
+
if($r) {
info( t('Privacy group created.') . EOL );
}
else {
notice( t('Could not create privacy group.') . EOL );
}
- goaway(z_root() . '/group');
-
}
+
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/group', 'group_edit');
-
+
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
@@ -61,14 +61,15 @@ class Group extends Controller {
if(! $r) {
notice( t('Privacy group not found.') . EOL );
goaway(z_root() . '/connections');
-
+
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
+ $group_hash = $group['hash'];
$public = intval($_POST['public']);
-
+
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
- call_hooks ('privacygroup_extras_post',$hookinfo);
+ call_hooks('privacygroup_extras_post',$hookinfo);
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
@@ -79,22 +80,30 @@ class Group extends Controller {
);
if($r)
info( t('Privacy group updated.') . EOL );
-
-
- Libsync::build_sync_packet(local_channel(),null,true);
}
-
- goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
}
- return;
+
+ $channel = App::get_channel();
+
+ $default_group = ((isset($_POST['set_default_group'])) ? $group_hash : (($channel['channel_default_group'] === $group_hash) ? '' : $channel['channel_default_group']));
+ $default_acl = ((isset($_POST['set_default_acl'])) ? '<' . $group_hash . '>' : (($channel['channel_allow_gid'] === '<' . $group_hash . '>') ? '' : $channel['channel_allow_gid']));
+
+ q("update channel set channel_default_group = '%s', channel_allow_gid = '%s'
+ where channel_id = %d",
+ dbesc($default_group),
+ dbesc($default_acl),
+ intval(local_channel())
+ );
+
+ Libsync::build_sync_packet(local_channel(),null,true);
+
+ goaway(z_root() . '/group/' . argv(1) . ((argv(2)) ? '/' . argv(2) : ''));
+
+ return;
}
-
+
function get() {
- $change = false;
-
- logger('mod_group: ' . App::$cmd,LOGGER_DEBUG);
-
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
@@ -103,12 +112,14 @@ class Group extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Privacy Groups App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Management of privacy groups');
- return $o;
+ $papp = Apps::get_papp('Privacy Groups');
+ return Apps::app_render($papp, 'module');
}
+ logger('mod_group: ' . App::$cmd,LOGGER_DEBUG);
+
+ $change = false;
+
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if($switchtotext === false)
@@ -119,64 +130,45 @@ class Group extends Controller {
if((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) {
- $new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
-
- $groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval(local_channel())
- );
-
- $i = 0;
- foreach($groups as $group) {
- $entries[$i]['name'] = $group['gname'];
- $entries[$i]['id'] = $group['id'];
- $entries[$i]['count'] = count(group_get_members($group['id']));
- $i++;
- }
-
$hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ];
call_hooks ('privacygroup_extras',$hookinfo);
$pgrp_extras = $hookinfo['pgrp_extras'];
+ $is_default_acl = ['set_default_acl', t('Post to this group by default'), 0, '', [t('No'), t('Yes')]];
+ $is_default_group = ['set_default_group', t('Add new contacts to this group by default'), 0, '', [t('No'), t('Yes')]];
+
+
$tpl = get_markup_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
'$title' => t('Privacy Groups'),
- '$add_new_label' => t('Add Group'),
- '$new' => $new,
// new group form
'$gname' => array('groupname',t('Privacy group name')),
- '$public' => array('public',t('Members are visible to other channels'), false),
+ '$public' => array('public',t('Members are visible to other channels'), 0, '', [t('No'), t('Yes')]),
'$pgrp_extras' => $pgrp_extras,
'$form_security_token' => get_form_security_token("group_edit"),
'$submit' => t('Submit'),
-
- // groups list
- '$title' => t('Privacy Groups'),
- '$name_label' => t('Name'),
- '$count_label' => t('Members'),
- '$entries' => $entries
+ '$is_default_acl' => $is_default_acl,
+ '$is_default_group' => $is_default_group,
]);
return $o;
}
-
-
-
$context = array('$submit' => t('Submit'));
$tpl = get_markup_template('group_edit.tpl');
-
+
if((argc() == 3) && (argv(1) === 'drop')) {
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
-
+
if(intval(argv(2))) {
$r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
- if($r)
- $result = group_rmv(local_channel(),$r[0]['gname']);
+ if($r)
+ $result = AccessList::remove(local_channel(),$r[0]['gname']);
if($result) {
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
call_hooks ('privacygroup_extras_drop',$hookinfo);
@@ -188,23 +180,23 @@ class Group extends Controller {
goaway(z_root() . '/group');
// NOTREACHED
}
-
-
+
+
if((argc() > 2) && intval(argv(1)) && argv(2)) {
-
+
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
-
+
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
-
+
}
-
+
if((argc() > 1) && (intval(argv(1)))) {
-
+
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
@@ -215,28 +207,28 @@ class Group extends Controller {
goaway(z_root() . '/connections');
}
$group = $r[0];
-
-
- $members = group_get_members($group['id']);
-
+
+
+ $members = AccessList::members(local_channel(), $group['id']);
+
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
-
+
if($change) {
-
+
if(in_array($change,$preselected)) {
- group_rmv_member(local_channel(),$group['gname'],$change);
+ AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
- group_add_member(local_channel(),$group['gname'],$change);
+ AccessList::member_add(local_channel(),$group['gname'],$change);
}
-
- $members = group_get_members($group['id']);
-
+
+ $members = AccessList::members(local_channel(), $group['id']);
+
$preselected = array();
if(count($members)) {
foreach($members as $member)
@@ -254,25 +246,25 @@ class Group extends Controller {
'$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
- '$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
+ '$public' => array('public',t('Members are visible to other channels'), $group['visible'], '', [t('No'), t('Yes')]),
'$form_security_token_edit' => get_form_security_token('group_edit'),
- '$delete' => t('Delete Group'),
+ '$delete' => t('Delete'),
'$form_security_token_drop' => get_form_security_token("group_drop"),
'$pgrp_extras' => $pgrp_extras,
);
-
+
}
-
+
if(! isset($group))
return;
-
+
$groupeditor = array(
'label_members' => t('Group members'),
'members' => array(),
'label_contacts' => t('Not in this group'),
'contacts' => array(),
);
-
+
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card');
foreach($members as $member) {
@@ -282,13 +274,13 @@ class Group extends Controller {
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
- group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']);
+ AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']);
}
-
+
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
-
+
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card');
foreach($r as $member) {
@@ -299,20 +291,26 @@ class Group extends Controller {
}
}
}
-
+
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Click a channel to toggle membership');
$context['$pgrp_extras'] = $pgrp_extras;
-
+
+ $channel = App::get_channel();
+
+ $context['$is_default_acl'] = ['set_default_acl', t('Post to this group by default'), intval($group['hash'] === trim($channel['channel_allow_gid'], '<>')), '', [t('No'), t('Yes')]];
+ $context['$is_default_group'] = ['set_default_group', t('Add new contacts to this group by default'), intval($group['hash'] === $channel['channel_default_group']), '', [t('No'), t('Yes')]];
+
+
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
-
+
return replace_macros($tpl, $context);
-
+
}
-
-
+
+
}
diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php
index 912c84fd2..1cc26c199 100644
--- a/Zotlabs/Module/Hcard.php
+++ b/Zotlabs/Module/Hcard.php
@@ -5,7 +5,7 @@ namespace Zotlabs\Module;
class Hcard extends \Zotlabs\Web\Controller {
function init() {
-
+
if(argc() > 1)
$which = argv(1);
else {
@@ -13,12 +13,12 @@ class Hcard extends \Zotlabs\Web\Controller {
\App::$error = 404;
return;
}
-
+
logger('hcard_request: ' . $which, LOGGER_DEBUG);
$profile = '';
$channel = \App::get_channel();
-
+
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
@@ -30,22 +30,22 @@ class Hcard extends \Zotlabs\Web\Controller {
$profile = '';
$profile = $r[0]['profile_guid'];
}
-
- head_add_link( [
- 'rel' => 'alternate',
+
+ head_add_link( [
+ 'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Posts and comments'),
'href' => z_root() . '/feed/' . $which
]);
- head_add_link( [
- 'rel' => 'alternate',
+ head_add_link( [
+ 'rel' => 'alternate',
'type' => 'application/atom+xml',
'title' => t('Only posts'),
'href' => z_root() . '/feed/' . $which . '?f=&top=1'
]);
-
+
if(! $profile) {
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
dbesc(argv(1))
@@ -54,20 +54,20 @@ class Hcard extends \Zotlabs\Web\Controller {
\App::$profile = $x[0];
}
}
-
+
profile_load($which,$profile);
-
-
+
+
}
-
-
+
+
function get() {
- $x = new \Zotlabs\Widget\Profile();
+ $x = new \Zotlabs\Widget\Fullprofile();
return $x->widget(array());
-
+
}
-
-
-
+
+
+
}
diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php
index 2bfab986f..315d05af6 100644
--- a/Zotlabs/Module/Home.php
+++ b/Zotlabs/Module/Home.php
@@ -40,7 +40,7 @@ class Home extends Controller {
if (!$dest)
$dest = get_config('system', 'startpage');
if (!$dest)
- $dest = z_root() . '/network';
+ $dest = z_root() . '/hq';
goaway($dest);
}
diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php
index a2c4100ad..5001bbe62 100644
--- a/Zotlabs/Module/Hq.php
+++ b/Zotlabs/Module/Hq.php
@@ -1,6 +1,10 @@
<?php
namespace Zotlabs\Module;
+use App;
+use Zotlabs\Widget\Messages;
+
+
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
@@ -14,61 +18,51 @@ class Hq extends \Zotlabs\Web\Controller {
if(! local_channel())
return;
- \App::$profile_uid = local_channel();
+ App::$profile_uid = local_channel();
}
- function post() {
+ function get($update = 0, $load = false) {
- if(!local_channel())
+ if(!local_channel()) {
return;
-
- if($_REQUEST['notify_id']) {
- q("update notify set seen = 1 where id = %d and uid = %d",
- intval($_REQUEST['notify_id']),
- intval(local_channel())
- );
}
- killme();
+ $item_hash = '';
- }
+ if(argc() > 1 && argv(1) !== 'load') {
+ $item_hash = unpack_link_id(argv(1));
+ }
- function get($update = 0, $load = false) {
+ if(isset($_REQUEST['mid'])) {
+ $item_hash = unpack_link_id($_REQUEST['mid']);
+ }
- if(!local_channel())
+ if($item_hash === false) {
+ notice(t('Malformed message id.') . EOL);
return;
-
- if(argc() > 1 && argv(1) !== 'load') {
- $item_hash = argv(1);
}
- if($_REQUEST['mid'])
- $item_hash = $_REQUEST['mid'];
-
$item_normal = item_normal();
$item_normal_update = item_normal_update();
+ $sys = get_sys_channel();
+ $sys_item = false;
+ $sql_extra = '';
if(! $item_hash) {
$r = q("SELECT mid FROM item
WHERE uid = %d $item_normal
AND mid = parent_mid
+ AND item_private IN (0, 1)
ORDER BY created DESC LIMIT 1",
intval(local_channel())
);
-
if($r[0]['mid']) {
- $item_hash = 'b64.' . base64url_encode($r[0]['mid']);
+ $item_hash = $r[0]['mid'];
}
}
if($item_hash) {
- if(strpos($item_hash,'b64.') === 0)
- $decoded = @base64url_decode(substr($item_hash,4));
-
- if($decoded)
- $item_hash = $decoded;
-
$target_item = null;
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid = '%s' limit 1",
@@ -88,15 +82,10 @@ class Hq extends \Zotlabs\Web\Controller {
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
- $sys = get_sys_channel();
- $sql_extra = item_permissions_sql($sys['channel_id']);
-
- $sys_item = false;
-
}
if(! $update) {
- $channel = \App::get_channel();
+ $channel = App::get_channel();
$channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
@@ -110,7 +99,7 @@ class Hq extends \Zotlabs\Web\Controller {
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
- 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
+ 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'permissions' => $channel_acl,
'bang' => '',
@@ -125,13 +114,8 @@ class Hq extends \Zotlabs\Web\Controller {
'reset' => t('Reset form')
];
- $o = replace_macros(get_markup_template("hq.tpl"),
- [
- '$no_messages' => (($target_item) ? false : true),
- '$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ],
- '$editor' => status_editor($a,$x,false,'Hq')
- ]
- );
+ $a = '';
+ $o = status_editor($a, $x, true);
}
@@ -142,10 +126,9 @@ class Hq extends \Zotlabs\Web\Controller {
if($target_item) {
// if the target item is not a post (eg a like) we want to address its thread parent
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
- $mid = $target_item['mid'];
+
// if we got a decoded hash we must encode it again before handing to javascript
- if($decoded)
- $mid = 'b64.' . base64url_encode($mid);
+ $mid = gen_link_id($target_item['mid']);
}
else {
$mid = '';
@@ -153,9 +136,9 @@ class Hq extends \Zotlabs\Web\Controller {
$o .= '<div id="live-hq"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
- . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n";
+ . "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . ";</script>\r\n";
- \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
+ App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
'$baseurl' => z_root(),
'$pgtype' => 'hq',
'$uid' => local_channel(),
@@ -201,6 +184,7 @@ class Hq extends \Zotlabs\Web\Controller {
if(!$r) {
$sys_item = true;
+ $sql_extra = item_permissions_sql($sys['channel_id']);
$r = q("SELECT item.id AS item_id FROM item
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
@@ -227,6 +211,7 @@ class Hq extends \Zotlabs\Web\Controller {
if(!$r) {
$sys_item = true;
+ $sql_extra = item_permissions_sql($sys['channel_id']);
$r = q("SELECT item.parent AS item_id FROM item
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
@@ -245,7 +230,7 @@ class Hq extends \Zotlabs\Web\Controller {
if($r) {
$items = q("SELECT item.*, item.id AS item_id
FROM item
- WHERE parent = '%s' $item_normal ",
+ WHERE parent = '%s' $item_normal $sql_extra",
dbesc($r[0]['item_id'])
);
@@ -267,4 +252,16 @@ class Hq extends \Zotlabs\Web\Controller {
}
+ function post() {
+ if (!local_channel())
+ return;
+
+ $options['offset'] = $_REQUEST['offset'];
+ $options['type'] = $_REQUEST['type'];
+
+ $ret = Messages::get_messages_page($options);
+
+ json_return_and_die($ret);
+ }
+
}
diff --git a/Zotlabs/Module/Impel.php b/Zotlabs/Module/Impel.php
index e05027d9f..869de2669 100644
--- a/Zotlabs/Module/Impel.php
+++ b/Zotlabs/Module/Impel.php
@@ -1,5 +1,9 @@
<?php
-namespace Zotlabs\Module; /** @file */
+namespace Zotlabs\Module;
+
+use URLify;
+
+/** @file */
// import page design element
@@ -9,33 +13,33 @@ require_once('include/menu.php');
class Impel extends \Zotlabs\Web\Controller {
function init() {
-
+
$ret = array('success' => false);
-
+
if(! local_channel())
json_return_and_die($ret);
-
+
logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA);
-
+
$elm = $_REQUEST['element'];
$x = base64url_decode($elm);
if(! $x)
json_return_and_die($ret);
-
+
$j = json_decode($x,true);
if(! $j)
json_return_and_die($ret);
-
+
// logger('element: ' . print_r($j,true));
$channel = \App::get_channel();
-
+
$arr = array();
$is_menu = false;
-
+
// a portable menu has its links rewritten with the local baseurl
$portable_menu = false;
-
+
switch($j['type']) {
case 'webpage':
$arr['item_type'] = ITEM_TYPE_WEBPAGE;
@@ -58,12 +62,12 @@ class Impel extends \Zotlabs\Web\Controller {
case 'menu':
$is_menu = true;
$installed_type = t('menu');
- break;
+ break;
default:
logger('mod_impel: unrecognised element type' . print_r($j,true));
break;
}
-
+
if($is_menu) {
$m = array();
$m['menu_channel_id'] = local_channel();
@@ -73,23 +77,23 @@ class Impel extends \Zotlabs\Web\Controller {
$m['menu_created'] = datetime_convert($j['created']);
if($j['edited'])
$m['menu_edited'] = datetime_convert($j['edited']);
-
+
$m['menu_flags'] = 0;
if($j['flags']) {
if(in_array('bookmark',$j['flags']))
$m['menu_flags'] |= MENU_BOOKMARK;
if(in_array('system',$j['flags']))
$m['menu_flags'] |= MENU_SYSTEM;
-
+
}
-
+
$menu_id = menu_create($m);
-
+
if($menu_id) {
if(is_array($j['items'])) {
foreach($j['items'] as $it) {
$mitem = array();
-
+
$mitem['mitem_link'] = str_replace('[channelurl]',z_root() . '/channel/' . $channel['channel_address'],$it['link']);
$mitem['mitem_link'] = str_replace('[pageurl]',z_root() . '/page/' . $channel['channel_address'],$it['link']);
$mitem['mitem_link'] = str_replace('[cloudurl]',z_root() . '/cloud/' . $channel['channel_address'],$it['link']);
@@ -115,7 +119,7 @@ class Impel extends \Zotlabs\Web\Controller {
intval(local_channel())
);
}
- }
+ }
$ret['success'] = true;
}
$x = $ret;
@@ -132,22 +136,21 @@ class Impel extends \Zotlabs\Web\Controller {
$arr['owner_xchan'] = get_observer_hash();
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
-
+
if(! $j['mid']) {
$j['uuid'] = item_message_id();
$j['mid'] = z_root() . '/item/' . $j['uuid'];
}
$arr['uuid'] = $j['uuid'];
$arr['mid'] = $arr['parent_mid'] = $j['mid'];
-
-
+
+
if($j['pagetitle']) {
- require_once('library/urlify/URLify.php');
- $pagetitle = strtolower(\URLify::transliterate($j['pagetitle']));
+ $pagetitle = strtolower(URLify::transliterate($j['pagetitle']));
}
-
+
// Verify ability to use html or php!!!
-
+
$execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
$i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
@@ -156,7 +159,7 @@ class Impel extends \Zotlabs\Web\Controller {
);
\Zotlabs\Lib\IConfig::Set($arr,'system',$namespace,(($pagetitle) ? $pagetitle : 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
@@ -174,24 +177,24 @@ class Impel extends \Zotlabs\Web\Controller {
else
$x = item_store($arr,$execflag);
}
-
+
if($x && $x['success']) {
$item_id = $x['item_id'];
}
}
-
+
if($x['success']) {
$ret['success'] = true;
- info( sprintf( t('%s element installed'), $installed_type));
+ info( sprintf( t('%s element installed'), $installed_type));
}
else {
- notice( sprintf( t('%s element installation failed'), $installed_type));
+ notice( sprintf( t('%s element installation failed'), $installed_type));
}
-
- //??? should perhaps return ret?
+
+ //??? should perhaps return ret?
json_return_and_die(true);
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php
index 4622a588d..ec47e370b 100644
--- a/Zotlabs/Module/Import.php
+++ b/Zotlabs/Module/Import.php
@@ -2,14 +2,15 @@
namespace Zotlabs\Module;
-require_once('include/zot.php');
require_once('include/channel.php');
require_once('include/import.php');
require_once('include/perm_upgrade.php');
-require_once('library/urlify/URLify.php');
-use Zotlabs\Lib\Crypto;
+use App;
+use URLify;
+use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Libzot;
+use Zotlabs\Web\Controller;
/**
@@ -18,7 +19,7 @@ use Zotlabs\Lib\Libzot;
* Import a channel, either by direct file upload or via
* connection to another server.
*/
-class Import extends \Zotlabs\Web\Controller {
+class Import extends Controller {
/**
* @brief Import channel into account.
@@ -27,95 +28,94 @@ class Import extends \Zotlabs\Web\Controller {
*/
function import_account($account_id) {
- if(! $account_id){
+ if (!$account_id) {
logger('No account ID supplied');
return;
}
- $max_friends = account_service_class_fetch($account_id,'total_channels');
- $max_feeds = account_service_class_fetch($account_id,'total_feeds');
- $data = null;
- $seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
- $import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
- $moving = intval($_REQUEST['moving']);
- $src = $_FILES['filename']['tmp_name'];
- $filename = basename($_FILES['filename']['name']);
- $filesize = intval($_FILES['filename']['size']);
- $filetype = $_FILES['filename']['type'];
- $newname = trim(strtolower($_REQUEST['newname']));
+ $max_friends = account_service_class_fetch($account_id, 'total_channels');
+ $max_feeds = account_service_class_fetch($account_id, 'total_feeds');
+ $data = null;
+ $seize = ((x($_REQUEST, 'make_primary')) ? intval($_REQUEST['make_primary']) : 0);
+ $import_posts = ((x($_REQUEST, 'import_posts')) ? intval($_REQUEST['import_posts']) : 0);
+ $moving = false; //intval($_REQUEST['moving']);
+ $src = $_FILES['filename']['tmp_name'];
+ $filename = basename($_FILES['filename']['name']);
+ $filesize = intval($_FILES['filename']['size']);
+ $filetype = $_FILES['filename']['type'];
+ $newname = trim(strtolower($_REQUEST['newname']));
// import channel from file
- if($src) {
+ if ($src) {
// This is OS specific and could also fail if your tmpdir isn't very
// large mostly used for Diaspora which exports gzipped files.
- if(strpos($filename,'.gz')){
- @rename($src,$src . '.gz');
+ if (strpos($filename, '.gz')) {
+ @rename($src, $src . '.gz');
@system('gunzip ' . escapeshellarg($src . '.gz'));
}
- if($filesize) {
+ if ($filesize) {
$data = @file_get_contents($src);
}
unlink($src);
}
// import channel from another server
- if(! $src) {
- $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
- if(! $old_address) {
+ if (!$src) {
+ $old_address = ((x($_REQUEST, 'old_address')) ? $_REQUEST['old_address'] : '');
+ if (!$old_address) {
logger('Nothing to import.');
- notice( t('Nothing to import.') . EOL);
+ notice(t('Nothing to import.') . EOL);
return;
- } else if(strpos($old_address, 'ï¼ ')) {
+ }
+ else if (strpos($old_address, 'ï¼ ')) {
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
$old_address = str_replace('ï¼ ', '@', $old_address);
}
- $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
- $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
+ $email = ((x($_REQUEST, 'email')) ? $_REQUEST['email'] : '');
+ $password = ((x($_REQUEST, 'password')) ? $_REQUEST['password'] : '');
- $channelname = substr($old_address,0,strpos($old_address,'@'));
- $servername = substr($old_address,strpos($old_address,'@')+1);
+ $channelname = substr($old_address, 0, strpos($old_address, '@'));
+ $servername = substr($old_address, strpos($old_address, '@') + 1);
$api_path = probe_api_path($servername);
- if(! $api_path) {
- notice( t('Unable to download data from old server') . EOL);
+ if (!$api_path) {
+ notice(t('Unable to download data from old server') . EOL);
return;
}
$api_path .= 'channel/export/basic?f=&channel=' . $channelname;
- if($import_posts)
- $api_path .= '&posts=1';
- $binary = false;
+ $binary = false;
$redirects = 0;
- $opts = array('http_auth' => $email . ':' . $password);
- $ret = z_fetch_url($api_path, $binary, $redirects, $opts);
- if($ret['success']) {
+ $opts = ['http_auth' => $email . ':' . $password];
+ $ret = z_fetch_url($api_path, $binary, $redirects, $opts);
+ if ($ret['success']) {
$data = $ret['body'];
}
else {
- notice( t('Unable to download data from old server') . EOL);
+ notice(t('Unable to download data from old server') . EOL);
return;
}
}
- if(! $data) {
+ if (!$data) {
logger('Empty import file.');
- notice( t('Imported file is empty.') . EOL);
+ notice(t('Imported file is empty.') . EOL);
return;
}
- $data = json_decode($data,true);
+ $data = json_decode($data, true);
//logger('import: data: ' . print_r($data,true));
//print_r($data);
- if(! array_key_exists('compatibility',$data)) {
- call_hooks('import_foreign_channel_data',$data);
- if($data['handled'])
+ if (!array_key_exists('compatibility', $data)) {
+ call_hooks('import_foreign_channel_data', $data);
+ if ($data['handled'])
return;
}
@@ -133,47 +133,47 @@ class Import extends \Zotlabs\Web\Controller {
// prevent incompatible osada or zap data from horking your database
- if(array_path_exists('compatibility/codebase',$data)) {
+ if (array_path_exists('compatibility/codebase', $data)) {
notice('Data export format is not compatible with this software');
return;
}
- if(version_compare($data['compatibility']['version'], '4.7.3', '<=')) {
+ if (version_compare($data['compatibility']['version'], '4.7.3', '<=')) {
// zot6 transition: cloning is not compatible with older versions
notice('Data export format is not compatible with this software (not a zot6 channel)');
return;
}
- if($moving)
+ if ($moving)
$seize = 1;
// import channel
- $relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
+ $relocate = ((array_key_exists('relocate', $data)) ? $data['relocate'] : null);
- if(array_key_exists('channel',$data)) {
+ if (array_key_exists('channel', $data)) {
- $max_identities = account_service_class_fetch($account_id,'total_identities');
+ $max_identities = account_service_class_fetch($account_id, 'total_identities');
- if($max_identities !== false) {
- $r = q("select channel_id from channel where channel_account_id = %d",
+ if ($max_identities !== false) {
+ $r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0",
intval($account_id)
);
- if($r && count($r) > $max_identities) {
- notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL);
+ if ($r && count($r) > $max_identities) {
+ notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL);
return;
}
}
- if($newname) {
- $x = false;
+ if ($newname) {
+ $x = false;
- if(get_config('system','unicode_usernames')) {
- $x = punify(mb_strtolower($newname));
- }
+ if (get_config('system', 'unicode_usernames')) {
+ $x = punify(mb_strtolower($newname));
+ }
- if((! $x) || strlen($x) > 64) {
- $x = strtolower(\URLify::transliterate($newname));
+ if ((!$x) || strlen($x) > 64) {
+ $x = strtolower(URLify::transliterate($newname));
}
$newname = $x;
}
@@ -182,65 +182,38 @@ class Import extends \Zotlabs\Web\Controller {
}
else {
$moving = false;
- $channel = \App::get_channel();
+ $channel = App::get_channel();
}
- if(! $channel) {
- logger('Channel not found. ', print_r($channel,true));
- notice( t('No channel. Import failed.') . EOL);
+ if (!$channel) {
+ logger('Channel not found. ', print_r($channel, true));
+ notice(t('No channel. Import failed.') . EOL);
return;
}
- if(is_array($data['config'])) {
- import_config($channel,$data['config']);
+ if (is_array($data['config'])) {
+ import_config($channel, $data['config']);
}
logger('import step 2');
- if(array_key_exists('channel',$data)) {
- if($data['photo']) {
+ if (array_key_exists('channel', $data)) {
+ if ($data['photo']) {
require_once('include/photo/photo_driver.php');
- import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']);
+ import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], $account_id, $channel['channel_id']);
}
- if(is_array($data['profile']))
- import_profiles($channel,$data['profile']);
+ if (is_array($data['profile']))
+ import_profiles($channel, $data['profile']);
}
logger('import step 3');
// create new hubloc for the new channel at this site
- if(array_key_exists('channel',$data)) {
- if($channel['channel_portable_id']) {
- $r = hubloc_store_lowlevel(
- [
- 'hubloc_guid' => $channel['channel_guid'],
- 'hubloc_guid_sig' => $channel['channel_guid_sig'],
- 'hubloc_hash' => $channel['channel_portable_id'],
- 'hubloc_addr' => channel_reddress($channel),
- 'hubloc_network' => 'zot',
- 'hubloc_primary' => (($seize) ? 1 : 0),
- 'hubloc_url' => z_root(),
- 'hubloc_url_sig' => base64url_encode(Crypto::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(),
- 'hubloc_id_url' => channel_url($channel)
- ]
- );
-
- // reset the original primary hubloc if it is being seized
- if($seize) {
- $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
- dbesc($channel['channel_portable_id']),
- dbesc(z_root())
- );
- }
- }
+ if (array_key_exists('channel', $data)) {
- // create a new zot6 hubloc if we have got a channel_portable_id
+ // create a new zot6 hubloc
$r = hubloc_store_lowlevel(
[
@@ -251,18 +224,18 @@ class Import extends \Zotlabs\Web\Controller {
'hubloc_network' => 'zot6',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
- 'hubloc_url_sig' => 'sha256.' . base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])),
- 'hubloc_host' => \App::get_hostname(),
+ 'hubloc_url_sig' => Libzot::sign(z_root(), $channel['channel_prvkey']),
+ 'hubloc_host' => App::get_hostname(),
'hubloc_callback' => z_root() . '/zot',
- 'hubloc_sitekey' => get_config('system','pubkey'),
+ 'hubloc_sitekey' => get_config('system', 'pubkey'),
'hubloc_updated' => datetime_convert(),
'hubloc_id_url' => channel_url($channel),
- 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
+ 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), get_config('system', 'pubkey'))
]
);
// reset the original primary hubloc if it is being seized
- if($seize) {
+ if ($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
@@ -273,57 +246,33 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 4');
-
// import xchans and contact photos
- if(array_key_exists('channel',$data) && $seize) {
+ if (array_key_exists('channel', $data) && $seize) {
// replace any existing xchan we may have on this site if we're seizing control
- $r = q("delete from xchan where ( xchan_hash = '%s' or xchan_hash = '%s' ) ",
- dbesc($channel['channel_hash']),
- dbesc($channel['channel_portable_id'])
+ $r = q("delete from xchan where xchan_hash = '%s'",
+ dbesc($channel['channel_hash'])
);
- if($channel['channel_portable_id']) {
- $r = xchan_store_lowlevel(
- [
- 'xchan_hash' => $channel['channel_portable_id'],
- 'xchan_guid' => $channel['channel_guid'],
- 'xchan_guid_sig' => $channel['channel_guid_sig'],
- 'xchan_pubkey' => $channel['channel_pubkey'],
- 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
- 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
- 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
- 'xchan_addr' => channel_reddress($channel),
- 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
- 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
- 'xchan_follow' => z_root() . '/follow?f=&url=%s',
- 'xchan_name' => $channel['channel_name'],
- 'xchan_network' => 'zot',
- 'xchan_photo_date' => datetime_convert(),
- 'xchan_name_date' => datetime_convert()
- ]
- );
- }
-
$r = xchan_store_lowlevel(
[
- 'xchan_hash' => $channel['channel_hash'],
- 'xchan_guid' => $channel['channel_guid'],
- 'xchan_guid_sig' => $channel['channel_guid_sig'],
- 'xchan_pubkey' => $channel['channel_pubkey'],
- 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
- 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
- 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
- 'xchan_addr' => channel_reddress($channel),
- 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
- 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
- 'xchan_follow' => z_root() . '/follow?f=&url=%s',
- 'xchan_name' => $channel['channel_name'],
- 'xchan_network' => 'zot6',
- 'xchan_photo_date' => datetime_convert(),
- 'xchan_name_date' => datetime_convert()
+ 'xchan_hash' => $channel['channel_hash'],
+ 'xchan_guid' => $channel['channel_guid'],
+ 'xchan_guid_sig' => $channel['channel_guid_sig'],
+ 'xchan_pubkey' => $channel['channel_pubkey'],
+ 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
+ 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
+ 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
+ 'xchan_addr' => channel_reddress($channel),
+ 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
+ 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
+ 'xchan_follow' => z_root() . '/follow?f=&url=%s',
+ 'xchan_name' => $channel['channel_name'],
+ 'xchan_network' => 'zot6',
+ 'xchan_photo_date' => datetime_convert(),
+ 'xchan_name_date' => datetime_convert()
]
);
@@ -333,26 +282,18 @@ class Import extends \Zotlabs\Web\Controller {
// import xchans
$xchans = $data['xchan'];
- if($xchans) {
- foreach($xchans as $xchan) {
-
- if($xchan['xchan_network'] === 'zot') {
- $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
- if($hash !== $xchan['xchan_hash']) {
- logger('forged xchan: ' . print_r($xchan,true));
- continue;
- }
- }
+ if ($xchans) {
+ foreach ($xchans as $xchan) {
- if($xchan['xchan_network'] === 'zot6') {
- $zhash = Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
- if($zhash !== $xchan['xchan_hash']) {
- logger('forged xchan: ' . print_r($xchan,true));
+ if ($xchan['xchan_network'] === 'zot6') {
+ $zhash = Libzot::make_xchan_hash($xchan['xchan_guid'], $xchan['xchan_pubkey']);
+ if ($zhash !== $xchan['xchan_hash']) {
+ logger('forged xchan: ' . print_r($xchan, true));
continue;
}
}
- if(! array_key_exists('xchan_hidden',$xchan)) {
+ if (!array_key_exists('xchan_hidden', $xchan)) {
$xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0);
$xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0);
$xchan['xchan_censored'] = (($xchan['xchan_flags'] & 0x0004) ? 1 : 0);
@@ -365,14 +306,14 @@ class Import extends \Zotlabs\Web\Controller {
$r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($xchan['xchan_hash'])
);
- if($r)
+ if ($r)
continue;
- create_table_from_array('xchan',$xchan);
+ create_table_from_array('xchan', $xchan);
require_once('include/photo/photo_driver.php');
- if($xchan['xchan_hash'] === $channel['channel_hash']) {
+ if ($xchan['xchan_hash'] === $channel['channel_hash']) {
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
@@ -381,13 +322,13 @@ class Import extends \Zotlabs\Web\Controller {
);
}
else {
- $photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']);
- if($photos[4])
+ $photos = import_xchan_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
+ if ($photos[4])
$photodate = NULL_DATE;
else
$photodate = $xchan['xchan_photo_date'];
- $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
+ q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@@ -404,22 +345,22 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 7');
// this must happen after xchans got imported!
- if(is_array($data['hubloc'])) {
- import_hublocs($channel,$data['hubloc'],$seize,$moving);
+ if (is_array($data['hubloc'])) {
+ import_hublocs($channel, $data['hubloc'], $seize, $moving);
}
$friends = 0;
- $feeds = 0;
+ $feeds = 0;
// import contacts
$abooks = $data['abook'];
- if($abooks) {
- foreach($abooks as $abook) {
+ if ($abooks) {
+ foreach ($abooks as $abook) {
$abook_copy = $abook;
$abconfig = null;
- if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
+ if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
$abconfig = $abook['abconfig'];
unset($abook['abook_id']);
@@ -432,33 +373,33 @@ class Import extends \Zotlabs\Web\Controller {
$abook['abook_account'] = $account_id;
$abook['abook_channel'] = $channel['channel_id'];
- if(! array_key_exists('abook_blocked',$abook)) {
- $abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001 ) ? 1 : 0);
- $abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002 ) ? 1 : 0);
- $abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004 ) ? 1 : 0);
- $abook['abook_archived'] = (($abook['abook_flags'] & 0x0008 ) ? 1 : 0);
- $abook['abook_pending'] = (($abook['abook_flags'] & 0x0010 ) ? 1 : 0);
- $abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020 ) ? 1 : 0);
- $abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0);
- $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0);
+ if (!array_key_exists('abook_blocked', $abook)) {
+ $abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001) ? 1 : 0);
+ $abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002) ? 1 : 0);
+ $abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004) ? 1 : 0);
+ $abook['abook_archived'] = (($abook['abook_flags'] & 0x0008) ? 1 : 0);
+ $abook['abook_pending'] = (($abook['abook_flags'] & 0x0010) ? 1 : 0);
+ $abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020) ? 1 : 0);
+ $abook['abook_self'] = (($abook['abook_flags'] & 0x0080) ? 1 : 0);
+ $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100) ? 1 : 0);
}
- if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) {
+ if (array_key_exists('abook_instance', $abook) && $abook['abook_instance'] && strpos($abook['abook_instance'], z_root()) === false) {
$abook['abook_not_here'] = 1;
}
- if($abook['abook_self']) {
- $role = get_pconfig($channel['channel_id'],'system','permissions_role');
- if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
+ if ($abook['abook_self']) {
+ $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role');
+ if (($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) {
q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ",
dbesc($abook['abook_xchan'])
);
}
}
else {
- if($max_friends !== false && $friends > $max_friends)
+ if ($max_friends !== false && $friends > $max_friends)
continue;
- if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
+ if ($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds))
continue;
}
@@ -466,9 +407,9 @@ class Import extends \Zotlabs\Web\Controller {
dbesc($abook['abook_xchan']),
intval($channel['channel_id'])
);
- if($r) {
- foreach($abook as $k => $v) {
- $r = q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d",
+ if ($r) {
+ foreach ($abook as $k => $v) {
+ q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d",
dbesc($k),
dbesc($v),
dbesc($abook['abook_xchan']),
@@ -479,17 +420,17 @@ class Import extends \Zotlabs\Web\Controller {
else {
abook_store_lowlevel($abook);
- $friends ++;
- if(intval($abook['abook_feed']))
- $feeds ++;
+ $friends++;
+ if (intval($abook['abook_feed']))
+ $feeds++;
}
- translate_abook_perms_inbound($channel,$abook_copy);
+ translate_abook_perms_inbound($channel, $abook_copy);
- if($abconfig) {
+ if ($abconfig) {
/// @FIXME does not handle sync of del_abconfig
- foreach($abconfig as $abc) {
- set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
+ foreach ($abconfig as $abc) {
+ set_abconfig($channel['channel_id'], $abc['xchan'], $abc['cat'], $abc['k'], $abc['v']);
}
}
}
@@ -497,13 +438,14 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 8');
}
+
// import groups
$groups = $data['group'];
- if($groups) {
- $saved = array();
- foreach($groups as $group) {
- $saved[$group['hash']] = array('old' => $group['id']);
- if(array_key_exists('name', $group)) {
+ if ($groups) {
+ $saved = [];
+ foreach ($groups as $group) {
+ $saved[$group['hash']] = ['old' => $group['id']];
+ if (array_key_exists('name', $group)) {
$group['gname'] = $group['name'];
unset($group['name']);
}
@@ -515,8 +457,8 @@ class Import extends \Zotlabs\Web\Controller {
$r = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
- if($r) {
- foreach($r as $rr) {
+ if ($r) {
+ foreach ($r as $rr) {
$saved[$rr['hash']]['new'] = $rr['id'];
}
}
@@ -524,12 +466,12 @@ class Import extends \Zotlabs\Web\Controller {
// import group members
$group_members = $data['group_member'];
- if($group_members) {
- foreach($group_members as $group_member) {
+ if ($group_members) {
+ foreach ($group_members as $group_member) {
unset($group_member['id']);
$group_member['uid'] = $channel['channel_id'];
- foreach($saved as $x) {
- if($x['old'] == $group_member['gid'])
+ foreach ($saved as $x) {
+ if ($x['old'] == $group_member['gid'])
$group_member['gid'] = $x['new'];
}
create_table_from_array('pgrp_member', $group_member);
@@ -538,65 +480,85 @@ class Import extends \Zotlabs\Web\Controller {
logger('import step 9');
- if(is_array($data['obj']))
- import_objs($channel,$data['obj']);
- if(is_array($data['likes']))
- import_likes($channel,$data['likes']);
+ if (is_array($data['obj']))
+ import_objs($channel, $data['obj']);
- if(is_array($data['app']))
- import_apps($channel,$data['app']);
+ if (is_array($data['likes']))
+ import_likes($channel, $data['likes']);
- if(is_array($data['sysapp']))
- import_sysapps($channel,$data['sysapp']);
+ if (is_array($data['app']))
+ import_apps($channel, $data['app']);
- if(is_array($data['chatroom']))
- import_chatrooms($channel,$data['chatroom']);
+ if (is_array($data['sysapp']))
+ import_sysapps($channel, $data['sysapp']);
- if(is_array($data['conv']))
- import_conv($channel,$data['conv']);
+ if (is_array($data['chatroom']))
+ import_chatrooms($channel, $data['chatroom']);
- if(is_array($data['mail']))
- import_mail($channel,$data['mail']);
+ if (is_array($data['event']))
+ import_events($channel, $data['event']);
- if(is_array($data['event']))
- import_events($channel,$data['event']);
+ if (is_array($data['event_item']))
+ import_items($channel, $data['event_item'], false, $relocate);
- if(is_array($data['event_item']))
- import_items($channel,$data['event_item'],false,$relocate);
+ if (is_array($data['menu']))
+ import_menus($channel, $data['menu']);
- if(is_array($data['menu']))
- import_menus($channel,$data['menu']);
+ if (is_array($data['wiki']))
+ import_items($channel, $data['wiki'], false, $relocate);
- if(is_array($data['wiki']))
- import_items($channel,$data['wiki'],false,$relocate);
+ if (is_array($data['webpages']))
+ import_items($channel, $data['webpages'], false, $relocate);
- if(is_array($data['webpages']))
- import_items($channel,$data['webpages'],false,$relocate);
+ $addon = ['channel' => $channel, 'data' => $data];
+ call_hooks('import_channel', $addon);
- $addon = array('channel' => $channel,'data' => $data);
- call_hooks('import_channel',$addon);
+ if ($import_posts && array_key_exists('item', $data) && $data['item']) {
+ import_items($channel, $data['item'], false, $relocate);
+ }
- $saved_notification_flags = notifications_off($channel['channel_id']);
+ // Immediately notify old server about the new clone
+ Master::Summon(['Notifier', 'refresh_all', $channel['channel_id']]);
- if($import_posts && array_key_exists('item',$data) && $data['item'])
- import_items($channel,$data['item'],false,$relocate);
+ // This will indirectly perform a refresh_all *and* update the directory
+ Master::Summon(['Directory', $channel['channel_id']]);
- notifications_on($channel['channel_id'],$saved_notification_flags);
+ $cf_api_compat = true;
- if(array_key_exists('item_id',$data) && $data['item_id'])
- import_item_ids($channel,$data['item_id']);
+ if ($api_path && $import_posts) { // we are importing from a server and not a file
+ if (version_compare($data['compatibility']['version'], '6.3.4', '>=')) {
- // This will indirectly perform a refresh_all *and* update the directory
+ $m = parse_url($api_path);
- \Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
+ $hz_server = $m['scheme'] . '://' . $m['host'];
+ $since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00');
+ $until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day');
- notice( t('Import completed.') . EOL);
+ $poll_interval = get_config('system', 'poll_interval', 3);
+ $page = 0;
+
+ Master::Summon(['Content_importer', sprintf('%d', $page), $since, $until, $channel['channel_address'], urlencode($hz_server)]);
+ Master::Summon(['File_importer', sprintf('%d', $page), $channel['channel_address'], urlencode($hz_server)]);
+ }
+ else {
+ $cf_api_compat = false;
+ }
+ }
change_channel($channel['channel_id']);
- goaway(z_root() . '/network' );
+ if ($api_path && $import_posts && $cf_api_compat) {
+ goaway(z_root() . '/import_progress');
+ }
+
+ if (!$cf_api_compat) {
+ notice(t('Automatic content and files import was not possible due to API version incompatiblity. Please import content and files manually!') . EOL);
+ }
+
+ goaway(z_root());
+
}
/**
@@ -604,7 +566,7 @@ class Import extends \Zotlabs\Web\Controller {
*/
function post() {
$account_id = get_account_id();
- if(! $account_id)
+ if (!$account_id)
return;
check_form_security_token_redirectOnErr('/import', 'channel_import');
@@ -619,33 +581,35 @@ class Import extends \Zotlabs\Web\Controller {
*/
function get() {
- if(! get_account_id()) {
- notice( t('You must be logged in to use this feature.') . EOL);
+ if (!get_account_id()) {
+ notice(t('You must be logged in to use this feature.') . EOL);
return '';
}
- $o = replace_macros(get_markup_template('channel_import.tpl'),array(
- '$title' => t('Import Channel'),
- '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
+ nav_set_selected('Channel Import');
+
+ $o = replace_macros(get_markup_template('channel_import.tpl'), [
+ '$title' => t('Channel Import'),
+ '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'),
'$label_filename' => t('File to Upload'),
- '$choice' => t('Or provide the old server/hub details'),
+ '$choice' => t('Or provide the old server/hub details'),
- '$old_address' => [ 'old_address', t('Your old identity address (xyz@example.com)'), '', ''],
- '$email' => [ 'email', t('Your old login email address'), '', '' ],
- '$password' => [ 'password', t('Your old login password'), '', '' ],
- '$import_posts' => [ 'import_posts', t('Import a few months of posts if possible (limited by available memory'), false, '', [ t('No'), t('Yes') ]],
+ '$old_address' => ['old_address', t('Your old identity address (xyz@example.com)'), '', ''],
+ '$email' => ['email', t('Your old login email address'), '', ''],
+ '$password' => ['password', t('Your old login password'), '', ''],
+ '$import_posts' => ['import_posts', t('Import your items and files (limited by available memory)'), false, '', [t('No'), t('Yes')]],
'$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'),
- '$make_primary' => [ 'make_primary', t('Make this hub my primary location'), false, '', [ t('No'), t('Yes') ] ],
- '$moving' => [ 'moving', t('Move this channel (disable all previous locations)'), false, '', [ t('No'), t('Yes') ] ],
- '$newname' => [ 'newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')],
+ '$make_primary' => ['make_primary', t('Make this hub my primary location'), false, '', [t('No'), t('Yes')]],
+ '$moving' => ['moving', t('Move this channel (disable all previous locations)'), false, '', [t('No'), t('Yes')]],
+ '$newname' => ['newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')],
'$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'),
'$form_security_token' => get_form_security_token('channel_import'),
- '$submit' => t('Submit')
- ));
+ '$submit' => t('Submit')
+ ]);
return $o;
}
diff --git a/Zotlabs/Module/Import_items.php b/Zotlabs/Module/Import_items.php
index c2b2506fe..1a1e8d061 100644
--- a/Zotlabs/Module/Import_items.php
+++ b/Zotlabs/Module/Import_items.php
@@ -1,6 +1,11 @@
<?php
+
namespace Zotlabs\Module;
+use App;
+use ZipArchive;
+use Zotlabs\Web\Controller;
+
require_once('include/import.php');
/**
@@ -8,128 +13,184 @@ require_once('include/import.php');
*
* Import existing posts and content from an export file.
*/
-class Import_items extends \Zotlabs\Web\Controller {
+class Import_items extends Controller {
function post() {
- if(! local_channel())
+ if (!local_channel())
return;
check_form_security_token_redirectOnErr('/import_items', 'import_items');
- $data = null;
+ $data = null;
$src = $_FILES['filename']['tmp_name'];
$filename = basename($_FILES['filename']['name']);
$filesize = intval($_FILES['filename']['size']);
$filetype = $_FILES['filename']['type'];
- if($src) {
+ $channel = App::get_channel();
+
+ if ($src) {
+
+ if ($filetype === 'application/zip') {
+ $zip = new ZipArchive;
+
+ $r = $zip->open($src);
+ if ($r === true) {
+ for ($i = 0; $i < $zip->count(); $i++) {
+ $data = $zip->getFromIndex($i);
+ self::import($channel, $data);
+ }
+ $zip->close();
+ unlink($src);
+ return;
+ }
+
+ notice(t('Not a zip file or zip file corrupted.') . EOL);
+ unlink($src);
+ return;
+ }
+
// This is OS specific and could also fail if your tmpdir isn't very large
// mostly used for Diaspora which exports gzipped files.
- if(strpos($filename,'.gz')){
- @rename($src,$src . '.gz');
- @system('gunzip ' . escapeshellarg($src . '.gz'));
- }
+ //if(strpos($filename,'.gz')){
+ //@rename($src,$src . '.gz');
+ //@system('gunzip ' . escapeshellarg($src . '.gz'));
+ //}
- if($filesize) {
+ if ($filesize) {
$data = @file_get_contents($src);
+ self::import($channel, $data);
}
unlink($src);
+ return;
}
+ /*
+ if(! $src) {
+
+ $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
+
+ if(! $old_address) {
+ logger('Nothing to import.');
+ notice( t('Nothing to import.') . EOL);
+ return;
+ }
+
+ $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
+ $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
+
+ $year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
+
+ $channelname = substr($old_address,0,strpos($old_address,'@'));
+ $servername = substr($old_address,strpos($old_address,'@')+1);
+
+ $scheme = 'https://';
+ $api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
+ $binary = false;
+ $redirects = 0;
+ $opts = array('http_auth' => $email . ':' . $password);
+ $url = $scheme . $servername . $api_path;
+ $ret = z_fetch_url($url, $binary, $redirects, $opts);
+ if(! $ret['success'])
+ $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
+ if($ret['success'])
+ $data = $ret['body'];
+ else
+ notice( t('Unable to download data from old server') . EOL);
+ }
+ */
- if(! $src) {
+ }
- $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : '');
- if(! $old_address) {
- logger('Nothing to import.');
- notice( t('Nothing to import.') . EOL);
- return;
- }
+ /**
+ * @brief Generate item import page.
+ *
+ * @return string with parsed HTML.
+ */
+ function get() {
- $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : '');
- $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : '');
-
- $year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : '');
-
- $channelname = substr($old_address,0,strpos($old_address,'@'));
- $servername = substr($old_address,strpos($old_address,'@')+1);
-
- $scheme = 'https://';
- $api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year);
- $binary = false;
- $redirects = 0;
- $opts = array('http_auth' => $email . ':' . $password);
- $url = $scheme . $servername . $api_path;
- $ret = z_fetch_url($url, $binary, $redirects, $opts);
- if(! $ret['success'])
- $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
- if($ret['success'])
- $data = $ret['body'];
- else
- notice( t('Unable to download data from old server') . EOL);
+ if (!local_channel()) {
+ notice(t('Permission denied') . EOL);
+ return login();
}
- if(! $data) {
+ $o = replace_macros(get_markup_template('item_import.tpl'), [
+ '$title' => t('Import Items'),
+ '$desc' => t('Use this form to import existing posts and content from an export file.'),
+ '$label_filename' => t('File to Upload'),
+ '$form_security_token' => get_form_security_token('import_items'),
+ '$submit' => t('Submit')
+ ]);
+
+ return $o;
+ }
+
+
+ public static function import($channel, $data) {
+
+ if (!$data) {
logger('Empty file.');
- notice( t('Imported file is empty.') . EOL);
+ notice(t('Imported file is empty.') . EOL);
return;
}
$data = json_decode($data, true);
-
//logger('import: data: ' . print_r($data,true));
//print_r($data);
- if(! is_array($data))
+ if (!is_array($data)) {
return;
+ }
- if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) {
- $v1 = substr($data['compatibility']['database'],-4);
- $v2 = substr(DB_UPDATE_VERSION,-4);
- if($v2 > $v1) {
- $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 );
- notice($t . EOL);
- }
+ //if (array_key_exists('compatibility', $data) && array_key_exists('database', $data['compatibility'])) {
+ //$v1 = substr($data['compatibility']['database'], -4);
+ //$v2 = substr(DB_UPDATE_VERSION, -4);
+ //if ($v2 > $v1) {
+ //$t = sprintf(t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1);
+ //notice($t . EOL);
+ //}
+ //}
+
+ if (array_key_exists('item', $data) && is_array($data['item'])) {
+ import_items($channel, $data['item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
+ info(t('Content import completed') . EOL);
}
- $channel = \App::get_channel();
+ if (array_key_exists('chatroom', $data) && is_array($data['chatroom'])) {
+ import_chatrooms($channel, $data['chatroom']);
+ info(t('Chatroom import completed') . EOL);
- if(array_key_exists('item',$data) && $data['item']) {
- import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
}
- if(array_key_exists('item_id',$data) && $data['item_id']) {
- import_item_ids($channel,$data['item_id']);
- }
+ if (array_key_exists('event', $data) && is_array($data['event'])) {
+ import_events($channel, $data['event']);
+ info(t('Channel calendar import 1/2 completed') . EOL);
- info( t('Import completed') . EOL);
- }
+ }
+ if (array_key_exists('event_item', $data) && is_array($data['event_item'])) {
+ import_items($channel, $data['event_item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
+ info(t('Channel calendar import 2/2 completed') . EOL);
+ }
- /**
- * @brief Generate item import page.
- *
- * @return string with parsed HTML.
- */
- function get() {
+ if (array_key_exists('menu', $data) && is_array($data['menu'])) {
+ import_menus($channel, $data['menu']);
+ info(t('Menu import completed') . EOL);
+ }
- if(! local_channel()) {
- notice( t('Permission denied') . EOL);
- return login();
+ if (array_key_exists('wiki', $data) && is_array($data['wiki'])) {
+ import_items($channel, $data['wiki'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
+ info(t('Wiki import completed') . EOL);
}
- $o = replace_macros(get_markup_template('item_import.tpl'), array(
- '$title' => t('Import Items'),
- '$desc' => t('Use this form to import existing posts and content from an export file.'),
- '$label_filename' => t('File to Upload'),
- '$form_security_token' => get_form_security_token('import_items'),
- '$submit' => t('Submit')
- ));
+ if (array_key_exists('webpages', $data) && is_array($data['webpages'])) {
+ import_items($channel, $data['webpages'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null));
+ info(t('Webpages import completed') . EOL);
+ }
- return $o;
}
}
diff --git a/Zotlabs/Module/Import_progress.php b/Zotlabs/Module/Import_progress.php
new file mode 100644
index 000000000..761d2f215
--- /dev/null
+++ b/Zotlabs/Module/Import_progress.php
@@ -0,0 +1,122 @@
+<?php
+namespace Zotlabs\Module;
+
+use Zotlabs\Lib\PConfig;
+use Zotlabs\Daemon\Master;
+
+class Import_progress extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ if(! local_channel())
+ return;
+
+ }
+
+ function get() {
+
+ if(! local_channel()) {
+ return;
+ }
+
+ nav_set_selected('Channel Import');
+
+ // items
+ $c = PConfig::Get(local_channel(), 'import', 'content_progress');
+
+ if ($c) {
+ $total_cpages = floor(intval($c['items_total']) / intval($c['items_page']));
+ if(!$total_cpages) {
+ $total_cpages = 1; // because of floor
+ }
+
+ $cpage = $c['last_page'] + 1; // because page count start at 0
+
+ $cprogress = intval(floor((intval($cpage) * 100) / $total_cpages));
+ $ccompleted_str = t('Item sync completed!');
+
+ if(argv(1) === 'resume_itemsync' && $cprogress < 100) {
+ Master::Summon($c['next_cmd']);
+ goaway('/import_progress');
+ }
+ }
+ else {
+ $cprogress = 'waiting to start...';
+
+ if (PConfig::Get(local_channel(), 'import', 'content_completed')) {
+ // There was nothing todo. Fake 100% and mention that there were no files found
+ $cprogress = 100;
+ }
+
+ $ccompleted_str = t('Item sync completed but no items were found!');
+
+ if(argv(1) === 'resume_itemsync') {
+ Master::Summon(["Content_importer","0","0001-01-01 00:00:00","2021-10-02 19:49:14","ct5","https%3A%2F%2Fhub.somaton.com"]);
+ goaway('/import_progress');
+ }
+ }
+
+ $cprogress_str = ((intval($cprogress)) ? $cprogress . '%' : $cprogress);
+
+ // files
+ $f = PConfig::Get(local_channel(), 'import', 'files_progress');
+
+ if ($f) {
+ $total_fpages = floor(intval($f['files_total']) / intval($f['files_page']));
+ if(!$total_fpages) {
+ $total_fpages = 1;
+ }
+
+ $fpage = $f['last_page'] + 1;
+
+ $fprogress = intval(floor((intval($fpage) * 100) / $total_fpages));
+ $fcompleted_str = t('File sync completed!');
+
+ if(argv(1) === 'resume_filesync' && $fprogress < 100) {
+ Master::Summon($f['next_cmd']);
+ goaway('/import_progress');
+ }
+
+
+ }
+ else {
+ $fprogress = 'waiting to start...';
+
+ if (PConfig::Get(local_channel(), 'import', 'files_completed')) {
+ // There was nothing todo. Fake 100% and mention that there were no files found
+ $fprogress = 100;
+ }
+
+ $fcompleted_str = t('File sync completed but no files were found!');
+ }
+
+ $fprogress_str = ((intval($fprogress)) ? $fprogress . '%' : $fprogress);
+
+ if(is_ajax()) {
+ $ret = [
+ 'cprogress' => $cprogress,
+ 'fprogress' => $fprogress
+ ];
+
+ json_return_and_die($ret);
+ }
+
+ $o = replace_macros(get_markup_template("import_progress.tpl"), [
+ '$chtitle_str' => t('Channel clone status'),
+ '$ctitle_str' => t('Item sync status'),
+ '$ftitle_str' => t('File sync status'),
+ '$cprogress_str' => $cprogress_str,
+ '$cprogress' => intval($cprogress),
+ '$fprogress_str' => $fprogress_str,
+ '$fprogress' => intval($fprogress),
+ '$fcompleted_str' => $fcompleted_str,
+ '$ccompleted_str' => $ccompleted_str,
+ '$chcompleted_str' => t('Channel cloning completed!'),
+ '$resume_str' => t('Resume'),
+ '$resume_helper_str' => t('Only resume if sync stalled!')
+ ]);
+
+ return $o;
+ }
+
+}
diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php
index 34f1858fd..2a126ac27 100644
--- a/Zotlabs/Module/Invite.php
+++ b/Zotlabs/Module/Invite.php
@@ -129,11 +129,11 @@ class Invite extends Controller {
if(! $recip) continue;
// see if we have an email address who@domain.tld
- if (!preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $recip)) {
- $feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol;
- $ko++;
- continue;
- }
+ //if (!preg_match('/^.{2,64}\@[a-z0-9.-]{2,32}\.[a-z]{2,12}$/', $recip)) {
+ //$feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol;
+ //$ko++;
+ //continue;
+ //}
if(! validate_email($recip)) {
$feedbk .= 'ZAI0204E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a real email address'), $recip) . $eol;
$ko++;
@@ -225,7 +225,7 @@ class Invite extends Controller {
'$projectname' => t('$Projectname'),
'$invite_code' => $invite_code,
'$invite_where' => z_root() . '/register',
- '$invite_whereami' => str_replace('@', '@+', $reonar['whereami']),
+ '$invite_whereami' => $reonar['whereami'],
'$invite_whoami' => z_root() . '/channel/' . $reonar['whoami'],
'$invite_anywhere' => z_root() . '/pubsites'
)
@@ -306,9 +306,8 @@ class Invite extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Invite')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = 'ZAI0102E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL;
- return $o;
+ $papp = Apps::get_papp('Invite');
+ return Apps::app_render($papp, 'module');
}
if (! (get_config('system','invitation_also') || get_config('system','invitation_only')) ) {
@@ -423,8 +422,6 @@ class Invite extends Controller {
// let take one descriptive for template (as said is never used)
$invite_code = 'INVITATE2020';
- // what languages we use now
- $lccmy = ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en');
// and all the localized templates belonging to invite
$tpls = glob('view/*/invite.*.tpl');
@@ -445,6 +442,9 @@ class Invite extends Controller {
$langs = array_keys($tpla);
asort($langs);
+ // Use the current language if we have a template for it. Otherwise fall back to 'en'.
+ $lccmy = ((in_array(App::$language, $langs)) ? App::$language : 'en');
+
$tplx = array_unique($tplx);
asort($tplx);
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 73a943039..574a90c1a 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Module;
+use App;
+use URLify;
use Zotlabs\Lib\Config;
use Zotlabs\Lib\IConfig;
use Zotlabs\Lib\Enotify;
@@ -15,7 +17,6 @@ use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\ThreadListener;
use Zotlabs\Access\PermissionRoles;
-use App;
require_once('include/crypto.php');
require_once('include/items.php');
@@ -37,8 +38,6 @@ require_once('include/conversation.php');
* posting categories go through item_store() instead of this function.
*
*/
-
-
class Item extends Controller {
@@ -46,11 +45,9 @@ class Item extends Controller {
if (Libzot::is_zot_request()) {
- $conversation = false;
-
$item_id = argv(1);
- if(! $item_id)
+ if (!$item_id)
http_status_exit(404, 'Not found');
$portable_id = EMPTY_STR;
@@ -70,8 +67,8 @@ class Item extends Controller {
dbesc(z_root() . '/item/' . $item_id)
);
- if (! $r) {
- http_status_exit(404,'Not found');
+ if (!$r) {
+ http_status_exit(404, 'Not found');
}
// process an authenticated fetch
@@ -79,10 +76,10 @@ class Item extends Controller {
$sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
- if (! check_channelallowed($portable_id)) {
+ if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
- if (! check_siteallowed($sigdata['signer'])) {
+ if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
@@ -92,8 +89,8 @@ class Item extends Controller {
dbesc($portable_id)
);
}
- elseif (Config::get('system','require_authenticated_fetch',false)) {
- http_status_exit(403,'Permission denied');
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
}
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
@@ -101,47 +98,47 @@ class Item extends Controller {
$sql_extra = item_permissions_sql(0);
- if (! $i) {
+ if (!$i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid'])
);
}
- if(! $i) {
- http_status_exit(403,'Forbidden');
+ if (!$i) {
+ http_status_exit(403, 'Forbidden');
}
- $parents_str = ids_to_querystr($i,'item_id');
+ $parents_str = ids_to_querystr($i, 'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal order by item.id asc",
dbesc($parents_str)
);
- if(! $items) {
+ if (!$items) {
http_status_exit(404, 'Not found');
}
- xchan_query($items,true);
- $items = fetch_post_tags($items,true);
+ xchan_query($items, true);
+ $items = fetch_post_tags($items, true);
- if(! $items)
+ if (!$items)
http_status_exit(404, 'Not found');
$chan = channelx_by_n($items[0]['uid']);
- if(! $chan)
+ if (!$chan)
http_status_exit(404, 'Not found');
- if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
http_status_exit(403, 'Forbidden');
$i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection');
- if(! $i)
+ if (!$i)
http_status_exit(404, 'Not found');
- if($portable_id && (! intval($items[0]['item_private']))) {
+ if ($portable_id && (!intval($items[0]['item_private']))) {
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
}
@@ -149,25 +146,25 @@ class Item extends Controller {
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
- ]], $i);
+ ]], $i);
- $headers = [];
- $headers['Content-Type'] = 'application/x-zot+json' ;
- $x['signature'] = LDSignatures::sign($x,$chan);
- $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
- $headers['Digest'] = HTTPSig::generate_digest_header($ret);
+ $headers = [];
+ $headers['Content-Type'] = 'application/x-zot+json';
+ $x['signature'] = LDSignatures::sign($x, $chan);
+ $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
+ $headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
- $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
+ $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
HTTPSig::set_headers($h);
echo $ret;
killme();
}
- if(ActivityStreams::is_as_request()) {
+ if (ActivityStreams::is_as_request()) {
$item_id = argv(1);
- if(! $item_id)
+ if (!$item_id)
http_status_exit(404, 'Not found');
$portable_id = EMPTY_STR;
@@ -189,8 +186,8 @@ class Item extends Controller {
dbesc($item_id)
);
- if (! $r) {
- http_status_exit(404,'Not found');
+ if (!$r) {
+ http_status_exit(404, 'Not found');
}
// process an authenticated fetch
@@ -198,10 +195,10 @@ class Item extends Controller {
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
- if (! check_channelallowed($portable_id)) {
+ if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
- if (! check_siteallowed($sigdata['signer'])) {
+ if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
@@ -211,8 +208,8 @@ class Item extends Controller {
dbesc($portable_id)
);
}
- elseif (Config::get('system','require_authenticated_fetch',false)) {
- http_status_exit(403,'Permission denied');
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
}
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
@@ -220,40 +217,40 @@ class Item extends Controller {
$sql_extra = item_permissions_sql(0);
- if (! $i) {
+ if (!$i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid'])
);
}
- if(! $i) {
- http_status_exit(403,'Forbidden');
+ if (!$i) {
+ http_status_exit(403, 'Forbidden');
}
// If we get to this point we have determined we can access the original in $r (fetched much further above), so use it.
- xchan_query($r,true);
- $items = fetch_post_tags($r,false);
+ xchan_query($r, true);
+ $items = fetch_post_tags($r, false);
$chan = channelx_by_n($items[0]['uid']);
- if(! $chan)
+ if (!$chan)
http_status_exit(404, 'Not found');
- if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
http_status_exit(403, 'Forbidden');
- $i = Activity::encode_item($items[0],true);
+ $i = Activity::encode_item($items[0]);
- if(! $i)
+ if (!$i)
http_status_exit(404, 'Not found');
- if ($portable_id && (! intval($items[0]['item_private']))) {
+ if ($portable_id && (!intval($items[0]['item_private']))) {
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($items[0]['uid']),
dbesc($portable_id)
);
- if (! $c) {
+ if (!$c) {
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
}
}
@@ -262,16 +259,16 @@ class Item extends Controller {
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
- ]], $i);
-
- $headers = [];
- $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
- $x['signature'] = LDSignatures::sign($x,$chan);
- $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
- $headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
- $headers['Digest'] = HTTPSig::generate_digest_header($ret);
+ ]], $i);
+
+ $headers = [];
+ $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
+ $x['signature'] = LDSignatures::sign($x, $chan);
+ $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
+ $headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
+ $headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
- $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
+ $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
HTTPSig::set_headers($h);
echo $ret;
killme();
@@ -279,17 +276,18 @@ class Item extends Controller {
}
- if(argc() > 1 && argv(1) !== 'drop') {
- $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ",
+ if (argc() > 1 && argv(1) !== 'drop') {
+ $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
dbesc(z_root() . '/item/' . argv(1)),
- dbesc(z_root() . '/activity/' . argv(1))
+ dbesc(z_root() . '/activity/' . argv(1)),
+ dbesc(argv(1))
);
- if($x) {
- foreach($x as $xv) {
+ if ($x) {
+ foreach ($x as $xv) {
if (intval($xv['item_wall'])) {
$c = channelx_by_n($xv['uid']);
if ($c) {
- goaway($c['xchan_url'] . '?mid=' . gen_link_id($xv['mid']));
+ goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . gen_link_id($xv['mid']));
}
}
}
@@ -301,17 +299,16 @@ class Item extends Controller {
}
-
function post() {
// This will change. Figure out who the observer is and whether or not
// they have permission to post here. Else ignore the post.
- if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname')))
+ if ((!local_channel()) && (!remote_channel()) && (!x($_REQUEST, 'anonname')))
return;
- $uid = local_channel();
- $channel = null;
+ $uid = local_channel();
+ $channel = null;
$observer = null;
$datarray = [];
@@ -320,34 +317,34 @@ class Item extends Controller {
* Is this a reply to something?
*/
- $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
- $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
- $mode = (($_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network');
+ $parent = ((x($_REQUEST, 'parent')) ? intval($_REQUEST['parent']) : 0);
+ $parent_mid = ((x($_REQUEST, 'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
+ $mode = (($_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network');
- $remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ $remote_xchan = ((x($_REQUEST, 'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($remote_xchan)
);
- if($r)
+ if ($r)
$remote_observer = $r[0];
else
$remote_xchan = $remote_observer = false;
- $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
+ $profile_uid = ((x($_REQUEST, 'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
require_once('include/channel.php');
$sys = get_sys_channel();
- if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
- $uid = intval($sys['channel_id']);
- $channel = $sys;
+ if ($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
+ $uid = intval($sys['channel_id']);
+ $channel = $sys;
$observer = $sys;
}
- if(x($_REQUEST,'dropitems')) {
+ if (x($_REQUEST, 'dropitems')) {
require_once('include/items.php');
- $arr_drop = explode(',',$_REQUEST['dropitems']);
+ $arr_drop = explode(',', $_REQUEST['dropitems']);
drop_items($arr_drop);
- $json = array('success' => 1);
+ $json = ['success' => 1];
echo json_encode($json);
killme();
}
@@ -356,12 +353,12 @@ class Item extends Controller {
// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
- $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
+ $api_source = ((x($_REQUEST, 'api_source') && $_REQUEST['api_source']) ? true : false);
$consensus = intval($_REQUEST['consensus']);
$nocomment = intval($_REQUEST['nocomment']);
- $is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false);
+ $is_poll = ((trim((string)$_REQUEST['poll_answers'][0]) != '' && trim((string)$_REQUEST['poll_answers'][1]) != '') ? true : false);
// 'origin' (if non-zero) indicates that this network is where the message originated,
// for the purpose of relaying comments to other conversation members.
@@ -372,77 +369,75 @@ class Item extends Controller {
// If you are unsure, it is prudent (and important) to leave it unset.
- $origin = (($api_source && array_key_exists('origin',$_REQUEST)) ? intval($_REQUEST['origin']) : 1);
+ $origin = (($api_source && array_key_exists('origin', $_REQUEST)) ? intval($_REQUEST['origin']) : 1);
// To represent message-ids on other networks - this will create an iconfig record
- $namespace = (($api_source && array_key_exists('namespace',$_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
- $remote_id = (($api_source && array_key_exists('remote_id',$_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
+ $namespace = (($api_source && array_key_exists('namespace', $_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
+ $remote_id = (($api_source && array_key_exists('remote_id', $_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
$owner_hash = null;
- $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
- $created = ((x($_REQUEST,'created')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['created']) : datetime_convert());
- $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0);
- $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : '');
- $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
- $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
- $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : '');
- $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0);
- $item_obscured = ((x($_REQUEST,'obscured')) ? intval($_REQUEST['obscured']) : 0);
- $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
- $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): '');
- $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
- $obj_type = ((x($_REQUEST,'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
+ $message_id = ((x($_REQUEST, 'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
+ $created = ((x($_REQUEST, 'created')) ? datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['created']) : datetime_convert());
+ $post_id = ((x($_REQUEST, 'post_id')) ? intval($_REQUEST['post_id']) : 0);
+ $app = ((x($_REQUEST, 'source')) ? strip_tags($_REQUEST['source']) : '');
+ $return_path = ((x($_REQUEST, 'return')) ? $_REQUEST['return'] : '');
+ $preview = ((x($_REQUEST, 'preview')) ? intval($_REQUEST['preview']) : 0);
+ $categories = ((x($_REQUEST, 'category')) ? escape_tags($_REQUEST['category']) : '');
+ $webpage = ((x($_REQUEST, 'webpage')) ? intval($_REQUEST['webpage']) : 0);
+ $item_obscured = ((x($_REQUEST, 'obscured')) ? intval($_REQUEST['obscured']) : 0);
+ $pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '');
+ $layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
+ $plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
+ $obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
// allow API to bulk load a bunch of imported items with sending out a bunch of posts.
- $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0);
+ $nopush = ((x($_REQUEST, 'nopush')) ? intval($_REQUEST['nopush']) : 0);
/*
* Check service class limits
*/
- if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) {
- $ret = $this->item_check_service_class($uid,(($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
+ if ($uid && !(x($_REQUEST, 'parent')) && !(x($_REQUEST, 'post_id'))) {
+ $ret = $this->item_check_service_class($uid, (($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
if (!$ret['success']) {
- notice( t($ret['message']) . EOL) ;
- if($api_source)
- return ( [ 'success' => false, 'message' => 'service class exception' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ notice(t($ret['message']) . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'service class exception']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
}
- if($pagetitle) {
- require_once('library/urlify/URLify.php');
- $pagetitle = strtolower(\URLify::transliterate($pagetitle));
+ if ($pagetitle) {
+ $pagetitle = strtolower(URLify::transliterate($pagetitle));
}
- $item_flags = $item_restrict = 0;
$expires = NULL_DATE;
+ $comments_closed = NULL_DATE;
- $route = '';
- $parent_item = null;
+ $route = '';
+ $parent_item = null;
$parent_contact = null;
- $thr_parent = '';
- $parid = 0;
- $r = false;
+ $thr_parent = '';
+ $r = false;
- if($parent || $parent_mid) {
+ if ($parent || $parent_mid) {
- if(! x($_REQUEST,'type'))
+ if (!x($_REQUEST, 'type'))
$_REQUEST['type'] = 'net-comment';
- if($obj_type == ACTIVITY_OBJ_NOTE)
+ if ($obj_type == ACTIVITY_OBJ_NOTE)
$obj_type = ACTIVITY_OBJ_COMMENT;
- if($parent) {
+ if ($parent) {
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
intval($parent)
);
}
- elseif($parent_mid && $uid) {
+ elseif ($parent_mid && $uid) {
// This is coming from an API source, and we are logged in
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
dbesc($parent_mid),
@@ -450,10 +445,10 @@ class Item extends Controller {
);
}
// if this isn't the real parent of the conversation, find it
- if($r) {
- $parid = $r[0]['parent'];
+ if ($r) {
+ $parid = $r[0]['parent'];
$parent_mid = $r[0]['mid'];
- if($r[0]['id'] != $r[0]['parent']) {
+ if ($r[0]['id'] != $r[0]['parent']) {
$r = q("SELECT * FROM item WHERE id = parent AND parent = %d LIMIT 1",
intval($parid)
);
@@ -462,24 +457,24 @@ class Item extends Controller {
// if interacting with a pubstream item,
// create a copy of the parent in your stream
- if($r[0]['uid'] === $sys['channel_id'] && local_channel()) {
- $r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ];
+ if ($r[0]['uid'] === $sys['channel_id'] && local_channel()) {
+ $r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
}
}
- if(! $r) {
- notice( t('Unable to locate original post.') . EOL);
- if($api_source)
- return ( [ 'success' => false, 'message' => 'invalid post id' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ if (!$r) {
+ notice(t('Unable to locate original post.') . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'invalid post id']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
- xchan_query($r,true);
+ xchan_query($r, true);
$parent_item = $r[0];
- $parent = $r[0]['id'];
+ $parent = $r[0]['id'];
// multi-level threading - preserve the info but re-parent to our single level threading
@@ -491,52 +486,52 @@ class Item extends Controller {
$moderated = false;
- if(! $observer) {
- $observer = \App::get_observer();
- if(! $observer) {
+ if (!$observer) {
+ $observer = App::get_observer();
+ if (!$observer) {
$observer = anon_identity_init($_REQUEST);
- if($observer) {
- $moderated = true;
+ if ($observer) {
+ $moderated = true;
$remote_xchan = $remote_observer = $observer;
}
}
}
- if(! $observer) {
- notice( t('Permission denied.') . EOL) ;
- if($api_source)
- return ( [ 'success' => false, 'message' => 'permission denied' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ if (!$observer) {
+ notice(t('Permission denied.') . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'permission denied']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
- if($parent) {
+ if ($parent) {
logger('mod_item: item_post parent=' . $parent);
$can_comment = false;
- $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item);
- if (!$can_comment) {
- if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])==1 )
- $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments');
- }
-
- if(! $can_comment) {
- notice( t('Permission denied.') . EOL) ;
- if($api_source)
- return ( [ 'success' => false, 'message' => 'permission denied' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ $can_comment = can_comment_on_post($observer['xchan_hash'], $parent_item);
+ if (!$can_comment) {
+ if ((array_key_exists('owner', $parent_item)) && intval($parent_item['owner']['abook_self']) == 1)
+ $can_comment = perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_comments');
+ }
+
+ if (!$can_comment) {
+ notice(t('Permission denied.') . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'permission denied']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
}
else {
- if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) {
- notice( t('Permission denied.') . EOL) ;
- if($api_source)
- return ( [ 'success' => false, 'message' => 'permission denied' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], ($webpage) ? 'write_pages' : 'post_wall')) {
+ notice(t('Permission denied.') . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'permission denied']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
}
@@ -546,53 +541,53 @@ class Item extends Controller {
$orig_post = null;
- if($namespace && $remote_id) {
+ if ($namespace && $remote_id) {
// It wasn't an internally generated post - see if we've got an item matching this remote service id
$i = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1",
dbesc($namespace),
dbesc($remote_id)
);
- if($i)
+ if ($i)
$post_id = $i[0]['iid'];
}
$iconfig = null;
- if($post_id) {
+ if ($post_id) {
$i = q("SELECT * FROM item WHERE uid = %d AND id = %d LIMIT 1",
intval($profile_uid),
intval($post_id)
);
- if(! count($i))
+ if (!count($i))
killme();
$orig_post = $i[0];
- $iconfig = q("select * from iconfig where iid = %d",
+ $iconfig = q("select * from iconfig where iid = %d",
intval($post_id)
);
}
- if(! $channel) {
- if($uid && $uid == $profile_uid) {
- $channel = \App::get_channel();
+ if (!$channel) {
+ if ($uid && $uid == $profile_uid) {
+ $channel = App::get_channel();
}
else {
// posting as yourself but not necessarily to a channel you control
$r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1",
intval($profile_uid)
);
- if($r)
+ if ($r)
$channel = $r[0];
}
}
- if(! $channel) {
+ if (!$channel) {
logger("mod_item: no channel.");
- if($api_source)
- return ( [ 'success' => false, 'message' => 'no channel' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ if ($api_source)
+ return (['success' => false, 'message' => 'no channel']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
@@ -601,37 +596,37 @@ class Item extends Controller {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($channel['channel_hash'])
);
- if($r && count($r)) {
+ if ($r && count($r)) {
$owner_xchan = $r[0];
}
else {
logger("mod_item: no owner.");
- if($api_source)
- return ( [ 'success' => false, 'message' => 'no owner' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ if ($api_source)
+ return (['success' => false, 'message' => 'no owner']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
- $walltowall = false;
+ $walltowall = false;
$walltowall_comment = false;
- if($remote_xchan && ! $moderated)
+ if ($remote_xchan && !$moderated)
$observer = $remote_observer;
- if($observer) {
+ if ($observer) {
logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG);
// wall-to-wall detection.
// For top-level posts, if the author and owner are different it's a wall-to-wall
// For comments, We need to additionally look at the parent and see if it's a wall post that originated locally.
- if($observer['xchan_name'] != $owner_xchan['xchan_name']) {
- if(($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) {
+ if ($observer['xchan_name'] != $owner_xchan['xchan_name']) {
+ if (($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) {
$walltowall_comment = true;
- $walltowall = true;
+ $walltowall = true;
}
- if(! $parent) {
+ if (!$parent) {
$walltowall = true;
}
}
@@ -639,83 +634,80 @@ class Item extends Controller {
$acl = new \Zotlabs\Access\AccessList($channel);
- $view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream');
- $comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments');
+ $view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream');
+ $comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'post_comments');
- $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy,true));
- if($webpage)
+ $public_policy = ((x($_REQUEST, 'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy, true));
+ if ($webpage)
$public_policy = '';
- if($public_policy)
+ if ($public_policy)
$private = 1;
- if($orig_post) {
+ if ($orig_post) {
$private = 0;
// webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
- if($webpage) {
+ if ($webpage) {
$acl->set_from_array($_REQUEST);
}
else {
$acl->set($orig_post);
- $public_policy = $orig_post['public_policy'];
- $private = $orig_post['item_private'];
+ $public_policy = $orig_post['public_policy'];
+ $private = $orig_post['item_private'];
}
- if($public_policy || $acl->is_private()) {
+ if ($public_policy || $acl->is_private()) {
$private = (($private) ? $private : 1);
}
- $location = $orig_post['location'];
- $coord = $orig_post['coord'];
- $verb = $orig_post['verb'];
- $app = $orig_post['app'];
- $title = escape_tags(trim($_REQUEST['title']));
- $summary = trim($_REQUEST['summary']);
- $body = trim($_REQUEST['body']);
- $item_flags = $orig_post['item_flags'];
-
- $item_origin = $orig_post['item_origin'];
- $item_unseen = $orig_post['item_unseen'];
- $item_starred = $orig_post['item_starred'];
- $item_uplink = $orig_post['item_uplink'];
- $item_consensus = $orig_post['item_consensus'];
- $item_wall = $orig_post['item_wall'];
- $item_thread_top = $orig_post['item_thread_top'];
- $item_notshown = $orig_post['item_notshown'];
- $item_nsfw = $orig_post['item_nsfw'];
- $item_relay = $orig_post['item_relay'];
- $item_mentionsme = $orig_post['item_mentionsme'];
- $item_nocomment = $orig_post['item_nocomment'];
- $item_obscured = $orig_post['item_obscured'];
- $item_verified = $orig_post['item_verified'];
- $item_retained = $orig_post['item_retained'];
- $item_rss = $orig_post['item_rss'];
- $item_deleted = $orig_post['item_deleted'];
- $item_type = $orig_post['item_type'];
- $item_hidden = $orig_post['item_hidden'];
- $item_unpublished = $orig_post['item_unpublished'];
- $item_delayed = $orig_post['item_delayed'];
- $item_pending_remove = $orig_post['item_pending_remove'];
- $item_blocked = $orig_post['item_blocked'];
-
-
-
- $postopts = $orig_post['postopts'];
- $created = $orig_post['created'];
- $expires = $orig_post['expires'];
- $mid = $orig_post['mid'];
- $parent_mid = $orig_post['parent_mid'];
- $plink = $orig_post['plink'];
-
+ $location = $orig_post['location'];
+ $coord = $orig_post['coord'];
+ $verb = $orig_post['verb'];
+ $app = $orig_post['app'];
+ $title = escape_tags(trim($_REQUEST['title']));
+ $summary = trim($_REQUEST['summary']);
+ $body = trim($_REQUEST['body']);
+ $item_flags = $orig_post['item_flags'];
+ $item_origin = $orig_post['item_origin'];
+ $item_unseen = $orig_post['item_unseen'];
+ $item_starred = $orig_post['item_starred'];
+ $item_uplink = $orig_post['item_uplink'];
+ $item_consensus = $orig_post['item_consensus'];
+ $item_wall = $orig_post['item_wall'];
+ $item_thread_top = $orig_post['item_thread_top'];
+ $item_notshown = $orig_post['item_notshown'];
+ $item_nsfw = $orig_post['item_nsfw'];
+ $item_relay = $orig_post['item_relay'];
+ $item_mentionsme = $orig_post['item_mentionsme'];
+ $item_nocomment = $orig_post['item_nocomment'];
+ $item_obscured = $orig_post['item_obscured'];
+ $item_verified = $orig_post['item_verified'];
+ $item_retained = $orig_post['item_retained'];
+ $item_rss = $orig_post['item_rss'];
+ $item_deleted = $orig_post['item_deleted'];
+ $item_type = $orig_post['item_type'];
+ $item_hidden = $orig_post['item_hidden'];
+ $item_unpublished = $orig_post['item_unpublished'];
+ $item_delayed = $orig_post['item_delayed'];
+ $item_pending_remove = $orig_post['item_pending_remove'];
+ $item_blocked = $orig_post['item_blocked'];
+ $postopts = $orig_post['postopts'];
+ $created = $orig_post['created'];
+ $expires = $orig_post['expires'];
+ $comments_closed = $orig_post['comments_closed'];
+ $mid = $orig_post['mid'];
+ $thr_parent = $orig_post['thr_parent'];
+ $parent_mid = $orig_post['parent_mid'];
+ $plink = $orig_post['plink'];
}
else {
- if(! $walltowall) {
- if((array_key_exists('contact_allow',$_REQUEST))
- || (array_key_exists('group_allow',$_REQUEST))
- || (array_key_exists('contact_deny',$_REQUEST))
- || (array_key_exists('group_deny',$_REQUEST))) {
+ if (!$walltowall) {
+ if ((array_key_exists('contact_allow', $_REQUEST))
+ || (array_key_exists('group_allow', $_REQUEST))
+ || (array_key_exists('contact_deny', $_REQUEST))
+ || (array_key_exists('group_deny', $_REQUEST))) {
$acl->set_from_array($_REQUEST);
}
- elseif(! $api_source) {
+ elseif (!$api_source) {
// if no ACL has been defined and we aren't using the API, the form
// didn't send us any parameters. This means there's no ACL or it has
@@ -723,27 +715,27 @@ class Item extends Controller {
// If $api_source is set and there are no ACL parameters, we default
// to the channel permissions which were set in the ACL contructor.
- $acl->set(array('allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
+ $acl->set(['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']);
}
}
- $location = notags(trim($_REQUEST['location']));
- $coord = notags(trim($_REQUEST['coord']));
- $verb = notags(trim($_REQUEST['verb']));
- $title = escape_tags(trim($_REQUEST['title']));
- $summary = trim($_REQUEST['summary']);
- $body = trim($_REQUEST['body']);
- $body .= trim($_REQUEST['attachment']);
- $postopts = '';
+ $location = notags(trim((string)$_REQUEST['location']));
+ $coord = notags(trim((string)$_REQUEST['coord']));
+ $verb = notags(trim((string)$_REQUEST['verb']));
+ $title = escape_tags(trim((string)$_REQUEST['title']));
+ $summary = trim((string)$_REQUEST['summary']);
+ $body = trim((string)$_REQUEST['body']);
+ $body .= trim((string)$_REQUEST['attachment']);
+ $postopts = '';
- $allow_empty = ((array_key_exists('allow_empty',$_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
+ $allow_empty = ((array_key_exists('allow_empty', $_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
$private = (($private) ? $private : intval($acl->is_private() || ($public_policy)));
// If this is a comment, set the permissions from the parent.
- if($parent_item) {
+ if ($parent_item) {
$acl->set($parent_item);
$private = intval($parent_item['item_private']);
$public_policy = $parent_item['public_policy'];
@@ -751,51 +743,50 @@ class Item extends Controller {
$webpage = $parent_item['item_type'];
}
- if((! $allow_empty) && (! strlen($body))) {
- if($preview)
+ if ((!$allow_empty) && (!strlen($body))) {
+ if ($preview)
killme();
- info( t('Empty post discarded.') . EOL );
- if($api_source)
- return ( [ 'success' => false, 'message' => 'no content' ] );
- if(x($_REQUEST,'return'))
- goaway(z_root() . "/" . $return_path );
+ info(t('Empty post discarded.') . EOL);
+ if ($api_source)
+ return (['success' => false, 'message' => 'no content']);
+ if (x($_REQUEST, 'return'))
+ goaway(z_root() . "/" . $return_path);
killme();
}
}
-
- if(feature_enabled($profile_uid,'content_expire')) {
- if(x($_REQUEST,'expire')) {
- $expires = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expire']);
- if($expires <= datetime_convert())
+ if (feature_enabled($profile_uid, 'content_expire')) {
+ if (x($_REQUEST, 'expire')) {
+ $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expire']);
+ if ($expires <= datetime_convert())
$expires = NULL_DATE;
}
}
- $mimetype = notags(trim($_REQUEST['mimetype']));
- if(! $mimetype)
+ $mimetype = notags(trim((string)$_REQUEST['mimetype']));
+ if (!$mimetype)
$mimetype = 'text/bbcode';
$execflag = ((intval($uid) == intval($profile_uid)
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
- if($preview) {
- $summary = z_input_filter($summary,$mimetype,$execflag);
- $body = z_input_filter($body,$mimetype,$execflag);
+ if ($preview) {
+ $summary = z_input_filter($summary, $mimetype, $execflag);
+ $body = z_input_filter($body, $mimetype, $execflag);
}
- $arr = [ 'profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype ];
- call_hooks('post_content',$arr);
- $summary = $arr['summary'];
- $body = $arr['content'];
+ $arr = ['profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype];
+ call_hooks('post_content', $arr);
+ $summary = $arr['summary'];
+ $body = $arr['content'];
$mimetype = $arr['mimetype'];
- $gacl = $acl->get();
+ $gacl = $acl->get();
$str_contact_allow = $gacl['allow_cid'];
$str_group_allow = $gacl['allow_gid'];
$str_contact_deny = $gacl['deny_cid'];
@@ -806,23 +797,18 @@ class Item extends Controller {
// if this is a wall-to-wall post to a group, turn it into a direct message
- $role = get_pconfig($profile_uid,'system','permissions_role');
-
- $rolesettings = PermissionRoles::role_perms($role);
-
- $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
-
- $is_group = (($channel_type === 'group') ? true : false);
+ $is_group = get_pconfig($profile_uid, 'system', 'group_actor');
- if (($is_group) && ($walltowall) && (! $walltowall_comment)) {
- $groupww = true;
+ if (($is_group) && ($walltowall) && (!$walltowall_comment)) {
+ $groupww = true;
$str_contact_allow = $owner_xchan['xchan_hash'];
- $str_group_allow = '';
+ $str_group_allow = '';
}
$post_tags = [];
- if($mimetype === 'text/bbcode') {
+
+ if ($mimetype === 'text/bbcode') {
require_once('include/text.php');
@@ -837,27 +823,27 @@ class Item extends Controller {
$results = linkify_tags($body, ($uid) ? $uid : $profile_uid);
- if($results) {
+ if ($results) {
// Set permissions based on tag replacements
set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
- foreach($results as $result) {
+ foreach ($results as $result) {
$success = $result['success'];
- if($success['replaced']) {
- $post_tags[] = array(
+ if ($success['replaced']) {
+ $post_tags[] = [
'uid' => $profile_uid,
'ttype' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $success['term'],
'url' => $success['url']
- );
+ ];
}
}
}
- if(($str_contact_allow) && (! $str_group_allow)) {
+ if (($str_contact_allow) && (!$str_group_allow)) {
// direct message - private between individual channels but not groups
$private = 2;
}
@@ -882,45 +868,45 @@ class Item extends Controller {
*
*/
- if(! $preview) {
- fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
- fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($summary,'[/crypt]')) ? $_POST['media_str'] : $summary),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
- fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+ if (!$preview) {
+ fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
+ fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($summary, '[/crypt]')) ? $_POST['media_str'] : $summary), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
+ fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
}
$attachments = '';
- $match = false;
+ $match = false;
- if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
- $attachments = array();
- $i = 0;
- foreach($match[2] as $mtch) {
+ if (preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/', $body, $match)) {
+ $attachments = [];
+ $i = 0;
+ foreach ($match[2] as $mtch) {
$attach_link = '';
- $hash = substr($mtch,0,strpos($mtch,','));
- $rev = intval(substr($mtch,strpos($mtch,',')));
- $r = attach_by_hash_nodata($hash, $observer['xchan_hash'], $rev);
- if($r['success']) {
- $attachments[] = array(
+ $hash = substr($mtch, 0, strpos($mtch, ','));
+ $rev = intval(substr($mtch, strpos($mtch, ',')));
+ $r = attach_by_hash_nodata($hash, $observer['xchan_hash'], $rev);
+ if ($r['success']) {
+ $attachments[] = [
'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 = str_replace($match[1][$i],$attach_link,$body);
+ $body = str_replace($match[1][$i], $attach_link, $body);
$i++;
}
}
- if(preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/',$body,$match)) {
+ if (preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/', $body, $match)) {
// process share by id
$i = 0;
- foreach($match[2] as $mtch) {
+ foreach ($match[2] as $mtch) {
$reshare = new \Zotlabs\Lib\Share($mtch);
- $body = str_replace($match[1][$i],$reshare->bbcode(),$body);
+ $body = str_replace($match[1][$i], $reshare->bbcode(), $body);
$i++;
}
}
@@ -928,32 +914,32 @@ class Item extends Controller {
// BBCODE end alert
}
- if(strlen($categories)) {
+ if (strlen($categories)) {
- $cats = explode(',',$categories);
- foreach($cats as $cat) {
+ $cats = explode(',', $categories);
+ foreach ($cats as $cat) {
- if($webpage == ITEM_TYPE_CARD) {
+ if ($webpage == ITEM_TYPE_CARD) {
$catlink = z_root() . '/cards/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
}
- elseif($webpage == ITEM_TYPE_ARTICLE) {
+ elseif ($webpage == ITEM_TYPE_ARTICLE) {
$catlink = z_root() . '/articles/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
}
else {
$catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat));
}
- $post_tags[] = array(
+ $post_tags[] = [
'uid' => $profile_uid,
'ttype' => TERM_CATEGORY,
'otype' => TERM_OBJ_POST,
'term' => trim($cat),
'url' => $catlink
- );
+ ];
}
}
- if($orig_post) {
+ if ($orig_post) {
// preserve original tags
$t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )",
intval($orig_post['id']),
@@ -963,120 +949,133 @@ class Item extends Controller {
intval(TERM_FILE),
intval(TERM_COMMUNITYTAG)
);
- if($t) {
- foreach($t as $t1) {
- $post_tags[] = array(
+ if ($t) {
+ foreach ($t as $t1) {
+ $post_tags[] = [
'uid' => $profile_uid,
'ttype' => $t1['ttype'],
'otype' => TERM_OBJ_POST,
'term' => $t1['term'],
'url' => $t1['url'],
- );
+ ];
}
}
}
- $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
- $item_wall = (($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment') ? 1 : 0);
- $item_origin = (($origin) ? 1 : 0);
+ $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
+ $item_wall = (($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment') ? 1 : 0);
+ $item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
// determine if this is a wall post
- if($parent) {
+ if ($parent) {
$item_wall = $parent_item['item_wall'];
}
else {
- if(! $webpage) {
+ if (!$webpage) {
$item_wall = 1;
}
}
- if($moderated)
+ if ($moderated)
$item_blocked = ITEM_MODERATED;
- if(! strlen($verb))
- $verb = ACTIVITY_POST ;
+ if (!strlen($verb))
+ $verb = ACTIVITY_POST;
+
+ $notify_type = (($parent) ? 'comment-new' : 'wall-new');
- $notify_type = (($parent) ? 'comment-new' : 'wall-new' );
+ $uuid = (($message_id) ? $message_id : item_message_id());
- if(! $mid) {
- $uuid = (($message_id) ? $message_id : item_message_id());
- $mid = z_root() . '/item/' . $uuid;
+ if (!$mid) {
+ $mid = z_root() . '/item/' . $uuid;
}
- if($is_poll) {
+ if ($is_poll) {
$poll = [
- 'question' => $body,
- 'answers' => $_REQUEST['poll_answers'],
+ 'question' => $body,
+ 'answers' => $_REQUEST['poll_answers'],
'multiple_answers' => $_REQUEST['poll_multiple_answers'],
- 'expire_value' => $_REQUEST['poll_expire_value'],
- 'expire_unit' => $_REQUEST['poll_expire_unit']
+ 'expire_value' => $_REQUEST['poll_expire_value'],
+ 'expire_unit' => $_REQUEST['poll_expire_unit']
];
- $obj = $this->extract_poll_data($poll, [ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
+ $obj = $this->extract_poll_data($poll, ['item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny]);
}
else {
- $obj = $this->extract_bb_poll_data($body,[ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]);
+ $obj = $this->extract_bb_poll_data($body, ['item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny]);
}
if ($obj) {
- $obj['url'] = $mid;
- $obj['attributedTo'] = channel_url($channel);
- $datarray['obj'] = $obj;
+ $obj['url'] = $mid;
+ $obj['id'] = $mid;
+ $obj['diaspora:guid'] = $uuid;
+ $obj['attributedTo'] = channel_url($channel);
+ $obj['published'] = $created;
+ $obj['name'] = $title;
+
+ $datarray['obj'] = $obj;
+
+ if ($obj['endTime']) {
+ $d = datetime_convert('UTC','UTC', $obj['endTime']);
+ if ($d > NULL_DATE) {
+ $comments_closed = $d;
+ }
+ }
+
$obj_type = 'Question';
}
- if(! $parent_mid) {
+ if (!$parent_mid) {
$parent_mid = $mid;
}
- if($parent_item)
+ if ($parent_item)
$parent_mid = $parent_item['mid'];
-
// Fallback so that we alway have a thr_parent
- if(!$thr_parent)
+ if (!$thr_parent)
$thr_parent = $mid;
- $item_thread_top = ((! $parent) ? 1 : 0);
+ $item_thread_top = ((!$parent) ? 1 : 0);
// fix permalinks for cards
- if($webpage == ITEM_TYPE_CARD) {
+ if ($webpage == ITEM_TYPE_CARD) {
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
}
- if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) {
+ if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) {
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.iid = %d limit 1",
intval($parent_item['id'])
);
- if($r) {
+ if ($r) {
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . $r[0]['v'];
}
}
- if($webpage == ITEM_TYPE_ARTICLE) {
+ if ($webpage == ITEM_TYPE_ARTICLE) {
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
}
- if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) {
+ if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) {
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.iid = %d limit 1",
intval($parent_item['id'])
);
- if($r) {
+ if ($r) {
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . $r[0]['v'];
}
}
- if ((! $plink) && ($item_thread_top)) {
+ if ((!$plink) && ($item_thread_top)) {
// $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
// $plink = substr($plink,0,190);
$plink = $mid;
@@ -1094,6 +1093,7 @@ class Item extends Controller {
$datarray['created'] = $created;
$datarray['edited'] = (($orig_post) ? datetime_convert() : $created);
$datarray['expires'] = $expires;
+ $datarray['comments_closed'] = (($nocomment) ? $created : $comments_closed);
$datarray['commented'] = (($orig_post) ? datetime_convert() : $created);
$datarray['received'] = (($orig_post) ? datetime_convert() : $created);
$datarray['changed'] = (($orig_post) ? datetime_convert() : $created);
@@ -1149,33 +1149,33 @@ class Item extends Controller {
// A specific ACL over-rides public_policy completely
- if(! empty_acl($datarray))
+ if (!empty_acl($datarray))
$datarray['public_policy'] = '';
- if($iconfig)
+ if ($iconfig)
$datarray['iconfig'] = $iconfig;
// preview mode - prepare the body for display and send it via json
- if($preview) {
+ if ($preview) {
require_once('include/conversation.php');
- $datarray['owner'] = $owner_xchan;
+ $datarray['owner'] = $owner_xchan;
$datarray['author'] = $observer;
$datarray['attach'] = json_encode($datarray['attach']);
- $o = conversation(array($datarray),'search',false,'preview');
- // logger('preview: ' . $o, LOGGER_DEBUG);
- echo json_encode(array('preview' => $o));
+ $o = conversation([$datarray], 'search', false, 'preview');
+ // logger('preview: ' . $o, LOGGER_DEBUG);
+ echo json_encode(['preview' => $o]);
killme();
}
- if($orig_post)
+ if ($orig_post)
$datarray['edit'] = true;
// suppress duplicates, *unless* you're editing an existing post. This could get picked up
// as a duplicate if you're editing it very soon after posting it initially and you edited
// some attribute besides the content, such as title or categories.
- if(feature_enabled($profile_uid,'suppress_duplicates') && (! $orig_post)) {
+ if (feature_enabled($profile_uid, 'suppress_duplicates') && (!$orig_post)) {
$z = q("select created from item where uid = %d and created > %s - INTERVAL %s and body = '%s' limit 1",
intval($profile_uid),
@@ -1184,45 +1184,45 @@ class Item extends Controller {
dbesc($body)
);
- if($z) {
+ if ($z) {
$datarray['cancel'] = 1;
- notice( t('Duplicate post suppressed.') . EOL);
+ notice(t('Duplicate post suppressed.') . EOL);
logger('Duplicate post. Faking plugin cancel.');
}
}
- call_hooks('post_local',$datarray);
+ call_hooks('post_local', $datarray);
- if(x($datarray,'cancel')) {
+ if (x($datarray, 'cancel')) {
logger('mod_item: post cancelled by plugin or duplicate suppressed.');
- if($return_path)
+ if ($return_path)
goaway(z_root() . "/" . $return_path);
- if($api_source)
- return ( [ 'success' => false, 'message' => 'operation cancelled' ] );
- $json = array('cancel' => 1);
+ if ($api_source)
+ return (['success' => false, 'message' => 'operation cancelled']);
+ $json = ['cancel' => 1];
$json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
echo json_encode($json);
killme();
}
- if(mb_strlen($datarray['title']) > 191)
- $datarray['title'] = mb_substr($datarray['title'],0,191);
+ if (mb_strlen($datarray['title']) > 191)
+ $datarray['title'] = mb_substr($datarray['title'], 0, 191);
- if($webpage) {
- IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
+ if ($webpage) {
+ IConfig::Set($datarray, 'system', webpage_to_namespace($webpage),
(($pagetitle) ? $pagetitle : basename($datarray['mid'])), true);
}
- elseif($namespace) {
- IConfig::Set($datarray,'system', $namespace,
+ elseif ($namespace) {
+ IConfig::Set($datarray, 'system', $namespace,
(($remote_id) ? $remote_id : basename($datarray['mid'])), true);
}
- if($orig_post) {
+ if ($orig_post) {
$datarray['id'] = $post_id;
- $x = item_store_update($datarray,$execflag);
+ $x = item_store_update($datarray, $execflag);
// We only need edit activities for other federated protocols
// which do not support edits natively. While this does federate
@@ -1236,82 +1236,80 @@ class Item extends Controller {
// item_create_edit_activity($x);
- if(! $parent) {
+ if (!$parent) {
$r = q("select * from item where id = %d",
intval($post_id)
);
- if($r) {
+ if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
- Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
+ Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
}
- if(! $nopush)
- Master::Summon([ 'Notifier', 'edit_post', $post_id ]);
+ if (!$nopush)
+ Master::Summon(['Notifier', 'edit_post', $post_id]);
- if($api_source)
- return($x);
+ if ($api_source)
+ return ($x);
- if((x($_REQUEST,'return')) && strlen($return_path)) {
+ if ((x($_REQUEST, 'return')) && strlen($return_path)) {
logger('return: ' . $return_path);
- goaway(z_root() . "/" . $return_path );
+ goaway(z_root() . "/" . $return_path);
}
killme();
}
- else
- $post_id = 0;
- $post = item_store($datarray,$execflag);
+ $post = item_store($datarray, $execflag);
$post_id = $post['item_id'];
$datarray = $post['item'];
- if($post_id) {
+ if ($post_id) {
logger('mod_item: saved item ' . $post_id);
- if($parent) {
+ if ($parent) {
// prevent conversations which you are involved from being expired
- if(local_channel())
+ if (local_channel())
retain_item($parent);
// only send comment notification if this is a wall-to-wall comment,
// otherwise it will happen during delivery
- if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
- Enotify::submit(array(
- 'type' => NOTIFY_COMMENT,
- 'from_xchan' => $datarray['author_xchan'],
- 'to_xchan' => $datarray['owner_xchan'],
- 'item' => $datarray,
- 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
- 'verb' => ACTIVITY_POST,
- 'otype' => 'item',
- 'parent' => $parent,
- 'parent_mid' => $parent_item['mid']
- ));
+ if (($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
+ Enotify::submit([
+ 'type' => NOTIFY_COMMENT,
+ 'from_xchan' => $datarray['author_xchan'],
+ 'to_xchan' => $datarray['owner_xchan'],
+ 'item' => $datarray,
+ 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
+ 'verb' => ACTIVITY_POST,
+ 'otype' => 'item',
+ 'parent' => $parent,
+ 'parent_mid' => $parent_item['mid']
+ ]);
}
}
else {
$parent = $post_id;
- if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
- Enotify::submit(array(
- 'type' => NOTIFY_WALL,
- 'from_xchan' => $datarray['author_xchan'],
- 'to_xchan' => $datarray['owner_xchan'],
- 'item' => $datarray,
- 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
- 'verb' => ACTIVITY_POST,
- 'otype' => 'item'
- ));
+ if (($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
+ Enotify::submit([
+ 'type' => NOTIFY_WALL,
+ 'from_xchan' => $datarray['author_xchan'],
+ 'to_xchan' => $datarray['owner_xchan'],
+ 'item' => $datarray,
+ 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
+ 'verb' => ACTIVITY_POST,
+ 'otype' => 'item'
+ ]);
}
- if($uid && $uid == $profile_uid && (is_item_normal($datarray))) {
+ if ($uid && $uid == $profile_uid && (is_item_normal($datarray))) {
q("update channel set channel_lastpost = '%s' where channel_id = %d",
dbesc(datetime_convert()),
intval($uid)
@@ -1323,7 +1321,7 @@ class Item extends Controller {
// This way we don't see every picture in your new photo album posted to your wall at once.
// They will show up as people comment on them.
- if(intval($parent_item['item_hidden'])) {
+ if (intval($parent_item['item_hidden'])) {
$r = q("UPDATE item SET item_hidden = 0 WHERE id = %d",
intval($parent_item['id'])
);
@@ -1331,22 +1329,22 @@ class Item extends Controller {
}
else {
logger('mod_item: unable to retrieve post that was just stored.');
- notice( t('System error. Post not saved.') . EOL);
- if($return_path)
- goaway(z_root() . "/" . $return_path );
- if($api_source)
- return ( [ 'success' => false, 'message' => 'system error' ] );
+ notice(t('System error. Post not saved.') . EOL);
+ if ($return_path)
+ goaway(z_root() . "/" . $return_path);
+ if ($api_source)
+ return (['success' => false, 'message' => 'system error']);
killme();
}
- if($parent || $datarray['item_private'] == 1) {
+ if ($parent || $datarray['item_private'] == 1) {
$r = q("select * from item where id = %d",
intval($post_id)
);
- if($r) {
+ if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
- Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true))));
+ Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
}
@@ -1359,42 +1357,46 @@ class Item extends Controller {
$nopush = false;
}
- if(! $nopush)
- Master::Summon([ 'Notifier', $notify_type, $post_id ]);
+ if (!$nopush)
+ Master::Summon(['Notifier', $notify_type, $post_id]);
logger('post_complete');
- if($moderated) {
+ if ($moderated) {
info(t('Your comment is awaiting approval.') . EOL);
}
// figure out how to return, depending on from whence we came
- if($api_source)
+ if ($api_source)
return $post;
- if($return_path) {
+ if ($return_path) {
+ if ($return_path === 'hq') {
+ goaway(z_root() . '/hq/' . gen_link_id($datarray['mid']));
+ }
+
goaway(z_root() . "/" . $return_path);
}
- if($mode === 'channel')
+ if ($mode === 'channel')
profile_load($channel['channel_address']);
- $item[] = $datarray;
- $item[0]['owner'] = $owner_xchan;
+ $item[] = $datarray;
+ $item[0]['owner'] = $owner_xchan;
$item[0]['author'] = $observer;
$item[0]['attach'] = $datarray['attach'];
$json = [
'success' => 1,
- 'id' => $post_id,
- 'html' => conversation($item,$mode,true,'r_preview'),
+ 'id' => $post_id,
+ 'html' => conversation($item, $mode, true, 'r_preview'),
];
- if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
+ if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload']))
$json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
- logger('post_json: ' . print_r($json,true), LOGGER_DEBUG);
+ logger('post_json: ' . print_r($json, true), LOGGER_DEBUG);
echo json_encode($json);
killme();
@@ -1404,10 +1406,10 @@ class Item extends Controller {
function get() {
- if((! local_channel()) && (! remote_channel()))
+ if ((!local_channel()) && (!remote_channel()))
return;
- if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
+ if ((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
require_once('include/items.php');
@@ -1416,16 +1418,16 @@ class Item extends Controller {
intval(argv(2))
);
- if($i) {
- $can_delete = false;
+ if ($i) {
+ $can_delete = false;
$local_delete = false;
- if(local_channel() && local_channel() == $i[0]['uid']) {
+ if (local_channel() && local_channel() == $i[0]['uid']) {
$local_delete = true;
}
$ob_hash = get_observer_hash();
- if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
+ if ($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
$can_delete = true;
}
@@ -1433,15 +1435,15 @@ class Item extends Controller {
// If the item originated on this site+channel the deletion will propagate downstream.
// Otherwise just the local copy is removed.
- if(is_site_admin()) {
+ if (is_site_admin()) {
$local_delete = true;
- if(intval($i[0]['item_origin']))
+ if (intval($i[0]['item_origin']))
$can_delete = true;
}
- if(! ($can_delete || $local_delete)) {
- notice( t('Permission denied.') . EOL);
+ if (!($can_delete || $local_delete)) {
+ notice(t('Permission denied.') . EOL);
return;
}
@@ -1450,35 +1452,34 @@ class Item extends Controller {
$complex = false;
- if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
+ if (intval($i[0]['item_type']) || ($local_delete && (!$can_delete))) {
drop_item($i[0]['id']);
}
else {
// complex deletion that needs to propagate and be performed in phases
- drop_item($i[0]['id'],true,DROPITEM_PHASE1);
+ drop_item($i[0]['id'], true, DROPITEM_PHASE1);
$complex = true;
}
$r = q("select * from item where id = %d",
intval($i[0]['id'])
);
- if($r) {
+ if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
- Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
+ Libsync::build_sync_packet($i[0]['uid'], ['item' => [encode_item($sync_item[0], true)]]);
}
- if($complex) {
- tag_deliver($i[0]['uid'],$i[0]['id']);
+ if ($complex) {
+ tag_deliver($i[0]['uid'], $i[0]['id']);
}
}
}
}
-
- function item_check_service_class($channel_id,$iswebpage) {
- $ret = array('success' => false, 'message' => '');
+ function item_check_service_class($channel_id, $iswebpage) {
+ $ret = ['success' => false, 'message' => ''];
if ($iswebpage) {
$r = q("select count(i.id) as total from item i
@@ -1494,23 +1495,23 @@ class Item extends Controller {
);
}
- if(! $r) {
+ if (!$r) {
$ret['message'] = t('Unable to obtain post information from database.');
return $ret;
}
if (!$iswebpage) {
- $max = engr_units_to_bytes(service_class_fetch($channel_id,'total_items'));
- if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) {
- $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f top level posts.'),$max);
- return $result;
+ $max = engr_units_to_bytes(service_class_fetch($channel_id, 'total_items'));
+ if (!service_class_allows($channel_id, 'total_items', $r[0]['total'])) {
+ $ret['message'] .= upgrade_message() . sprintf(t('You have reached your limit of %1$.0f top level posts.'), $max);
+ return $ret;
}
}
else {
- $max = engr_units_to_bytes(service_class_fetch($channel_id,'total_pages'));
- if(! service_class_allows($channel_id,'total_pages',$r[0]['total'])) {
- $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f webpages.'),$max);
- return $result;
+ $max = engr_units_to_bytes(service_class_fetch($channel_id, 'total_pages'));
+ if (!service_class_allows($channel_id, 'total_pages', $r[0]['total'])) {
+ $ret['message'] .= upgrade_message() . sprintf(t('You have reached your limit of %1$.0f webpages.'), $max);
+ return $ret;
}
}
@@ -1518,51 +1519,51 @@ class Item extends Controller {
return $ret;
}
- function extract_bb_poll_data(&$body,$item) {
+ function extract_bb_poll_data(&$body, $item) {
$multiple = false;
- if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) {
+ if (strpos($body, '[/question]') === false && strpos($body, '[/answer]') === false) {
return false;
}
- if (strpos($body,'[nobb]') !== false) {
+ if (strpos($body, '[nobb]') !== false) {
return false;
}
- $obj = [];
- $ptr = [];
- $matches = null;
+ $obj = [];
+ $ptr = [];
+ $matches = null;
$obj['type'] = 'Question';
- if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism',$body,$matches,PREG_SET_ORDER)) {
+ if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism', $body, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
- $ptr[] = [ 'name' => $match[1], 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
- $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
+ $ptr[] = ['name' => $match[1], 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
+ $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
}
}
$matches = null;
- if (preg_match('/\[question\](.*?)\[\/question\]/ism',$body,$matches)) {
+ if (preg_match('/\[question\](.*?)\[\/question\]/ism', $body, $matches)) {
$obj['content'] = bbcode($matches[1]);
- $body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body);
- $obj['oneOf'] = $ptr;
+ $body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body);
+ $obj['oneOf'] = $ptr;
}
$matches = null;
- if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism',$body,$matches)) {
+ if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism', $body, $matches)) {
$obj['content'] = bbcode($matches[1]);
- $body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body);
- $obj['anyOf'] = $ptr;
+ $body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body);
+ $obj['anyOf'] = $ptr;
}
$matches = null;
- if (preg_match('/\[ends\](.*?)\[\/ends\]/ism',$body,$matches)) {
- $obj['endTime'] = datetime_convert(date_default_timezone_get(),'UTC', $matches[1],ATOM_TIME);
- $body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body);
+ if (preg_match('/\[ends\](.*?)\[\/ends\]/ism', $body, $matches)) {
+ $obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', $matches[1], ATOM_TIME);
+ $body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body);
}
@@ -1570,7 +1571,7 @@ class Item extends Controller {
$obj['to'] = Activity::map_acl($item);
}
else {
- $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
+ $obj['to'] = [ACTIVITY_PUBLIC_INBOX];
}
return $obj;
@@ -1580,23 +1581,23 @@ class Item extends Controller {
function extract_poll_data($poll, $item) {
- $multiple = intval($poll['multiple_answers']);
+ $multiple = intval($poll['multiple_answers']);
$expire_value = intval($poll['expire_value']);
- $expire_unit = $poll['expire_unit'];
- $question = $poll['question'];
- $answers = $poll['answers'];
+ $expire_unit = $poll['expire_unit'];
+ $question = $poll['question'];
+ $answers = $poll['answers'];
- $obj = [];
- $ptr = [];
- $obj['type'] = 'Question';
+ $obj = [];
+ $ptr = [];
+ $obj['type'] = 'Question';
$obj['content'] = bbcode($question);
- foreach($answers as $answer) {
- if(trim($answer))
- $ptr[] = [ 'name' => escape_tags($answer), 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
+ foreach ($answers as $answer) {
+ if (trim($answer))
+ $ptr[] = ['name' => escape_tags($answer), 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
}
- if($multiple) {
+ if ($multiple) {
$obj['anyOf'] = $ptr;
}
else {
@@ -1605,11 +1606,13 @@ class Item extends Controller {
$obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME);
+ $obj['directMessage'] = (intval($item['item_private']) === 2);
+
if ($item['item_private']) {
$obj['to'] = Activity::map_acl($item);
}
else {
- $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
+ $obj['to'] = [ACTIVITY_PUBLIC_INBOX];
}
return $obj;
@@ -1617,5 +1620,4 @@ class Item extends Controller {
}
-
}
diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php
index a32f933a6..fe185ebea 100644
--- a/Zotlabs/Module/Lang.php
+++ b/Zotlabs/Module/Lang.php
@@ -7,16 +7,60 @@ use Zotlabs\Web\Controller;
class Lang extends Controller {
+ const MYP = 'ZIN';
+ const VERSION = '2.0.0';
+
+ function post() {
+
+ $re = [];
+ $isajax = is_ajax();
+ $eol = $isajax ? "\n" : EOL;
+
+ if (! Apps::system_app_installed(local_channel(), 'Language')) {
+ $re['msg'] = 'ZIN0202E, ' . t('Language App') . ' (' . t('Not Installed') . ')' ;
+ notice( $re['msg'] . EOL);
+ if ($isajax) {
+ echo json_encode( $re );
+ killme();
+ exit;
+ } else {
+ return;
+ }
+ }
+
+ $lc = x($_POST['zinlc']) && preg_match('/^\?\?|[a-z]{2,2}[x_\-]{0,1}[a-zA-Z]{0,2}$/', $_POST['zinlc'])
+ ? $_POST['zinlc'] : '';
+ $lcs= x($_POST['zinlcs']) && preg_match('/^[a-z,_\-]{0,191}$/', $_POST['zinlcs'])
+ ? $_POST['zinlcs'] : '';
+
+ if ($isajax) {
+
+ if ($lc == '??') {
+ $re['lc'] = get_best_language();
+ $re['lcs'] = language_list();
+ } else {
+ $re['lc'] = $lc;
+ $re['alc'] = App::$language;
+ $re['slc'] = $_SESSION['language'];
+ $_SESSION['language'] = $lc;
+ App::$language = $lc;
+ load_translation_table($lc, true);
+ }
+
+ echo json_encode( $re );
+ killme();
+ exit;
+ }
+ }
+
function get() {
if(local_channel()) {
if(! Apps::system_app_installed(local_channel(), 'Language')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
-
- $o = '<b>' . t('Language App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Change UI language');
- return $o;
+ //Do not display any associated widgets at this point
+ App::$pdl = '';
+ $papp = Apps::get_papp('Language');
+ return Apps::app_render($papp, 'module');
}
}
@@ -24,5 +68,5 @@ class Lang extends Controller {
return lang_selector();
}
-
+
}
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
index e3fe4a954..8b36e8396 100644
--- a/Zotlabs/Module/Like.php
+++ b/Zotlabs/Module/Like.php
@@ -91,6 +91,12 @@ class Like extends Controller {
'id' => $arr['item']['id'],
'html' => conversation($items, $conv_mode, true, $page_mode),
];
+
+ // mod photos
+ if (isset($_REQUEST['reload']) && $_REQUEST['reload']) {
+ $ret['reload'] = 1;
+ }
+
return $ret;
}
diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php
index 76c679cc5..038c739d5 100644
--- a/Zotlabs/Module/Linkinfo.php
+++ b/Zotlabs/Module/Linkinfo.php
@@ -5,37 +5,40 @@ namespace Zotlabs\Module;
class Linkinfo extends \Zotlabs\Web\Controller {
function get() {
-
+
logger('linkinfo: ' . print_r($_REQUEST,true));
-
+
$text = null;
$str_tags = '';
- $process_oembed = true;
-
+ $process_oembed = true;
+
$br = "\n";
-
+
if(x($_GET,'binurl'))
$url = trim(hex2bin($_GET['binurl']));
else
$url = trim($_GET['url']);
-
+
if(substr($url,0,1) === '!') {
$process_oembed = false;
$url = substr($url,1);
}
$url = strip_zids($url);
-
+
if((substr($url,0,1) != '/') && (substr($url,0,4) != 'http'))
$url = 'http://' . $url;
-
-
+
+ $x = parse_url($url);
+ if ($x)
+ $url = str_replace($x['host'], punify($x['host']), $url);
+
if($_GET['title'])
$title = strip_tags(trim($_GET['title']));
-
+
if($_GET['description'])
$text = strip_tags(trim($_GET['description']));
-
+
if($_GET['tags']) {
$arr_tags = str_getcsv($_GET['tags']);
if(count($arr_tags)) {
@@ -43,23 +46,25 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$str_tags = $br . implode(' ',$arr_tags) . $br;
}
}
-
+
logger('linkinfo: ' . $url);
-
- // Replace plink URL with 'share' tag if possible
- preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid);
-
- if (!empty($mid) && $mid[1] == 'mid=b64.')
- $mid[2] = base64_decode($mid[2]);
-
- $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
- dbesc((empty($mid) ? $url : $mid[2])),
- intval(local_channel())
- );
- if ($r) {
- echo "[share=" . $r[0]['id'] . "][/share]";
- killme();
- }
+
+ // Replace plink URL with 'share' tag if possible
+ preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid);
+
+ if (!empty($mid)) {
+ $mid[2] = unpack_link_id($mid[2]);
+ }
+
+ $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
+ dbesc((empty($mid) ? $url : $mid[2])),
+ intval(local_channel())
+ );
+
+ if ($r) {
+ echo "[share=" . $r[0]['id'] . "][/share]";
+ killme();
+ }
$result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true));
if($result['success']) {
@@ -108,13 +113,13 @@ class Linkinfo extends \Zotlabs\Web\Controller {
}
}
}
-
+
$template = $br . '#^[url=%s]%s[/url]%s' . $br;
-
+
$arr = array('url' => $url, 'text' => '');
-
+
call_hooks('parse_link', $arr);
-
+
if(strlen($arr['text'])) {
echo $arr['text'];
killme();
@@ -127,28 +132,28 @@ class Linkinfo extends \Zotlabs\Web\Controller {
killme();
}
}
-
+
if($url && $title && $text) {
-
+
$text = $br . '[quote]' . trim($text) . '[/quote]' . $br;
-
+
$title = str_replace(array("\r","\n"),array('',''),$title);
-
+
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
-
+
logger('linkinfo (unparsed): returns: ' . $result);
-
+
echo $result;
killme();
}
-
+
$siteinfo = self::parseurl_getsiteinfo($url);
-
+
// If the site uses this platform, use zrl rather than url so they get zids sent to them by default
-
+
if(is_matrix_url($url))
$template = str_replace('url','zrl',$template);
-
+
if($siteinfo["title"] == "") {
echo sprintf($template,$url,$url,'') . $str_tags;
killme();
@@ -156,19 +161,19 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$text = $siteinfo["text"];
$title = $siteinfo["title"];
}
-
+
$image = "";
if(is_array($siteinfo["images"]) && count($siteinfo["images"])){
/* Execute below code only if image is present in siteinfo */
-
+
$total_images = 0;
$max_images = get_config('system','max_bookmark_images');
if($max_images === false)
$max_images = 2;
else
$max_images = intval($max_images);
-
+
foreach ($siteinfo["images"] as $imagedata) {
if ($url) {
$image .= sprintf('[url=%s]', $url);
@@ -183,57 +188,57 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
-
+
if(strlen($text)) {
$text = $br.'[quote]'.trim($text).'[/quote]'.$br ;
}
-
+
if($image) {
$text = $br.$br.$image.$text;
}
$title = str_replace(array("\r","\n"),array('',''),$title);
-
+
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
-
+
logger('linkinfo: returns: ' . $result, LOGGER_DEBUG);
-
+
echo trim($result);
killme();
-
+
}
-
-
+
+
public static function deletexnode(&$doc, $node) {
$xpath = new \DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}
-
+
public static function completeurl($url, $scheme) {
$urlarr = parse_url($url);
-
+
if (isset($urlarr["scheme"]))
return($url);
-
+
$schemearr = parse_url($scheme);
-
+
$complete = $schemearr["scheme"]."://".$schemearr["host"];
-
+
if ($schemearr["port"] != "")
$complete .= ":".$schemearr["port"];
-
+
if(strpos($urlarr['path'],'/') !== 0)
$complete .= '/';
-
+
$complete .= $urlarr["path"];
-
+
if ($urlarr["query"] != "")
$complete .= "?".$urlarr["query"];
-
+
if ($urlarr["fragment"] != "")
$complete .= "#".$urlarr["fragment"];
-
+
return($complete);
}
@@ -251,7 +256,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$p = substr($m,strpos($m,'/')+1);
// get the channel to check permissions
-
+
$u = channelx_by_nick($nick);
if($u && $p) {
@@ -272,18 +277,18 @@ class Linkinfo extends \Zotlabs\Web\Controller {
return EMPTY_STR;
}
-
+
public static function parseurl_getsiteinfo($url) {
$siteinfo = array();
-
-
+
+
$result = z_fetch_url($url,false,0,array('novalidate' => true));
if(! $result['success'])
return $siteinfo;
-
+
$header = $result['header'];
$body = $result['body'];
-
+
// Check codepage in HTTP headers or HTML if not exist
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
if(empty($cp))
@@ -291,10 +296,10 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$body = mb_convert_encoding($body, 'UTF-8', $cp);
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
-
+
$doc = new \DOMDocument();
@$doc->loadHTML($body);
-
+
self::deletexnode($doc, 'style');
self::deletexnode($doc, 'script');
self::deletexnode($doc, 'option');
@@ -306,14 +311,14 @@ class Linkinfo extends \Zotlabs\Web\Controller {
self::deletexnode($doc, 'h6');
self::deletexnode($doc, 'ol');
self::deletexnode($doc, 'ul');
-
+
$xpath = new \DomXPath($doc);
-
+
//$list = $xpath->query("head/title");
$list = $xpath->query("//title");
foreach ($list as $node)
$siteinfo["title"] = html_entity_decode($node->nodeValue, ENT_QUOTES, "UTF-8");
-
+
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
@@ -321,9 +326,9 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
-
+
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
-
+
switch (strtolower($attr["name"])) {
case "fulltitle":
$siteinfo["title"] = trim($attr["content"]);
@@ -365,7 +370,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
-
+
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
@@ -373,9 +378,9 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
-
+
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
-
+
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
@@ -388,7 +393,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
break;
}
}
-
+
if ($siteinfo["image"] == "") {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
@@ -396,10 +401,10 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
-
+
$src = self::completeurl($attr["src"], $url);
$photodata = @getimagesize($src);
-
+
if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
@@ -413,36 +418,36 @@ class Linkinfo extends \Zotlabs\Web\Controller {
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
-
+
}
} else {
$src = self::completeurl($siteinfo["image"], $url);
-
+
unset($siteinfo["image"]);
-
+
$photodata = @getimagesize($src);
-
+
if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
-
+
if ($siteinfo["text"] == "") {
$text = "";
-
+
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
-
+
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
-
+
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
@@ -450,21 +455,21 @@ class Linkinfo extends \Zotlabs\Web\Controller {
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
-
+
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
-
+
while (strpos($text, " "))
$text = trim(str_replace(" ", " ", $text));
-
+
$text = substr(html_entity_decode($text, ENT_QUOTES, "UTF-8"), 0, 350);
$siteinfo["text"] = rtrim(substr($text, 0, strrpos($text, " ")), "?.,:;!-") . '...';
}
}
-
+
return($siteinfo);
}
-
+
private static function arr_add_hashes(&$item,$k) {
$item = '#' . $item;
diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php
index 11c781df0..3637482c7 100644
--- a/Zotlabs/Module/Lockview.php
+++ b/Zotlabs/Module/Lockview.php
@@ -1,21 +1,30 @@
<?php
+
namespace Zotlabs\Module;
+use Zotlabs\Lib\AccessList;
+use Zotlabs\Web\Controller;
+
require_once('include/security.php');
-class Lockview extends \Zotlabs\Web\Controller {
+class Lockview extends Controller {
function get() {
- $atokens = array();
+ $atokens = [];
+ $atoken_xchans = [];
+ $access_list = [];
+ $guest_access_list = [];
- if(local_channel()) {
+ if (local_channel()) {
$at = q("select * from atoken where atoken_uid = %d",
intval(local_channel())
);
- if($at) {
- foreach($at as $t) {
- $atokens[] = atoken_xchan($t);
+ if ($at) {
+ foreach ($at as $t) {
+ $atoken_xchan = atoken_xchan($t);
+ $atokens[] = array_merge($t, $atoken_xchan);
+ $atoken_xchans[] = $atoken_xchan['xchan_hash'];
}
}
}
@@ -23,20 +32,20 @@ class Lockview extends \Zotlabs\Web\Controller {
$type = ((argc() > 1) ? argv(1) : 0);
if (is_numeric($type)) {
$item_id = intval($type);
- $type='item';
+ $type = 'item';
}
else {
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
}
- if(! $item_id)
+ if (!$item_id)
killme();
- if (! in_array($type, array('item', 'photo', 'attach', 'event', 'menu_item', 'chatroom')))
+ if (!in_array($type, ['item', 'photo', 'attach', 'menu_item', 'chatroom']))
killme();
// we have different naming in in menu_item table and chatroom table
- switch($type) {
+ switch ($type) {
case 'menu_item':
$id = 'mitem_id';
break;
@@ -53,134 +62,177 @@ class Lockview extends \Zotlabs\Web\Controller {
intval($item_id)
);
- if(! $r)
+ if (!$r)
killme();
$item = $r[0];
+ $uid = null;
+ $url = '';
- //we have different naming in in menu_item table and chatroom table
- switch($type) {
+ switch ($type) {
case 'menu_item':
$uid = $item['mitem_channel_id'];
break;
case 'chatroom':
- $uid = $item['cr_uid'];
+ $uid = $item['cr_uid'];
+ $channel = channelx_by_n($uid);
+ $url = z_root() . '/chat/' . $channel['channel_address'] . '/' . $item['cr_id'];
break;
- default:
+ case 'item':
$uid = $item['uid'];
+ $url = $item['plink'];
+ break;
+ case 'photo':
+ $uid = $item['uid'];
+ $channel = channelx_by_n($uid);
+ $url = z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $item['resource_id'];
+ break;
+ case 'attach':
+ $uid = $item['uid'];
+ $channel = channelx_by_n($uid);
+ $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $item['display_path'];
+ break;
+ default:
break;
}
- if($uid != local_channel()) {
- echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
+ if (intval($uid) !== local_channel()) {
+ echo '<div class="dropdown-item-text">' . t('Remote privacy information not available') . '</div>';
killme();
}
- if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
- && (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
+ if (intval($item['item_private']) && (!strlen($item['allow_cid'])) && (!strlen($item['allow_gid']))
+ && (!strlen($item['deny_cid'])) && (!strlen($item['deny_gid']))) {
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
// specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
// next section.
- echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
+ echo '<div class="dropdown-item-text">' . translate_scope((!$item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
killme();
}
- $allowed_users = expand_acl($item['allow_cid']);
+ $allowed_users = expand_acl($item['allow_cid']);
$allowed_groups = expand_acl($item['allow_gid']);
- $deny_users = expand_acl($item['deny_cid']);
- $deny_groups = expand_acl($item['deny_gid']);
-
- $o = '<div class="dropdown-item">' . t('Visible to:') . '</div>';
- $l = array();
+ $deny_users = expand_acl($item['deny_cid']);
+ $deny_groups = expand_acl($item['deny_gid']);
- stringify_array_elms($allowed_groups,true);
- stringify_array_elms($allowed_users,true);
- stringify_array_elms($deny_groups,true);
- stringify_array_elms($deny_users,true);
+ stringify_array_elms($allowed_groups, true);
+ stringify_array_elms($allowed_users, true);
+ stringify_array_elms($deny_groups, true);
+ stringify_array_elms($deny_users, true);
+ $allowed_xchans = [];
$profile_groups = [];
- if($allowed_groups) {
- foreach($allowed_groups as $g) {
- if(substr($g,0,4) === '\'vp.') {
- $profile_groups[] = '\'' . substr($g,4);
+ if ($allowed_groups) {
+ foreach ($allowed_groups as $g) {
+ if (substr($g, 0, 4) === '\'vp.') {
+ $profile_groups[] = '\'' . substr($g, 4);
}
}
}
- if(count($profile_groups)) {
- $r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
- }
-
- if(count($allowed_groups)) {
- $r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
- }
- if(count($allowed_users)) {
- $r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
- if($atokens) {
- foreach($atokens as $at) {
- if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
- $l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
- }
+
+ if ($profile_groups) {
+ $r = q("SELECT id, profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
+ if ($r) {
+ foreach ($r as $rr) {
+ $pgrp_members = AccessList::profile_members_xchan($uid, $rr['id']);
+ $allowed_xchans = array_merge($allowed_xchans, $pgrp_members);
+ $access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '">' . $rr['profile_name'] . '</div>';
+ }
+ }
+ }
+
+ if ($allowed_groups) {
+ $r = q("SELECT id, gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
+ if ($r) {
+ foreach ($r as $rr) {
+ $pgrp_members = AccessList::members_xchan($uid, $rr['id']);
+ $allowed_xchans = array_merge($allowed_xchans, $pgrp_members);
+ $access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '">' . $rr['gname'] . '</div>';
}
}
}
+ if ($allowed_users) {
+ $r = q("SELECT xchan_name, xchan_hash FROM xchan WHERE xchan_hash IN ( " . implode(', ', $allowed_users) . " )");
+ if ($r) {
+ foreach ($r as $rr) {
+ $allowed_xchans[] = $rr['xchan_hash'];
+ if (!in_array($rr['xchan_hash'], $atoken_xchans)) {
+ $access_list[] = '<div class="dropdown-item-text">' . $rr['xchan_name'] . '</div>';
+ }
+ }
+ }
+ }
$profile_groups = [];
- if($deny_groups) {
- foreach($deny_groups as $g) {
- if(substr($g,0,4) === '\'vp.') {
- $profile_groups[] = '\'' . substr($g,4);
+ if ($deny_groups) {
+ foreach ($deny_groups as $g) {
+ if (substr($g, 0, 4) === '\'vp.') {
+ $profile_groups[] = '\'' . substr($g, 4);
}
}
}
- if(count($profile_groups)) {
+
+ if ($profile_groups) {
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
+ if ($r) {
+ foreach ($r as $rr) {
+ $access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '"><strike>' . $rr['profile_name'] . '</strike></b></div>';
+ }
+ }
}
-
-
- if(count($deny_groups)) {
+ if ($deny_groups) {
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>';
+ if ($r) {
+ foreach ($r as $rr) {
+ $access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '"><strike>' . $rr['gname'] . '</strike></b></div>';
+ }
+ }
}
- if(count($deny_users)) {
+
+ if ($deny_users) {
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
- if($r)
- foreach($r as $rr)
- $l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>';
-
- if($atokens) {
- foreach($atokens as $at) {
- if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
- $l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
- }
+ if ($r) {
+ foreach ($r as $rr) {
+ $access_list[] = '<div class="dropdown-item-text"><strike>' . $rr['xchan_name'] . '</strike></div>';
}
}
+ }
+
+ if ($atokens && $allowed_xchans && $url) {
+ $guest_access_list = [];
+ $allowed_xchans = array_unique($allowed_xchans);
+ foreach ($atokens as $atoken) {
+ if (in_array($atoken['xchan_hash'], $allowed_xchans)) {
+ $guest_access_list[] = '<div class="dropdown-item d-flex justify-content-between cursor-pointer" title="' . sprintf(t('Click to copy link to this ressource for guest %s to clipboard'), $atoken['xchan_name']) . '" data-token="' . $url . '?zat=' . $atoken['atoken_token'] . '" onclick="navigator.clipboard.writeText(this.dataset.token); $.jGrowl(\'' . t('Link copied') . '\', { sticky: false, theme: \'info\', life: 1000 });"><span>' . $atoken['xchan_name'] . '</span><i class="fa fa-copy p-1"></i></div>';
+ }
+ }
}
- echo $o . implode($l);
- killme();
+ $access_list_header = '';
+ if ($access_list) {
+ $access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
+ }
+ $guest_access_list_header = '';
+ if ($guest_access_list) {
+ $guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
+ }
+
+ $divider = '';
+ if ($access_list && $guest_access_list) {
+ $divider = '<div class="dropdown-divider"></div>';
+ }
+
+ echo $access_list_header . implode($access_list) . $divider . $guest_access_list_header . implode($guest_access_list);
+ killme();
}
diff --git a/Zotlabs/Module/Locs.php b/Zotlabs/Module/Locs.php
index 2dd359c95..1ece47231 100644
--- a/Zotlabs/Module/Locs.php
+++ b/Zotlabs/Module/Locs.php
@@ -28,9 +28,8 @@ class Locs extends Controller {
return;
}
- q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
- dbesc($channel['channel_hash']),
- dbesc($channel['channel_portable_id'])
+ q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND hubloc_hash = '%s'",
+ dbesc($channel['channel_hash'])
);
q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'",
@@ -81,10 +80,9 @@ class Locs extends Controller {
}
}
- q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
+ q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND hubloc_hash = '%s'",
dbesc($r[0]['hubloc_id_url']),
- dbesc($channel['channel_hash']),
- dbesc($channel['channel_portable_id'])
+ dbesc($channel['channel_hash'])
);
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
return;
@@ -118,11 +116,6 @@ class Locs extends Controller {
return;
}
- for($x = 0; $x < count($r); $x ++) {
- $r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
- $r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
- }
-
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
'$header' => t('Manage Channel Locations'),
'$loc' => t('Location'),
@@ -134,7 +127,8 @@ class Locs extends Controller {
'$sync_text' => t('Please wait several minutes between consecutive operations.'),
'$drop_text' => t('When possible, drop a location by logging into that website/hub and removing your channel.'),
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
- '$hubs' => $r
+ '$hubs' => $r,
+ '$base_url' => z_root()
));
return $o;
diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php
index bc2034b95..3f168c15d 100644
--- a/Zotlabs/Module/Manage.php
+++ b/Zotlabs/Module/Manage.php
@@ -61,7 +61,7 @@ class Manage extends \Zotlabs\Web\Controller {
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1';
-
+ /* this is not currently implemented in the UI and probably should not (performance)
$c = q("SELECT id, item_wall FROM item
WHERE item_unseen = 1 and uid = %d " . item_normal(),
intval($channels[$x]['channel_id'])
@@ -75,7 +75,7 @@ class Manage extends \Zotlabs\Web\Controller {
$channels[$x]['network'] ++;
}
}
-
+ */
$intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval($channels[$x]['channel_id'])
@@ -84,16 +84,7 @@ class Manage extends \Zotlabs\Web\Controller {
if($intr)
$channels[$x]['intros'] = intval($intr[0]['total']);
-
- $mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
- intval($channels[$x]['channel_id']),
- dbesc($channels[$x]['channel_hash'])
- );
-
- if($mails)
- $channels[$x]['mail'] = intval($mails[0]['total']);
-
-
+ /* this is not currently implemented in the UI and probably should not (performance)
$events = q("SELECT etype, dtstart, adjust FROM event
WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
ORDER BY dtstart ASC ",
@@ -126,6 +117,7 @@ class Manage extends \Zotlabs\Web\Controller {
}
}
}
+ */
}
}
@@ -167,7 +159,7 @@ class Manage extends \Zotlabs\Web\Controller {
}
$o = replace_macros(get_markup_template('channels.tpl'), array(
- '$header' => t('Channel Manager'),
+ '$header' => t('Channels'),
'$msg_selected' => t('Current Channel'),
'$selected' => local_channel(),
'$desc' => ((count($channels) > 1 || $delegates) ? t('Switch to one of your channels by selecting it.') : ''),
@@ -175,7 +167,6 @@ class Manage extends \Zotlabs\Web\Controller {
'$msg_make_default' => t('Make Default'),
'$create' => $create,
'$all_channels' => $channels,
- '$mail_format' => t('%d new messages'),
'$intros_format' => t('%d new introductions'),
'$channel_usage_message' => $channel_usage_message,
'$delegated_desc' => t('Delegated Channel'),
diff --git a/Zotlabs/Module/Manifest.php b/Zotlabs/Module/Manifest.php
new file mode 100644
index 000000000..4c418a56a
--- /dev/null
+++ b/Zotlabs/Module/Manifest.php
@@ -0,0 +1,55 @@
+<?php
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\System;
+use Zotlabs\Render\Theme;
+
+class Manifest extends Controller {
+
+ function init() {
+
+ // populate App::$theme_info
+ Theme::current();
+
+ $ret = [
+ 'name' => ucfirst(System::get_platform_name()),
+ 'short_name' => ucfirst(System::get_platform_name()),
+ 'icons' => [
+ [ 'src' => '/images/app/hz-72.png', 'sizes' => '72x72', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-96.png', 'sizes' => '96x96', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-128.png', 'sizes' => '128x128', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png', 'purpose' => 'any maskable' ],
+ [ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ],
+ [ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ]
+ ],
+ 'theme_color' => App::$theme_info['theme_color'],
+ 'background_color' => App::$theme_info['background_color'],
+ 'scope' => '/',
+ 'start_url' => z_root(),
+ 'display' => 'standalone',
+ 'share_target' => [
+ 'action' => '/rpost',
+ 'method' => 'POST',
+ 'enctype' => 'multipart/form-data',
+ 'params' => [
+ 'title' => 'title',
+ 'text' => 'body',
+ 'url' => 'url',
+ 'files' => [
+ [ 'name' => 'userfile',
+ 'accept' => [ 'image/*', 'audio/*', 'video/*', 'text/*', 'application/*' ]
+ ]
+ ]
+ ]
+ ]
+ ];
+
+ json_return_and_die($ret,'application/manifest+json');
+ }
+
+}
diff --git a/Zotlabs/Module/Message.php b/Zotlabs/Module/Message.php
deleted file mode 100644
index 5856bfbdf..000000000
--- a/Zotlabs/Module/Message.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-require_once('include/acl_selectors.php');
-require_once('include/message.php');
-require_once('include/zot.php');
-require_once("include/bbcode.php");
-
-
-class Message extends \Zotlabs\Web\Controller {
-
- function get() {
-
- $o = '';
- nav_set_selected('messages');
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return login();
- }
-
- $channel = \App::get_channel();
- head_set_icon($channel['xchan_photo_s']);
-
- $cipher = get_pconfig(local_channel(),'system','default_cipher');
- if(! $cipher)
- $cipher = 'aes256';
-
- /*
- if((argc() == 3) && (argv(1) === 'dropconv')) {
- if(! intval(argv(2)))
- return;
- $cmd = argv(1);
- $r = private_messages_drop(local_channel(), argv(2), true);
- if($r)
- info( t('Conversation removed.') . EOL );
- goaway(z_root() . '/mail/combined' );
- }
-
- if(argc() == 2) {
-
- switch(argv(1)) {
- case 'combined':
- $mailbox = 'combined';
- $header = t('Conversations');
- break;
- case 'inbox':
- $mailbox = 'inbox';
- $header = t('Received Messages');
- break;
- case 'outbox':
- $mailbox = 'outbox';
- $header = t('Sent Messages');
- break;
- default:
- break;
- }
-
- // private_messages_list() can do other more complicated stuff, for now keep it simple
-
- $r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']);
-
- if(! $r) {
- info( t('No messages.') . EOL);
- return $o;
- }
-
- $messages = array();
-
- foreach($r as $rr) {
-
- $messages[] = array(
- 'id' => $rr['id'],
- 'from_name' => $rr['from']['xchan_name'],
- 'from_url' => chanlink_hash($rr['from_xchan']),
- 'from_photo' => $rr['from']['xchan_photo_s'],
- 'to_name' => $rr['to']['xchan_name'],
- 'to_url' => chanlink_hash($rr['to_xchan']),
- 'to_photo' => $rr['to']['xchan_photo_s'],
- 'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'),
- 'delete' => t('Delete conversation'),
- 'body' => zidify_links(smilies(bbcode($rr['body']))),
- 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')),
- 'seen' => $rr['seen']
- );
- }
-
-
- $tpl = get_markup_template('mail_head.tpl');
- $o = replace_macros($tpl, array(
- '$header' => $header,
- '$messages' => $messages
- ));
-
-
- $o .= alt_pager(count($r));
-
- return $o;
-
- return;
-
- }
- */
-
- return;
- }
-
-}
diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php
index 453f08f9f..cb2ca566b 100644
--- a/Zotlabs/Module/Mood.php
+++ b/Zotlabs/Module/Mood.php
@@ -14,36 +14,36 @@ require_once('include/items.php');
class Mood extends Controller {
function init() {
-
+
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
return;
}
-
+
$uid = local_channel();
$channel = App::get_channel();
$verb = notags(trim($_GET['verb']));
-
- if(! $verb)
+
+ if(! $verb)
return;
-
+
$verbs = get_mood_verbs();
-
+
if(! array_key_exists($verb,$verbs))
return;
-
+
$activity = ACTIVITY_MOOD . '#' . urlencode($verb);
-
+
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0);
-
-
+
+
logger('mood: verb ' . $verb, LOGGER_DEBUG);
-
-
+
+
if($parent) {
- $r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
+ $r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
from item where id = %d and parent = %d and uid = %d limit 1",
intval($parent),
intval($parent),
@@ -59,24 +59,24 @@ class Mood extends Controller {
}
}
else {
-
+
$private = 0;
-
+
$allow_cid = $channel['channel_allow_cid'];
$allow_gid = $channel['channel_allow_gid'];
$deny_cid = $channel['channel_deny_cid'];
$deny_gid = $channel['channel_deny_gid'];
}
-
+
$poster = App::get_observer();
-
+
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
-
- $action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
-
+
+ $action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
+
$arr = array();
-
+
$arr['aid'] = get_account_id();
$arr['uid'] = $uid;
$arr['uuid'] = $uuid;
@@ -97,31 +97,31 @@ class Mood extends Controller {
$arr['item_unseen'] = 1;
if(! $parent_mid)
$item['item_thread_top'] = 1;
-
+
if ((! $arr['plink']) && intval($arr['item_thread_top'])) {
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
}
-
-
+
+
$post = item_store($arr);
$item_id = $post['item_id'];
-
+
if($item_id) {
\Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $item_id));
}
-
+
call_hooks('post_local_end', $arr);
-
+
if($_SESSION['return_url'])
goaway(z_root() . '/' . $_SESSION['return_url']);
-
+
return;
}
-
-
-
+
+
+
function get() {
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -130,26 +130,24 @@ class Mood extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Mood App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Set your current mood and tell your friends');
- return $o;
+ $papp = Apps::get_papp('Mood');
+ return Apps::app_render($papp, 'module');
}
nav_set_selected('Mood');
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0');
-
+
$verbs = get_mood_verbs();
-
+
$shortlist = array();
foreach($verbs as $k => $v)
if($v !== 'NOTRANSLATION')
$shortlist[] = array($k,$v);
-
-
+
+
$tpl = get_markup_template('mood_content.tpl');
-
+
$o = replace_macros($tpl,array(
'$title' => t('Mood'),
'$desc' => t('Set your current mood and tell your friends'),
@@ -157,9 +155,9 @@ class Mood extends Controller {
'$parent' => $parent,
'$submit' => t('Submit'),
));
-
+
return $o;
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index a21095940..f4f6cc8d1 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -1,12 +1,11 @@
<?php
namespace Zotlabs\Module;
-use Zotlabs\Lib\Group;
+use Zotlabs\Lib\AccessList;
use Zotlabs\Lib\Apps;
use App;
require_once('include/items.php');
-require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
@@ -22,11 +21,11 @@ class Network extends \Zotlabs\Web\Controller {
$search = $_GET['search'] ?? '';
- if(in_array(substr($search, 0, 1),[ '@', '!', '?']) || strpos($search, 'https://') === 0)
+ if(in_array(substr($search, 0, 1), [ '@', '!', '?']) || strpos($search, 'https://') === 0)
goaway(z_root() . '/search?f=&search=' . $search);
if(count($_GET) < 2) {
- $network_options = get_pconfig(local_channel(),'system','network_page_default');
+ $network_options = get_pconfig(local_channel(), 'system', 'network_page_default');
if($network_options)
goaway(z_root() . '/network?f=&' . $network_options);
}
@@ -84,7 +83,7 @@ class Network extends \Zotlabs\Web\Controller {
$search = $_GET['search'] ?? '';
if($search) {
- if(strpos($search,'#') === 0) {
+ if(strpos($search, '#') === 0) {
$hashtags = substr($search,1);
$search = '';
}
@@ -114,31 +113,31 @@ class Network extends \Zotlabs\Web\Controller {
$def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>');
}
- $default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
- $default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
-
- $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
- $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
- $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0);
- $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0);
- $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0);
- $cmin = ((array_key_exists('cmin',$_GET)) ? intval($_GET['cmin']) : $default_cmin);
- $cmax = ((array_key_exists('cmax',$_GET)) ? intval($_GET['cmax']) : $default_cmax);
- $file = ((x($_GET,'file')) ? $_GET['file'] : '');
- $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : '');
- $net = ((x($_GET,'net')) ? $_GET['net'] : '');
- $pf = ((x($_GET,'pf')) ? $_GET['pf'] : '');
- $unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : '');
-
- if (Apps::system_app_installed(local_channel(),'Affinity Tool')) {
- $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
+ $default_cmin = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmin', 0) : (-1));
+ $default_cmax = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmax', 99) : (-1));
+
+ $cid = ((x($_GET, 'cid')) ? intval($_GET['cid']) : 0);
+ $star = ((x($_GET, 'star')) ? intval($_GET['star']) : 0);
+ $liked = ((x($_GET, 'liked')) ? intval($_GET['liked']) : 0);
+ $conv = ((x($_GET, 'conv')) ? intval($_GET['conv']) : 0);
+ $spam = ((x($_GET, 'spam')) ? intval($_GET['spam']) : 0);
+ $cmin = ((array_key_exists('cmin', $_GET)) ? intval($_GET['cmin']) : $default_cmin);
+ $cmax = ((array_key_exists('cmax', $_GET)) ? intval($_GET['cmax']) : $default_cmax);
+ $file = ((x($_GET, 'file')) ? $_GET['file'] : '');
+ $xchan = ((x($_GET, 'xchan')) ? $_GET['xchan'] : '');
+ $net = ((x($_GET, 'net')) ? $_GET['net'] : '');
+ $pf = ((x($_GET, 'pf')) ? $_GET['pf'] : '');
+ $unseen = ((x($_GET, 'unseen')) ? $_GET['unseen'] : '');
+
+ if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
+ $affinity_locked = intval(get_pconfig(local_channel(), 'affinity', 'lock', 1));
if ($affinity_locked) {
- set_pconfig(local_channel(),'affinity','cmin',$cmin);
- set_pconfig(local_channel(),'affinity','cmax',$cmax);
+ set_pconfig(local_channel(), 'affinity', 'cmin', $cmin);
+ set_pconfig(local_channel(), 'affinity', 'cmax', $cmax);
}
}
- if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
+ if(x($_GET, 'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
$nouveau = true;
$cid_r = [];
@@ -164,8 +163,8 @@ class Network extends \Zotlabs\Web\Controller {
// search terms header
if($search || $hashtags) {
- $o .= replace_macros(get_markup_template("section_title.tpl"),array(
- '$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT,'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8'))
+ $o .= replace_macros(get_markup_template('section_title.tpl'), array(
+ '$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT, 'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8'))
));
}
@@ -193,7 +192,7 @@ class Network extends \Zotlabs\Web\Controller {
$x = array(
'is_owner' => true,
- 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
+ 'allow_location' => ((intval(get_pconfig($channel['channel_id'], 'system', 'use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
@@ -209,7 +208,7 @@ class Network extends \Zotlabs\Web\Controller {
'reset' => t('Reset form')
);
- $status_editor = status_editor($a,$x,false,'Network');
+ $status_editor = status_editor($a, $x, false, 'Network');
$o .= $status_editor;
}
@@ -221,7 +220,7 @@ class Network extends \Zotlabs\Web\Controller {
$sql_options = (($star)
- ? " and item_starred = 1 "
+ ? ' and item_starred = 1 '
: '');
$sql_nets = '';
@@ -233,9 +232,9 @@ class Network extends \Zotlabs\Web\Controller {
if($group) {
$contact_str = '';
- $contacts = group_get_members($group);
+ $contacts = AccessList::members(local_channel(), $group);
if($contacts) {
- $contact_str = ids_to_querystr($contacts,'xchan',true);
+ $contact_str = ids_to_querystr($contacts, 'xchan', true);
}
else {
$contact_str = " '0' ";
@@ -246,10 +245,10 @@ class Network extends \Zotlabs\Web\Controller {
$item_thread_top = '';
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
- $x = group_rec_byhash(local_channel(), $group_hash);
+ $x = AccessList::by_hash(local_channel(), $group_hash);
if($x) {
- $title = replace_macros(get_markup_template("section_title.tpl"),array(
+ $title = replace_macros(get_markup_template('section_title.tpl'), array(
'$title' => t('Privacy group: ') . $x['gname']
));
}
@@ -273,15 +272,17 @@ class Network extends \Zotlabs\Web\Controller {
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
// This is for nouveau view public forum cid queries (if a forum notification is clicked)
- $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
- intval(local_channel()),
- intval(TERM_FORUM),
- dbesc($cid_r[0]['xchan_name'])
- );
+ //$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
+ //intval(local_channel()),
+ //intval(TERM_FORUM),
+ //dbesc($cid_r[0]['xchan_name'])
+ //);
- $p_str = ids_to_querystr($p, 'parent');
- if($p_str)
- $p_sql = " OR item.parent IN ( $p_str ) ";
+ //$p_str = ids_to_querystr($p, 'parent');
+
+ $p_sql = '';
+ //if($p_str)
+ //$p_sql = " OR item.parent IN ( $p_str ) ";
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql ";
}
@@ -289,10 +290,10 @@ class Network extends \Zotlabs\Web\Controller {
// This is for threaded view cid queries (e.g. if a forum is selected from the forum filter)
$ttype = (($pf) ? TERM_FORUM : TERM_MENTION);
- $p1 = q("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal ");
- $p2 = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'");
+ $p1 = dbq("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal ");
+ $p2 = dbq("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'");
- $p_str = ids_to_querystr(array_merge($p1,$p2),'parent');
+ $p_str = ids_to_querystr(array_merge($p1, $p2), 'parent');
if(! $p_str)
killme();
@@ -300,7 +301,7 @@ class Network extends \Zotlabs\Web\Controller {
}
}
- $title = replace_macros(get_markup_template("section_title.tpl"),array(
+ $title = replace_macros(get_markup_template('section_title.tpl'), array(
'$title' => '<a href="' . zid($cid_r[0]['xchan_url']) . '" ><img src="' . zid($cid_r[0]['xchan_photo_s']) . '" alt="' . urlencode($cid_r[0]['xchan_name']) . '" /></a> <a href="' . zid($cid_r[0]['xchan_url']) . '" >' . $cid_r[0]['xchan_name'] . '</a>'
));
@@ -314,7 +315,7 @@ class Network extends \Zotlabs\Web\Controller {
if($r) {
$item_thread_top = '';
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($xchan) . "' or owner_xchan = '" . dbesc($xchan) . "' ) $item_normal ) ";
- $title = replace_macros(get_markup_template("section_title.tpl"),array(
+ $title = replace_macros(get_markup_template("section_title.tpl"), array(
'$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>'
));
@@ -345,13 +346,13 @@ class Network extends \Zotlabs\Web\Controller {
$sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
- $sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id ");
+ $sql_extra2 = (($nouveau) ? '' : ' AND item.parent = item.id ');
$sql_extra3 = (($nouveau) ? '' : $sql_extra3);
- if(x($_GET,'search')) {
+ if(x($_GET, 'search')) {
$search = escape_tags($_GET['search']);
- if(strpos($search,'#') === 0) {
- $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
+ if(strpos($search, '#') === 0) {
+ $sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG);
}
else {
$sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ",
@@ -368,8 +369,8 @@ class Network extends \Zotlabs\Web\Controller {
// The name 'verb' is a holdover from the earlier XML
// ActivityStreams specification.
- if (substr($verb,0,1) === '.') {
- $verb = substr($verb,1);
+ if (substr($verb, 0, 1) === '.') {
+ $verb = substr($verb, 1);
$sql_extra .= sprintf(" AND item.obj_type like '%s' ",
dbesc(protect_sprintf('%' . $verb . '%'))
);
@@ -382,13 +383,17 @@ class Network extends \Zotlabs\Web\Controller {
}
if(strlen($file)) {
- $sql_extra .= term_query('item',$file,TERM_FILE);
+ $sql_extra .= term_query('item', $file, TERM_FILE);
}
if ($dm) {
- $sql_extra .= " AND item_private = 2 ";
+ $sql_extra .= ' AND item_private = 2 ';
+ }
+ else {
+ $sql_extra .= ' AND item_private IN (0, 1) ';
}
+
if($conv) {
$item_thread_top = '';
$sql_extra .= " AND ( author_xchan = '" . dbesc($channel['channel_hash']) . "' OR item_mentionsme = 1 ) ";
@@ -401,38 +406,38 @@ class Network extends \Zotlabs\Web\Controller {
}
else {
- $itemspage = get_pconfig(local_channel(),'system','itemspage');
+ $itemspage = get_pconfig(local_channel(), 'system', 'itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
// cmin and cmax are both -1 when the affinity tool is disabled
- if(($cmin != (-1)) || ($cmax != (-1))) {
+ if(($cmin !== (-1)) || ($cmax !== (-1))) {
// Not everybody who shows up in the network stream will be in your address book.
// By default those that aren't are assumed to have closeness = 99; but this isn't
// recorded anywhere. So if cmax is 99, we'll open the search up to anybody in
// the stream with a NULL address book entry.
- $sql_nets .= " AND ";
+ $sql_nets .= ' AND ';
- if($cmax == 99)
- $sql_nets .= " ( ";
+ if($cmax === 99)
+ $sql_nets .= ' ( ';
- $sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " ";
- $sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) ";
+ $sql_nets .= '( abook.abook_closeness >= ' . intval($cmin) . ' ';
+ $sql_nets .= ' AND abook.abook_closeness <= ' . intval($cmax) . ' ) ';
- if($cmax == 99)
- $sql_nets .= " OR abook.abook_closeness IS NULL ) ";
+ if($cmax === 99)
+ $sql_nets .= ' OR abook.abook_closeness IS NULL ) ';
}
- $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
+ $net_query = (($net) ? ' left join xchan on xchan_hash = author_xchan ' : '');
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
- $abook_uids = " and abook.abook_channel = " . local_channel() . " ";
- $uids = " and item.uid = " . local_channel() . " ";
+ $abook_uids = ' and abook.abook_channel = ' . local_channel() . ' ';
+ $uids = ' and item.uid = ' . local_channel() . ' ';
if(feature_enabled(local_channel(), 'network_list_mode'))
$page_mode = 'list';
@@ -461,7 +466,7 @@ class Network extends \Zotlabs\Web\Controller {
if($nouveau && $load) {
// "New Item View" - show all items unthreaded in reverse created date order
- $items = q("SELECT item.*, item.id AS item_id, created FROM item
+ $items = dbq("SELECT item.*, item.id AS item_id, created FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_normal
@@ -471,26 +476,26 @@ class Network extends \Zotlabs\Web\Controller {
ORDER BY item.created DESC $pager_sql "
);
- $parents_str = ids_to_querystr($items,'item_id');
+ $parents_str = ids_to_querystr($items, 'item_id');
require_once('include/items.php');
xchan_query($items);
- $items = fetch_post_tags($items,true);
+ $items = fetch_post_tags($items, true);
}
elseif($update) {
// Normal conversation view
if($order === 'post')
- $ordering = "created";
+ $ordering = 'created';
else
- $ordering = "commented";
+ $ordering = 'commented';
if($load) {
// Fetch a page full of parent items for this page
- $r = q("SELECT item.parent AS item_id FROM item
+ $r = dbq("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_thread_top $item_normal
@@ -504,31 +509,28 @@ class Network extends \Zotlabs\Web\Controller {
else {
// this is an update
- $r = q("SELECT item.parent AS item_id FROM item
+ $r = dbq("SELECT item.parent AS item_id FROM item
left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids $item_normal_update $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
- $sql_extra3 $sql_extra $sql_options $sql_nets $net_query2"
+ $sql_extra3 $sql_extra $sql_options $sql_nets $net_query2 "
);
}
// Then fetch all the children of the parents that are on this page
if($r) {
-
- $parents_str = ids_to_querystr($r,'item_id');
-
- $items = q("SELECT item.*, item.id AS item_id FROM item
+ $parents_str = ids_to_querystr($r, 'item_id');
+ $items = dbq("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
- AND item.parent IN ( %s )
- $sql_extra ",
- dbesc($parents_str)
+ AND item.parent IN ( $parents_str )
+ $sql_extra "
);
- xchan_query($items,true);
- $items = fetch_post_tags($items,true);
- $items = conv_sort($items,$ordering);
+ xchan_query($items, true);
+ $items = fetch_post_tags($items, true);
+ $items = conv_sort($items, $ordering);
}
else {
$items = array();
@@ -546,7 +548,7 @@ class Network extends \Zotlabs\Web\Controller {
// We only launch liveUpdate if you aren't filtering in some incompatible
// way and also you aren't writing a comment (discovered in javascript).
- $maxheight = get_pconfig(local_channel(),'system','network_divmore_height');
+ $maxheight = get_pconfig(local_channel(), 'system', 'network_divmore_height');
if(! $maxheight)
$maxheight = 400;
@@ -591,7 +593,7 @@ class Network extends \Zotlabs\Web\Controller {
));
}
- $o .= conversation($items,$mode,$update,$page_mode);
+ $o .= conversation($items, $mode, $update, $page_mode);
if(($items) && (! $update))
$o .= alt_pager(count($items));
diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php
index 84d492f8f..24dbe2944 100644
--- a/Zotlabs/Module/New_channel.php
+++ b/Zotlabs/Module/New_channel.php
@@ -1,6 +1,8 @@
<?php
namespace Zotlabs\Module;
+use URLify;
+
require_once('include/channel.php');
require_once('include/permissions.php');
@@ -13,7 +15,6 @@ class New_channel extends \Zotlabs\Web\Controller {
$cmd = ((argc() > 1) ? argv(1) : '');
if($cmd === 'autofill.json') {
- require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['name']);
@@ -24,7 +25,7 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if((! $x) || strlen($x) > 64)
- $x = strtolower(\URLify::transliterate($n));
+ $x = strtolower(URLify::transliterate($n));
$test = array();
@@ -46,7 +47,6 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if($cmd === 'checkaddr.json') {
- require_once('library/urlify/URLify.php');
$result = array('error' => false, 'message' => '');
$n = trim($_REQUEST['nick']);
if(! $n) {
@@ -60,7 +60,7 @@ class New_channel extends \Zotlabs\Web\Controller {
}
if((! $x) || strlen($x) > 64)
- $x = strtolower(\URLify::transliterate($n));
+ $x = strtolower(URLify::transliterate($n));
$test = array();
@@ -138,7 +138,7 @@ class New_channel extends \Zotlabs\Web\Controller {
intval($aid)
);
if($r && (! intval($r[0]['total']))) {
- $default_role = get_config('system','default_permissions_role','social');
+ $default_role = get_config('system','default_permissions_role','personal');
}
$limit = account_service_class_fetch(get_account_id(),'total_identities');
@@ -170,12 +170,12 @@ class New_channel extends \Zotlabs\Web\Controller {
$privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" );
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
+ $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
$name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*");
$nickhub = '@' . \App::get_hostname();
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*");
- $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles);
+ $role = array('permissions_role' , t('Channel role'), ($privacy_role) ? $privacy_role : 'personal', '', $perm_roles);
$o = replace_macros(get_markup_template('new_channel.tpl'), array(
'$title' => t('Create a Channel'),
diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php
index b448cff83..57b8f30db 100644
--- a/Zotlabs/Module/Notes.php
+++ b/Zotlabs/Module/Notes.php
@@ -19,7 +19,12 @@ class Notes extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Notes'))
return EMPTY_STR;
- $ret = array('success' => true);
+ $ret = [
+ 'success' => false,
+ 'html' => ''
+ ];
+
+
if(array_key_exists('note_text',$_REQUEST)) {
$body = escape_tags($_REQUEST['note_text']);
@@ -33,12 +38,15 @@ class Notes extends Controller {
set_pconfig(local_channel(),'notes','text.bak',$old_text);
}
set_pconfig(local_channel(),'notes','text',$body);
+
+ $ret['html'] = bbcode($body);
+ $ret['success'] = true;
+
}
// push updates to channel clones
if((argc() > 1) && (argv(1) === 'sync')) {
- require_once('include/zot.php');
Libsync::build_sync_packet();
}
@@ -52,11 +60,9 @@ class Notes extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Notes')) {
//Do not display any associated widgets at this point
- App::$pdl = EMPTY_STR;
-
- $o = '<b>' . t('Notes App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('A simple notes app with a widget (note: notes are not encrypted)');
- return $o;
+ App::$pdl = '';
+ $papp = Apps::get_papp('Notes');
+ return Apps::app_render($papp, 'module');
}
$w = new \Zotlabs\Widget\Notes;
diff --git a/Zotlabs/Module/Notifications.php b/Zotlabs/Module/Notifications.php
index 8ecf5760a..c08628b47 100644
--- a/Zotlabs/Module/Notifications.php
+++ b/Zotlabs/Module/Notifications.php
@@ -8,10 +8,58 @@ class Notifications extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
return;
}
+ // ajax mark all unseen items read
+ if(x($_REQUEST, 'markRead')) {
+ switch($_REQUEST['markRead']) {
+ case 'dm':
+ $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private = 2",
+ intval(local_channel())
+ );
+ break;
+ case 'network':
+ $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private IN (0, 1)",
+ intval(local_channel())
+ );
+ break;
+ case 'home':
+ $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)",
+ intval(local_channel())
+ );
+ break;
+ case 'all_events':
+ $evdays = intval(get_pconfig(local_channel(), 'system', 'evdays', 3));
+ $r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ",
+ intval(local_channel()),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
+ dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
+ );
+ break;
+ case 'notify':
+ $r = q("UPDATE notify SET seen = 1 WHERE seen = 0 AND uid = %d",
+ intval(local_channel())
+ );
+ break;
+ case 'pubs':
+ unset($_SESSION['static_loadtime']);
+ break;
+ default:
+ break;
+ }
+ killme();
+ }
+
+ // ajax mark all comments of a parent item read
+ if(x($_REQUEST, 'markItemRead') && local_channel()) {
+ $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d",
+ intval(local_channel()),
+ intval($_REQUEST['markItemRead'])
+ );
+ killme();
+ }
+
nav_set_selected('Notifications');
$o = '';
diff --git a/Zotlabs/Module/Notify.php b/Zotlabs/Module/Notify.php
index cffcc8099..4cbcfee05 100644
--- a/Zotlabs/Module/Notify.php
+++ b/Zotlabs/Module/Notify.php
@@ -1,14 +1,38 @@
<?php
namespace Zotlabs\Module;
+use \Zotlabs\Lib\PConfig;
+use \Zotlabs\Web\Controller;
-
-class Notify extends \Zotlabs\Web\Controller {
+class Notify extends Controller {
function init() {
if(! local_channel())
return;
-
+
+ if($_REQUEST['notify_id']) {
+ $update_notices_per_parent = PConfig::Get(local_channel(), 'system', 'update_notices_per_parent', 1);
+
+ if($update_notices_per_parent) {
+ $r = q("SELECT parent FROM notify WHERE id = %d AND uid = %d",
+ intval($_REQUEST['notify_id']),
+ intval(local_channel())
+ );
+ q("update notify set seen = 1 where parent = '%s' and uid = %d",
+ dbesc($r[0]['parent']),
+ intval(local_channel())
+ );
+ }
+ else {
+ q("update notify set seen = 1 where id = %d and uid = %d",
+ intval($_REQUEST['notify_id']),
+ intval(local_channel())
+ );
+ }
+
+ killme();
+ }
+
if(argc() > 2 && argv(1) === 'view' && intval(argv(2))) {
$r = q("select * from notify where id = %d and uid = %d limit 1",
intval(argv(2)),
@@ -29,24 +53,24 @@ class Notify extends \Zotlabs\Web\Controller {
}
goaway(z_root());
}
-
-
+
+
}
-
-
+
+
function get() {
if(! local_channel())
return login();
-
+
$notif_tpl = get_markup_template('notifications.tpl');
-
+
$not_tpl = get_markup_template('notify.tpl');
require_once('include/bbcode.php');
-
+
$r = q("SELECT * from notify where uid = %d and seen = 0 order by created desc",
intval(local_channel())
);
-
+
if($r) {
foreach ($r as $it) {
$notif_content .= replace_macros($not_tpl,array(
@@ -56,18 +80,18 @@ class Notify extends \Zotlabs\Web\Controller {
'$item_when' => relative_date($it['created'])
));
}
- }
+ }
else {
$notif_content .= t('No more system notifications.');
}
-
+
$o .= replace_macros($notif_tpl,array(
'$notif_header' => t('System Notifications'),
'$tabs' => '', // $tabs,
'$notif_content' => $notif_content,
));
-
+
return $o;
-
+
}
}
diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php
index 27c062df2..061296257 100644
--- a/Zotlabs/Module/Oauth.php
+++ b/Zotlabs/Module/Oauth.php
@@ -17,22 +17,22 @@ class Oauth extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager'))
return;
-
+
if(x($_POST,'remove')){
check_form_security_token_redirectOnErr('/oauth', 'oauth');
-
+
$key = $_POST['remove'];
q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
dbesc($key),
local_channel());
goaway(z_root()."/oauth");
- return;
+ return;
}
-
+
if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) {
-
+
check_form_security_token_redirectOnErr('oauth', 'oauth');
-
+
$name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : '');
$key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : '');
$secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : '');
@@ -48,7 +48,7 @@ class Oauth extends Controller {
$ok = false;
notice( t('Key and Secret are required') . EOL);
}
-
+
if($ok) {
if ($_POST['submit']==t("Update")){
$r = q("UPDATE clients SET
@@ -96,13 +96,11 @@ class Oauth extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('OAuth Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('OAuth authentication tokens for mobile and remote apps');
- return $o;
+ $papp = Apps::get_papp('OAuth Apps Manager');
+ return Apps::app_render($papp, 'module');
}
-
+
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth_edit.tpl");
$o .= replace_macros($tpl, array(
@@ -118,18 +116,18 @@ class Oauth extends Controller {
));
return $o;
}
-
+
if((argc() > 2) && (argv(1) === 'edit')) {
$r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
dbesc(argv(2)),
local_channel());
-
+
if (!count($r)){
notice(t('Application not found.'));
return;
}
$app = $r[0];
-
+
$tpl = get_markup_template("oauth_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
@@ -144,26 +142,26 @@ class Oauth extends Controller {
));
return $o;
}
-
+
if((argc() > 2) && (argv(1) === 'delete')) {
check_form_security_token_redirectOnErr('/oauth', 'oauth', 't');
-
+
$r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
dbesc(argv(2)),
local_channel());
goaway(z_root()."/oauth");
- return;
+ return;
}
-
-
- $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
+
+
+ $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
FROM clients
LEFT JOIN tokens ON clients.client_id=tokens.client_id
WHERE clients.uid IN (%d,0)",
local_channel(),
local_channel());
-
-
+
+
$tpl = get_markup_template("oauth.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
@@ -178,7 +176,7 @@ class Oauth extends Controller {
'$apps' => $r,
));
return $o;
-
+
}
}
diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php
index db2687b4c..4b0b1991e 100644
--- a/Zotlabs/Module/Oauth2.php
+++ b/Zotlabs/Module/Oauth2.php
@@ -16,11 +16,11 @@ class Oauth2 extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager'))
return;
-
+
if(x($_POST,'remove')){
check_form_security_token_redirectOnErr('oauth2', 'oauth2');
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
- logger("REMOVE! ".$name." uid: ".local_channel());
+ logger("REMOVE! ".$name." uid: ".local_channel());
$key = $_POST['remove'];
q("DELETE FROM oauth_authorization_codes WHERE client_id='%s' AND user_id=%d",
dbesc($name),
@@ -35,13 +35,13 @@ class Oauth2 extends Controller {
intval(local_channel())
);
goaway(z_root()."/oauth2");
- return;
+ return;
}
-
+
if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) {
-
+
check_form_security_token_redirectOnErr('oauth2', 'oauth2');
-
+
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
$secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : '');
$redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : '');
@@ -53,7 +53,7 @@ class Oauth2 extends Controller {
$ok = false;
notice( t('Name and Secret are required') . EOL);
}
-
+
if($ok) {
if ($_POST['submit']==t("Update")){
$r = q("UPDATE oauth_clients SET
@@ -61,7 +61,7 @@ class Oauth2 extends Controller {
client_secret = '%s',
redirect_uri = '%s',
grant_types = '%s',
- scope = '%s',
+ scope = '%s',
user_id = %d
WHERE client_id='%s' and user_id = %s",
dbesc($name),
@@ -102,12 +102,10 @@ class Oauth2 extends Controller {
if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('OAuth2 Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('OAuth2 authenticatication tokens for mobile and remote apps');
- return $o;
+ $papp = Apps::get_papp('OAuth2 Apps Manager');
+ return Apps::app_render($papp, 'module');
}
-
+
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
@@ -123,20 +121,20 @@ class Oauth2 extends Controller {
));
return $o;
}
-
+
if((argc() > 2) && (argv(1) === 'edit')) {
$r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= %d",
dbesc(argv(2)),
intval(local_channel())
);
-
+
if (! $r){
notice(t('OAuth2 Application not found.'));
return;
}
$app = $r[0];
-
+
$tpl = get_markup_template("oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
@@ -151,10 +149,10 @@ class Oauth2 extends Controller {
));
return $o;
}
-
+
if((argc() > 2) && (argv(1) === 'delete')) {
check_form_security_token_redirectOnErr('oauth2', 'oauth2', 't');
-
+
$r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = %d",
dbesc(argv(2)),
intval(local_channel())
@@ -172,11 +170,11 @@ class Oauth2 extends Controller {
intval(local_channel())
);
goaway(z_root()."/oauth2");
- return;
+ return;
}
-
- $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my
+
+ $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my
FROM oauth_clients
LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND
oauth_clients.user_id=oauth_access_tokens.user_id
@@ -184,7 +182,7 @@ class Oauth2 extends Controller {
intval(local_channel()),
intval(local_channel())
);
-
+
$tpl = get_markup_template("oauth2.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
@@ -199,7 +197,7 @@ class Oauth2 extends Controller {
'$apps' => $r,
));
return $o;
-
+
}
}
diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php
index faad2fc52..8e048a487 100644
--- a/Zotlabs/Module/Oep.php
+++ b/Zotlabs/Module/Oep.php
@@ -77,8 +77,11 @@ class Oep extends \Zotlabs\Web\Controller {
$res = $matches[2];
}
- if(strpos($res,'b64.') === 0) {
- $res = base64url_decode(substr($res,4));
+ $res = unpack_link_id($res);
+
+ if ($res === false) {
+ notice(t('Malformed message id.') . EOL);
+ return;
}
$item_normal = item_normal();
@@ -122,12 +125,12 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
- "' profile='".$p[0]['author']['xchan_url'] .
- "' avatar='".$p[0]['author']['xchan_photo_s'].
- "' link='".$p[0]['plink'].
- "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
- "' posted='".$p[0]['created'].
- "' message_id='".$p[0]['mid']."']";
+ "' profile='".$p[0]['author']['xchan_url'] .
+ "' avatar='".$p[0]['author']['xchan_photo_s'].
+ "' link='".$p[0]['plink'].
+ "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
+ "' posted='".$p[0]['created'].
+ "' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
@@ -210,13 +213,13 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
- "' profile='".$p[0]['author']['xchan_url'] .
- "' avatar='".$p[0]['author']['xchan_photo_s'].
- "' link='".$p[0]['plink'].
- "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
- "' posted='".$p[0]['created'].
- "' message_id='".$p[0]['mid']."']";
- if($p[0]['title'])
+ "' profile='".$p[0]['author']['xchan_url'] .
+ "' avatar='".$p[0]['author']['xchan_photo_s'].
+ "' link='".$p[0]['plink'].
+ "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
+ "' posted='".$p[0]['created'].
+ "' message_id='".$p[0]['mid']."']";
+ if($p[0]['title'])
$o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $x;
@@ -296,14 +299,14 @@ class Oep extends \Zotlabs\Web\Controller {
$o = "[share author='".urlencode($p[0]['author']['xchan_name']).
- "' profile='".$p[0]['author']['xchan_url'] .
- "' avatar='".$p[0]['author']['xchan_photo_s'].
- "' link='".$p[0]['plink'].
- "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
- "' posted='".$p[0]['created'].
- "' message_id='".$p[0]['mid']."']";
- if($p[0]['title'])
- $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
+ "' profile='".$p[0]['author']['xchan_url'] .
+ "' avatar='".$p[0]['author']['xchan_photo_s'].
+ "' link='".$p[0]['plink'].
+ "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
+ "' posted='".$p[0]['created'].
+ "' message_id='".$p[0]['mid']."']";
+ if($p[0]['title'])
+ $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n";
$o .= $x;
$o .= "[/share]";
@@ -374,7 +377,7 @@ class Oep extends \Zotlabs\Web\Controller {
"' profile='".$p[0]['author']['xchan_url'] .
"' avatar='".$p[0]['author']['xchan_photo_s'].
"' link='".$p[0]['plink'].
- "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
+ "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') .
"' posted='".$p[0]['created'].
"' message_id='".$p[0]['mid']."']";
if($p[0]['title'])
diff --git a/Zotlabs/Module/Outbox.php b/Zotlabs/Module/Outbox.php
new file mode 100644
index 000000000..503b464d1
--- /dev/null
+++ b/Zotlabs/Module/Outbox.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\Config;
+use Zotlabs\Lib\ThreadListener;
+use Zotlabs\Web\Controller;
+use Zotlabs\Web\HTTPSig;
+
+class Outbox extends Controller {
+
+ function init() {
+ if (ActivityStreams::is_as_request()) {
+
+ if (observer_prohibited(true)) {
+ killme();
+ }
+
+ $channel = channelx_by_nick(argv(1));
+ if (!$channel) {
+ killme();
+ }
+
+ if (intval($channel['channel_system'])) {
+ killme();
+ }
+
+ $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ if (!check_channelallowed($portable_id)) {
+ http_status_exit(403, 'Permission denied');
+ }
+ if (!check_siteallowed($sigdata['signer'])) {
+ http_status_exit(403, 'Permission denied');
+ }
+ observer_auth($portable_id);
+ }
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
+ }
+
+ $observer_hash = get_observer_hash();
+
+ $params = [];
+
+ $params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
+ $params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : '');
+ $params['type'] = 'json';
+ $params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0);
+ $params['top'] = ((x($_REQUEST, 'top')) ? intval($_REQUEST['top']) : 0);
+ $params['direction'] = ((x($_REQUEST, 'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented
+ $params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : '');
+ $params['compat'] = 1;
+
+ $total = items_fetch(
+ [
+ 'total' => true,
+ 'wall' => 1,
+ 'datequery' => $params['end'],
+ 'datequery2' => $params['begin'],
+ 'direction' => dbesc($params['direction']),
+ 'pages' => $params['pages'],
+ 'order' => dbesc('post'),
+ 'top' => $params['top'],
+ 'cat' => $params['cat'],
+ 'compat' => $params['compat']
+ ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
+ );
+
+ if ($total) {
+ App::set_pager_total($total);
+ App::set_pager_itemspage(30);
+ }
+
+ if (App::$pager['unset'] && $total > 30) {
+ $ret = Activity::paged_collection_init($total, App::$query_string);
+ }
+ else {
+
+ $items = items_fetch(
+ [
+ 'wall' => 1,
+ 'datequery' => $params['end'],
+ 'datequery2' => $params['begin'],
+ 'records' => intval(App::$pager['itemspage']),
+ 'start' => intval(App::$pager['start']),
+ 'direction' => dbesc($params['direction']),
+ 'pages' => $params['pages'],
+ 'order' => dbesc('post'),
+ 'top' => $params['top'],
+ 'cat' => $params['cat'],
+ 'compat' => $params['compat']
+ ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
+ );
+
+ if ($items && $observer_hash) {
+
+ // check to see if this observer is a connection. If not, register any items
+ // belonging to this channel for notification of deletion/expiration
+
+ $x = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval($channel['channel_id']),
+ dbesc($observer_hash)
+ );
+ if (!$x) {
+ foreach ($items as $item) {
+ if (strpos($item['mid'], z_root()) === 0) {
+ ThreadListener::store($item['mid'], $observer_hash);
+ }
+ }
+ }
+ }
+
+ $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total);
+ }
+
+ as_return_and_die($ret, $channel);
+ }
+ }
+}
diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php
index 9a3513f34..e30aa5fb4 100644
--- a/Zotlabs/Module/Owa.php
+++ b/Zotlabs/Module/Owa.php
@@ -32,14 +32,14 @@ class Owa extends Controller {
$keyId = $sigblock['keyId'];
if ($keyId) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE hubloc_id_url = '%s'",
+ WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ",
dbesc($keyId)
);
if (! $r) {
$found = discover_by_webbie(str_replace('acct:','',$keyId));
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE hubloc_id_url = '%s'",
+ WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ",
dbesc($keyId)
);
}
diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php
index 36201544f..3b94c9611 100644
--- a/Zotlabs/Module/Pdledit.php
+++ b/Zotlabs/Module/Pdledit.php
@@ -27,10 +27,10 @@ class Pdledit extends Controller {
info( t('Layout updated.') . EOL);
goaway(z_root() . '/pdledit/' . $_REQUEST['module']);
}
-
-
+
+
function get() {
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -39,10 +39,8 @@ class Pdledit extends Controller {
if(! Apps::system_app_installed(local_channel(), 'PDL Editor')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('PDL Editor App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Provides the ability to edit system page layouts');
- return $o;
+ $papp = Apps::get_papp('PDL Editor');
+ return Apps::app_render($papp, 'module');
}
if(argc() > 2 && argv(2) === 'reset') {
@@ -68,7 +66,7 @@ class Pdledit extends Controller {
$edited[] = substr(str_replace('.pdl','',$rv['k']),4);
}
}
-
+
$files = glob('Zotlabs/Module/*.php');
if($files) {
foreach($files as $f) {
@@ -81,21 +79,21 @@ class Pdledit extends Controller {
}
$o .= '</div>';
-
+
// list module pdl files
return $o;
}
-
+
$t = get_pconfig(local_channel(),'system',$module);
$s = file_get_contents(theme_include($module));
if(! $t) {
$t = $s;
- }
+ }
if(! $t) {
notice( t('Layout not found.') . EOL);
return '';
}
-
+
$o = replace_macros(get_markup_template('pdledit.tpl'),array(
'$header' => t('Edit System Page Description'),
'$mname' => t('Module Name:'),
@@ -107,8 +105,8 @@ class Pdledit extends Controller {
'$content' => htmlspecialchars($t,ENT_COMPAT,'UTF-8'),
'$submit' => t('Submit')
));
-
+
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Pdledit_gui.php b/Zotlabs/Module/Pdledit_gui.php
new file mode 100644
index 000000000..b550b92d3
--- /dev/null
+++ b/Zotlabs/Module/Pdledit_gui.php
@@ -0,0 +1,553 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Web\Controller;
+use Zotlabs\Render\Comanche;
+use Zotlabs\Lib\Libsync;
+
+class Pdledit_gui extends Controller {
+
+ function post() {
+
+ if (!local_channel()) {
+ return;
+ }
+
+ if (!$_REQUEST['module']) {
+ return;
+ }
+
+ $module = $_REQUEST['module'];
+
+ $ret = [
+ 'success' => false,
+ 'module' => $module
+ ];
+
+ if ($_REQUEST['reset']) {
+ del_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl');
+ Libsync::build_sync_packet();
+ $ret['success'] = true;
+ json_return_and_die($ret);
+ }
+
+ if ($_REQUEST['save']) {
+ if (!$_REQUEST['data']) {
+ return $ret;
+ }
+
+ $data = json_decode($_REQUEST['data'],true);
+ $stored_pdl_result = self::get_pdl($module);
+ $pdl = $stored_pdl_result['pdl'];
+
+ foreach ($data as $region => $entries) {
+ $region_pdl = '';
+ foreach ($entries as $entry) {
+ $region_pdl .= base64_decode($entry) . "\r\n";
+ }
+ $pdl = preg_replace('/\[region=' . $region . '\](.*?)\[\/region\]/ism', '[region=' . $region . ']' . "\r\n" . $region_pdl . "\r\n" . '[/region]', $pdl);
+ }
+
+ set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
+ Libsync::build_sync_packet();
+
+ $ret['success'] = true;
+ json_return_and_die($ret);
+ }
+
+ if ($_REQUEST['save_src']) {
+ set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($_REQUEST['src']));
+ Libsync::build_sync_packet();
+
+ $ret['success'] = true;
+ json_return_and_die($ret);
+ }
+
+ if ($_REQUEST['save_template']) {
+ if (!$_REQUEST['data']) {
+ return $ret;
+ }
+
+ $template = $_REQUEST['data'][0]['value'];
+ $pdl_result = self::get_pdl($module);
+ $stored_template = self::get_template($pdl_result['pdl']);
+
+ if ($template === $stored_template) {
+ $ret['success'] = true;
+ return $ret;
+ }
+
+ $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl_result['pdl'], $matches);
+ if ($cnt) {
+ $pdl = str_replace('[template]' . $stored_template . '[/template]', '[template]' . $template . '[/template]', $pdl_result['pdl']);
+ }
+ else {
+ $pdl = '[template]' . $template . '[/template]' . "\r\n";
+ $pdl .= $pdl_result['pdl'];
+ }
+
+ set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
+ Libsync::build_sync_packet();
+
+ $ret['success'] = true;
+ json_return_and_die($ret);
+ }
+
+ }
+
+ function get() {
+
+ if(! local_channel()) {
+ return EMPTY_STR;
+ }
+
+ $module = argv(1);
+
+ if (!$module) {
+ goaway(z_root() . '/pdledit_gui/hq');
+ }
+
+ $pdl_result = self::get_pdl($module);
+
+ $pdl = $pdl_result['pdl'];
+ $modified = $pdl_result['modified'];
+
+ if(!$pdl) {
+ return t('Layout not found');
+ }
+
+ $template = self::get_template($pdl);
+
+ $template_info = self::get_template_info($template);
+
+ if(empty($template_info['contentregion'])) {
+ return t('This template does not support pdledi_gui (no content regions defined)');
+ }
+
+ App::$page['template'] = $template;
+
+ $regions = self::get_regions($pdl);
+
+ foreach ($regions as $k => $v) {
+ $region_str = '';
+ if (is_array($v)) {
+ ksort($v);
+ foreach ($v as $entry) {
+ // Get the info from the file and replace entry if we get anything useful
+ $widget_info = get_widget_info($entry['name']);
+ $entry['name'] = (($widget_info['name']) ? $widget_info['name'] : $entry['name']);
+ $entry['desc'] = (($widget_info['description']) ? $widget_info['description'] : $entry['desc']);
+
+ $region_str .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
+ '$entry' => $entry
+ ]);
+ }
+ }
+ App::$layout['region_' . $k] = $region_str;
+ }
+
+ $templates = self::get_templates();
+ $templates_html = replace_macros(get_markup_template('pdledit_gui_templates.tpl'), [
+ '$templates' => $templates,
+ '$active' => $template
+ ]);
+
+ $items_html = '';
+
+ //$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
+ //'$entry' => [
+ //'type' => 'content',
+ //'name' => t('Main page content'),
+ //'src' => base64_encode('$content')
+ //],
+ //'$disable_controls' => true
+ //]);
+
+ foreach (self::get_widgets($module) as $entry) {
+ $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
+ '$entry' => $entry,
+ '$disable_controls' => true
+ ]);
+ }
+
+ foreach (self::get_menus() as $entry) {
+ $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
+ '$entry' => $entry,
+ '$disable_controls' => true
+ ]);
+ }
+
+ foreach (self::get_blocks() as $entry) {
+ $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
+ '$entry' => $entry,
+ '$disable_controls' => true
+ ]);
+ }
+
+ App::$layout['region_content'] .= replace_macros(get_markup_template('pdledit_gui.tpl'), [
+ '$content_regions' => $template_info['contentregion'],
+ '$page_src' => base64_encode($pdl),
+ '$templates' => base64_encode($templates_html),
+ '$modules' => base64_encode(self::get_modules()),
+ '$items' => base64_encode($items_html),
+ '$module_modified' => $modified,
+ '$module' => $module
+ ]);
+
+ }
+
+ function get_templates() {
+ $ret = [];
+
+ $files = glob('view/php/*.php');
+ if($files) {
+ foreach($files as $f) {
+ $name = basename($f, '.php');
+ $x = get_template_info($name);
+ if(!empty($x['contentregion'])) {
+ $ret[] = [
+ 'name' => $name,
+ 'desc' => $x['description']
+ ];
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ function get_modules() {
+ $ret = '';
+
+ $files = glob('Zotlabs/Module/*.php');
+ if($files) {
+ foreach($files as $f) {
+ $name = lcfirst(basename($f,'.php'));
+
+ if ($name === 'admin' && !is_site_admin()) {
+ continue;
+ }
+
+ $x = theme_include('mod_' . $name . '.pdl');
+ if($x) {
+ $ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>';
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ function get_widgets($module) {
+ $ret = [];
+
+ $checkpaths = [
+ 'Zotlabs/Widget/*.php'
+ ];
+
+ foreach ($checkpaths as $path) {
+ $files = glob($path);
+ if($files) {
+ foreach($files as $f) {
+ $name = lcfirst(basename($f, '.php'));
+
+ $widget_info = get_widget_info($name);
+ if ($widget_info['requires'] && strpos($widget_info['requires'], 'admin') !== false && !is_site_admin()) {
+ continue;
+ }
+
+ if ($widget_info['requires'] && strpos($widget_info['requires'], $module) === false) {
+ continue;
+ }
+
+ $ret[] = [
+ 'type' => 'widget',
+ 'name' => $widget_info['name'] ?? $name,
+ 'desc' => $widget_info['description'] ?? '',
+ 'src' => base64_encode('[widget=' . $name . '][/widget]')
+ ];
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ function get_menus() {
+ $ret = [];
+
+ $r = q("select * from menu where menu_channel_id = %d and menu_flags = 0",
+ intval(local_channel())
+ );
+
+ foreach ($r as $rr) {
+ $name = $rr['menu_name'];
+ $desc = $rr['menu_desc'];
+ $ret[] = [
+ 'type' => 'menu',
+ 'name' => $name,
+ 'desc' => $desc,
+ 'src' => base64_encode('[menu]' . $name . '[/menu]')
+ ];
+ }
+
+ return $ret;
+ }
+
+ function get_blocks() {
+ $ret = [];
+
+ $r = q("select v, title, summary from item join iconfig on iconfig.iid = item.id and item.uid = %d
+ and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'",
+ intval(local_channel())
+ );
+
+ foreach ($r as $rr) {
+ $name = $rr['v'];
+ $desc = (($rr['title']) ? $rr['title'] : $rr['summary']);
+ $ret[] = [
+ 'type' => 'block',
+ 'name' => $name,
+ 'desc' => $desc,
+ 'src' => base64_encode('[block]' . $name . '[/block]')
+ ];
+ }
+
+ return $ret;
+ }
+
+ function get_template($pdl) {
+ $ret = 'default';
+
+ $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl, $matches);
+ if($cnt && isset($matches[1])) {
+ $ret = trim($matches[1]);
+ }
+
+ return $ret;
+ }
+
+ function get_regions($pdl) {
+ $ret = [];
+ $supported_regions = ['aside', 'content', 'right_aside'];
+
+ $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $pdl, $matches, PREG_SET_ORDER);
+ if($cnt) {
+ foreach($matches as $mtch) {
+ if (!in_array($mtch[1], $supported_regions)) {
+ continue;
+ }
+ $ret[$mtch[1]] = self::parse_region($mtch[2]);
+ }
+ }
+
+ return $ret;
+ }
+
+ function parse_region($pdl) {
+ $ret = [];
+
+ $cnt = preg_match_all('/\$content\b/ism', $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
+ if($cnt) {
+ foreach($matches as $mtch) {
+ $offset = intval($mtch[0][1]);
+ $name = trim($mtch[0][0]);
+ //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
+ $src = base64_encode($mtch[0][0]);
+ $ret[$offset] = [
+ 'type' => 'content',
+ 'name' => t('Main page content'),
+ 'desc' => t('The main page content can not be edited!'),
+ 'src' => $src
+ ];
+ }
+ }
+
+ $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
+ if($cnt) {
+ foreach($matches as $mtch) {
+ $offset = intval($mtch[1][1]);
+ $name = trim($mtch[1][0]);
+ //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
+ $src = base64_encode($mtch[0][0]);
+
+ $ret[$offset] = [
+ 'type' => 'menu',
+ 'name' => $name,
+ 'desc' => '',
+ 'src' => $src
+ ];
+ }
+ }
+
+ // menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu]
+ // allows different menu renderings to be applied
+
+ //$cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
+ //if($cnt) {
+ //foreach($matches as $mtch) {
+ //$s = str_replace($mtch[0],$this->menu(trim($mtch[2]),$mtch[1]),$s);
+ //}
+ //}
+
+
+ $cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
+ if($cnt) {
+ foreach($matches as $mtch) {
+ $offset = intval($mtch[1][1]);
+ $name = trim($mtch[1][0]);
+ //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
+ $src = base64_encode($mtch[0][0]);
+ $ret[$offset] = [
+ 'type' => 'block',
+ 'name' => $name,
+ 'desc' => '',
+ 'src' => $src
+ ];
+ }
+ }
+
+ //$cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER);
+ //if($cnt) {
+ //foreach($matches as $mtch) {
+ //$s = str_replace($mtch[0],$this->block(trim($mtch[2]),trim($mtch[1])),$s);
+ //}
+ //}
+
+ //$cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER);
+ //if($cnt) {
+ //foreach($matches as $mtch) {
+ //$s = str_replace($mtch[0],$this->js(trim($mtch[1])),$s);
+ //}
+ //}
+
+ //$cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER);
+ //if($cnt) {
+ //foreach($matches as $mtch) {
+ //$s = str_replace($mtch[0],$this->css(trim($mtch[1])),$s);
+ //}
+ //}
+
+ // need to modify this to accept parameters
+
+ $cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
+
+ if($cnt) {
+ foreach($matches as $mtch) {
+ $offset = intval($mtch[1][1]);
+ $name = trim($mtch[1][0]);
+ //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
+ $src = base64_encode($mtch[0][0]);
+ $ret[$offset] = [
+ 'type' => 'widget',
+ 'name' => $name,
+ 'desc' => '',
+ 'src' => $src
+ ];
+ }
+ }
+
+ return $ret;
+
+ }
+
+
+ /**
+ * @brief Parse template comment in search of template info.
+ *
+ * like
+ * \code
+ * * Name: MyWidget
+ * * Description: A widget
+ * * Version: 1.2.3
+ * * Author: John <profile url>
+ * * Author: Jane <email>
+ * * ContentRegionID: some_id
+ * * ContentRegionID: some_other_id
+ * *
+ *\endcode
+ * @param string $template the name of the template
+ * @return array with the information
+ */
+ function get_template_info($template){
+ $m = [];
+ $info = [
+ 'name' => $template,
+ 'description' => '',
+ 'author' => [],
+ 'maintainer' => [],
+ 'version' => '',
+ 'contentregion' => []
+ ];
+
+ $checkpaths = [
+ 'view/php/' . $template . '.php',
+ ];
+
+ $template_found = false;
+
+ foreach ($checkpaths as $path) {
+ if (is_file($path)) {
+ $template_found = true;
+ $f = file_get_contents($path);
+ break;
+ }
+ }
+
+ if(!($template_found && $f))
+ return $info;
+
+ $f = escape_tags($f);
+ $r = preg_match('|/\*.*\*/|msU', $f, $m);
+
+ if ($r) {
+ $ll = explode("\n", $m[0]);
+ foreach($ll as $l) {
+ $l = trim($l, "\t\n\r */");
+ if ($l != ''){
+ list($k, $v) = array_map('trim', explode(':', $l, 2));
+ $k = strtolower($k);
+ if (in_array($k, ['author', 'maintainer'])){
+ $r = preg_match('|([^<]+)<([^>]+)>|', $v, $m);
+ if ($r) {
+ $info[$k][] = array('name' => $m[1], 'link' => $m[2]);
+ } else {
+ $info[$k][] = array('name' => $v);
+ }
+ }
+ elseif (in_array($k, ['contentregion'])){
+ $info[$k][] = array_map('trim', explode(',', $v));
+ }
+ else {
+ $info[$k] = $v;
+ }
+ }
+ }
+ }
+
+ return $info;
+ }
+
+ function get_pdl($module) {
+ $ret = [
+ 'pdl' => null,
+ 'modified' => true
+ ];
+
+ $pdl_path = 'mod_' . $module . '.pdl';
+
+ $ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl_path);
+
+ if(!$ret['pdl']) {
+ $pdl_path = theme_include($pdl_path);
+ if ($pdl_path) {
+ $ret['pdl'] = file_get_contents($pdl_path);
+ $ret['modified'] = false;
+ }
+ }
+
+ return $ret;
+ }
+}
diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php
index 6a599282c..d42e45beb 100644
--- a/Zotlabs/Module/Permcats.php
+++ b/Zotlabs/Module/Permcats.php
@@ -3,132 +3,265 @@
namespace Zotlabs\Module;
use App;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Access\Permissions;
use Zotlabs\Web\Controller;
-use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
+use Zotlabs\Lib\AccessList;
+use Zotlabs\Lib\Permcat;
class Permcats extends Controller {
function post() {
- if(! local_channel())
- return;
-
- if(! Apps::system_app_installed(local_channel(), 'Permission Categories'))
+ if (!local_channel())
return;
$channel = App::get_channel();
check_form_security_token_redirectOnErr('/permcats', 'permcats');
+ $name = escape_tags(trim($_REQUEST['name']));
+ $is_system_role = isset($_REQUEST['is_system_role']);
+ $return_path = z_root() . '/permcats/' . $_REQUEST['return_path'];
+ $group_hash = $_REQUEST['group_select'] ?? '';
+ $deleted_role = $_REQUEST['deleted_role'] ?? '';
+ $new_role = $_REQUEST['new_role'] ?? '';
+ $contacts = [];
- $all_perms = \Zotlabs\Access\Permissions::Perms();
- $name = escape_tags(trim($_POST['name']));
- if(! $name) {
- notice( t('Permission category name is required.') . EOL);
- return;
+ if (argv(1) && hex2bin(argv(1)) !== $name) {
+ $return_path = z_root() . '/permcats/' . bin2hex($name);
}
+ if ($deleted_role && $new_role) {
+ $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0",
+ intval(local_channel()),
+ dbesc($deleted_role)
+ );
- $pcarr = [];
+ if ($r) {
+ $contacts = ids_to_array($r, 'abook_xchan');
+ }
- if($all_perms) {
- foreach($all_perms as $perm => $desc) {
- if(array_key_exists('perms_' . $perm, $_POST)) {
- $pcarr[] = $perm;
- }
+ if ($contacts) {
+ Permcat::assign($channel, $new_role, $contacts);
}
- }
-
- \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr);
- Libsync::build_sync_packet();
+ Permcat::delete(local_channel(), $deleted_role);
- info( t('Permission category saved.') . EOL);
-
- return;
- }
-
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat', 'default');
+ if ($deleted_role === $default_role) {
+ set_pconfig(local_channel(), 'system', 'default_permcat', $new_role);
+ }
- function get() {
+ Libsync::build_sync_packet();
+ info(t('Contact role deleted.') . EOL);
+
+ goaway(z_root() . '/permcats/' . bin2hex($new_role));
- if(! local_channel())
return;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
+ if ($group_hash === 'all_contacts') {
+ $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d and abook_self = 0 and abook_pending = 0",
+ intval(local_channel())
+ );
- $o = '<b>' . t('Permission Categories App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Create custom connection permission limits');
- return $o;
+ if ($r) {
+ $contacts = ids_to_array($r, 'abook_xchan');
+ }
}
- $channel = App::get_channel();
+ $group = null;
+ if (!$contacts && $group_hash) {
+ $group = AccessList::by_hash(local_channel(), $group_hash);
+ }
+
+ if ($group) {
+ $contacts = AccessList::members_xchan(local_channel(), $group['id']);
+ }
+
+ if (!$name) {
+ notice(t('Permission category name is required.') . EOL);
+ return;
+ }
+
+ set_pconfig(local_channel(), 'system', 'default_permcat', 'default');
+
+ if (isset($_REQUEST['default_role'])) {
+ set_pconfig(local_channel(), 'system', 'default_permcat', $name);
+ }
- if(argc() > 1)
- $name = hex2bin(argv(1));
+ if ($is_system_role) {
+ // if we have a system role just set the default and assign if aplicable and be done with it
+ if ($contacts) {
+ Permcat::assign($channel, $name, $contacts);
+ }
- if(argc() > 2 && argv(2) === 'drop') {
- \Zotlabs\Lib\Permcat::delete(local_channel(),$name);
+ info(t('Contact role saved.') . EOL);
Libsync::build_sync_packet();
- json_return_and_die([ 'success' => true ]);
+ goaway($return_path);
+ return;
}
+ $pcarr = [];
+ $all_perms = Permissions::Perms();
- $desc = t('Use this form to create permission rules for various classes of people or connections.');
+ if ($all_perms) {
+ foreach ($all_perms as $perm => $desc) {
+ if (array_key_exists('perms_' . $perm, $_POST)) {
+ $pcarr[] = $perm;
+ }
+ }
+ }
- $existing = [];
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $existing_raw_perms = [];
- $pcat = new \Zotlabs\Lib\Permcat(local_channel());
- $pcatlist = $pcat->listing();
- $permcats = [];
- if($pcatlist) {
- foreach($pcatlist as $pc) {
- if(($pc['name']) && ($name) && ($pc['name'] == $name))
- $existing = $pc['perms'];
- if(! $pc['system'])
- $permcats[bin2hex($pc['name'])] = $pc['localname'];
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
+ if ($pc['name'] && ($pc['name'] === $name)) {
+ $existing_raw_perms = $pc['raw_perms'];
+ }
+ }
+ }
+
+ if (!$contacts && array_diff_assoc($existing_raw_perms, Permissions::FilledPerms($pcarr))) {
+ // If we don't have anyone to assign the role to and an existing role has changed,
+ // we will re-assign the changed role to all its members if there are any.
+
+ $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0",
+ intval(local_channel()),
+ dbesc($name)
+ );
+
+ if ($r) {
+ $contacts = ids_to_array($r, 'abook_xchan');
}
+
+ }
+
+ Permcat::update(local_channel(), $name, $pcarr);
+
+ if ($contacts) {
+ Permcat::assign($channel, $name, $contacts);
+ }
+
+ Libsync::build_sync_packet();
+
+ info(t('Contact role saved.') . EOL);
+ goaway($return_path);
+
+ return;
+ }
+
+
+ function get() {
+
+ if (!local_channel())
+ return EMPTY_STR;
+
+ nav_set_selected('Contact Roles');
+
+ $name = '';
+ if (argc() > 1) {
+ $name = hex2bin(argv(1));
}
- $global_perms = \Zotlabs\Access\Permissions::Perms();
+ $perms = [];
+ $existing = [];
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $is_system_role = false;
+ $delete_role_select_options = [];
+ $is_default_role = (get_pconfig(local_channel(), 'system', 'default_permcat', 'default') === $name);
+ $localname = '';
+
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
+ if ($pc['name'] && $name && ($pc['name'] === $name)) {
+ $existing = $pc['perms'];
+ if (isset($pc['system']) && intval($pc['system']))
+ $is_system_role = $pc['name'];
+ }
+
+ if ($pc['name'] == $name) {
+ $localname = $pc['localname'];
+ }
- foreach($global_perms as $k => $v) {
- $thisperm = \Zotlabs\Lib\Permcat::find_permcat($existing,$k);
- $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
+ if ($pc['name'] !== $name) {
+ $delete_role_select_options[$pc['name']] = $pc['localname'];
+ }
- if($existing[$k])
- $thisperm = "1";
+ }
+ }
- $perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
+ // select for delete action
+ $delete_role_select = [
+ 'new_role',
+ (($is_default_role) ? t('Role to assign affected contacts and default role to') : t('Role to assign affected contacts to')),
+ '',
+ '',
+ $delete_role_select_options
+ ];
+
+ $global_perms = Permissions::Perms();
+
+ foreach ($global_perms as $k => $v) {
+ $thisperm = Permcat::find_permcat($existing, $k);
+ $checkinherited = PermissionLimits::Get(local_channel(), $k);
+
+ if ($existing[$k])
+ $thisperm = 1;
+
+ $perms[] = [
+ 'perms_' . $k,
+ $v,
+ '',
+ $thisperm,
+ 1,
+ (($checkinherited & PERMS_SPECIFIC) ? '' : '1'),
+ '',
+ $checkinherited
+ ];
}
+ $group_select_options = [
+ 'selected' => '',
+ 'form_id' => 'group_select',
+ 'label' => t('Assign this role to'),
+ 'after' => [
+ 'name' => t('All my contacts'),
+ 'id' => 'all_contacts',
+ 'selected' => false
+ ]
+ ];
+ $group_select = AccessList::select(local_channel(), $group_select_options);
$tpl = get_markup_template("permcats.tpl");
- $o .= replace_macros($tpl, array(
+ $o = replace_macros($tpl, [
'$form_security_token' => get_form_security_token("permcats"),
- '$title' => t('Permission Categories'),
- '$desc' => $desc,
- '$desc2' => $desc2,
- '$tokens' => $t,
- '$permcats' => $permcats,
- '$atoken' => $atoken,
- '$url1' => z_root() . '/channel/' . $channel['channel_address'],
- '$url2' => z_root() . '/photos/' . $channel['channel_address'],
- '$name' => array('name', t('Permission category name') . ' <span class="required">*</span>', (($name) ? $name : ''), ''),
- '$me' => t('My Settings'),
- '$perms' => $perms,
- '$inherited' => t('inherited'),
- '$notself' => 0,
- '$self' => 1,
- '$permlbl' => t('Individual Permissions'),
- '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
- '$submit' => t('Submit')
- ));
+ '$default_role' => ['default_role', t('Automatically assign this role to new contacts'), intval($is_default_role), '', [t('No'), t('Yes')]],
+ '$title' => t('Contact Roles'),
+ '$name' => ['name', t('Role name') . ' <span class="required">*</span>', (($localname) ? $localname : ''), (($is_system_role) ? t('System role - not editable') : ''), '', (($is_system_role) ? 'disabled' : '')],
+ '$delete_label' => t('Deleting') . ' ' . $localname,
+ '$current_role' => $name,
+ '$perms' => $perms,
+ '$inherited' => t('inherited'),
+ '$is_system_role' => $is_system_role,
+ '$permlbl' => t('Role Permissions'),
+ '$permnote' => t('Some permissions may be inherited from your <a href="settings">channel role</a>, which have higher priority than contact role settings.'),
+ '$submit' => t('Submit'),
+ '$return_path' => argv(1),
+ '$group_select' => $group_select,
+ '$delete_role_select' => $delete_role_select,
+ '$delet_role_button' => t('Delete')
+ ]);
+
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php
index 87697f5a7..10d2e8f47 100644
--- a/Zotlabs/Module/Photo.php
+++ b/Zotlabs/Module/Photo.php
@@ -3,6 +3,12 @@
namespace Zotlabs\Module;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Web\HTTPSig;
+use Zotlabs\Lib\Config;
+
+
require_once('include/security.php');
require_once('include/attach.php');
require_once('include/photo/photo_driver.php');
@@ -11,6 +17,48 @@ class Photo extends \Zotlabs\Web\Controller {
function init() {
+ if (ActivityStreams::is_as_request()) {
+
+ $sigdata = HTTPSig::verify(EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ if (! check_channelallowed($portable_id)) {
+ http_status_exit(403, 'Permission denied');
+ }
+ if (! check_siteallowed($sigdata['signer'])) {
+ http_status_exit(403, 'Permission denied');
+ }
+ observer_auth($portable_id);
+ }
+ elseif (Config::get('system','require_authenticated_fetch',false)) {
+ http_status_exit(403,'Permission denied');
+ }
+
+ $observer_xchan = get_observer_hash();
+ $allowed = false;
+
+ $bear = Activity::token_from_request();
+ if ($bear) {
+ logger('bear: ' . $bear, LOGGER_DEBUG);
+ }
+
+ $r = q("select * from item where resource_type = 'photo' and resource_id = '%s' limit 1",
+ dbesc(argv(1))
+ );
+ if ($r) {
+ $allowed = attach_can_view($r[0]['uid'],$observer_xchan,argv(1)/*,$bear*/);
+ }
+ if (! $allowed) {
+ http_status_exit(404,'Permission denied.');
+ }
+ $channel = channelx_by_n($r[0]['uid']);
+
+ $obj = json_decode($r[0]['obj'],true);
+
+ as_return_and_die($obj,$channel);
+
+ }
+
$streaming = null;
$channel = null;
$person = 0;
@@ -33,19 +81,19 @@ class Photo extends \Zotlabs\Web\Controller {
$cache_mode = [ 'on' => false, 'age' => 86400, 'exp' => true, 'leak' => false ];
call_hooks('cache_mode_hook', $cache_mode);
-
+
$observer_xchan = get_observer_hash();
$cachecontrol = ', no-cache';
if(isset($type)) {
-
+
/**
* Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
- *
+ *
*/
-
+
$default = get_default_profile_photo();
-
+
if($type === 'profile') {
switch($res) {
case 'm':
@@ -62,9 +110,9 @@ class Photo extends \Zotlabs\Web\Controller {
break;
}
}
-
+
$uid = $person;
-
+
$data = '';
if ($uid > 0) {
@@ -81,13 +129,13 @@ class Photo extends \Zotlabs\Web\Controller {
else
$data = dbunescbin($r[0]['content']);
}
-
+
if(! $data) {
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
-
+
$resolution = $d['imgscale'];
- $uid = $d['channel_id'];
+ $uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
@@ -105,11 +153,11 @@ class Photo extends \Zotlabs\Web\Controller {
$cachecontrol .= ', must-revalidate';
}
else {
-
+
/**
* Other photos
*/
-
+
/* Check for a cookie to indicate display pixel density, in order to detect high-resolution
displays. This procedure was derived from the "Retina Images" by Jeremey Worboys,
used in accordance with the Creative Commons Attribution 3.0 Unported License.
@@ -127,12 +175,12 @@ class Photo extends \Zotlabs\Web\Controller {
// $prvcachecontrol = 'no-cache';
$status = 'no cookie';
}
-
+
$resolution = 0;
-
+
if(strpos($photo,'.') !== false)
$photo = substr($photo,0,strpos($photo,'.'));
-
+
if(substr($photo,-2,1) == '-') {
$resolution = intval(substr($photo,-1,1));
$photo = substr($photo,0,-2);
@@ -140,7 +188,7 @@ class Photo extends \Zotlabs\Web\Controller {
if ($resolution == 2 && ($cookie_value > 1))
$resolution = 1;
}
-
+
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
dbesc($photo),
intval($resolution)
@@ -151,7 +199,7 @@ class Photo extends \Zotlabs\Web\Controller {
$u = intval($r[0]['photo_usage']);
if($u) {
$allowed = 1;
- if($u === PHOTO_COVER)
+ if($u === PHOTO_COVER)
if($resolution < PHOTO_RES_COVER_1200)
$allowed = (-1);
if($u === PHOTO_PROFILE)
@@ -184,9 +232,9 @@ class Photo extends \Zotlabs\Web\Controller {
dbesc($photo),
intval($resolution)
);
-
+
$exists = (($e) ? true : false);
-
+
if($exists && $allowed) {
$expires = strtotime($e[0]['expires'] . 'Z');
$data = dbunescbin($e[0]['content']);
@@ -209,16 +257,16 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
- }
+ }
else
http_status_exit(404,'not found');
}
if(! $data)
killme();
-
+
$etag = '"' . md5($data . $modified) . '"';
-
+
if($modified == 0)
$modified = time();
@@ -241,39 +289,39 @@ class Photo extends \Zotlabs\Web\Controller {
}
if(isset($prvcachecontrol)) {
-
+
// it is a private photo that they have no permission to view.
// tell the browser not to cache it, in case they authenticate
// and subsequently have permission to see it
-
+
header("Cache-Control: " . $prvcachecontrol);
-
+
}
else {
// The photo cache default is 1 day to provide a privacy trade-off,
- // as somebody reducing photo permissions on a photo that is already
+ // as somebody reducing photo permissions on a photo that is already
// "in the wild" won't be able to stop the photo from being viewed
// for this amount amount of time once it is in the browser cache.
- // The privacy expectations of your site members and their perception
+ // The privacy expectations of your site members and their perception
// of privacy where it affects the entire project may be affected.
- // This has performance considerations but we highly recommend you
- // leave it alone.
-
+ // This has performance considerations but we highly recommend you
+ // leave it alone.
+
$maxage = $cache_mode['age'];
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
$expires = time() + $maxage;
else
$maxage = $expires - time();
-
+
header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
- // set CDN/Infrastructure caching much lower than maxage
+ // set CDN/Infrastructure caching much lower than maxage
// in the event that infrastructure caching is present.
$smaxage = intval($maxage/12);
header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
-
+
}
header("Content-type: " . $mimetype);
@@ -281,7 +329,7 @@ class Photo extends \Zotlabs\Web\Controller {
header("ETag: " . $etag);
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
- // If it's a file resource, stream it.
+ // If it's a file resource, stream it.
if($streaming) {
if(strpos($streaming,'store') !== false)
$istream = fopen($streaming,'rb');
@@ -300,5 +348,5 @@ class Photo extends \Zotlabs\Web\Controller {
killme();
}
-
+
}
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index e62accb06..45fe3d9e0 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -171,6 +171,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
+
}
if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) {
@@ -501,6 +502,9 @@ class Photos extends \Zotlabs\Web\Controller {
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
+ if(is_ajax())
+ killme();
+
goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']);
}
@@ -709,13 +713,15 @@ class Photos extends \Zotlabs\Web\Controller {
]);
if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) {
- \App::set_pager_itemspage(30);
$album = $x['display_path'];
}
else {
- goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
+ $album = '/';
+ //goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']);
}
+ \App::set_pager_itemspage(30);
+
if($_GET['order'] === 'posted')
$order = 'ASC';
else
@@ -1178,10 +1184,8 @@ class Photos extends \Zotlabs\Web\Controller {
if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan'])
$drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete')));
-
$name_e = $profile_name;
$title_e = $item['title'];
- unobscure($item);
$body_e = prepare_text($item['body'],$item['mimetype']);
$comments .= replace_macros($template,array(
diff --git a/Zotlabs/Module/Pin.php b/Zotlabs/Module/Pin.php
index e02fb017b..f82327ce6 100644
--- a/Zotlabs/Module/Pin.php
+++ b/Zotlabs/Module/Pin.php
@@ -37,7 +37,7 @@ class Pin extends \Zotlabs\Web\Controller {
http_status_exit(404, 'Not found');
}
- $midb64 = 'b64.' . base64url_encode($r[0]['mid']);
+ $midb64 = gen_link_id($r[0]['mid']);
$pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false);
switch(argv(1)) {
diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php
deleted file mode 100644
index 6e8042eaf..000000000
--- a/Zotlabs/Module/Ping.php
+++ /dev/null
@@ -1,707 +0,0 @@
-<?php
-
-namespace Zotlabs\Module;
-
-use Zotlabs\Lib\Apps;
-
-require_once('include/bbcode.php');
-
-/**
- * @brief Ping Controller.
- *
- */
-class Ping extends \Zotlabs\Web\Controller {
-
- /**
- * @brief do several updates when pinged.
- *
- * This function does several tasks. Whenever called it checks for new messages,
- * introductions, notifications, etc. and returns a json with the results.
- *
- * @result JSON
- */
- function init() {
-
- $result = array();
- $notifs = array();
-
- $result['notify'] = 0;
- $result['home'] = 0;
- $result['network'] = 0;
- $result['intros'] = 0;
- $result['mail'] = 0;
- $result['register'] = 0;
- $result['events'] = 0;
- $result['events_today'] = 0;
- $result['birthdays'] = 0;
- $result['birthdays_today'] = 0;
- $result['all_events'] = 0;
- $result['all_events_today'] = 0;
- $result['notice'] = [];
- $result['info'] = [];
- $result['pubs'] = 0;
- $result['files'] = 0;
- $result['forums'] = 0;
- $result['forums_sub'] = [];
-
- if(! $_SESSION['static_loadtime'])
- $_SESSION['static_loadtime'] = datetime_convert();
-
- $t0 = dba_timer();
-
- header("content-type: application/json");
-
- $vnotify = false;
-
- $item_normal = item_normal();
-
- if(local_channel()) {
- $vnotify = get_pconfig(local_channel(),'system','vnotify');
- $evdays = intval(get_pconfig(local_channel(),'system','evdays'));
- $ob_hash = get_observer_hash();
- }
-
- // if unset show all visual notification types
- if($vnotify === false)
- $vnotify = (-1);
- if($evdays < 1)
- $evdays = 3;
-
- /**
- * If you have several windows open to this site and switch to a different channel
- * in one of them, the others may get into a confused state showing you a page or options
- * on that page which were only valid under the old identity. You session has changed.
- * Therefore we send a notification of this fact back to the browser where it is picked up
- * in javascript and which reloads the page it is on so that it is valid under the context
- * of the now current channel.
- */
-
- $result['invalid'] = ((intval($_GET['uid'])) && (intval($_GET['uid']) != local_channel()) ? 1 : 0);
-
- /**
- * Send all system messages (alerts) to the browser.
- * Some are marked as informational and some represent
- * errors or serious notifications. These typically
- * will popup on the current page (no matter what page it is)
- */
-
- if(x($_SESSION, 'sysmsg')){
- foreach ($_SESSION['sysmsg'] as $m){
- $result['notice'][] = array('message' => $m);
- }
- unset($_SESSION['sysmsg']);
- }
- if(x($_SESSION, 'sysmsg_info')){
- foreach ($_SESSION['sysmsg_info'] as $m){
- $result['info'][] = array('message' => $m);
- }
- unset($_SESSION['sysmsg_info']);
- }
- if(! ($vnotify & VNOTIFY_INFO))
- $result['info'] = array();
- if(! ($vnotify & VNOTIFY_ALERT))
- $result['notice'] = array();
-
- if(\App::$install) {
- echo json_encode($result);
- killme();
- }
-
- /**
- * Update chat presence indication (if applicable)
- */
-
- if(get_observer_hash() && (! $result['invalid'])) {
- $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
- dbesc(get_observer_hash()),
- dbesc($_SERVER['REMOTE_ADDR'])
- );
- $basic_presence = false;
- if($r) {
- $basic_presence = true;
- q("update chatpresence set cp_last = '%s' where cp_id = %d",
- dbesc(datetime_convert()),
- intval($r[0]['cp_id'])
- );
- }
- if(! $basic_presence) {
- q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
- values( '%s', '%s', '%s', '%s' ) ",
- dbesc(get_observer_hash()),
- dbesc(datetime_convert()),
- dbesc('online'),
- dbesc($_SERVER['REMOTE_ADDR'])
- );
- }
- }
-
- /**
- * Chatpresence continued... if somebody hasn't pinged recently, they've most likely left the page
- * and shouldn't count as online anymore. We allow an expection for bots.
- */
-
- q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ",
- db_utcnow(), db_quoteinterval('3 MINUTE')
- );
-
-
- $sql_extra = '';
- if(! ($vnotify & VNOTIFY_LIKE))
- $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
-
- if(local_channel()) {
- $notify_pubs = ($vnotify & VNOTIFY_PUBS) && can_view_public_stream() && Apps::system_app_installed(local_channel(), 'Public Stream');
- }
- else {
- $notify_pubs = can_view_public_stream();
- }
-
- if($notify_pubs) {
- $sys = get_sys_channel();
-
- $pubs = q("SELECT count(id) as total from item
- WHERE uid = %d
- AND item_unseen = 1
- AND author_xchan != '%s'
- AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "'
- $item_normal
- $sql_extra",
- intval($sys['channel_id']),
- dbesc(get_observer_hash())
- );
-
- if($pubs)
- $result['pubs'] = intval($pubs[0]['total']);
- }
-
-
-
- if((argc() > 1) && (argv(1) === 'pubs') && ($notify_pubs)) {
- $sys = get_sys_channel();
- $result = array();
-
- $r = q("SELECT * FROM item
- WHERE uid = %d
- AND item_unseen = 1
- AND author_xchan != '%s'
- AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "'
- $item_normal
- $sql_extra
- ORDER BY created DESC
- LIMIT 300",
- intval($sys['channel_id']),
- dbesc(get_observer_hash())
- );
-
- if($r) {
- xchan_query($r);
- foreach($r as $rr) {
- $rr['llink'] = str_replace('display/', 'pubstream/?f=&mid=', $rr['llink']);
- $result[] = \Zotlabs\Lib\Enotify::format($rr);
- }
- }
-
-// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- $t1 = dba_timer();
-
- if((! local_channel()) || ($result['invalid'])) {
- echo json_encode($result);
- killme();
- }
-
- /**
- * Everything following is only permitted under the context of a locally authenticated site member.
- */
-
- /**
- * Handle "mark all xyz notifications read" requests.
- */
-
- // mark all items read
- if(x($_REQUEST, 'markRead') && local_channel()) {
- switch($_REQUEST['markRead']) {
- case 'network':
- $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1",
- intval(local_channel())
- );
- break;
- case 'home':
- $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1",
- intval(local_channel())
- );
- break;
- case 'mail':
- $r = q("UPDATE mail SET mail_seen = 1 WHERE channel_id = %d AND mail_seen = 0",
- intval(local_channel())
- );
- break;
- case 'all_events':
- $r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
- break;
- case 'notify':
- $r = q("update notify set seen = 1 where uid = %d",
- intval(local_channel())
- );
- break;
- case 'pubs':
- unset($_SESSION['static_loadtime']);
- break;
- default:
- break;
- }
- }
-
- if(x($_REQUEST, 'markItemRead') && local_channel()) {
- $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d",
- intval(local_channel()),
- intval($_REQUEST['markItemRead'])
- );
- }
-
- /**
- * URL ping/something will return detail for "something", e.g. a json list with which to populate a notification
- * dropdown menu.
- */
- if(argc() > 1 && argv(1) === 'notify') {
- $t = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY CREATED DESC",
- intval(local_channel())
- );
-
- if($t) {
- foreach($t as $tt) {
- $message = trim(strip_tags(bbcode($tt['msg'])));
-
- if(strpos($message, $tt['xname']) === 0)
- $message = substr($message, strlen($tt['xname']) + 1);
-
- $mid = basename($tt['link']);
- $mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid);
-
- if(in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
- // we need the thread parent
- $r = q("select thr_parent from item where mid = '%s' and uid = %d limit 1",
- dbesc($mid),
- intval(local_channel())
- );
- $b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : 'b64.' . base64url_encode($r[0]['thr_parent']));
- }
- else {
- $b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
- }
-
- $notifs[] = array(
- 'notify_link' => z_root() . '/notify/view/' . $tt['id'],
- 'name' => $tt['xname'],
- 'url' => $tt['url'],
- 'photo' => $tt['photo'],
- 'when' => relative_date($tt['created']),
- 'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
- 'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'),
- 'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'),
- 'message' => $message
- );
- }
- }
-
- echo json_encode(array('notify' => $notifs));
- killme();
- }
-
- if(argc() > 1 && argv(1) === 'mail') {
- $channel = \App::get_channel();
- $t = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
- where channel_id = %d and mail_seen = 0 and mail_deleted = 0
- and from_xchan != '%s' order by created desc limit 50",
- intval(local_channel()),
- dbesc($channel['channel_hash'])
- );
-
- if($t) {
- foreach($t as $zz) {
- $notifs[] = array(
- 'notify_link' => z_root() . '/mail/' . $zz['id'],
- 'name' => $zz['xchan_name'],
- 'addr' => $zz['xchan_addr'],
- 'url' => $zz['xchan_url'],
- 'photo' => $zz['xchan_photo_s'],
- 'when' => relative_date($zz['created']),
- 'hclass' => (intval($zz['mail_seen']) ? 'notify-seen' : 'notify-unseen'),
- 'message' => t('sent you a private message'),
- );
- }
- }
-
- echo json_encode(array('notify' => $notifs));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
- $result = array();
-
- if(argv(1) === 'home') {
- $sql_extra .= ' and item_wall = 1 ';
- }
-
- $r = q("SELECT * FROM item
- WHERE uid = %d
- AND item_unseen = 1
- AND author_xchan != '%s'
- $item_normal
- $sql_extra
- ORDER BY created DESC
- LIMIT 300",
- intval(local_channel()),
- dbesc($ob_hash)
- );
-
- if($r) {
- xchan_query($r);
- foreach($r as $item) {
- $result[] = \Zotlabs\Lib\Enotify::format($item);
- }
- }
-// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'intros')) {
- $result = array();
-
- $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ORDER BY abook_created DESC LIMIT 50",
- intval(local_channel())
- );
-
- if($r) {
- foreach($r as $rr) {
- $result[] = array(
- 'notify_link' => z_root() . '/connections/ifpending',
- 'name' => $rr['xchan_name'],
- 'addr' => $rr['xchan_addr'],
- 'url' => $rr['xchan_url'],
- 'photo' => $rr['xchan_photo_s'],
- 'when' => relative_date($rr['abook_created']),
- 'hclass' => ('notify-unseen'),
- 'message' => t('added your channel')
- );
- }
- }
- logger('ping (intros): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if((argc() > 1 && (argv(1) === 'register')) && is_site_admin()) {
- $result = array();
-
- $r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0",
- intval(ACCOUNT_PENDING)
- );
- if($r) {
- foreach($r as $rr) {
- $result[] = array(
- 'notify_link' => z_root() . '/admin/accounts',
- 'name' => $rr['account_email'],
- 'addr' => $rr['account_email'],
- 'url' => '',
- 'photo' => z_root() . '/' . get_default_profile_photo(48),
- 'when' => relative_date($rr['account_created']),
- 'hclass' => ('notify-unseen'),
- 'message' => t('requires approval')
- );
- }
- }
- logger('ping (register): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'all_events')) {
- $bd_format = t('g A l F d') ; // 8 AM Friday January 18
-
- $result = array();
-
- $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash
- WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
- and etype in ( 'event', 'birthday' )
- ORDER BY dtstart DESC LIMIT 1000",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
-
- if($r) {
- foreach($r as $rr) {
-
- $strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart']);
- $today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
- $when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
-
- $result[] = array(
- 'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
- 'name' => $rr['xchan_name'],
- 'addr' => $rr['xchan_addr'],
- 'url' => $rr['xchan_url'],
- 'photo' => $rr['xchan_photo_s'],
- 'when' => $when,
- 'hclass' => ('notify-unseen'),
- 'message' => t('posted an event')
- );
- }
- }
- logger('ping (all_events): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- if(argc() > 1 && (argv(1) === 'files')) {
- $result = array();
-
- $r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item
- LEFT JOIN xchan on author_xchan = xchan_hash
- WHERE item.verb = '%s'
- AND item.obj_type = '%s'
- AND item.uid = %d
- AND item.owner_xchan != '%s'
- AND item.item_unseen = 1",
- dbesc(ACTIVITY_POST),
- dbesc(ACTIVITY_OBJ_FILE),
- intval(local_channel()),
- dbesc($ob_hash)
- );
- if($r) {
- foreach($r as $rr) {
- $result[] = array(
- 'notify_link' => z_root() . '/sharedwithme',
- 'name' => $rr['xchan_name'],
- 'addr' => $rr['xchan_addr'],
- 'url' => $rr['xchan_url'],
- 'photo' => $rr['xchan_photo_s'],
- 'when' => relative_date($rr['created']),
- 'hclass' => ('notify-unseen'),
- 'message' => t('shared a file with you')
- );
- }
- }
- logger('ping (files): ' . print_r($result, true), LOGGER_DATA);
- echo json_encode(array('notify' => $result));
- killme();
- }
-
- /**
- * Normal ping - just the counts, no detail
- */
- if($vnotify & VNOTIFY_SYSTEM) {
- $t = q("select count(*) as total from notify where uid = %d and seen = 0",
- intval(local_channel())
- );
- if($t)
- $result['notify'] = intval($t[0]['total']);
- }
-
- $t2 = dba_timer();
-
- if($vnotify & VNOTIFY_FILES) {
- $files = q("SELECT count(id) as total FROM item
- WHERE verb = '%s'
- AND obj_type = '%s'
- AND uid = %d
- AND owner_xchan != '%s'
- AND item_unseen = 1",
- dbesc(ACTIVITY_POST),
- dbesc(ACTIVITY_OBJ_FILE),
- intval(local_channel()),
- dbesc($ob_hash)
- );
- if($files)
- $result['files'] = intval($files[0]['total']);
- }
-
- $t3 = dba_timer();
-
- if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) {
-
- $r = q("SELECT id, item_wall FROM item
- WHERE uid = %d and item_unseen = 1
- $item_normal
- $sql_extra
- AND author_xchan != '%s'",
- intval(local_channel()),
- dbesc($ob_hash)
- );
-
- if($r) {
- $arr = array('items' => $r);
- call_hooks('network_ping', $arr);
-
- foreach ($r as $it) {
- if(intval($it['item_wall']))
- $result['home'] ++;
- else
- $result['network'] ++;
- }
- }
- }
- if(! ($vnotify & VNOTIFY_NETWORK))
- $result['network'] = 0;
- if(! ($vnotify & VNOTIFY_CHANNEL))
- $result['home'] = 0;
-
- $t4 = dba_timer();
-
- if($vnotify & VNOTIFY_INTRO) {
- $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
- intval(local_channel())
- );
-
- $t5 = dba_timer();
-
- if($intr)
- $result['intros'] = intval($intr[0]['total']);
- }
-
- $t6 = dba_timer();
- $channel = \App::get_channel();
-
- if($vnotify & VNOTIFY_MAIL) {
- $mails = q("SELECT count(id) as total from mail
- WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ",
- intval(local_channel()),
- dbesc($channel['channel_hash'])
- );
- if($mails)
- $result['mail'] = intval($mails[0]['total']);
- }
-
- if($vnotify & VNOTIFY_REGISTER) {
- if (\App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) {
- $regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0",
- intval(ACCOUNT_PENDING)
- );
- if($regs)
- $result['register'] = intval($regs[0]['total']);
- }
- }
-
- $t7 = dba_timer();
-
- if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) {
- $events = q("SELECT etype, dtstart, adjust FROM event
- WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0
- and etype in ( 'event', 'birthday' )
- ORDER BY dtstart ASC ",
- intval(local_channel()),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')),
- dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days'))
- );
-
- if($events) {
- $result['all_events'] = count($events);
-
- if($result['all_events']) {
- $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d');
- foreach($events as $x) {
- $bd = false;
- if($x['etype'] === 'birthday') {
- $result['birthdays'] ++;
- $bd = true;
- }
- else {
- $result['events'] ++;
- }
- if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['dtstart'], 'Y-m-d') === $str_now) {
- $result['all_events_today'] ++;
- if($bd)
- $result['birthdays_today'] ++;
- else
- $result['events_today'] ++;
- }
- }
- }
- }
- }
- if(! ($vnotify & VNOTIFY_EVENT))
- $result['all_events'] = $result['events'] = 0;
- if(! ($vnotify & VNOTIFY_EVENTTODAY))
- $result['all_events_today'] = $result['events_today'] = 0;
- if(! ($vnotify & VNOTIFY_BIRTHDAY))
- $result['birthdays'] = 0;
-
-
-
- if($vnotify & VNOTIFY_FORUMS) {
- $forums = get_forum_channels(local_channel());
-
- if($forums) {
- $item_normal = item_normal();
- $fcount = count($forums);
- $forums['total'] = 0;
-
- for($x = 0; $x < $fcount; $x ++) {
- $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
- intval(local_channel()),
- intval(TERM_FORUM),
- dbesc($forums[$x]['xchan_name'])
- );
-
- $p_str = ids_to_querystr($p, 'parent');
- $p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
-
- $r = q("select count(id) as unseen from item
- where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $item_normal $sql_extra",
- intval(local_channel()),
- dbesc($forums[$x]['xchan_hash']),
- dbesc($forums[$x]['xchan_hash'])
- );
- if($r[0]['unseen']) {
- $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']);
- $forums[$x]['name'] = $forums[$x]['xchan_name'];
- $forums[$x]['addr'] = $forums[$x]['xchan_addr'];
- $forums[$x]['url'] = $forums[$x]['xchan_url'];
- $forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
- $forums[$x]['unseen'] = $r[0]['unseen'];
- $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : '');
- $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
-
- $forums['total'] = $forums['total'] + $r[0]['unseen'];
-
- unset($forums[$x]['abook_id']);
- unset($forums[$x]['xchan_hash']);
- unset($forums[$x]['xchan_name']);
- unset($forums[$x]['xchan_url']);
- unset($forums[$x]['xchan_photo_s']);
-
- //if($forums[$x]['private_forum'])
- // unset($forums[$x]['private_forum']);
-
- }
- else {
- unset($forums[$x]);
- }
- }
- $result['forums'] = $forums['total'];
- unset($forums['total']);
-
- $result['forums_sub'] = $forums;
- }
- }
-
- $x = json_encode($result);
-
- $t8 = dba_timer();
-
-// logger('ping timer: ' . sprintf('%01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f',$t8 - $t7, $t7 - $t6, $t6 - $t5, $t5 - $t4, $t4 - $t3, $t3 - $t2, $t2 - $t1, $t1 - $t0));
-
- echo $x;
- killme();
- }
-
-}
diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php
index 1f1edfa18..d60a7f426 100644
--- a/Zotlabs/Module/Poke.php
+++ b/Zotlabs/Module/Poke.php
@@ -9,11 +9,11 @@ use Zotlabs\Web\Controller;
*
* Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
* This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
- * other web request. You must be logged in and connected to a channel.
+ * other web request. You must be logged in and connected to a channel.
* If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
* parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
* may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
- * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
+ * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
*
* private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
*
@@ -25,41 +25,41 @@ require_once('include/items.php');
class Poke extends Controller {
function init() {
-
+
if(! local_channel())
return;
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
return;
}
-
+
$uid = local_channel();
$channel = App::get_channel();
-
+
$verb = notags(trim($_REQUEST['verb']));
-
- if(! $verb)
+
+ if(! $verb)
return;
-
+
$verbs = get_poke_verbs();
-
+
if(! array_key_exists($verb,$verbs))
return;
-
+
$activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
-
+
$contact_id = intval($_REQUEST['cid']);
$xchan = trim($_REQUEST['xchan']);
if(! ($contact_id || $xchan))
return;
-
+
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
-
+
logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
-
-
+
+
if($contact_id) {
$r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
intval($contact_id),
@@ -71,17 +71,17 @@ class Poke extends Controller {
dbesc($xchan . '%')
);
}
-
+
if(! $r) {
logger('poke: no target.');
return;
}
-
+
$target = $r[0];
$parent_item = null;
-
+
if($parent) {
- $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
+ $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
from item where id = %d and parent = %d and uid = %d limit 1",
intval($parent),
intval($parent),
@@ -98,18 +98,18 @@ class Poke extends Controller {
}
}
elseif($contact_id) {
-
+
$item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
-
+
$allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
$allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
$deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
$deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
}
-
-
+
+
$arr = array();
-
+
$arr['item_wall'] = 1;
@@ -124,7 +124,7 @@ class Poke extends Controller {
$arr['item_private'] = $item_private;
$arr['obj_type'] = ACTIVITY_OBJ_PERSON;
$arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
-
+
$obj = array(
'type' => ACTIVITY_OBJ_PERSON,
'title' => $target['xchan_name'],
@@ -134,25 +134,25 @@ class Poke extends Controller {
array('rel' => 'photo', 'type' => $target['xchan_photo_mimetype'], 'href' => $target['xchan_photo_l'])
),
);
-
+
$arr['obj'] = json_encode($obj);
-
+
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['item_unseen'] = 1;
if(! $parent_item)
$item['item_thread_top'] = 1;
-
-
+
+
post_activity_item($arr);
-
+
return;
}
-
-
-
+
+
+
function get() {
-
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
@@ -161,19 +161,17 @@ class Poke extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Poke App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Poke somebody in your addressbook');
- return $o;
+ $papp = Apps::get_papp('Poke');
+ return Apps::app_render($papp, 'module');
}
nav_set_selected('Poke');
-
+
$name = '';
$id = '';
-
+
if(intval($_REQUEST['c'])) {
- $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
+ $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
where abook_id = %d and abook_channel = %d limit 1",
intval($_REQUEST['c']),
intval(local_channel())
@@ -183,17 +181,17 @@ class Poke extends Controller {
$id = $r[0]['abook_id'];
}
}
-
+
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
-
+
$verbs = get_poke_verbs();
-
+
$shortlist = array();
foreach($verbs as $k => $v)
if($v[1] !== 'NOTRANSLATION')
$shortlist[] = array($k,$v[1]);
-
-
+
+
$poke_basic = get_config('system','poke_basic');
if($poke_basic) {
$title = t('Poke');
@@ -203,7 +201,7 @@ class Poke extends Controller {
$title = t('Poke/Prod');
$desc = t('Poke, prod or do other things to somebody');
}
-
+
$o = replace_macros(get_markup_template('poke_content.tpl'),array(
'$title' => $title,
'$poke_basic' => $poke_basic,
@@ -218,8 +216,8 @@ class Poke extends Controller {
'$name' => $name,
'$id' => $id
));
-
+
return $o;
-
+
}
}
diff --git a/Zotlabs/Module/Post.php b/Zotlabs/Module/Post.php
deleted file mode 100644
index f67cbf020..000000000
--- a/Zotlabs/Module/Post.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * @file Zotlabs/Module/Post.php
- *
- * @brief Zot endpoint.
- *
- */
-
-namespace Zotlabs\Module;
-
-require_once('include/zot.php');
-
-/**
- * @brief Post module.
- *
- */
-class Post extends \Zotlabs\Web\Controller {
-
- function init() {
- if(array_key_exists('auth', $_REQUEST)) {
- $x = new \Zotlabs\Zot\Auth($_REQUEST);
- exit;
- }
- }
-
- function post() {
- if(array_key_exists('data',$_REQUEST)) {
- $z = new \Zotlabs\Zot\Receiver($_REQUEST['data'], get_config('system', 'prvkey'), new \Zotlabs\Zot\ZotHandler());
- exit;
- }
-
- }
-
-}
diff --git a/Zotlabs/Module/Prate.php b/Zotlabs/Module/Prate.php
deleted file mode 100644
index 8b71657b8..000000000
--- a/Zotlabs/Module/Prate.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-
-use Zotlabs\Lib\Crypto;
-
-class Prate extends \Zotlabs\Web\Controller {
-
- function init() {
- if($_SERVER['REQUEST_METHOD'] === 'post')
- return;
-
- if(! local_channel())
- return;
-
- $channel = \App::get_channel();
-
- $target = argv(1);
- if(! $target)
- return;
-
- $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc($target)
- );
- if($r)
- json_return_and_die(array('rating' => $r[0]['xlink_rating'],'rating_text' => $r[0]['xlink_rating_text']));
- killme();
- }
-
- function post() {
-
- if(! local_channel())
- return;
-
- $channel = \App::get_channel();
-
- $target = trim($_REQUEST['target']);
- if(! $target)
- return;
-
- if($target === $channel['channel_hash'])
- return;
-
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
-
- $signed = $target . '.' . $rating . '.' . $rating_text;
-
- $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey']));
-
-
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($target)
- );
- if($z) {
- $record = $z[0]['xlink_id'];
- $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
- where xlink_id = %d",
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert()),
- intval($record)
- );
- }
- else {
- $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
- dbesc($channel['channel_hash']),
- dbesc($target),
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert())
- );
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan'])
- );
- if($z)
- $record = $z[0]['xlink_id'];
- }
- if($record) {
- \Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record));
- }
-
- json_return_and_die(array('result' => true));;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-}
diff --git a/Zotlabs/Module/Probe.php b/Zotlabs/Module/Probe.php
deleted file mode 100644
index 3bc4dac72..000000000
--- a/Zotlabs/Module/Probe.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-use App;
-use Zotlabs\Lib\Apps;
-use Zotlabs\Lib\Crypto;
-
-require_once('include/zot.php');
-
-class Probe extends \Zotlabs\Web\Controller {
-
- function get() {
-
- if(local_channel()) {
- if(! Apps::system_app_installed(local_channel(), 'Remote Diagnostics')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
-
- $o = '<b>' . t('Remote Diagnostics App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Perform diagnostics on remote channels');
- return $o;
- }
- }
-
- nav_set_selected('Remote Diagnostics');
-
- $o .= '<h3>Remote Diagnostics</h3>';
-
- $o .= '<form action="probe" method="get">';
- $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
- $o .= '<input type="submit" name="submit" value="Submit" /></form>';
-
- $o .= '<br /><br />';
-
- if(x($_GET,'addr')) {
- $channel = App::get_channel();
- $addr = trim($_GET['addr']);
- $do_import = ((intval($_GET['import']) && is_site_admin()) ? true : false);
-
- $j = \Zotlabs\Zot\Finger::run($addr,$channel,false);
-
- $o .= '<pre>';
- if(! $j['success']) {
- $o .= "<strong>https connection failed. Trying again with auto failover to http.</strong>\r\n\r\n";
- $j = \Zotlabs\Zot\Finger::run($addr,$channel,true);
- if(! $j['success']) {
- return $o;
- }
- }
- if($do_import && $j)
- $x = import_xchan($j);
- if($j && $j['permissions'] && $j['permissions']['iv'])
- $j['permissions'] = json_decode(Crypto::unencapsulate($j['permissions'],$channel['channel_prvkey']),true);
- $o .= str_replace("\n",'<br />',print_r($j,true));
- $o .= '</pre>';
- }
- return $o;
- }
-
-}
diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php
index d6c80b653..022efc2cd 100644
--- a/Zotlabs/Module/Profile_photo.php
+++ b/Zotlabs/Module/Profile_photo.php
@@ -1,7 +1,11 @@
<?php
+
namespace Zotlabs\Module;
+use App;
+use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Libsync;
+use Zotlabs\Web\Controller;
/*
* @file Profile_photo.php
@@ -15,109 +19,123 @@ require_once('include/photos.php');
require_once('include/channel.php');
/* @brief Function for sync'ing permissions of profile-photos and their profile
-*
-* @param $profileid The id number of the profile to sync
-* @return void
-*/
-
+ *
+ */
+class Profile_photo extends Controller {
-class Profile_photo extends \Zotlabs\Web\Controller {
-
/* @brief Initalize the profile-photo edit view
*
- * @return void
- *
*/
-
+
function init() {
-
- if(! local_channel()) {
+
+ if (!local_channel()) {
return;
}
-
- $channel = \App::get_channel();
- profile_load($channel['channel_address']);
-
+
+ $channel = App::get_channel();
+ $profile = App::$argv[1];
+
+ profile_load($channel['channel_address'], $profile);
+
+
}
-
+
/* @brief Evaluate posted values
*
- * @param $a Current application
- * @return void
- *
*/
-
+
function post() {
-
- if(! local_channel()) {
+
+ if (!local_channel()) {
return;
}
-
- $channel = \App::get_channel();
-
+
+ $channel = App::get_channel();
+
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
-
- // Remove cover photo
- if(isset($_POST['remove'])) {
-
- $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
- intval(PHOTO_PROFILE),
- intval(local_channel())
- );
-
- if($r) {
- q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
- intval(local_channel())
- );
-
- $sync = attach_export_data($channel,$r[0]['resource_id']);
- if($sync)
- Libsync:: build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+
+ $r = q("select id, profile_guid, is_default, gender from profile where uid = %d",
+ intval(local_channel())
+ );
+
+ $profile_id = intval($_POST['profile']);
+ $default_profile_id = null;
+ $profile = [];
+
+ foreach ($r as $rr) {
+ if ($rr['is_default']) {
+ $default_profile_id = intval($rr['id']);
}
-
+
+ if ($profile_id === intval($rr['id'])) {
+ $profile = $rr;
+ }
+ }
+
+ $is_default_profile = ($profile_id === $default_profile_id);
+
+ // Remove profile photo
+ if (isset($_POST['remove'])) {
+
+ if ($is_default_profile) {
+
+ $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
+ intval(PHOTO_PROFILE),
+ intval(local_channel())
+ );
+
+ if ($r) {
+ q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval(local_channel())
+ );
+
+ q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
+ dbesc(z_root() . '/photo/profile/l/' . local_channel()),
+ dbesc(z_root() . '/photo/profile/m/' . local_channel()),
+ intval(local_channel())
+ );
+ }
+ }
+ else {
+ q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
+ dbesc(z_root() . '/' . get_default_profile_photo(300)),
+ dbesc(z_root() . '/' . get_default_profile_photo(80)),
+ intval($profile_id),
+ intval(local_channel())
+ );
+ }
+
+ $sync = attach_export_data($channel, $r[0]['resource_id']);
+ if ($sync)
+ Libsync:: build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
+
$_SESSION['reload_avatar'] = true;
-
- goaway(z_root() . '/profiles');
+
+ goaway(z_root() . '/profiles/' . $profile_id);
}
-
- if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
-
+
+ if ((array_key_exists('cropfinal', $_POST)) && (intval($_POST['cropfinal']) == 1)) {
+
// logger('crop: ' . print_r($_POST,true));
// phase 2 - we have finished cropping
-
- if(argc() != 2) {
- notice( t('Image uploaded but image cropping failed.') . EOL );
+
+ if (argc() != 2) {
+ notice(t('Image uploaded but image cropping failed.') . EOL);
return;
}
-
- $image_id = argv(1);
-
- if(substr($image_id,-2,1) == '-') {
- $scale = substr($image_id,-1,1);
- $image_id = substr($image_id,0,-2);
- }
+ $image_id = argv(1);
- // unless proven otherwise
- $is_default_profile = 1;
-
- if($_REQUEST['profile']) {
- $r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
- intval($_REQUEST['profile']),
- intval(local_channel())
- );
- if($r) {
- $profile = $r[0];
- if(! intval($profile['is_default']))
- $is_default_profile = 0;
- }
- }
+ if (substr($image_id, -2, 1) == '-') {
+ $scale = substr($image_id, -1, 1);
+ $image_id = substr($image_id, 0, -2);
+ }
-
$srcX = intval($_POST['xstart']);
$srcY = intval($_POST['ystart']);
$srcW = intval($_POST['xfinal']) - $srcX;
@@ -126,45 +144,45 @@ class Profile_photo extends \Zotlabs\Web\Controller {
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1",
dbesc($image_id),
dbesc(local_channel()),
- intval($scale));
- if($r) {
-
- $base_image = $r[0];
+ intval($scale)
+ );
+
+ if ($r) {
+
+ $base_image = $r[0];
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
-
+
$im = photo_factory($base_image['content'], $base_image['mimetype']);
- if($im->is_valid()) {
-
- $im->cropImage(300,$srcX,$srcY,$srcW,$srcH);
-
+ if ($im->is_valid()) {
+
+ $im->cropImage(300, $srcX, $srcY, $srcW, $srcH);
+
$aid = get_account_id();
-
- $p = [
- 'aid' => $aid,
- 'uid' => local_channel(),
+
+ $p = [
+ 'aid' => $aid,
+ 'uid' => local_channel(),
'resource_id' => $base_image['resource_id'],
- 'filename' => $base_image['filename'],
+ 'filename' => $base_image['filename'],
'album' => t('Profile Photos'),
'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path'],
- 'photo_usage' => PHOTO_PROFILE,
- 'edited' => dbescdate($base_image['edited'])
+ 'photo_usage' => (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL),
+ 'edited' => dbescdate($base_image['edited'])
];
-
- $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
-
+
$r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
-
+
$im->scaleImage(80);
$r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
-
+
$im->scaleImage(48);
$r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
- if($r1 === false || $r2 === false || $r3 === false) {
+ if ($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
- notice( t('Image resize failed.') . EOL );
- $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
+ notice(t('Image resize failed.') . EOL);
+ q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
dbesc($base_image['resource_id']),
local_channel(),
intval(PHOTO_RES_PROFILE_300),
@@ -179,59 +197,55 @@ class Profile_photo extends \Zotlabs\Web\Controller {
intval(PHOTO_RES_PROFILE_80),
intval(PHOTO_RES_PROFILE_48)
);
- if($x) {
- foreach($x as $xx) {
+ if ($x) {
+ foreach ($x as $xx) {
@unlink(dbunescbin($xx['content']));
}
}
-
+
return;
}
-
+
// If setting for the default profile, unset the profile photo flag from any other photos I own
-
- if($is_default_profile) {
- $r = q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
+ if ($is_default_profile) {
+ q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
dbesc(z_root() . '/photo/profile/l/' . local_channel()),
dbesc(z_root() . '/photo/profile/m/' . local_channel()),
intval(local_channel())
);
-
- $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
+ q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
AND resource_id != '%s' AND uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE),
dbesc($base_image['resource_id']),
intval(local_channel())
);
-
- send_profile_photo_activity($channel,$base_image,$profile);
-
+ send_profile_photo_activity($channel, $base_image, $profile);
}
else {
- $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
+ q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'),
dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'),
- intval($_REQUEST['profile']),
+ intval($profile_id),
intval(local_channel())
);
}
-
+
// set $send to false in profiles_build_sync() to return the data
- // so that we only send one sync packet.
+ // so that we only send one sync packet.
+
+ $sync_profiles = profiles_build_sync(local_channel(), false);
- $sync_profiles = profiles_build_sync(local_channel(),false);
-
// We'll set the updated profile-photo timestamp even if it isn't the default profile,
// so that browsers will do a cache update unconditionally
// Also set links back to site-specific profile photo url in case it was
- // changed to a generic URL by a clone operation. Otherwise the new photo may
+ // changed to a generic URL by a clone operation. Otherwise the new photo may
// not get pushed to other sites correctly.
-
- $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
+
+ q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
where xchan_hash = '%s'",
dbesc($im->getType()),
dbescdate($base_image['edited']),
@@ -241,341 +255,372 @@ class Profile_photo extends \Zotlabs\Web\Controller {
dbesc($channel['xchan_hash'])
);
- photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']);
+ photo_profile_setperms(local_channel(), $base_image['resource_id'], $profile_id);
- $sync = attach_export_data($channel,$base_image['resource_id']);
- if($sync)
- Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles));
+ $sync = attach_export_data($channel, $base_image['resource_id']);
+ if ($sync)
+ Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync], 'profile' => $sync_profiles]);
// Similarly, tell the nav bar to bypass the cache and update the avatar image.
$_SESSION['reload_avatar'] = true;
-
- info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
-
+
+ info(t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
+
// Update directory in background
- \Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
-
+ Master::Summon(['Directory', $channel['channel_id']]);
+
}
else
- notice( t('Unable to process image') . EOL);
+ notice(t('Unable to process image') . EOL);
}
-
- goaway(z_root() . '/profiles');
+
+ goaway(z_root() . '/profiles/' . $profile_id);
return; // NOTREACHED
}
-
+
// A new photo was uploaded. Store it and save some important details
// in App::$data for use in the cropping function
-
-
- $hash = photo_new_resource();
+
+ $hash = photo_new_resource();
$importing = false;
- $smallest = 0;
-
+ $smallest = 0;
- if($_REQUEST['importfile']) {
- $hash = $_REQUEST['importfile'];
+ if ($_REQUEST['importfile']) {
+ $hash = $_REQUEST['importfile'];
$importing = true;
}
else {
- require_once('include/attach.php');
-
- $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true));
-
- logger('attach_store: ' . print_r($res,true));
+
+ $matches = [];
+ $partial = false;
+
+ if (array_key_exists('HTTP_CONTENT_RANGE', $_SERVER)) {
+ $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/', $_SERVER['HTTP_CONTENT_RANGE'], $matches);
+ if ($pm) {
+ logger('Content-Range: ' . print_r($matches, true));
+ $partial = true;
+ }
+ }
+
+ if ($partial) {
+ $x = save_chunk($channel, $matches[1], $matches[2], $matches[3]);
+
+ if ($x['partial']) {
+ header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
+ json_return_and_die($x);
+ }
+ else {
+ header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
+
+ $_FILES['userfile'] = [
+ 'name' => $x['name'],
+ 'type' => $x['type'],
+ 'tmp_name' => $x['tmp_name'],
+ 'error' => $x['error'],
+ 'size' => $x['size']
+ ];
+ }
+ }
+ else {
+ if (!array_key_exists('userfile', $_FILES)) {
+ $_FILES['userfile'] = [
+ 'name' => $_FILES['files']['name'],
+ 'type' => $_FILES['files']['type'],
+ 'tmp_name' => $_FILES['files']['tmp_name'],
+ 'error' => $_FILES['files']['error'],
+ 'size' => $_FILES['files']['size']
+ ];
+ }
+ }
+
+ $res = attach_store(App::get_channel(), get_observer_hash(), '', ['album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']);
+
+ json_return_and_die(['message' => $hash]);
+
}
-
- if(($res && intval($res['data']['is_photo'])) || $importing) {
+
+ if (($res && intval($res['data']['is_photo'])) || $importing) {
$i = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale",
dbesc($hash),
intval(local_channel())
);
-
- if(! $i) {
- notice( t('Image upload failed.') . EOL );
+
+ if (!$i) {
+ notice(t('Image upload failed.') . EOL);
return;
}
+
$os_storage = false;
-
- foreach($i as $ii) {
- if(intval($ii['imgscale']) < PHOTO_RES_640) {
- $smallest = intval($ii['imgscale']);
+
+ foreach ($i as $ii) {
+ if (intval($ii['imgscale']) < PHOTO_RES_640) {
+ $smallest = intval($ii['imgscale']);
$os_storage = intval($ii['os_storage']);
- $imagedata = $ii['content'];
- $filetype = $ii['mimetype'];
+ $imagedata = $ii['content'];
+ $filetype = $ii['mimetype'];
}
}
}
-
+
$imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata));
- $ph = photo_factory($imagedata, $filetype);
-
- if(! $ph->is_valid()) {
- notice( t('Unable to process image.') . EOL );
+ $ph = photo_factory($imagedata, $filetype);
+
+ if (!$ph->is_valid()) {
+ notice(t('Unable to process image.') . EOL);
return;
}
-
- return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
+
+ return $this->profile_photo_crop_ui_head($ph, $hash, $smallest);
// This will "fall through" to the get() method, and since
- // App::$data['imagecrop'] is set, it will proceed to cropping
- // rather than present the upload form
+ // App::$data['imagecrop'] is set, it will proceed to cropping
+ // rather than present the upload form
}
-
-
+
+
/* @brief Generate content of profile-photo view
*
- * @param $a Current application
- * @return void
- *
*/
-
-
+
+
function get() {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL );
+
+ if (!local_channel()) {
+ notice(t('Permission denied.') . EOL);
return;
}
-
- $channel = \App::get_channel();
- $pf = 0;
- $newuser = false;
-
- if(argc() == 2 && argv(1) === 'new')
- $newuser = true;
-
- if(argv(1) === 'use') {
- if (argc() < 3) {
- notice( t('Permission denied.') . EOL );
- return;
- };
-
- $resource_id = argv(2);
-
- $pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0);
+ $channel = App::get_channel();
+ $profile_id = (($_REQUEST['profile']) ? intval($_REQUEST['profile']) : intval(argv(1)));
+ $default_profile_id = null;
- $c = q("select id, is_default from profile where uid = %d",
- intval(local_channel())
- );
+ $r = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
+ intval(local_channel())
+ );
- $multi_profiles = true;
- if(($c) && (count($c) === 1) && (intval($c[0]['is_default']))) {
- $_REQUEST['profile'] = $c[0]['id'];
- $multi_profiles = false;
+ foreach ($r as $rr) {
+ if ($rr['is_default']) {
+ $default_profile_id = intval($rr['id']);
}
- else {
- $_REQUEST['profile'] = $pf;
+
+ if ($profile_id === intval($rr['id'])) {
+ $profile = $rr;
}
+ }
+
+ $is_default_profile = ($profile_id === $default_profile_id);
+
+ if (argv(1) === 'use') {
+ if (argc() < 3) {
+ notice(t('Permission denied.') . EOL);
+ return;
+ };
+
+ $resource_id = argv(2);
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
intval(local_channel()),
dbesc($resource_id)
);
- if(! $r) {
- notice( t('Photo not available.') . EOL );
+ if (!$r) {
+ notice(t('Photo not available.') . EOL);
return;
}
$havescale = false;
- foreach($r as $rr) {
- if($rr['imgscale'] == PHOTO_RES_PROFILE_80)
+ foreach ($r as $rr) {
+ if ($rr['imgscale'] == PHOTO_RES_PROFILE_80)
$havescale = true;
}
-
+
// set an already loaded and cropped photo as profile photo
-
- if($havescale) {
- // unset any existing profile photos
- $x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
- intval(PHOTO_NORMAL),
- intval(PHOTO_PROFILE),
+
+ if ($havescale) {
+
+ if ($is_default_profile) {
+
+ // unset any existing profile photos
+ q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval(local_channel())
+ );
+
+ $edited = datetime_convert();
+
+ q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
+ intval(PHOTO_PROFILE),
+ dbescdate($edited),
+ intval(local_channel()),
+ dbesc($resource_id)
+ );
+
+ q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
+ dbescdate($edited),
+ dbesc($channel['xchan_hash'])
+
+ );
+
+ }
+
+ q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
+ dbesc(z_root() . '/photo/' . $resource_id . '-4'),
+ dbesc(z_root() . '/photo/' . $resource_id . '-5'),
+ intval($profile_id),
intval(local_channel())
);
- $edited = datetime_convert();
-
- $x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
- intval(PHOTO_PROFILE),
- dbescdate($edited),
- intval(local_channel()),
- dbesc($resource_id)
- );
-
- $x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
- dbescdate($edited),
- dbesc($channel['xchan_hash'])
- );
-
- photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']);
+ photo_profile_setperms(local_channel(), $resource_id, $profile_id);
- $sync = attach_export_data($channel,$resource_id);
- if($sync)
- Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ $sync = attach_export_data($channel, $resource_id);
+ if ($sync)
+ Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
$_SESSION['reload_avatar'] = true;
- \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
-
- goaway(z_root() . '/profiles');
+ Master::Summon(['Directory', local_channel()]);
+
+ goaway(z_root() . '/profiles/' . $profile_id);
}
-
+
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']),
intval(local_channel())
-
+
);
- if(! $r) {
- notice( t('Photo not available.') . EOL );
+ if (!$r) {
+ notice(t('Photo not available.') . EOL);
return;
}
-
- if(intval($r[0]['os_storage']))
+
+ if (intval($r[0]['os_storage'])) {
$data = @file_get_contents(dbunescbin($r[0]['content']));
- else
- $data = dbunescbin($r[0]['content']);
-
- $ph = photo_factory($data, $r[0]['mimetype']);
+ }
+ else {
+ $data = dbunescbin($r[0]['content']);
+ }
+
+ $ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0;
- if($ph->is_valid()) {
+
+ if ($ph->is_valid()) {
+
// go ahead as if we have just uploaded a new photo to crop
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d order by imgscale",
dbesc($r[0]['resource_id']),
intval(local_channel())
);
-
- if($i) {
+
+ if ($i) {
$hash = $i[0]['resource_id'];
- foreach($i as $ii) {
- if(intval($ii['imgscale']) < PHOTO_RES_640) {
+ foreach ($i as $ii) {
+ if (intval($ii['imgscale']) < PHOTO_RES_640) {
$smallest = intval($ii['imgscale']);
}
}
- }
- }
-
- if($multi_profiles) {
- \App::$data['importfile'] = $resource_id;
- }
- else {
- $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
+ }
}
+ $this->profile_photo_crop_ui_head($ph, $hash, $smallest);
+
// falls through with App::$data['imagecrop'] set so we go straight to the cropping section
}
-
- // present an upload form
- $profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
- intval(local_channel())
- );
+ $importing = ((array_key_exists('importfile', App::$data)) ? true : false);
- if($profiles) {
- for($x = 0; $x < count($profiles); $x ++) {
- $profiles[$x]['selected'] = false;
- if($pf && $profiles[$x]['id'] == $pf)
- $profiles[$x]['selected'] = true;
- if((! $pf) && $profiles[$x]['is_default'])
- $profiles[$x]['selected'] = true;
- }
- }
+ if (!x(App::$data, 'imagecrop')) {
- $importing = ((array_key_exists('importfile',\App::$data)) ? true : false);
-
- if(! x(\App::$data,'imagecrop')) {
-
$tpl = get_markup_template('profile_photo.tpl');
-
- $o .= replace_macros($tpl,array(
- '$user' => \App::$channel['channel_address'],
- '$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')),
- '$importfile' => (($importing) ? \App::$data['importfile'] : ''),
- '$lbl_upfile' => t('Upload File:'),
- '$lbl_profiles' => t('Select a profile:'),
- '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
- '$submit' => (($importing) ? t('Use') : t('Upload')),
- '$remove' => t('Remove'),
- '$profiles' => $profiles,
- '$single' => ((count($profiles) == 1) ? true : false),
- '$profile0' => $profiles[0],
- '$embedPhotos' => t('Use a photo from your albums'),
- '$embedPhotosModalTitle' => t('Use a photo from your albums'),
+
+ $o = replace_macros($tpl, [
+ '$user' => App::$channel['channel_address'],
+ '$info' => (($is_default_profile) ? t('This profile photo will be visible to anybody on the internet and may be distributed to other websites.') : t('This profile photo will be visible only to channels with permission to view this profile.')),
+ '$importfile' => (($importing) ? App::$data['importfile'] : ''),
+ '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
+ '$submit' => t('Upload'),
+ '$remove' => t('Reset to default'),
+ '$profile_id' => $profile_id,
+ '$profile' => $profile,
+ '$embedPhotos' => t('Use a photo from your albums'),
+ '$embedPhotosModalTitle' => t('Use a photo from your albums'),
'$embedPhotosModalCancel' => t('Cancel'),
- '$embedPhotosModalOK' => t('OK'),
- '$modalchooseimages' => t('Choose images to embed'),
- '$modalchoosealbum' => t('Choose an album'),
- '$modaldiffalbum' => t('Choose a different album'),
- '$modalerrorlist' => t('Error getting album list'),
- '$modalerrorlink' => t('Error getting photo link'),
- '$modalerroralbum' => t('Error getting album'),
- '$form_security_token' => get_form_security_token("profile_photo"),
- '$select' => t('Select existing photo'),
- ));
-
+ '$embedPhotosModalOK' => t('OK'),
+ '$modalchooseimages' => t('Choose images to embed'),
+ '$modalchoosealbum' => t('Choose an album'),
+ '$modaldiffalbum' => t('Choose a different album'),
+ '$modalerrorlist' => t('Error getting album list'),
+ '$modalerrorlink' => t('Error getting photo link'),
+ '$modalerroralbum' => t('Error getting album'),
+ '$form_security_token' => get_form_security_token("profile_photo"),
+ '$select' => t('Select existing'),
+ ]);
+
call_hooks('profile_photo_content_end', $o);
-
+
return $o;
}
else {
// present a cropping form
- $filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'];
- $resolution = \App::$data['imagecrop_resolution'];
- $tpl = get_markup_template("cropbody.tpl");
- $o .= replace_macros($tpl,array(
- '$filename' => $filename,
- '$profile' => intval($_REQUEST['profile']),
- '$resource' => \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'],
- '$image_url' => z_root() . '/photo/' . $filename,
- '$title' => t('Crop Image'),
- '$desc' => t('Please adjust the image cropping for optimum viewing.'),
+ $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'];
+ $tpl = get_markup_template("cropbody.tpl");
+
+ $o = replace_macros($tpl, [
+ '$filename' => $filename,
+ '$profile' => $profile_id,
+ '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
+ '$image_url' => z_root() . '/photo/' . $filename,
+ '$title' => t('Crop Image'),
+ '$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("profile_photo"),
- '$done' => t('Done Editing')
- ));
+ '$done' => t('Done editing')
+ ]);
+
return $o;
}
-
+
return; // NOTREACHED
}
-
+
/* @brief Generate the UI for photo-cropping
*
- * @param $a Current application
- * @param $ph Photo-Factory
- * @return void
+ * @param $ph
+ * @param $hash
+ * @param $smallest
*
*/
-
-
-
- function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
-
- $max_length = get_config('system','max_image_length');
- if(! $max_length)
+
+
+ function profile_photo_crop_ui_head($ph, $hash, $smallest) {
+
+ $max_length = get_config('system', 'max_image_length');
+
+ if (!$max_length) {
$max_length = MAX_IMAGE_LENGTH;
- if($max_length > 0)
+ }
+ if ($max_length > 0) {
$ph->scaleImage($max_length);
-
- \App::$data['width'] = $ph->getWidth();
- \App::$data['height'] = $ph->getHeight();
-
- if(\App::$data['width'] < 500 || \App::$data['height'] < 500) {
+ }
+
+ App::$data['width'] = $ph->getWidth();
+ App::$data['height'] = $ph->getHeight();
+
+ if (App::$data['width'] < 500 || App::$data['height'] < 500) {
$ph->scaleImageUp(400);
- \App::$data['width'] = $ph->getWidth();
- \App::$data['height'] = $ph->getHeight();
+ App::$data['width'] = $ph->getWidth();
+ App::$data['height'] = $ph->getHeight();
}
-
-
- \App::$data['imagecrop'] = $hash;
- \App::$data['imagecrop_resolution'] = $smallest;
- \App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
+
+ App::$data['imagecrop'] = $hash;
+ App::$data['imagecrop_resolution'] = $smallest;
+ App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []);
+
return;
}
-
-
+
+
}
diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php
index 9aa342223..e248cd028 100644
--- a/Zotlabs/Module/Profiles.php
+++ b/Zotlabs/Module/Profiles.php
@@ -163,35 +163,6 @@ class Profiles extends \Zotlabs\Web\Controller {
killme();
}
-
-
-
- // Run profile_load() here to make sure the theme is set before
- // we start loading content
- if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
- if(feature_enabled(local_channel(),'multi_profiles'))
- $id = \App::$argv[1];
- else {
- $x = q("select id from profile where uid = %d and is_default = 1",
- intval(local_channel())
- );
- if($x)
- $id = $x[0]['id'];
- }
- $r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1",
- intval($id),
- intval(local_channel())
- );
- if(! count($r)) {
- notice( t('Profile not found.') . EOL);
- \App::$error = 404;
- return;
- }
-
- $chan = \App::get_channel();
-
- profile_load($chan['channel_address'],$r[0]['id']);
- }
}
function post() {
@@ -317,8 +288,6 @@ class Profiles extends \Zotlabs\Web\Controller {
$work = fix_mce_lf(escape_tags(trim($_POST['work'])));
$education = fix_mce_lf(escape_tags(trim($_POST['education'])));
- $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
-
// start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving
// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
@@ -514,6 +483,16 @@ class Profiles extends \Zotlabs\Web\Controller {
$value = $locality . $comma1 . $region . $comma2 . $country_name;
}
+ $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
+
+ $suggestme = ((x($_POST, 'suggestme')) ? intval($_POST['suggestme']) : 0);
+ set_pconfig(local_channel(), 'system', 'suggestme', $suggestme);
+
+ $show_presence = (((x($_POST, 'show_presence')) && (intval($_POST['show_presence']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'show_online_status', $show_presence);
+
+ $publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
+
profile_activity($changes,$value);
}
@@ -552,7 +531,8 @@ class Profiles extends \Zotlabs\Web\Controller {
employment = '%s',
education = '%s',
hide_friends = %d,
- profile_vcard = '%s'
+ profile_vcard = '%s',
+ publish = %d
WHERE id = %d AND uid = %d",
dbesc($profile_name),
dbesc($name),
@@ -588,6 +568,7 @@ class Profiles extends \Zotlabs\Web\Controller {
dbesc($education),
intval($hide_friends),
dbesc($profile_vcard),
+ intval($publish),
intval(argv(1)),
intval(local_channel())
);
@@ -595,32 +576,31 @@ class Profiles extends \Zotlabs\Web\Controller {
if($r)
info( t('Profile updated.') . EOL);
- $r = q("select * from profile where id = %d and uid = %d limit 1",
- intval(argv(1)),
- intval(local_channel())
- );
- if($r) {
- require_once('include/zot.php');
- Libsync::build_sync_packet(local_channel(),array('profile' => $r));
- }
-
$channel = \App::get_channel();
if($namechanged && $is_default) {
- $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
+ // change name on all associated xchans by matching the url
+ q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
dbesc($name),
dbesc(datetime_convert()),
dbesc(z_root() . '/channel/' . $channel['channel_address'])
);
- $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
+ q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
dbesc($name),
dbesc($channel['xchan_hash'])
);
}
+ $r = q("select * from profile where id = %d and uid = %d limit 1",
+ intval(argv(1)),
+ intval(local_channel())
+ );
+
+ if($r) {
+ Libsync::build_sync_packet(local_channel(), ['profile' => $r]);
+ }
+
if($is_default) {
- // reload the info for the sidebar widget - why does this not work?
- profile_load($channel['channel_address']);
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
}
}
@@ -631,13 +611,13 @@ class Profiles extends \Zotlabs\Web\Controller {
$o = '';
- $channel = \App::get_channel();
-
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
+ $channel = \App::get_channel();
+
require_once('include/channel.php');
$profile_fields_basic = get_profile_fields_basic();
@@ -653,15 +633,20 @@ class Profiles extends \Zotlabs\Web\Controller {
if($x)
$id = $x[0]['id'];
}
+
$r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1",
intval($id),
intval(local_channel())
);
+
if(! $r) {
notice( t('Profile not found.') . EOL);
return;
}
+ // make sure we got uptodate data
+ profile_load($channel['channel_address'], $id);
+
$editselect = 'none';
\App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array(
@@ -675,13 +660,43 @@ class Profiles extends \Zotlabs\Web\Controller {
else
$fields = $profile_fields_basic;
- $hide_friends = array(
- 'hide_friends',
- t('Hide your connections list from viewers of this profile'),
- $r[0]['hide_friends'],
- '',
- array(t('No'),t('Yes'))
- );
+ $show_presence = [];
+ $profile_in_dir = '';
+ $suggestme = '';
+ $hide_friends = [];
+ $is_default = (($r[0]['is_default']) ? 1 : 0);
+
+ if ($is_default) {
+
+ $hide_friends = array(
+ 'hide_friends',
+ t('Hide my connections from viewers of this profile'),
+ $r[0]['hide_friends'],
+ '',
+ [t('No'), t('Yes')]
+ );
+
+
+ $opt_tpl = get_markup_template("field_checkbox.tpl");
+ if (get_config('system', 'publish_all')) {
+ $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
+ }
+ else {
+ $profile_in_dir = replace_macros($opt_tpl, [
+ '$field' => ['profile_in_directory', t('Publish my default profile in the network directory'), $r[0]['publish'], '', [t('No'), t('Yes')]],
+ ]);
+ }
+
+ $suggestme = get_pconfig(local_channel(), 'system', 'suggestme');
+ $suggestme = (($suggestme === false) ? '0' : $suggestme); // default if not set: 0
+
+ $suggestme = replace_macros($opt_tpl, [
+ '$field' => ['suggestme', t('Suggest me as a potential contact to new members'), $suggestme, '', [t('No'), t('Yes')]],
+ ]);
+
+ $show_presence_val = intval(get_pconfig(local_channel(), 'system', 'show_online_status'));
+ $show_presence = ['show_presence', t('Reveal my online status'), $show_presence_val, '', [t('No'), t('Yes')]];
+ }
$q = q("select * from profdef where true");
if($q) {
@@ -702,15 +717,15 @@ class Profiles extends \Zotlabs\Web\Controller {
//logger('extra_fields: ' . print_r($extra_fields,true));
- $vc = $r[0]['profile_vcard'];
- $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
- $vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] );
+ //$vc = $r[0]['profile_vcard'];
+ //$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
+ //$vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] );
$f = get_config('system','birthday_input_format');
if(! $f)
$f = 'ymd';
- $is_default = (($r[0]['is_default']) ? 1 : 0);
+
$tpl = get_markup_template("profile_edit.tpl");
$o .= replace_macros($tpl,array(
@@ -719,12 +734,12 @@ class Profiles extends \Zotlabs\Web\Controller {
'$profile_clone_link' => 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone"),
'$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"),
'$fields' => $fields,
- '$vcard' => $vcard,
+ //'$vcard' => $vcard,
'$guid' => $r[0]['profile_guid'],
'$banner' => t('Edit Profile Details'),
'$submit' => t('Submit'),
'$viewprof' => t('View this profile'),
- '$editvis' => t('Edit visibility'),
+ '$editvis' => t('Edit visibility'),
'$tools_label' => t('Profile Tools'),
'$coverpic' => t('Change cover photo'),
'$profpic' => t('Change profile photo'),
@@ -732,7 +747,7 @@ class Profiles extends \Zotlabs\Web\Controller {
'$cl_prof' => t('Clone this profile'),
'$del_prof' => t('Delete this profile'),
'$addthing' => t('Add profile things'),
- '$personal' => t('Personal'),
+ '$basic' => t('Basic'),
'$location' => t('Location'),
'$relation' => t('Relationship'),
'$miscellaneous'=> t('Miscellaneous'),
@@ -784,23 +799,28 @@ class Profiles extends \Zotlabs\Web\Controller {
'$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']),
'$channels' => array('channels', t('My other channels'), $r[0]['channels']),
'$extra_fields' => $extra_fields,
- '$comms' => t('Communications'),
- '$tel_label' => t('Phone'),
- '$email_label' => t('Email'),
- '$impp_label' => t('Instant messenger'),
- '$url_label' => t('Website'),
- '$adr_label' => t('Address'),
- '$note_label' => t('Note'),
- '$mobile' => t('Mobile'),
- '$home' => t('Home'),
- '$work' => t('Work'),
- '$other' => t('Other'),
- '$add_card' => t('Add Contact'),
- '$add_field' => t('Add Field'),
- '$create' => t('Create'),
- '$update' => t('Update'),
- '$delete' => t('Delete'),
- '$cancel' => t('Cancel'),
+ //'$comms' => t('Communications'),
+ //'$tel_label' => t('Phone'),
+ //'$email_label' => t('Email'),
+ //'$impp_label' => t('Instant messenger'),
+ //'$url_label' => t('Website'),
+ //'$adr_label' => t('Address'),
+ //'$note_label' => t('Note'),
+ //'$mobile' => t('Mobile'),
+ //'$home' => t('Home'),
+ //'$work' => t('Work'),
+ //'$other' => t('Other'),
+ //'$add_card' => t('Add Contact'),
+ //'$add_field' => t('Add Field'),
+ //'$create' => t('Create'),
+ //'$update' => t('Update'),
+ //'$delete' => t('Delete'),
+ //'$cancel' => t('Cancel'),
+
+ '$show_presence' => $show_presence,
+ '$suggestme' => $suggestme,
+ '$profile_in_dir' => $profile_in_dir,
+
));
$arr = array('profile' => $r[0], 'entry' => $o);
diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php
index 4b64d9af6..fd5aeaa72 100644
--- a/Zotlabs/Module/Pubsites.php
+++ b/Zotlabs/Module/Pubsites.php
@@ -6,7 +6,6 @@ use Zotlabs\Lib\Libzotdir;
class Pubsites extends \Zotlabs\Web\Controller {
function get() {
- require_once('include/dir_fns.php');
$dirmode = intval(get_config('system','directory_mode'));
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index 113f0a196..583974e22 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -16,10 +16,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
if(! Apps::system_app_installed(local_channel(), 'Public Stream')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Public Stream App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('The unmoderated public stream of this hub');
- return $o;
+ $papp = Apps::get_papp('Public Stream');
+ return Apps::app_render($papp, 'module');
}
}
@@ -44,19 +42,16 @@ class Pubstream extends \Zotlabs\Web\Controller {
$site_firehose = false;
}
- $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
- $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
-
-
- if(strpos($mid,'b64.') === 0)
- $decoded = @base64url_decode(substr($mid,4));
- if($decoded)
- $mid = $decoded;
+ $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
+ if ($mid === false) {
+ notice(t('Malformed message id.') . EOL);
+ return;
+ }
+ $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$item_normal = item_normal();
$item_normal_update = item_normal_update();
-
- $net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : '');
+ $net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : '');
$title = replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => (($hashtags) ? '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8') : '')
@@ -65,15 +60,15 @@ class Pubstream extends \Zotlabs\Web\Controller {
$o = (($hashtags) ? $title : '');
if(local_channel() && (! $update)) {
-
+
$channel = \App::get_channel();
$channel_acl = array(
- 'allow_cid' => $channel['channel_allow_cid'],
- 'allow_gid' => $channel['channel_allow_gid'],
- 'deny_cid' => $channel['channel_deny_cid'],
+ 'allow_cid' => $channel['channel_allow_cid'],
+ 'allow_gid' => $channel['channel_allow_gid'],
+ 'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
- );
+ );
$x = array(
'is_owner' => true,
@@ -94,12 +89,12 @@ class Pubstream extends \Zotlabs\Web\Controller {
'jotnets' => true,
'reset' => t('Reset form')
);
-
+
$o .= '<div id="jot-popup">';
$o .= status_editor($a,$x,false,'Pubstream');
$o .= '</div>';
}
-
+
if(! $update && !$load) {
nav_set_selected(t('Public Stream'));
@@ -110,15 +105,14 @@ class Pubstream extends \Zotlabs\Web\Controller {
$maxheight = get_config('system','home_divmore_height');
if(! $maxheight)
$maxheight = 400;
-
+
$o .= '<div id="live-pubstream"></div>' . "\r\n";
- $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
- . "; var profile_page = " . \App::$pager['page']
+ $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
+ . "; var profile_page = " . \App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
-
- //if we got a decoded hash we must encode it again before handing to javascript
- if($decoded)
- $mid = 'b64.' . base64url_encode($mid);
+
+ //if we got a decoded hash we must encode it again before handing to javascript
+ $mid = gen_link_id($mid);
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
@@ -151,7 +145,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
'$dbegin' => ''
));
}
-
+
if($update && ! $load) {
// only setup pagination on initial page view
$pager_sql = '';
@@ -160,10 +154,10 @@ class Pubstream extends \Zotlabs\Web\Controller {
\App::set_pager_itemspage(10);
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
}
-
+
require_once('include/channel.php');
require_once('include/security.php');
-
+
if($site_firehose) {
$uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
}
@@ -173,7 +167,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$sql_extra = item_permissions_sql($sys['channel_id']);
\App::$data['firehose'] = intval($sys['channel_id']);
}
-
+
if(get_config('system','public_list_mode'))
$page_mode = 'list';
else
@@ -184,7 +178,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
- $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
+ $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
@@ -196,13 +190,13 @@ class Pubstream extends \Zotlabs\Web\Controller {
//logger('update: ' . $update . ' load: ' . $load);
if($update) {
-
- $ordering = "commented";
-
+
+ $ordering = get_config('system', 'pubstream_ordering', 'commented');
+
if($load) {
if($mid) {
$r = q("SELECT parent AS item_id FROM item
- left join abook on item.author_xchan = abook.abook_xchan
+ left join abook on item.author_xchan = abook.abook_xchan
$net_query
WHERE mid = '%s' $uids $item_normal
and (abook.abook_blocked = 0 or abook.abook_flags is null)
@@ -212,7 +206,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
}
else {
// Fetch a page full of parent items for this page
- $r = q("SELECT item.id AS item_id FROM item
+ $r = dbq("SELECT item.id AS item_id FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
$net_query
WHERE true $uids and item.item_thread_top = 1 $item_normal
@@ -234,7 +228,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
);
}
else {
- $r = q("SELECT parent AS item_id FROM item
+ $r = dbq("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
$net_query
WHERE true $uids $item_normal_update
@@ -247,20 +241,19 @@ class Pubstream extends \Zotlabs\Web\Controller {
// Then fetch all the children of the parents that are on this page
$parents_str = '';
-
+
if($r) {
-
+
$parents_str = ids_to_querystr($r,'item_id');
-
- $items = q("SELECT item.*, item.id AS item_id FROM item
+
+ $items = dbq("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
- AND item.parent IN ( %s )
- $sql_extra ",
- dbesc($parents_str)
+ AND item.parent IN ( $parents_str )
+ $sql_extra"
);
-
+
// use effective_uid param of xchan_query to help sort out comment permission
- // for sys_channel owned items.
+ // for sys_channel owned items.
xchan_query($items,true,(($sys) ? local_channel() : 0));
$items = fetch_post_tags($items,true);
@@ -269,9 +262,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
else {
$items = array();
}
-
+
}
-
+
// fake it
$mode = (($hashtags) ? 'search' : 'pubstream');
@@ -279,13 +272,13 @@ class Pubstream extends \Zotlabs\Web\Controller {
if($mid)
$o .= '<div id="content-complete"></div>';
-
+
if(($items) && (! $update))
$o .= alt_pager(count($items));
$_SESSION['loadtime'] = datetime_convert();
return $o;
-
+
}
}
diff --git a/Zotlabs/Module/Randprof.php b/Zotlabs/Module/Randprof.php
index c38b07ead..731d3aece 100644
--- a/Zotlabs/Module/Randprof.php
+++ b/Zotlabs/Module/Randprof.php
@@ -15,7 +15,7 @@ class Randprof extends \Zotlabs\Web\Controller {
$x = random_profile();
if($x)
goaway(chanlink_hash($x));
-
+
/** FIXME this doesn't work at the moment as a fallback */
goaway(z_root() . '/profile');
}
@@ -25,13 +25,11 @@ class Randprof extends \Zotlabs\Web\Controller {
if(! Apps::system_app_installed(local_channel(), 'Random Channel')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Random Channel App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Visit a random channel in the $Projectname network');
- return $o;
+ $papp = Apps::get_papp('Random Channel');
+ return Apps::app_render($papp, 'module');
}
}
}
-
+
}
diff --git a/Zotlabs/Module/Rate.php b/Zotlabs/Module/Rate.php
deleted file mode 100644
index d29c370fc..000000000
--- a/Zotlabs/Module/Rate.php
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-
-
-use Zotlabs\Lib\Crypto;
-
-class Rate extends \Zotlabs\Web\Controller {
-
- function init() {
-
- if(! local_channel())
- return;
-
- $channel = \App::get_channel();
-
- $target = $_REQUEST['target'];
- if(! $target)
- return;
-
- \App::$data['target'] = $target;
-
- if($target) {
- $r = q("SELECT * FROM xchan where xchan_hash like '%s' LIMIT 1",
- dbesc($target)
- );
- if($r) {
- \App::$poi = $r[0];
- }
- else {
- $r = q("select * from site where site_url like '%s' and site_type = %d",
- dbesc('%' . $target),
- intval(SITE_TYPE_ZOT)
- );
- if($r) {
- \App::$data['site'] = $r[0];
- \App::$data['site']['site_url'] = strtolower($r[0]['site_url']);
- }
- }
- }
-
-
- return;
-
- }
-
-
- function post() {
-
- if(! local_channel())
- return;
-
- if(! \App::$data['target'])
- return;
-
- if(! $_REQUEST['execute'])
- return;
-
- $channel = \App::get_channel();
-
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
-
- $signed = \App::$data['target'] . '.' . $rating . '.' . $rating_text;
-
- $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey']));
-
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc(\App::$data['target'])
- );
-
- if($z) {
- $record = $z[0]['xlink_id'];
- $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
- where xlink_id = %d",
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert()),
- intval($record)
- );
- }
- else {
- $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
- dbesc($channel['channel_hash']),
- dbesc(\App::$data['target']),
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert())
- );
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc(\App::$data['target'])
- );
- if($z)
- $record = $z[0]['xlink_id'];
- }
-
- if($record) {
- \Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record));
- }
-
- }
-
- function get() {
-
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
- return;
- }
-
- // if(! \App::$data['target']) {
- // notice( t('No recipients.') . EOL);
- // return;
- // }
-
- $rating_enabled = get_config('system','rating_enabled');
- if(! $rating_enabled) {
- notice('Ratings are disabled on this site.');
- return;
- }
-
- $channel = \App::get_channel();
-
- $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc(\App::$data['target'])
- );
- if($r) {
- \App::$data['xlink'] = $r[0];
- $rating_val = $r[0]['xlink_rating'];
- $rating_text = $r[0]['xlink_rating_text'];
- }
- else {
- $rating_val = 0;
- $rating_text = '';
- }
-
- if($rating_enabled) {
- $rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
- '$min' => -10,
- '$val' => $rating_val
- ));
- }
- else {
- $rating = false;
- }
-
- $o = replace_macros(get_markup_template('rating_form.tpl'),array(
- '$header' => t('Rating'),
- '$website' => t('Website:'),
- '$site' => ((\App::$data['site']) ? '<a href="' . \App::$data['site']['site_url'] . '" >' . \App::$data['site']['site_url'] . '</a>' : ''),
- 'target' => \App::$data['target'],
- '$tgt_name' => ((\App::$poi && \App::$poi['xchan_name']) ? \App::$poi['xchan_name'] : sprintf( t('Remote Channel [%s] (not yet known on this site)'), substr(\App::$data['target'],0,16))),
- '$lbl_rating' => t('Rating (this information is public)'),
- '$lbl_rating_txt' => t('Optionally explain your rating (this information is public)'),
- '$rating_txt' => $rating_text,
- '$rating' => $rating,
- '$rating_val' => $rating_val,
- '$slide' => $slide,
- '$submit' => t('Submit')
- ));
-
- return $o;
-
- }
-}
diff --git a/Zotlabs/Module/Ratings.php b/Zotlabs/Module/Ratings.php
deleted file mode 100644
index 055b16ca3..000000000
--- a/Zotlabs/Module/Ratings.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-require_once('include/dir_fns.php');
-
-
-class Ratings extends \Zotlabs\Web\Controller {
-
- function init() {
-
- if(observer_prohibited()) {
- return;
- }
-
- if(local_channel())
- load_contact_links(local_channel());
-
- $dirmode = intval(get_config('system','directory_mode'));
-
- $x = find_upstream_directory($dirmode);
- if($x)
- $url = $x['url'];
-
- $rating_enabled = get_config('system','rating_enabled');
-
- if(! $rating_enabled)
- return;
-
- if(argc() > 1)
- $hash = argv(1);
-
- if(! $hash) {
- notice('Must supply a channel identififier.');
- return;
- }
-
- $results = false;
-
- $x = z_fetch_url($url . '/ratingsearch/' . urlencode($hash));
-
-
- if($x['success'])
- $results = json_decode($x['body'],true);
-
-
- if((! $results) || (! $results['success'])) {
-
- notice('No results.');
- return;
- }
-
- if(array_key_exists('xchan_hash',$results['target']))
- \App::$poi = $results['target'];
-
- $friends = array();
- $others = array();
-
- if($results['ratings']) {
- foreach($results['ratings'] as $n) {
- if(is_array(\App::$contacts) && array_key_exists($n['xchan_hash'],\App::$contacts))
- $friends[] = $n;
- else
- $others[] = $n;
- }
- }
-
- \App::$data = array('target' => $results['target'], 'results' => array_merge($friends,$others));
-
- if(! \App::$data['results']) {
- notice( t('No ratings') . EOL);
- }
-
- return;
- }
-
-
-
-
-
- function get() {
-
- if(observer_prohibited()) {
- notice( t('Public access denied.') . EOL);
- return;
- }
-
- $rating_enabled = get_config('system','rating_enabled');
-
- if(! $rating_enabled)
- return;
-
- $site_target = ((array_key_exists('target',\App::$data) && array_key_exists('site_url',\App::$data['target'])) ?
- '<a href="' . \App::$data['target']['site_url'] . '" >' . \App::$data['target']['site_url'] . '</a>' : '');
-
-
- $o = replace_macros(get_markup_template('prep.tpl'),array(
- '$header' => t('Ratings'),
- '$rating_lbl' => t('Rating: ' ),
- '$website' => t('Website: '),
- '$site' => $site_target,
- '$rating_text_lbl' => t('Description: '),
- '$raters' => \App::$data['results']
- ));
-
- return $o;
- }
-
-
-}
diff --git a/Zotlabs/Module/Ratingsearch.php b/Zotlabs/Module/Ratingsearch.php
deleted file mode 100644
index dcbfd6a9b..000000000
--- a/Zotlabs/Module/Ratingsearch.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-
-
-class Ratingsearch extends \Zotlabs\Web\Controller {
-
- function init() {
-
- $ret = array('success' => false);
-
- $dirmode = intval(get_config('system','directory_mode'));
-
- if($dirmode == DIRECTORY_MODE_NORMAL) {
- $ret['message'] = 'This site is not a directory server.';
- json_return_and_die($ret);
- }
-
- if(argc() > 1)
- $hash = argv(1);
-
- if(! $hash) {
- $ret['message'] = 'No channel identifier';
- json_return_and_die($ret);
- }
-
- if(strpos($hash,'@')) {
- $r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
- dbesc($hash)
- );
- if($r)
- $hash = $r[0]['hubloc_hash'];
- }
-
- $p = q("select * from xchan where xchan_hash like '%s'",
- dbesc($hash . '%')
- );
-
- if($p)
- $target = $p[0]['xchan_hash'];
- else {
- $p = q("select * from site where site_url like '%s' and site_type = %d ",
- dbesc('%' . $hash),
- intval(SITE_TYPE_ZOT)
- );
- if($p) {
- $target = strtolower($hash);
- }
- else {
- $ret['message'] = 'Rating target not found';
- json_return_and_die($ret);
- }
- }
-
- if($p)
- $ret['target'] = $p[0];
-
- $ret['success'] = true;
-
- $r = q("select * from xlink left join xchan on xlink_xchan = xchan_hash
- where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1
- and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
- order by xchan_name asc",
- dbesc($target)
- );
-
- if($r) {
- $ret['ratings'] = $r;
- }
- else
- $ret['ratings'] = array();
-
- json_return_and_die($ret);
-
- }
-
-
-}
diff --git a/Zotlabs/Module/Rbmark.php b/Zotlabs/Module/Rbmark.php
index 226cef69e..87b774495 100644
--- a/Zotlabs/Module/Rbmark.php
+++ b/Zotlabs/Module/Rbmark.php
@@ -6,12 +6,11 @@ require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/taxonomy.php');
require_once('include/conversation.php');
-require_once('include/zot.php');
require_once('include/bookmarks.php');
/**
* remote bookmark
- *
+ *
* https://yoursite/rbmark?f=&title=&url=&private=&remote_return=
*
* This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
@@ -31,45 +30,45 @@ class Rbmark extends \Zotlabs\Web\Controller {
function post() {
if($_POST['submit'] !== t('Save'))
return;
-
+
logger('rbmark_post: ' . print_r($_REQUEST,true));
-
+
$channel = \App::get_channel();
-
+
$t = array('url' => escape_tags($_REQUEST['url']),'term' => escape_tags($_REQUEST['title']));
bookmark_add($channel,$channel,$t,((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0),
array('menu_id' => ((x($_REQUEST,'menu_id')) ? intval($_REQUEST['menu_id']) : 0),
'menu_name' => ((x($_REQUEST,'menu_name')) ? escape_tags($_REQUEST['menu_name']) : ''),
'ischat' => ((x($_REQUEST['ischat'])) ? intval($_REQUEST['ischat']) : 0)
));
-
+
goaway(z_root() . '/bookmarks');
-
+
}
-
-
+
+
function get() {
-
+
$o = '';
-
+
if(! local_channel()) {
-
+
// The login procedure is going to bugger our $_REQUEST variables
// so save them in the session.
-
+
if(array_key_exists('url',$_REQUEST)) {
$_SESSION['bookmark'] = $_REQUEST;
}
return login();
}
-
+
// If we have saved rbmark session variables, but nothing in the current $_REQUEST, recover the saved variables
-
+
if((! array_key_exists('url',$_REQUEST)) && (array_key_exists('bookmark',$_SESSION))) {
$_REQUEST = $_SESSION['bookmark'];
unset($_SESSION['bookmark']);
}
-
+
if($_REQUEST['remote_return']) {
$_SESSION['remote_return'] = $_REQUEST['remote_return'];
}
@@ -78,12 +77,12 @@ class Rbmark extends \Zotlabs\Web\Controller {
goaway($_SESSION['remote_return']);
goaway(z_root() . '/bookmarks');
}
-
+
$channel = \App::get_channel();
-
-
+
+
$m = menu_list($channel['channel_id'],'',MENU_BOOKMARK);
-
+
$menus = array();
if($m) {
$menus = array(0 => '');
@@ -92,10 +91,10 @@ class Rbmark extends \Zotlabs\Web\Controller {
}
}
$menu_select = array('menu_id',t('Select a bookmark folder'),false,'',$menus);
-
-
+
+
$o .= replace_macros(get_markup_template('rbmark.tpl'), array(
-
+
'$header' => t('Save Bookmark'),
'$url' => array('url',t('URL of bookmark'),escape_tags($_REQUEST['url'])),
'$title' => array('title',t('Description'),escape_tags($_REQUEST['title'])),
@@ -104,18 +103,18 @@ class Rbmark extends \Zotlabs\Web\Controller {
'$submit' => t('Save'),
'$menu_name' => array('menu_name',t('Or enter new bookmark folder name'),'',''),
'$menus' => $menu_select
-
+
));
-
-
-
-
-
-
+
+
+
+
+
+
return $o;
-
+
}
-
-
-
+
+
+
}
diff --git a/Zotlabs/Module/Regate.php b/Zotlabs/Module/Regate.php
index 379195461..33bb8d957 100644
--- a/Zotlabs/Module/Regate.php
+++ b/Zotlabs/Module/Regate.php
@@ -2,6 +2,9 @@
namespace Zotlabs\Module;
+use Zotlabs\Lib\Connect;
+use Zotlabs\Daemon\Master;
+
require_once('include/security.php');
/**
@@ -184,7 +187,24 @@ class Regate extends \Zotlabs\Web\Controller {
$new_channel = auto_channel_create($cra['account']['account_id']);
if($new_channel['success']) {
+
$channel_id = $new_channel['channel']['channel_id'];
+
+ // If we have an inviter, connect.
+ if ($didx === 'i' && intval($r['reg_byc'])) {
+ $invite_channel = channelx_by_n($r['reg_byc']);
+ if ($invite_channel) {
+ $f = Connect::connect($new_channel['channel'], $invite_channel['xchan_addr']);
+ if ($f['success']) {
+ $can_view_stream = intval(get_abconfig($channel_id, $f['abook']['abook_xchan'], 'their_perms', 'view_stream'));
+ // If we can view their stream, pull in some posts
+ if ($can_view_stream) {
+ Master::Summon(['Onepoll', $f['abook']['abook_id']]);
+ }
+ }
+ }
+ }
+
change_channel($channel_id);
$nextpage = 'profiles/' . $channel_id;
$msg_code = 'ZAR1239I';
diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php
index 876d61ca6..4d475ead6 100644
--- a/Zotlabs/Module/Removeme.php
+++ b/Zotlabs/Module/Removeme.php
@@ -5,67 +5,67 @@ namespace Zotlabs\Module;
class Removeme extends \Zotlabs\Web\Controller {
function post() {
-
+
if(! local_channel())
return;
-
+
if($_SESSION['delegate'])
return;
-
+
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password']))))
return;
-
+
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify']))))
return;
-
+
if($_POST['verify'] !== $_SESSION['remove_account_verify'])
return;
-
-
+
+
$account = \App::get_account();
-
-
+
+
$x = account_verify_password($account['account_email'],$_POST['qxz_password']);
if(! ($x && $x['account']))
return;
-
+
if($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
- if($account['account_password_changed'] > d1) {
+ if($account['account_password_changed'] > $d1) {
notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL);
return;
}
}
-
+
$global_remove = 0; //intval($_POST['global']);
channel_remove(local_channel(),1 - $global_remove,true);
-
+
}
-
-
+
+
function get() {
-
+
if(! local_channel())
goaway(z_root());
-
+
$hash = random_string();
-
+
$_SESSION['remove_account_verify'] = $hash;
-
+
$tpl = get_markup_template('removeme.tpl');
$o .= replace_macros($tpl, array(
'$basedir' => z_root(),
'$hash' => $hash,
- '$title' => t('Remove This Channel'),
- '$desc' => [ t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!') ],
+ '$title' => t('Remove Channel'),
+ '$desc' => [ t('WARNING: '), t('This channel will be permanently removed. '), t('This action can not be undone!') ],
'$passwd' => t('Please enter your password for verification:'),
// '$global' => [ 'global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), [ t('No'),t('Yes') ] ],
'$submit' => t('Remove Channel')
));
-
- return $o;
-
+
+ return $o;
+
}
-
+
}
diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php
index 031270845..013817597 100644
--- a/Zotlabs/Module/Rpost.php
+++ b/Zotlabs/Module/Rpost.php
@@ -1,12 +1,13 @@
<?php
namespace Zotlabs\Module; /** @file */
+use Zotlabs\Lib\Libzot;
+
require_once('include/acl_selectors.php');
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/taxonomy.php');
require_once('include/conversation.php');
-require_once('include/zot.php');
/**
* remote post
@@ -42,7 +43,7 @@ class Rpost extends \Zotlabs\Web\Controller {
// by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
// blocks them.
- $url = get_rpost_path(\App::get_observer());
+ $url = Libzot::get_rpost_path(\App::get_observer());
// make sure we're not looping to our own hub
if(($url) && (! stristr($url, \App::get_hostname()))) {
foreach($_GET as $key => $arg) {
@@ -65,6 +66,73 @@ class Rpost extends \Zotlabs\Web\Controller {
nav_set_selected('Post');
+ if (local_channel() && array_key_exists('userfile',$_FILES)) {
+
+ $channel = App::get_channel();
+ $observer = App::get_observer();
+
+ $def_album = get_pconfig($channel['channel_id'],'system','photo_path');
+ $def_attach = get_pconfig($channel['channel_id'],'system','attach_path');
+
+ $r = attach_store($channel, (($observer) ? $observer['xchan_hash'] : ''), '', [
+ 'source' => 'editor',
+ 'visible' => 0,
+ 'album' => $def_album,
+ 'directory' => $def_attach,
+ 'flags' => 1, // indicates temporary permissions are created
+ 'allow_cid' => '<' . $channel['channel_hash'] . '>'
+ ]);
+
+ if (! $r['success']) {
+ notice( $r['message'] . EOL);
+ }
+
+ $s = EMPTY_STR;
+
+ if (intval($r['data']['is_photo'])) {
+ $s .= "\n\n" . $r['body'] . "\n\n";
+ }
+
+ $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
+
+ if (strpos($r['data']['filetype'],'video') === 0) {
+ $s .= "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n";
+ }
+
+ if (strpos($r['data']['filetype'],'audio') === 0) {
+ $s .= "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n";
+ }
+
+ if ($r['data']['filetype'] === 'image/svg+xml') {
+ $x = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
+ if ($x) {
+ $bb = svg2bb($x);
+ if ($bb) {
+ $s .= "\n\n" . $bb;
+ }
+ else {
+ logger('empty return from svgbb');
+ }
+ }
+ else {
+ logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
+ }
+ }
+
+ if ($r['data']['filetype'] === 'text/calendar') {
+ $content = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
+ if ($content) {
+ $ev = ical_to_ev($content);
+ if ($ev) {
+ $s .= "\n\n" . format_event_bbcode($ev[0]) . "\n\n";
+ }
+ }
+ }
+
+ $s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
+ $_REQUEST['body'] = ((array_key_exists('body',$_REQUEST)) ? $_REQUEST['body'] . $s : $s);
+ }
+
// If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables
if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) {
diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php
index 2ad79e3f6..fdc251b07 100644
--- a/Zotlabs/Module/Search.php
+++ b/Zotlabs/Module/Search.php
@@ -3,9 +3,11 @@
namespace Zotlabs\Module;
use App;
+use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Zotfinger;
class Search extends Controller {
@@ -25,10 +27,11 @@ class Search extends Controller {
nav_set_selected('Search');
- require_once("include/bbcode.php");
- require_once('include/security.php');
+ require_once('include/bbcode.php');
require_once('include/conversation.php');
require_once('include/items.php');
+ require_once('include/security.php');
+
$format = (($_REQUEST['format']) ? $_REQUEST['format'] : '');
if ($format !== '') {
@@ -38,11 +41,9 @@ class Search extends Controller {
$observer = App::get_observer();
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
- $o = '<div id="live-search"></div>' . "\r\n";
+ $o = '<div class="generic-content-wrapper-styled">' . "\r\n";
- $o .= '<div class="generic-content-wrapper-styled">' . "\r\n";
-
- $o .= '<h3>' . t('Search') . '</h3>';
+ $o .= '<h2>' . t('Search') . '</h2>';
if (x(App::$data, 'search'))
$search = trim(App::$data['search']);
@@ -58,26 +59,31 @@ class Search extends Controller {
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
- $j = Activity::fetch(punify($search), App::get_channel());
- if ($j) {
- $AS = new ActivityStreams($j);
- if ($AS->is_valid()) {
- // check if is_an_actor, otherwise import activity
- if (is_array($AS->obj) && !ActivityStreams::is_an_actor($AS->obj)) {
- $item = Activity::decode_note($AS);
- if ($item) {
- logger('parsed_item: ' . print_r($item, true), LOGGER_DATA);
- Activity::store(App::get_channel(), $observer_hash, $AS, $item, true, true);
- goaway(z_root() . '/display/' . gen_link_id($item['mid']));
- }
+ if (strpos($search, 'b64.') !== false) {
+ if (strpos($search, '?') !== false) {
+ $search = strtok($search, '?');
+ }
+
+ $search = unpack_link_id(basename($search));
+ }
+
+ $f = Libzot::fetch_conversation(App::get_channel(), punify($search), true);
+
+ if ($f) {
+ $mid = $f[0]['message_id'];
+ foreach ($f as $m) {
+ if (strpos($search, $m['message_id']) === 0) {
+ $mid = $m['message_id'];
+ break;
}
}
+
+ goaway(z_root() . '/hq/' . gen_link_id($mid));
}
else {
- // try other fetch providers (e.g. diaspora)
+ // try other fetch providers (e.g. diaspora, pubcrawl)
$hookdata = [
- 'channel' => App::get_channel(),
- 'data' => $search
+ 'url' => punify($search)
];
call_hooks('fetch_provider', $hookdata);
}
@@ -87,21 +93,21 @@ class Search extends Controller {
$tag = true;
$search = substr($search, 1);
}
- if (strpos($search, '@') === 0) {
+ elseif(strpos($search, '@') === 0) {
$search = substr($search, 1);
goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
}
- if (strpos($search, '!') === 0) {
+ elseif(strpos($search, '!') === 0) {
$search = substr($search, 1);
goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
}
- if (strpos($search, '?') === 0) {
+ elseif(strpos($search, '?') === 0) {
$search = substr($search, 1);
goaway(z_root() . '/help' . '?f=1&navsearch=1&search=' . $search);
}
// look for a naked webbie
- if (strpos($search,'@') !== false && strpos($search,'http') !== 0) {
+ if (strpos($search, '@') !== false && strpos($search, 'http') !== 0) {
goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search);
}
@@ -216,7 +222,7 @@ class Search extends Controller {
}
if ($r) {
$str = ids_to_querystr($r, 'item_id');
- $r = q("select *, id as item_id from item where id in ( " . $str . ") order by created desc ");
+ $r = dbq("select *, id as item_id from item where id in ( " . $str . ") order by created desc");
}
}
else {
@@ -234,7 +240,7 @@ class Search extends Controller {
$items = [];
}
- if ($format == 'json') {
+ if ($format === 'json') {
$result = [];
require_once('include/conversation.php');
foreach ($items as $item) {
diff --git a/Zotlabs/Module/Settings.php b/Zotlabs/Module/Settings.php
index 79031c98f..624cbb0c1 100644
--- a/Zotlabs/Module/Settings.php
+++ b/Zotlabs/Module/Settings.php
@@ -1,7 +1,6 @@
<?php
namespace Zotlabs\Module; /** @file */
-require_once('include/zot.php');
require_once('include/security.php');
class Settings extends \Zotlabs\Web\Controller {
@@ -11,68 +10,68 @@ class Settings extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
-
+
if($_SESSION['delegate'])
return;
-
+
\App::$profile_uid = local_channel();
-
+
// default is channel settings in the absence of other arguments
-
+
if(argc() == 1) {
// We are setting these values - don't use the argc(), argv() functions here
\App::$argc = 2;
\App::$argv[] = 'channel';
- }
+ }
$this->sm = new \Zotlabs\Web\SubModule();
}
-
-
+
+
function post() {
-
+
if(! local_channel())
return;
-
+
if($_SESSION['delegate'])
return;
-
+
// logger('mod_settings: ' . print_r($_REQUEST,true));
-
+
if(argc() > 1) {
if($this->sm->call('post') !== false) {
return;
}
}
-
+
goaway(z_root() . '/settings' );
return; // NOTREACHED
}
-
-
-
+
+
+
function get() {
-
+
nav_set_selected('Settings');
-
+
if((! local_channel()) || ($_SESSION['delegate'])) {
notice( t('Permission denied.') . EOL );
return login();
}
-
-
+
+
$channel = \App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
-
+
$o = $this->sm->call('get');
if($o !== false)
return $o;
$o = '';
-
- }
+
+ }
}
diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php
index ab85eb450..65240c635 100644
--- a/Zotlabs/Module/Settings/Calendar.php
+++ b/Zotlabs/Module/Settings/Calendar.php
@@ -11,14 +11,14 @@ class Calendar {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Calendar {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Calendar Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php
index 2eed1efc9..840efc162 100644
--- a/Zotlabs/Module/Settings/Channel.php
+++ b/Zotlabs/Module/Settings/Channel.php
@@ -2,6 +2,10 @@
namespace Zotlabs\Module\Settings;
+use App;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Access\PermissionRoles;
+use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
@@ -10,597 +14,279 @@ require_once('include/selectors.php');
class Channel {
-
function post() {
- $channel = \App::get_channel();
-
check_form_security_token_redirectOnErr('/settings', 'settings');
-
call_hooks('settings_post', $_POST);
-
- $set_perms = '';
-
- $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
- $oldrole = get_pconfig(local_channel(),'system','permissions_role');
-
- // This mapping can be removed after 3.4 release
- if($oldrole === 'social_party') {
- $oldrole = 'social_federation';
- }
-
- if(($role != $oldrole) || ($role === 'custom')) {
-
- if($role === 'custom') {
- $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0);
- $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
- $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : '');
- $r = q("update channel set channel_default_group = '%s' where channel_id = %d",
- dbesc($def_group),
- intval(local_channel())
- );
-
- $global_perms = \Zotlabs\Access\Permissions::Perms();
-
- foreach($global_perms as $k => $v) {
- \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,intval($_POST[$k]));
- }
- $acl = new \Zotlabs\Access\AccessList($channel);
- $acl->set_from_array($_POST);
- $x = $acl->get();
-
- $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s',
- channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d",
- dbesc($x['allow_cid']),
- dbesc($x['allow_gid']),
- dbesc($x['deny_cid']),
- dbesc($x['deny_gid']),
- intval(local_channel())
- );
- }
- else {
- $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']);
- if(! $role_permissions) {
- notice('Permissions category could not be found.');
- return;
- }
- $hide_presence = 1 - (intval($role_permissions['online']));
- if($role_permissions['default_collection']) {
- $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- if(! $r) {
- require_once('include/group.php');
- group_add(local_channel(), t('Friends'));
- group_add_member(local_channel(),t('Friends'),$channel['channel_hash']);
- $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- }
- if($r) {
- q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d",
- dbesc($r[0]['hash']),
- dbesc('<' . $r[0]['hash'] . '>'),
- intval(local_channel())
- );
- }
- else {
- notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
- return;
- }
- }
- // no default collection
- else {
- q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '',
- channel_deny_cid = '' where channel_id = %d",
- intval(local_channel())
- );
- }
- if($role_permissions['perms_connect']) {
- $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
- foreach($x as $k => $v) {
- set_abconfig(local_channel(),$channel['channel_hash'],'my_perms',$k, $v);
- if($role_permissions['perms_auto']) {
- set_pconfig(local_channel(),'autoperms',$k,$v);
- }
- else {
- del_pconfig(local_channel(),'autoperms',$k);
- }
- }
- }
-
- if($role_permissions['limits']) {
- foreach($role_permissions['limits'] as $k => $v) {
- \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,$v);
- }
- }
- if(array_key_exists('directory_publish',$role_permissions)) {
- $publish = intval($role_permissions['directory_publish']);
- }
- }
-
- set_pconfig(local_channel(),'system','hide_online_status',$hide_presence);
- set_pconfig(local_channel(),'system','permissions_role',$role);
- }
-
- $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
- $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
- $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : '');
- $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : '');
- $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0);
- $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0);
- $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3);
- $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
- $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
-
- $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0);
- $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0);
- $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0);
- $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0);
-
- $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
-
- $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
- $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
- $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
- $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
- $autoperms = ((x($_POST,'autoperms')) ? intval($_POST['autoperms']) : 0);
-
- $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
- $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
- $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
- $adult = (($_POST['adult'] == 1) ? 1 : 0);
- $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default');
-
- $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : '');
-
- $pageflags = $channel['channel_pageflags'];
- $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
- if($adult != $existing_adult)
+ $channel = App::get_channel();
+ $role = ((x($_POST, 'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
+ $timezone = ((x($_POST, 'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
+ $defloc = ((x($_POST, 'defloc')) ? notags(trim($_POST['defloc'])) : '');
+ $evdays = ((x($_POST, 'evdays')) ? intval($_POST['evdays']) : 3);
+ $photo_path = ((x($_POST, 'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
+ $attach_path = ((x($_POST, 'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
+ $allow_location = (((x($_POST, 'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1 : 0);
+ $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1 : 0);
+ $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1 : 0);
+ $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1 : 0);
+ $adult = (($_POST['adult'] == 1) ? 1 : 0);
+ $mailhost = ((array_key_exists('mailhost', $_POST)) ? notags(trim($_POST['mailhost'])) : '');
+ $pageflags = $channel['channel_pageflags'];
+ $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
+ $expire = ((x($_POST, 'expire')) ? intval($_POST['expire']) : 0);
+ $incl = ((x($_POST['message_filter_incl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_incl']), ENT_QUOTES) : '');
+ $excl = ((x($_POST['message_filter_excl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_excl']), ENT_QUOTES) : '');
+
+ if ($adult != $existing_adult) {
$pageflags = ($pageflags ^ PAGE_ADULT);
-
-
+ }
+
$notify = 0;
-
- if(x($_POST,'notify1'))
+ if (x($_POST, 'notify1'))
$notify += intval($_POST['notify1']);
- if(x($_POST,'notify2'))
+ if (x($_POST, 'notify2'))
$notify += intval($_POST['notify2']);
- if(x($_POST,'notify3'))
+ if (x($_POST, 'notify3'))
$notify += intval($_POST['notify3']);
- if(x($_POST,'notify4'))
+ if (x($_POST, 'notify4'))
$notify += intval($_POST['notify4']);
- if(x($_POST,'notify5'))
+ if (x($_POST, 'notify5'))
$notify += intval($_POST['notify5']);
- if(x($_POST,'notify6'))
+ if (x($_POST, 'notify6'))
$notify += intval($_POST['notify6']);
- if(x($_POST,'notify7'))
+ if (x($_POST, 'notify7'))
$notify += intval($_POST['notify7']);
- if(x($_POST,'notify8'))
+ if (x($_POST, 'notify8'))
$notify += intval($_POST['notify8']);
-
-
+
+
$vnotify = 0;
-
- if(x($_POST,'vnotify1'))
+ if (x($_POST, 'vnotify1'))
$vnotify += intval($_POST['vnotify1']);
- if(x($_POST,'vnotify2'))
+ if (x($_POST, 'vnotify2'))
$vnotify += intval($_POST['vnotify2']);
- if(x($_POST,'vnotify3'))
+ if (x($_POST, 'vnotify3'))
$vnotify += intval($_POST['vnotify3']);
- if(x($_POST,'vnotify4'))
+ if (x($_POST, 'vnotify4'))
$vnotify += intval($_POST['vnotify4']);
- if(x($_POST,'vnotify5'))
+ if (x($_POST, 'vnotify5'))
$vnotify += intval($_POST['vnotify5']);
- if(x($_POST,'vnotify6'))
+ if (x($_POST, 'vnotify6'))
$vnotify += intval($_POST['vnotify6']);
- if(x($_POST,'vnotify7'))
+ if (x($_POST, 'vnotify7'))
$vnotify += intval($_POST['vnotify7']);
- if(x($_POST,'vnotify8'))
+ if (x($_POST, 'vnotify8'))
$vnotify += intval($_POST['vnotify8']);
- if(x($_POST,'vnotify9'))
+ if (x($_POST, 'vnotify9'))
$vnotify += intval($_POST['vnotify9']);
- if(x($_POST,'vnotify10'))
+ if (x($_POST, 'vnotify10'))
$vnotify += intval($_POST['vnotify10']);
- if(x($_POST,'vnotify11') && is_site_admin())
+ if (x($_POST, 'vnotify11') && is_site_admin())
$vnotify += intval($_POST['vnotify11']);
- if(x($_POST,'vnotify12'))
+ if (x($_POST, 'vnotify12'))
$vnotify += intval($_POST['vnotify12']);
- if(x($_POST,'vnotify13'))
+ if (x($_POST, 'vnotify13'))
$vnotify += intval($_POST['vnotify13']);
- if(x($_POST,'vnotify14'))
+ if (x($_POST, 'vnotify14'))
$vnotify += intval($_POST['vnotify14']);
- if(x($_POST,'vnotify15'))
+ if (x($_POST, 'vnotify15'))
$vnotify += intval($_POST['vnotify15']);
-
- $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0;
-
- $err = '';
-
- $name_change = false;
-
- if($username != $channel['channel_name']) {
- $name_change = true;
- require_once('include/channel.php');
- $err = validate_channelname($username);
- if($err) {
- notice($err);
- return;
- }
- }
-
- if($timezone != $channel['channel_timezone']) {
- if(strlen($timezone))
+
+ $always_show_in_notices = ((x($_POST, 'always_show_in_notices')) ? 1 : 0);
+ $update_notices_per_parent = ((x($_POST, 'update_notices_per_parent')) ? 1 : 0);
+
+ if ($timezone !== $channel['channel_timezone']) {
+ if (strlen($timezone))
date_default_timezone_set($timezone);
}
-
- set_pconfig(local_channel(),'system','use_browser_location',$allow_location);
- set_pconfig(local_channel(),'system','suggestme', $suggestme);
- set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend);
- set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup);
- set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange);
- set_pconfig(local_channel(),'system','blocktags',$blocktags);
- set_pconfig(local_channel(),'system','vnotify',$vnotify);
- set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices);
- set_pconfig(local_channel(),'system','evdays',$evdays);
- set_pconfig(local_channel(),'system','photo_path',$photo_path);
- set_pconfig(local_channel(),'system','attach_path',$attach_path);
- set_pconfig(local_channel(),'system','default_permcat',$defpermcat);
- set_pconfig(local_channel(),'system','email_notify_host',$mailhost);
- set_pconfig(local_channel(),'system','autoperms',$autoperms);
-
- $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
- dbesc($username),
+
+ if (!$role) {
+ notice(t('Please select a channel role') . EOL);
+ return;
+ }
+
+ if ($role !== get_pconfig(local_channel(), 'system', 'permissions_role')) {
+ $role_permissions = PermissionRoles::role_perms($_POST['permissions_role']);
+
+ if (isset($role_permissions['limits'])) {
+ foreach ($role_permissions['limits'] as $k => $v) {
+ PermissionLimits::Set(local_channel(), $k, $v);
+ }
+ }
+
+ set_pconfig(local_channel(), 'system', 'group_actor', 0);
+ if (isset($role_permissions['channel_type']) && $role_permissions['channel_type'] === 'group') {
+ set_pconfig(local_channel(), 'system', 'group_actor', 1);
+ }
+ }
+
+ set_pconfig(local_channel(), 'system', 'permissions_role', $role);
+ set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location);
+ set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend);
+ set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup);
+ set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange);
+ set_pconfig(local_channel(), 'system', 'vnotify', $vnotify);
+ set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices);
+ set_pconfig(local_channel(), 'system', 'update_notices_per_parent', $update_notices_per_parent);
+ set_pconfig(local_channel(), 'system', 'evdays', $evdays);
+ set_pconfig(local_channel(), 'system', 'photo_path', $photo_path);
+ set_pconfig(local_channel(), 'system', 'attach_path', $attach_path);
+ set_pconfig(local_channel(), 'system', 'email_notify_host', $mailhost);
+ set_pconfig(local_channel(), 'system', 'message_filter_incl', $incl);
+ set_pconfig(local_channel(), 'system', 'message_filter_excl', $excl);
+
+ $r = q("update channel set channel_pageflags = %d, channel_timezone = '%s',
+ channel_location = '%s', channel_notifyflags = %d, channel_expire_days = %d
+ where channel_id = %d",
intval($pageflags),
dbesc($timezone),
dbesc($defloc),
intval($notify),
- intval($unkmail),
- intval($maxreq),
intval($expire),
intval(local_channel())
- );
- if($r)
- info( t('Settings updated.') . EOL);
-
- if(! is_null($publish)) {
- $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d",
- intval($publish),
- intval(local_channel())
- );
- }
-
- if($name_change) {
- // change name on all associated xchans by matching the url
- $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_url = '%s'",
- dbesc($username),
- dbesc(datetime_convert()),
- dbesc(z_root() . '/channel/' . $channel['channel_address'])
- );
- $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1",
- dbesc($username),
- intval($channel['channel_id'])
- );
- }
-
- \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
-
+ );
+ if ($r)
+ info(t('Settings updated.') . EOL);
+
+ Master::Summon(['Directory', local_channel()]);
Libsync::build_sync_packet();
-
-
- if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
-
+
+ if ($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) {
+
// FIXME - set to un-verified, blocked and redirect to logout
// Q: Why? Are we verifying people or email addresses?
// A: the policy is to verify email addresses
}
-
- goaway(z_root() . '/settings' );
+
+ goaway(z_root() . '/settings');
return; // NOTREACHED
}
-
+
function get() {
-
- require_once('include/acl_selectors.php');
- require_once('include/permissions.php');
+ load_pconfig(local_channel());
- $yes_no = array(t('No'),t('Yes'));
-
-
- $p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1",
- intval(local_channel())
- );
- if(count($p))
- $profile = $p[0];
-
- load_pconfig(local_channel(),'expire');
-
- $channel = \App::get_channel();
-
- $global_perms = \Zotlabs\Access\Permissions::Perms();
-
- $permiss = array();
-
- $perm_opts = array(
- array( t('Nobody except yourself'), 0),
- array( t('Only those you specifically allow'), PERMS_SPECIFIC),
- array( t('Approved connections'), PERMS_CONTACTS),
- array( t('Any connections'), PERMS_PENDING),
- array( t('Anybody on this website'), PERMS_SITE),
- array( t('Anybody in this network'), PERMS_NETWORK),
- array( t('Anybody authenticated'), PERMS_AUTHED),
- array( t('Anybody on the internet'), PERMS_PUBLIC)
- );
-
- $limits = \Zotlabs\Access\PermissionLimits::Get(local_channel());
- $anon_comments = get_config('system','anonymous_comments',true);
-
- foreach($global_perms as $k => $perm) {
- $options = array();
- $can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false);
- foreach($perm_opts as $opt) {
- if($opt[1] == PERMS_PUBLIC && (! $can_be_public))
- continue;
- $options[$opt[1]] = $opt[0];
- }
- $permiss[] = array($k,$perm,$limits[$k],'',$options);
- }
-
- // logger('permiss: ' . print_r($permiss,true));
-
- $username = $channel['channel_name'];
- $nickname = $channel['channel_address'];
- $timezone = $channel['channel_timezone'];
- $notify = $channel['channel_notifyflags'];
- $defloc = $channel['channel_location'];
-
- $maxreq = $channel['channel_max_friend_req'];
- $expire = $channel['channel_expire_days'];
- $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
- $sys_expire = get_config('system','default_expire_days');
-
-// $unkmail = \App::$user['unkmail'];
-// $cntunkmail = \App::$user['cntunkmail'];
-
- $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
-
-
- $expire_items = get_pconfig(local_channel(), 'expire','items');
- $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
-
- $expire_notes = get_pconfig(local_channel(), 'expire','notes');
- $expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1
-
- $expire_starred = get_pconfig(local_channel(), 'expire','starred');
- $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
-
- $expire_photos = get_pconfig(local_channel(), 'expire','photos');
- $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
-
- $expire_network_only = get_pconfig(local_channel(), 'expire','network_only');
- $expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0
-
-
- $suggestme = get_pconfig(local_channel(), 'system','suggestme');
- $suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0
-
- $post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend');
- $post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0
-
- $post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup');
- $post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0
-
- $post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange');
- $post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0
-
- $blocktags = get_pconfig(local_channel(),'system','blocktags');
- $blocktags = (($blocktags===false) ? '0' : $blocktags);
-
- $timezone = date_default_timezone_get();
-
- $opt_tpl = get_markup_template("field_checkbox.tpl");
- if(get_config('system','publish_all')) {
- $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
- }
- else {
- $profile_in_dir = replace_macros($opt_tpl,array(
- '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no),
- ));
- }
-
- $suggestme = replace_macros($opt_tpl,array(
- '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no),
-
- ));
-
- $subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
-
- $webbie = $nickname . '@' . \App::get_hostname();
- $intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname());
-
-
- $tpl_addr = get_markup_template("settings_nick_set.tpl");
-
- $prof_addr = replace_macros($tpl_addr,array(
- '$desc' => t('Your channel address is'),
+ $channel = App::get_channel();
+ $nickname = $channel['channel_address'];
+ $timezone = $channel['channel_timezone'];
+ $notify = $channel['channel_notifyflags'];
+ $defloc = $channel['channel_location'];
+ $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
+ $post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend');
+ $post_newfriend = (($post_newfriend === false) ? '0' : $post_newfriend); // default if not set: 0
+ $post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup');
+ $post_joingroup = (($post_joingroup === false) ? '0' : $post_joingroup); // default if not set: 0
+ $post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange');
+ $post_profilechange = (($post_profilechange === false) ? '0' : $post_profilechange); // default if not set: 0
+ $subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
+ $webbie = $nickname . '@' . App::get_hostname();
+ $intl_nickname = unpunify($nickname) . '@' . unpunify(App::get_hostname());
+ $disable_discover_tab = intval(get_config('system', 'disable_discover_tab', 1)) == 1;
+ $site_firehose = intval(get_config('system', 'site_firehose', 0)) == 1;
+
+ $expire = $channel['channel_expire_days'];
+ $sys_expire = get_config('system', 'default_expire_days');
+
+ $tpl_addr = get_markup_template("settings_nick_set.tpl");
+ $prof_addr = replace_macros($tpl_addr, [
+ '$desc' => t('Your channel address is'),
'$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . '&nbsp;(' . $webbie . ')'),
- '$subdir' => $subdir,
- '$davdesc' => t('Your files/photos are accessible via WebDAV at'),
- '$davpath' => z_root() . '/dav/' . $nickname,
- '$basepath' => \App::get_hostname()
- ));
+ '$subdir' => $subdir,
+ '$davdesc' => t('Your files/photos are accessible via WebDAV at'),
+ '$davpath' => z_root() . '/dav/' . $nickname,
+ '$basepath' => App::get_hostname()
+ ]);
+ $evdays = get_pconfig(local_channel(), 'system', 'evdays');
+ if (!$evdays)
+ $evdays = 3;
+ $always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices');
+ $update_notices_per_parent = get_pconfig(local_channel(), 'system', 'update_notices_per_parent', 1);
- $pcat = new \Zotlabs\Lib\Permcat(local_channel());
- $pcatlist = $pcat->listing();
- $permcats = [];
- if($pcatlist) {
- foreach($pcatlist as $pc) {
- $permcats[$pc['name']] = $pc['localname'];
- }
+ $vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
+ if ($vnotify === false)
+ $vnotify = (-1);
+
+ $perm_roles = PermissionRoles::channel_roles();
+ $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role');
+
+ if (!in_array($permissions_role, ['public', 'personal', 'group', 'custom'])) {
+ notice(t('Please select a channel role') . EOL);
+ array_unshift($perm_roles , '');
}
- $default_permcat = get_pconfig(local_channel(),'system','default_permcat','default');
+ $plugin = ['basic' => '', 'notify' => ''];
+ call_hooks('channel_settings', $plugin);
+
+ $yes_no = [t('No'), t('Yes')];
-
$stpl = get_markup_template('settings.tpl');
-
- $acl = new \Zotlabs\Access\AccessList($channel);
- $perm_defaults = $acl->get();
-
- require_once('include/group.php');
- $group_select = mini_group_select(local_channel(),$channel['channel_default_group']);
-
- $evdays = get_pconfig(local_channel(),'system','evdays');
- if(! $evdays)
- $evdays = 3;
-
- $permissions_role = get_pconfig(local_channel(),'system','permissions_role');
- if(! $permissions_role)
- $permissions_role = 'custom';
- // compatibility mapping - can be removed after 3.4 release
- if($permissions_role === 'social_party')
- $permissions_role = 'social_federation';
-
- if(in_array($permissions_role,['forum','repository']))
- $autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [
- '$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]);
- else
- $autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />';
-
- $permissions_set = (($permissions_role != 'custom') ? true : false);
-
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
-
- $vnotify = get_pconfig(local_channel(),'system','vnotify');
- $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
- if($vnotify === false)
- $vnotify = (-1);
+ $o = replace_macros($stpl, [
+ '$ptitle' => t('Channel Settings'),
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$uid' => local_channel(),
+ '$form_security_token' => get_form_security_token("settings"),
+ '$role' => ['permissions_role', t('Channel role'), $permissions_role, '', $perm_roles],
+ '$nickname_block' => $prof_addr,
+ '$h_basic' => t('Basic Settings'),
+ '$timezone' => ['timezone_select', t('Channel timezone:'), $timezone, '', get_timezones()],
+ '$defloc' => ['defloc', t('Default post location:'), $defloc, t('Geographical location to display on your posts')],
+ '$allowloc' => ['allow_location', t('Use browser location'), ((get_pconfig(local_channel(), 'system', 'use_browser_location')) ? 1 : ''), '', $yes_no],
+ '$adult' => ['adult', t('Adult content'), $adult_flag, t('This channel frequently or regularly publishes adult content'), $yes_no],
+ '$maxreq' => ['maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')],
+ '$h_not' => t('Notification Settings'),
+ '$activity_options' => t('By default post a status message when:'),
+ '$post_newfriend' => ['post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no],
+ '$post_joingroup' => ['post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no],
+ '$post_profilechange' => ['post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no],
+ '$lbl_not' => t('Send a notification email when:'),
+ '$notify1' => ['notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no],
+ '$notify2' => ['notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no],
+ '$notify3' => ['notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no],
+ '$notify4' => ['notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no],
+ '$notify5' => ['notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no],
+ '$notify6' => ['notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no],
+ '$notify7' => ['notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no],
+ '$notify8' => ['notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no],
+ '$notify9' => ['notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no],
+ '$lbl_vnot' => t('Show visual notifications including:'),
+ '$vnotify1' => ['vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no],
+ '$vnotify2' => ['vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no],
+ '$vnotify3' => ['vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no],
+ '$vnotify4' => ['vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no],
+ '$vnotify5' => ['vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no],
+ '$vnotify6' => ['vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no],
+ '$vnotify7' => ['vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no],
+ '$vnotify8' => ['vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no],
+ '$vnotify9' => ['vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no],
+ '$vnotify10' => ['vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no],
+ '$vnotify11' => ((is_site_admin()) ? ['vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no] : []),
+ '$vnotify12' => ['vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no],
+ '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? [] : ['vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no]),
+ '$vnotify14' => ['vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no],
+ '$vnotify15' => ['vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no],
+ '$mailhost' => ['mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(), 'system', 'email_notify_host', App::get_hostname()), sprintf(t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'), App::get_hostname())],
+ '$always_show_in_notices' => ['always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no],
+ '$update_notices_per_parent' => ['update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no],
+ '$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'),
+ '$desktop_notifications_request' => t('Grant permission'),
+ '$evdays' => ['evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')],
+ '$basic_addon' => $plugin['basic'],
+ '$notify_addon' => $plugin['notify'],
+ '$photo_path' => ['photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')],
+ '$attach_path' => ['attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')],
+ '$removeme' => t('Remove Channel'),
+ '$removechannel' => t('Remove this channel.'),
+ '$expire' => ['expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')],
+ '$message_filter_excl' => ['message_filter_excl', t('Do not import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_excl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')],
+ '$message_filter_incl' => ['message_filter_incl', t('Only import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_incl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')]
+ ]);
+
+ call_hooks('settings_form', $o);
- $plugin = [ 'basic' => '', 'security' => '', 'notify' => '' ];
- call_hooks('channel_settings',$plugin);
-
- $disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1;
- $site_firehose = intval(get_config('system','site_firehose',0)) == 1;
-
-
- $o .= replace_macros($stpl,array(
- '$ptitle' => t('Channel Settings'),
-
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$uid' => local_channel(),
- '$form_security_token' => get_form_security_token("settings"),
- '$nickname_block' => $prof_addr,
- '$h_basic' => t('Basic Settings'),
- '$username' => array('username', t('Full Name:'), $username,''),
- '$email' => array('email', t('Email Address:'), $email, ''),
- '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()),
- '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')),
- '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
-
- '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
-
- '$h_prv' => t('Security and Privacy Settings'),
- '$permissions_set' => $permissions_set,
- '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
-
- '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
-
- '$lbl_pmacro' => t('Simple Privacy Settings:'),
- '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
- '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
- '$pmacro1' => t('Private - <em>default private, never open or public</em>'),
- '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
- '$permiss_arr' => $permiss,
- '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
-
- '$lbl_p2macro' => t('Channel Permission Limits'),
-
- '$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')),
- '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
- '$permissions' => t('Default Privacy Group'),
- '$permdesc' => t("\x28click to open/close\x29"),
- '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))),
-
- '$allow_cid' => acl2json($perm_defaults['allow_cid']),
- '$allow_gid' => acl2json($perm_defaults['allow_gid']),
- '$deny_cid' => acl2json($perm_defaults['deny_cid']),
- '$deny_gid' => acl2json($perm_defaults['deny_gid']),
- '$suggestme' => $suggestme,
- '$group_select' => $group_select,
- '$role' => array('permissions_role' , t('Channel role and privacy'), $permissions_role, '', $perm_roles),
- '$defpermcat' => [ 'defpermcat', t('Default permissions category'), $default_permcat, '', $permcats ],
- '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
- '$profile_in_dir' => $profile_in_dir,
- '$hide_friends' => $hide_friends,
- '$hide_wall' => $hide_wall,
- '$unkmail' => $unkmail,
- '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")),
-
- '$autoperms' => $autoperms,
- '$h_not' => t('Notification Settings'),
- '$activity_options' => t('By default post a status message when:'),
- '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
- '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
- '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no),
- '$lbl_not' => t('Send a notification email when:'),
- '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no),
- '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no),
- '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no),
- '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no),
- '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no),
- '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no),
- '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no),
- '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no),
-
- '$notify9' => array('notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no),
-
-
- '$lbl_vnot' => t('Show visual notifications including:'),
-
- '$vnotify1' => array('vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no),
- '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no),
- '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no),
- '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no),
- '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no),
- '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no),
- '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no),
- '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no),
- '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no),
- '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no),
- '$vnotify11' => ((is_site_admin()) ? array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no) : array()),
- '$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no),
- '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? array() : array('vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)),
- '$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no),
- '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no),
- '$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ],
- '$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
-
- '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
- '$basic_addon' => $plugin['basic'],
- '$sec_addon' => $plugin['security'],
- '$notify_addon' => $plugin['notify'],
-
- '$h_advn' => t('Advanced Account/Page Type Settings'),
- '$h_descadvn' => t('Change the behaviour of this account for special situations'),
- '$pagetype' => $pagetype,
- '$lbl_misc' => t('Miscellaneous Settings'),
- '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
- '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
- '$removeme' => t('Remove Channel'),
- '$removechannel' => t('Remove this channel.'),
- ));
-
- call_hooks('settings_form',$o);
-
- //$o .= '</form>' . "\r\n";
-
return $o;
}
}
diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php
index e8faa7fb2..470dbe4c3 100644
--- a/Zotlabs/Module/Settings/Channel_home.php
+++ b/Zotlabs/Module/Settings/Channel_home.php
@@ -13,7 +13,7 @@ class Channel_home {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
@@ -25,10 +25,10 @@ class Channel_home {
$channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : '');
set_pconfig(local_channel(),'system','channel_menu',$channel_menu);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -82,7 +82,7 @@ class Channel_home {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Channel Home Settings'),
@@ -90,7 +90,7 @@ class Channel_home {
'$extra_settings_html' => $extra_settings_html,
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php
index 4369deb27..52a95a3d1 100644
--- a/Zotlabs/Module/Settings/Connections.php
+++ b/Zotlabs/Module/Settings/Connections.php
@@ -11,14 +11,14 @@ class Connections {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Connections {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Connections Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php
index d1dd0677e..09ea61f60 100644
--- a/Zotlabs/Module/Settings/Directory.php
+++ b/Zotlabs/Module/Settings/Directory.php
@@ -11,14 +11,14 @@ class Directory {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Directory {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Directory Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php
index cade0a529..11181907b 100644
--- a/Zotlabs/Module/Settings/Display.php
+++ b/Zotlabs/Module/Settings/Display.php
@@ -24,7 +24,6 @@ class Display {
$preload_images = ((x($_POST,'preload_images')) ? intval($_POST['preload_images']) : 0);
- $channel_menu = ((x($_POST,'channel_menu')) ? intval($_POST['channel_menu']) : 0);
$user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0);
$nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0);
$title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0);
@@ -46,7 +45,6 @@ class Display {
set_pconfig(local_channel(),'system','itemspage', $itemspage);
set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile));
set_pconfig(local_channel(),'system','title_tosource',$title_tosource);
- set_pconfig(local_channel(),'system','channel_menu', $channel_menu);
set_pconfig(local_channel(),'system','start_menu', $start_menu);
$newschema = '';
@@ -197,7 +195,6 @@ class Display {
'$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')),
'$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 30 items')),
'$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no),
- '$channel_menu' => [ 'channel_menu', t('Provide channel menu in navigation bar'), get_pconfig(local_channel(),'system','channel_menu',get_config('system','channel_menu',0)), t('Default: channel menu located in app menu'),$yes_no ],
'$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no),
'$theme_config' => $theme_config,
'$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no]
diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php
index cf6dd2807..85c3e69ae 100644
--- a/Zotlabs/Module/Settings/Editor.php
+++ b/Zotlabs/Module/Settings/Editor.php
@@ -11,14 +11,14 @@ class Editor {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Editor {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Editor Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Events.php b/Zotlabs/Module/Settings/Events.php
index ab393c932..0a0e3516c 100644
--- a/Zotlabs/Module/Settings/Events.php
+++ b/Zotlabs/Module/Settings/Events.php
@@ -11,14 +11,14 @@ class Events {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Events {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Events Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php
index cbc494cf8..6fb57eafb 100644
--- a/Zotlabs/Module/Settings/Manage.php
+++ b/Zotlabs/Module/Settings/Manage.php
@@ -12,14 +12,14 @@ class Manage {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -35,14 +35,14 @@ class Manage {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Channel Manager Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php
index 9f5bdb2e5..eae963a25 100644
--- a/Zotlabs/Module/Settings/Network.php
+++ b/Zotlabs/Module/Settings/Network.php
@@ -21,10 +21,10 @@ class Network {
$network_divmore_height = 50;
set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -53,7 +53,7 @@ class Network {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Stream Settings'),
@@ -61,7 +61,7 @@ class Network {
'$extra_settings_html' => $extra_settings_html,
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Photos.php b/Zotlabs/Module/Settings/Photos.php
index 8195d660b..f68c8847b 100644
--- a/Zotlabs/Module/Settings/Photos.php
+++ b/Zotlabs/Module/Settings/Photos.php
@@ -7,18 +7,18 @@ use Zotlabs\Lib\Libsync;
class Photos {
function post() {
-
+
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -34,14 +34,14 @@ class Photos {
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Photos Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Settings/Privacy.php b/Zotlabs/Module/Settings/Privacy.php
new file mode 100644
index 000000000..847bb3b8f
--- /dev/null
+++ b/Zotlabs/Module/Settings/Privacy.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Zotlabs\Module\Settings;
+
+use App;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Access\Permissions;
+use Zotlabs\Daemon\Master;
+use Zotlabs\Lib\Group;
+use Zotlabs\Lib\Libsync;
+
+class Privacy {
+
+ function post() {
+
+ check_form_security_token_redirectOnErr('/settings/privacy', 'settings');
+ call_hooks('settings_post', $_POST);
+
+ $index_opt_out = (((x($_POST, 'index_opt_out')) && (intval($_POST['index_opt_out']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'index_opt_out', $index_opt_out);
+
+ $autoperms = (((x($_POST, 'autoperms')) && (intval($_POST['autoperms']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'autoperms', $autoperms);
+
+ $role = get_pconfig(local_channel(), 'system', 'permissions_role');
+ if ($role === 'custom') {
+
+ $global_perms = Permissions::Perms();
+
+ foreach ($global_perms as $k => $v) {
+ PermissionLimits::Set(local_channel(), $k, intval($_POST[$k]));
+ }
+
+ $group_actor = (((x($_POST, 'group_actor')) && (intval($_POST['group_actor']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'group_actor', $group_actor);
+
+ }
+
+ info(t('Privacy settings updated.') . EOL);
+ Master::Summon(['Directory', local_channel()]);
+ Libsync::build_sync_packet();
+
+ goaway(z_root() . '/settings/privacy');
+ return; // NOTREACHED
+ }
+
+ function get() {
+
+ load_pconfig(local_channel());
+
+ $channel = App::get_channel();
+ $global_perms = Permissions::Perms();
+ $permiss = [];
+
+ $perm_opts = [
+ [t('Only me'), 0],
+ [t('Only those you specifically allow'), PERMS_SPECIFIC],
+ [t('Approved connections'), PERMS_CONTACTS],
+ [t('Any connections'), PERMS_PENDING],
+ [t('Anybody on this website'), PERMS_SITE],
+ [t('Anybody in this network'), PERMS_NETWORK],
+ [t('Anybody authenticated'), PERMS_AUTHED],
+ [t('Anybody on the internet'), PERMS_PUBLIC]
+ ];
+
+ $help = [
+ 'view_stream',
+ 'view_wiki',
+ 'view_pages',
+ 'view_storage'
+ ];
+
+ $help_txt = t('Advise: set to "Anybody on the internet" and use privacy groups to restrict access');
+ $limits = PermissionLimits::Get(local_channel());
+ $anon_comments = get_config('system', 'anonymous_comments', true);
+
+ foreach ($global_perms as $k => $perm) {
+ $options = [];
+ $can_be_public = (strstr($k, 'view') || ($k === 'post_comments' && $anon_comments));
+
+ foreach ($perm_opts as $opt) {
+ if ($opt[1] == PERMS_PUBLIC && (!$can_be_public))
+ continue;
+
+ $options[$opt[1]] = $opt[0];
+ }
+
+ $permiss[] = [
+ $k,
+ $perm,
+ $limits[$k],
+ ((in_array($k, $help)) ? $help_txt : ''),
+ $options
+ ];
+ }
+
+ //logger('permiss: ' . print_r($permiss,true));
+
+ $autoperms = get_pconfig(local_channel(), 'system', 'autoperms');
+ $index_opt_out = get_pconfig(local_channel(), 'system', 'index_opt_out');
+ $group_actor = get_pconfig(local_channel(), 'system', 'group_actor');
+
+ $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role', 'custom');
+ $permission_limits = ($permissions_role === 'custom');
+
+ $stpl = get_markup_template('settings_privacy.tpl');
+
+ $o = replace_macros($stpl, [
+ '$ptitle' => t('Privacy Settings'),
+ '$submit' => t('Submit'),
+ '$form_security_token' => get_form_security_token("settings"),
+ '$permission_limits' => $permission_limits,
+ '$permiss_arr' => $permiss,
+ '$permission_limits_label' => t('Advanced configuration'),
+ '$permission_limits_warning' => [
+ t('Proceed with caution'),
+ t('Changing advanced configuration settings can impact your, and your contacts channels functionality and security.'),
+ t('Accept the risk and continue')
+ ],
+ '$autoperms' => ['autoperms', t('Automatically approve new contacts'), $autoperms, '', [t('No'), t('Yes')]],
+ '$index_opt_out' => ['index_opt_out', t('Opt-out of search engine indexing'), $index_opt_out, '', [t('No'), t('Yes')]],
+ '$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]]
+ ]);
+
+ return $o;
+ }
+}
diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php
index 67b03e04f..0ff2dfb6d 100644
--- a/Zotlabs/Module/Settings/Profiles.php
+++ b/Zotlabs/Module/Settings/Profiles.php
@@ -13,17 +13,17 @@ class Profiles {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
$profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : '');
set_pconfig(local_channel(),'system','profile_assign',$profile_assign);
-
+
Libsync::build_sync_packet();
- if($_POST['rpath'])
+ if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
goaway($_POST['rpath']);
return;
@@ -38,12 +38,12 @@ class Profiles {
$extra_settings_html = '';
if(feature_enabled(local_channel(),'multi_profiles'))
- $extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign',''));
+ $extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign',''), t('Default profile for new contacts'));
$tpl = get_markup_template("settings_module.tpl");
$o .= replace_macros($tpl, array(
- '$rpath' => $rpath,
+ '$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Profiles Settings'),
@@ -51,7 +51,7 @@ class Profiles {
'$extra_settings_html' => $extra_settings_html,
'$submit' => t('Submit')
));
-
+
return $o;
}
diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php
index ca8c19600..f068cbef8 100644
--- a/Zotlabs/Module/Setup.php
+++ b/Zotlabs/Module/Setup.php
@@ -69,17 +69,22 @@ class Setup extends \Zotlabs\Web\Controller {
$dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : '');
$dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : '');
$dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0);
+
$phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : '');
$adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : '');
$siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : '');
+ if (empty($db_charset)) {
+ $db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8');
+ }
+
// $siteurl should not have a trailing slash
$siteurl = rtrim($siteurl,'/');
require_once('include/dba/dba_driver.php');
- $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
+ $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true);
if(! \DBA::$dba->connected) {
echo 'Database Connect failed: ' . \DBA::$dba->error;
@@ -94,11 +99,16 @@ class Setup extends \Zotlabs\Web\Controller {
$dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : '');
$dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : '');
$dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0);
+
$phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : '');
$timezone = ((isset($_POST['timezone'])) ? trim($_POST['timezone']) : '');
$adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : '');
$siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : '');
+ if (empty($db_charset)) {
+ $db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8');
+ }
+
if($siteurl != z_root()) {
$test = z_fetch_url($siteurl."/setup/testrewrite");
if((! $test['success']) || ($test['body'] != 'ok')) {
@@ -112,7 +122,7 @@ class Setup extends \Zotlabs\Web\Controller {
if(! isset(\DBA::$dba->connected)) {
// connect to db
- $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
+ $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true);
}
if(! isset(\DBA::$dba->connected)) {
diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php
index e535f6ebf..ef665e727 100644
--- a/Zotlabs/Module/Sources.php
+++ b/Zotlabs/Module/Sources.php
@@ -13,7 +13,7 @@ class Sources extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Channel Sources'))
return;
-
+
$source = intval($_REQUEST['source']);
$xchan = escape_tags($_REQUEST['xchan']);
$abook = intval($_REQUEST['abook']);
@@ -22,21 +22,21 @@ class Sources extends Controller {
$frequency = $_REQUEST['frequency'];
$name = escape_tags($_REQUEST['name']);
$tags = escape_tags($_REQUEST['tags']);
-
+
$channel = \App::get_channel();
-
+
if($name == '*')
$xchan = '*';
-
+
if($abook) {
$r = q("select abook_xchan from abook where abook_id = %d and abook_channel = %d limit 1",
intval($abook),
intval(local_channel())
);
- if($r)
+ if($r)
$xchan = $r[0]['abook_xchan'];
}
-
+
if(! $xchan) {
notice ( t('Failed to create source. No channel selected.') . EOL);
return;
@@ -69,27 +69,25 @@ class Sources extends Controller {
if($r) {
info( t('Source updated.') . EOL);
}
-
+
}
}
-
-
+
+
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
-
+
if(! Apps::system_app_installed(local_channel(), 'Channel Sources')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Sources App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Automatically import channel content from other channels or feeds');
- return $o;
+ $papp = Apps::get_papp('Channel Sources');
+ return Apps::app_render($papp, 'module');
}
-
+
// list sources
if(argc() == 1) {
$r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_channel_id = %d",
@@ -111,23 +109,23 @@ class Sources extends Controller {
));
return $o;
}
-
+
if(argc() == 2 && argv(1) === 'new') {
// TODO add the words 'or RSS feed' and corresponding code to manage feeds and frequency
-
+
$o = replace_macros(get_markup_template('sources_new.tpl'), array(
'$title' => t('New Source'),
'$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
'$words' => array( 'words', t('Only import content with these words (one per line)'),'',t('Leave blank to import all public content')),
'$name' => array( 'name', t('Channel Name'), '', '', '', 'autocomplete="off"'),
'$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),'',t('Optional')),
- '$resend' => [ 'resend', t('Resend posts with this channel as author'), 0, t('Copyrights may apply'), [ t('No'), t('Yes') ]],
+ '$resend' => [ 'resend', t('Resend posts with this channel as author'), 0, t('Copyrights may apply'), [ t('No'), t('Yes') ]],
'$submit' => t('Submit')
));
return $o;
-
+
}
-
+
if(argc() == 2 && intval(argv(1))) {
// edit source
$r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_id = %d and src_channel_id = %d limit 1",
@@ -144,9 +142,9 @@ class Sources extends Controller {
notice( t('Source not found.') . EOL);
return '';
}
-
+
$r[0]['src_patt'] = htmlspecialchars($r[0]['src_patt'], ENT_QUOTES,'UTF-8');
-
+
$o = replace_macros(get_markup_template('sources_edit.tpl'), array(
'$title' => t('Edit Source'),
'$drop' => t('Delete Source'),
@@ -156,15 +154,15 @@ class Sources extends Controller {
'$xchan' => $r[0]['src_xchan'],
'$abook' => $x[0]['abook_id'],
'$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),$r[0]['src_tag'],t('Optional')),
- '$resend' => [ 'resend', t('Resend posts with this channel as author'), get_abconfig(local_channel(), $r[0]['xchan_hash'],'system','rself'), t('Copyrights may apply'), [ t('No'), t('Yes') ]],
+ '$resend' => [ 'resend', t('Resend posts with this channel as author'), get_abconfig(local_channel(), $r[0]['xchan_hash'],'system','rself'), t('Copyrights may apply'), [ t('No'), t('Yes') ]],
'$name' => array( 'name', t('Channel Name'), $r[0]['xchan_name'], ''),
'$submit' => t('Submit')
));
return $o;
-
+
}
-
+
if(argc() == 3 && intval(argv(1)) && argv(2) === 'drop') {
$r = q("select * from source where src_id = %d and src_channel_id = %d limit 1",
intval(argv(1)),
@@ -182,12 +180,12 @@ class Sources extends Controller {
info( t('Source removed') . EOL);
else
notice( t('Unable to remove source.') . EOL);
-
+
goaway(z_root() . '/sources');
-
+
}
-
+
// shouldn't get here.
-
+
}
}
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index 6f3df299f..3dab3d465 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -34,6 +34,7 @@ class Sse extends Controller {
self::$uid = local_channel();
self::$ob_hash = get_observer_hash();
self::$sse_id = false;
+ self::$vnotify = -1;
if(! self::$ob_hash) {
if(session_id()) {
@@ -45,7 +46,9 @@ class Sse extends Controller {
}
}
- self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
+ if (self::$uid) {
+ self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
+ }
$sleep_seconds = 3;
@@ -94,6 +97,14 @@ class Sse extends Controller {
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
+ // We do not have the local_channel in the addon.
+ // Reset pubs here if the app is not installed.
+ if (self::$uid && (!(self::$vnotify & VNOTIFY_PUBS) || !Apps::system_app_installed(self::$uid, 'Public Stream'))) {
+ $result['pubs']['count'] = 0;
+ $result['pubs']['notifications'] = [];
+ $result['pubs']['offset'] = -1;
+ }
+
if($result && !$lock) {
echo "event: notifications\n";
echo 'data: ' . json_encode($result);
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
index 109b043ad..3a13b0a6f 100644
--- a/Zotlabs/Module/Sse_bs.php
+++ b/Zotlabs/Module/Sse_bs.php
@@ -37,7 +37,7 @@ class Sse_bs extends Controller {
self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify', -1);
self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays'));
- self::$limit = 50;
+ self::$limit = 30;
self::$offset = 0;
self::$xchans = '';
@@ -55,10 +55,13 @@ class Sse_bs extends Controller {
self::$xchans = ids_to_querystr($x, 'xchan_hash', true);
}
- if(intval(argv(2)) > 0)
+ if(intval(argv(2)) > 0) {
self::$offset = argv(2);
- else
+ }
+ else {
$_SESSION['sse_loadtime'] = datetime_convert();
+ }
+
$network = false;
$dm = false;
@@ -100,7 +103,6 @@ class Sse_bs extends Controller {
self::bs_forums(),
self::bs_pubs($pubs),
self::bs_files(),
- self::bs_mail(),
self::bs_all_events(),
self::bs_register(),
self::bs_info_notice()
@@ -122,7 +124,7 @@ class Sse_bs extends Controller {
$str = '';
foreach($arr as $a) {
- $mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\'';
+ $mids[] = '\'' . dbesc(unpack_link_id($a)) . '\'';
}
$str = implode(',', $mids);
@@ -371,7 +373,7 @@ class Sse_bs extends Controller {
$result['pubs']['notifications'] = [];
$result['pubs']['count'] = 0;
- if(! (self::$vnotify & VNOTIFY_PUBS)) {
+ if(! (self::$vnotify & VNOTIFY_PUBS) || !Apps::system_app_installed(self::$uid, 'Public Stream')) {
$result['pubs']['offset'] = -1;
return $result;
}
@@ -558,7 +560,7 @@ class Sse_bs extends Controller {
$b64mids = [];
foreach($mids as $mid)
- $b64mids[] = 'b64.' . base64url_encode($mid);
+ $b64mids[] = gen_link_id($mid);
$forums[$x]['notify_link'] = z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id'];
$forums[$x]['name'] = $forums[$x]['xchan_name'];
@@ -634,36 +636,6 @@ class Sse_bs extends Controller {
}
- function bs_mail() {
-
- $result['mail']['notifications'] = [];
- $result['mail']['count'] = 0;
- $result['mail']['offset'] = -1;
-
- if(! self::$uid)
- return $result;
-
- if(! (self::$vnotify & VNOTIFY_MAIL))
- return $result;
-
- $r = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan
- where channel_id = %d and mail_seen = 0 and mail_deleted = 0
- and from_xchan != '%s' order by created desc",
- intval(self::$uid),
- dbesc(self::$ob_hash)
- );
-
- if($r) {
- foreach($r as $rr) {
- $result['mail']['notifications'][] = Enotify::format_mail($rr);
- }
- $result['mail']['count'] = count($r);
- }
-
- return $result;
-
- }
-
function bs_all_events() {
$result['all_events']['notifications'] = [];
diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php
index 0ed6ea8d7..22822bb87 100644
--- a/Zotlabs/Module/Suggest.php
+++ b/Zotlabs/Module/Suggest.php
@@ -36,10 +36,8 @@ class Suggest extends \Zotlabs\Web\Controller {
if(! Apps::system_app_installed(local_channel(), 'Suggest Channels')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Suggest Channels App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Suggestions for channels in the $Projectname network you might be interested in');
- return $o;
+ $papp = Apps::get_papp('Suggest Channels');
+ return Apps::app_render($papp, 'module');
}
$o = '';
diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php
index 1ba41dcc5..a41003f6b 100644
--- a/Zotlabs/Module/Tokens.php
+++ b/Zotlabs/Module/Tokens.php
@@ -5,6 +5,11 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
+use Zotlabs\Lib\AccessList;
+use Zotlabs\Lib\Permcat;
+use Zotlabs\Lib\Libsync;
+
+require_once('include/security.php');
class Tokens extends Controller {
@@ -13,15 +18,65 @@ class Tokens extends Controller {
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Guest Access'))
- return;
-
$channel = App::get_channel();
+ if(! Apps::system_app_installed($channel['channel_id'], 'Guest Access'))
+ return;
+
check_form_security_token_redirectOnErr('tokens', 'tokens');
+
+ if(isset($_POST['delete'])) {
+ $r = q("select * from atoken where atoken_id = %d and atoken_uid = %d",
+ intval($_POST['atoken_id']),
+ intval(local_channel())
+ );
+
+ if (!$r) {
+ return;
+ }
+
+ $atoken = $r[0];
+ $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $atoken['atoken_guid'];
+
+ $atoken['deleted'] = true;
+
+ $r = q("SELECT abook.*, xchan.*
+ FROM abook left join xchan on abook_xchan = xchan_hash
+ WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
+ intval($channel['channel_id']),
+ dbesc($atoken_xchan)
+ );
+
+ if (!$r) {
+ return;
+ }
+
+ $clone = $r[0];
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+ $clone['deleted'] = true;
+
+ $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
+ if ($abconfig) {
+ $clone['abconfig'] = $abconfig;
+ }
+
+ atoken_delete($atoken['atoken_id']);
+ Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => [ $atoken ] ], true);
+
+ return;
+ }
+
$token_errs = 0;
if(array_key_exists('token',$_POST)) {
$atoken_id = (($_POST['atoken_id']) ? intval($_POST['atoken_id']) : 0);
+
+ if (! $atoken_id) {
+ $atoken_guid = new_uuid();
+ }
+
$name = trim(escape_tags($_POST['name']));
$token = trim($_POST['token']);
if((! $name) || (! $token))
@@ -30,10 +85,10 @@ class Tokens extends Controller {
$expires = datetime_convert(date_default_timezone_get(),'UTC',$_POST['expires']);
else
$expires = NULL_DATE;
- $max_atokens = service_class_fetch(local_channel(),'access_tokens');
+ $max_atokens = service_class_fetch($channel['channel_id'],'access_tokens');
if($max_atokens) {
$r = q("select count(atoken_id) as total where atoken_uid = %d",
- intval(local_channel())
+ intval($channel['channel_id'])
);
if($r && intval($r[0]['total']) >= $max_tokens) {
notice( sprintf( t('This channel is limited to %d tokens'), $max_tokens) . EOL);
@@ -45,8 +100,19 @@ class Tokens extends Controller {
notice( t('Name and Password are required.') . EOL);
return;
}
+
+ $old_atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'",
+ intval($channel['channel_id']),
+ dbesc($name)
+ );
+
+ if ($old_atok) {
+ $old_atok = $old_atok[0];
+ $old_xchan = atoken_xchan($old_atok);
+ }
+
if($atoken_id) {
- $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s'
+ $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s'
where atoken_id = %d and atoken_uid = %d",
dbesc($name),
dbesc($token),
@@ -56,8 +122,9 @@ class Tokens extends Controller {
);
}
else {
- $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )
- values ( %d, %d, '%s', '%s', '%s' ) ",
+ $r = q("insert into atoken (atoken_guid, atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )
+ values ('%s', %d, %d, '%s', '%s', '%s' ) ",
+ dbesc($atoken_guid),
intval($channel['channel_account_id']),
intval($channel['channel_id']),
dbesc($name),
@@ -66,26 +133,89 @@ class Tokens extends Controller {
);
}
- $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $name;
+ $atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'",
+ intval($channel['channel_id']),
+ dbesc($name)
+ );
+
+ if ($atok) {
+ $xchan = atoken_xchan($atok[0]);
+ atoken_create_xchan($xchan);
+ $atoken_xchan = $xchan['xchan_hash'];
+ if ($old_atok && $old_xchan) {
+ $r = q("update xchan set xchan_name = '%s' where xchan_hash = '%s'",
+ dbesc($xchan['xchan_name']),
+ dbesc($old_xchan['xchan_hash'])
+ );
+ }
+ }
+
- $all_perms = \Zotlabs\Access\Permissions::Perms();
+ if (! $atoken_id) {
- if($all_perms) {
- foreach($all_perms as $perm => $desc) {
- if(array_key_exists('perms_' . $perm, $_POST)) {
- set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,intval($_POST['perms_' . $perm]));
- }
- else {
- set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,0);
+ // If this is a new token, create a new abook record
+
+ $closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness',80);
+ $profile_assign = get_pconfig($channel['channel_id'], 'system', 'profile_assign', '');
+
+ $r = abook_store_lowlevel(
+ [
+ 'abook_account' => $channel['channel_account_id'],
+ 'abook_channel' => $channel['channel_id'],
+ 'abook_closeness' => intval($closeness),
+ 'abook_xchan' => $atoken_xchan,
+ 'abook_profile' => $profile_assign,
+ 'abook_feed' => 0,
+ 'abook_created' => datetime_convert(),
+ 'abook_updated' => datetime_convert(),
+ 'abook_instance' => z_root(),
+ ]
+ );
+
+ if (! $r) {
+ logger('abook creation failed');
+ }
+
+ /** If there is a default group for this channel, add this connection to it */
+ if ($channel['channel_default_group']) {
+ $g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']);
+ if ($g) {
+ AccessList::member_add($channel['channel_id'], '', $atoken_xchan,$g['id']);
}
}
}
-
+
+ $role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : '');
+ \Zotlabs\Lib\Permcat::assign($channel, $role, [$atoken_xchan]);
+
+ $r = q("SELECT abook.*, xchan.*
+ FROM abook left join xchan on abook_xchan = xchan_hash
+ WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
+ intval($channel['chnnel_id']),
+ dbesc($atoken_xchan)
+ );
+
+ if (! $r) {
+ return;
+ }
+
+ $clone = $r[0];
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+
+ $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
+ if ($abconfig) {
+ $clone['abconfig'] = $abconfig;
+ }
+
+ Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => $atok ], true);
info( t('Token saved.') . EOL);
return;
}
-
+
function get() {
@@ -95,16 +225,17 @@ class Tokens extends Controller {
if(! Apps::system_app_installed(local_channel(), 'Guest Access')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Guest Access App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Create access tokens so that non-members can access private content');
- return $o;
+ $papp = Apps::get_papp('Guest Access');
+ return Apps::app_render($papp, 'module');
}
+ nav_set_selected('Guest Access');
+
$channel = App::get_channel();
$atoken = null;
$atoken_xchan = '';
+ $atoken_abook = [];
if(argc() > 1) {
$id = argv(1);
@@ -116,78 +247,54 @@ class Tokens extends Controller {
if($atoken) {
$atoken = $atoken[0];
- $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name'];
- }
-
- if($atoken && argc() > 2 && argv(2) === 'drop') {
- atoken_delete($id);
- $atoken = null;
- $atoken_xchan = '';
- }
- }
-
- $t = q("select * from atoken where atoken_uid = %d",
- intval(local_channel())
- );
-
- $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.');
-
- $desc2 = t('You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:');
+ $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_guid'];
- $global_perms = \Zotlabs\Access\Permissions::Perms();
- $their_perms = [];
-
- $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false);
+ $atoken_abook = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval(local_channel()),
+ dbesc($atoken_xchan)
+ );
- if($atoken_xchan) {
- $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
- intval(local_channel()),
- dbesc($atoken_xchan)
- );
- if($theirs) {
- foreach($theirs as $t) {
- $their_perms[$t['k']] = $t['v'];
- }
+ $atoken_abook = $atoken_abook[0];
}
}
- foreach($global_perms as $k => $v) {
- $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
-//fixme
- $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
+ $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in privacy groups and visitors may login using these credentials to access private content.');
- if($existing[$k])
- $thisperm = "1";
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
+ $current_permcat = (($atoken_abook) ? $atoken_abook['abook_role'] : $default_role);
- $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
+ $roles_dict = [];
+ foreach ($pcatlist as $role) {
+ $roles_dict[$role['name']] = $role['localname'];
}
+ if (!$current_permcat) {
+ notice(t('Please select a role for this guest!') . EOL);
+ $permcats[] = '';
+ }
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
+ $permcats[$pc['name']] = $pc['localname'];
+ }
+ }
$tpl = get_markup_template("tokens.tpl");
$o .= replace_macros($tpl, array(
- '$form_security_token' => get_form_security_token("tokens"),
- '$title' => t('Guest Access Tokens'),
- '$desc' => $desc,
- '$desc2' => $desc2,
- '$tokens' => $t,
+ '$form_security_token' => get_form_security_token('tokens'),
+ '$permcat' => ['permcat', t('Select a role for this guest'), $current_permcat, '', $permcats],
+ '$title' => t('Guest Access'),
+ '$desc' => $desc,
'$atoken' => $atoken,
- '$url1' => z_root() . '/channel/' . $channel['channel_address'],
- '$url2' => z_root() . '/photos/' . $channel['channel_address'],
'$name' => array('name', t('Login Name') . ' <span class="required">*</span>', (($atoken) ? $atoken['atoken_name'] : ''),''),
- '$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : autoname(8)), ''),
+ '$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : new_token()), ''),
'$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), (($atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''),
- '$them' => t('Their Settings'),
- '$me' => t('My Settings'),
- '$perms' => $perms,
- '$inherited' => t('inherited'),
- '$notself' => 1,
- '$self' => 0,
- '$permlbl' => t('Individual Permissions'),
- '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
- '$submit' => t('Submit')
+ '$submit' => t('Submit'),
+ '$delete' => t('Delete')
));
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php
index 55c316317..870c42802 100644
--- a/Zotlabs/Module/Uexport.php
+++ b/Zotlabs/Module/Uexport.php
@@ -2,89 +2,199 @@
namespace Zotlabs\Module;
use App;
+use ZipArchive;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
class Uexport extends Controller {
function init() {
- if(! local_channel())
- killme();
+ if(! local_channel()) {
+ return;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Channel Export'))
+ if(! Apps::system_app_installed(local_channel(), 'Channel Export')) {
return;
+ }
if(argc() > 1) {
- $sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : '');
$zap_compat = (($_REQUEST['zap_compat']) ? intval($_REQUEST['zap_compat']) : false);
-
$channel = App::get_channel();
+ $year = null;
+ $month = null;
if(argc() > 1 && intval(argv(1)) > 1900) {
$year = intval(argv(1));
}
-
+
if(argc() > 2 && intval(argv(2)) > 0 && intval(argv(2)) <= 12) {
$month = intval(argv(2));
}
-
- header('content-type: application/json');
- header('content-disposition: attachment; filename="' . $channel['channel_address'] . (($year) ? '-' . $year : '') . (($month) ? '-' . $month : '') . (($_REQUEST['sections']) ? '-' . $_REQUEST['sections'] : '') . '.json"' );
-
- if($year) {
- echo json_encode(identity_export_year(local_channel(),$year,$month, $zap_compat));
+
+ $sections = [];
+ $section = '';
+ if(argc() > 1 && ctype_lower(argv(1))) {
+ $section = argv(1);
+ }
+
+ switch ($section) {
+ case 'channel':
+ $sections = get_default_export_sections();
+ break;
+ case 'chatrooms':
+ $sections = ['chatrooms'];
+ break;
+ case 'events':
+ $sections = ['events'];
+ break;
+ case 'webpages':
+ $sections = ['webpages'];
+ break;
+ case 'wikis':
+ $sections = ['wikis'];
+ break;
+ case 'custom':
+ default:
+ $custom_sections = ['channel', 'connections', 'config', 'apps', 'chatrooms', 'events', 'webpages', 'wikis'];
+ $raw_sections = (($_REQUEST['sections']) ? explode(',', $_REQUEST['sections']) : '');
+ if ($raw_sections) {
+ foreach ($raw_sections as $raw_section) {
+ if(in_array($raw_section, $custom_sections)) {
+ $sections[] = $raw_section;
+ }
+ }
+ }
+ }
+
+ if ($sections) {
+
+ $export = json_encode(identity_basic_export(local_channel(), $sections, $zap_compat));
+
+ header('Content-Type: application/json');
+ header('Content-Disposition: attachment; filename="' . $channel['channel_address'] . '-' . implode('-', $sections) . '.json"');
+ header('Content-Length: ' . strlen($export));
+
+ echo $export;
+
+ killme();
+ }
+ elseif ($year && !$month) {
+ $zip_dir = 'store/[data]/' . $channel['channel_address'] . '/tmp';
+ if (!is_dir($zip_dir))
+ mkdir($zip_dir, STORAGE_DEFAULT_PERMISSIONS, true);
+
+ $zip_file = $channel['channel_address'] . '-' . $year . '.zip';
+ $zip_path = $zip_dir . '/' . $zip_file;
+ $zip_content_available = false;
+ $zip = new ZipArchive();
+
+ if ($zip->open($zip_path, ZipArchive::CREATE) === true) {
+ $month = 1;
+ while ($month <= 12) {
+ $name = $channel['channel_address'] . '-' . $year . '-' . $month . '.json';
+ $content = conv_item_export_year(local_channel(), $year, $month, $zap_compat);
+ if(isset($content['item'])) {
+ $zip_content_available = true;
+ $zip->addFromString($name, json_encode($content));
+ }
+ $month++;
+ }
+ $zip->setCompressionName($zip_path, ZipArchive::CM_STORE);
+ $zip->close();
+ }
+ if (!$zip_content_available) {
+ unlink($zip_path);
+ notice(t('No content available for year') . ' ' . $year . EOL);
+ goaway('/uexport');
+ }
+
+ header('Content-Type: application/zip');
+ header('Content-Disposition: attachment; filename="' . $zip_file . '"');
+ header('Content-Length: ' . filesize($zip_path));
+
+ $istream = fopen($zip_path, 'rb');
+ $ostream = fopen('php://output', 'wb');
+ if ($istream && $ostream) {
+ pipe_streams($istream, $ostream);
+ fclose($istream);
+ fclose($ostream);
+ }
+
+ unlink($zip_path);
killme();
}
-
- if(argc() > 1 && argv(1) === 'basic') {
- echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat));
+ elseif ($year && $month) {
+ $export = json_encode(conv_item_export_year(local_channel(), $year, $month, $zap_compat));
+
+ header('Content-Type: application/json');
+ header('Content-Disposition: attachment; filename="' . $channel['channel_address'] . '-' . $year . '-' . $month . '.json"');
+ header('Content-Length: ' . strlen($export));
+
+ echo $export;
+
killme();
}
-
- // Warning: this option may consume a lot of memory
-
- if(argc() > 1 && argv(1) === 'complete') {
- $sections = get_default_export_sections();
- $sections[] = 'items';
- echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat));
+ else {
killme();
}
}
}
-
+
function get() {
+ if(! local_channel()) {
+ return;
+ }
+
if(! Apps::system_app_installed(local_channel(), 'Channel Export')) {
//Do not display any associated widgets at this point
App::$pdl = '';
+ $papp = Apps::get_papp('Channel Export');
+ return Apps::app_render($papp, 'module');
+ }
+
+ $account = App::get_account();
+ $year_start = datetime_convert('UTC', date_default_timezone_get(), $account['account_created'], 'Y');
+ $year_end = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y');
+ $years = [];
- $o = '<b>' . t('Channel Export App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Export your channel');
- return $o;
+ while ($year_start <= $year_end) {
+ $years[] = $year_start;
+ $year_start++;
}
-
- $y = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
-
- $yearurl = z_root() . '/uexport/' . $y;
- $janurl = z_root() . '/uexport/' . $y . '/1';
- $impurl = '/import_items';
+
+ $item_import_url = '/import_items';
+ $channel_import_url = '/import';
+
$o = replace_macros(get_markup_template('uexport.tpl'), array(
'$title' => t('Export Channel'),
- '$basictitle' => t('Export Channel'),
- '$basic' => t('Export your basic channel information to a file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new server hub, but does not contain your content.'),
- '$fulltitle' => t('Export Content'),
- '$full' => t('Export your channel information and recent content to a JSON backup that can be restored or imported to another server hub. This backs up all of your connections, permissions, profile data and several months of posts. This file may be VERY large. Please be patient - it may take several minutes for this download to begin.'),
-
- '$by_year' => t('Export your posts from a given year.'),
-
- '$extra' => t('You may also export your posts and conversations for a particular year or month. Adjust the date in your browser location bar to select other dates. If the export fails (possibly due to memory exhaustion on your server hub), please try again selecting a more limited date range.'),
- '$extra2' => sprintf( t('To select all posts for a given year, such as this year, visit <a href="%1$s">%2$s</a>'),$yearurl,$yearurl),
- '$extra3' => sprintf( t('To select all posts for a given month, such as January of this year, visit <a href="%1$s">%2$s</a>'),$janurl,$janurl),
- '$extra4' => sprintf( t('These content files may be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel. For best results please import or restore these in date order (oldest first).'),$impurl,$impurl)
-
+
+ '$channel_title' => t('Export channel'),
+ '$channel_info' => t('This will export your identity and social graph into a file which can be used to import your channel to a new hub.'),
+
+ '$years' => $years,
+ '$content_title' => t('Export content'),
+ '$content_info' => t('This will export your posts, direct messages, articles and cards per month stored into a zip file per year. Months with no posts will be dismissed.'),
+
+ '$wikis_title' => t('Export wikis'),
+ '$wikis_info' => t('This will export your wikis and wiki pages.'),
+
+ '$webpages_title' => t('Export webpages'),
+ '$webpages_info' => t('This will export your webpages and menus.'),
+
+ '$events_title' => t('Export channel calendar'),
+ '$events_info' => t('This will export your channel calendar events and associated items. CalDAV calendars are not included.'),
+
+ '$chatrooms_title' => t('Export chatrooms'),
+ '$chatrooms_info' => t('This will export your chatrooms. Chat history is dismissed.'),
+
+ '$items_extra_info' => sprintf( t('This export can be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel.'), $item_import_url, $item_import_url),
));
- return $o;
+ return $o;
}
-
+
+
+
+
}
diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php
index a0c293ddf..d54f61c36 100644
--- a/Zotlabs/Module/Viewconnections.php
+++ b/Zotlabs/Module/Viewconnections.php
@@ -6,7 +6,7 @@ require_once('include/selectors.php');
class Viewconnections extends \Zotlabs\Web\Controller {
function init() {
-
+
if(observer_prohibited()) {
return;
}
@@ -16,58 +16,58 @@ class Viewconnections extends \Zotlabs\Web\Controller {
}
}
-
+
function get() {
-
+
if(observer_prohibited()) {
notice( t('Public access denied.') . EOL);
return;
}
-
+
if(((! count(\App::$profile)) || (\App::$profile['hide_friends']))) {
notice( t('Permission denied.') . EOL);
return;
- }
-
+ }
+
if(! perm_is_allowed(\App::$profile['uid'], get_observer_hash(),'view_contacts')) {
notice( t('Permission denied.') . EOL);
return;
- }
-
+ }
+
if(! $_REQUEST['aj'])
$_SESSION['return_url'] = \App::$query_string;
-
-
+
+
$is_owner = ((local_channel() && local_channel() == \App::$profile['uid']) ? true : false);
-
- $abook_flags = " and abook_pending = 0 and abook_self = 0 ";
+
+ $abook_flags = " and abook_pending = 0 and abook_self = 0 and abook_blocked = 0 and abook_ignored = 0 ";
$sql_extra = '';
-
+
if(! $is_owner) {
$abook_flags .= " and abook_hidden = 0 ";
$sql_extra = " and xchan_hidden = 0 ";
}
-
+
$r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra ",
intval(\App::$profile['uid'])
);
if($r) {
\App::set_pager_total($r[0]['total']);
}
-
+
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra order by xchan_name LIMIT %d OFFSET %d ",
intval(\App::$profile['uid']),
intval(\App::$pager['itemspage']),
intval(\App::$pager['start'])
);
-
+
if((! $r) && (! $_REQUEST['aj'])) {
info( t('No connections.') . EOL );
return $o;
}
-
+
$contacts = array();
-
+
foreach($r as $rr) {
$oneway = false;
@@ -103,7 +103,7 @@ class Viewconnections extends \Zotlabs\Web\Controller {
'id' => $rr['abook_id'],
'archived' => (intval($rr['abook_archived']) ? true : false),
'img_hover' => sprintf( t('Visit %s\'s profile [%s]'), $rr['xchan_name'], $rr['xchan_url']),
- 'thumb' => $rr['xchan_photo_m'],
+ 'thumb' => $rr['xchan_photo_m'],
'name' => substr($rr['xchan_name'],0,20),
'username' => $rr['xchan_addr'],
'link' => $url,
@@ -137,11 +137,11 @@ class Viewconnections extends \Zotlabs\Web\Controller {
// '$paginate' => paginate($a),
));
}
-
+
if(! $contacts)
$o .= '<div id="content-complete"></div>';
-
+
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php
index d67a6f176..4f909d33d 100644
--- a/Zotlabs/Module/Vote.php
+++ b/Zotlabs/Module/Vote.php
@@ -24,7 +24,7 @@ class Vote extends Controller {
$fetch = null;
$id = argv(1);
$response = $_REQUEST['answer'];
-
+
if ($id) {
$fetch = q("select * from item where id = %d limit 1",
intval($id)
@@ -42,7 +42,7 @@ class Vote extends Controller {
}
$valid = false;
-
+
if ($obj['oneOf']) {
foreach($obj['oneOf'] as $selection) {
// logger('selection: ' . $selection);
@@ -80,7 +80,6 @@ class Vote extends Controller {
$item = [];
-
$item['aid'] = $channel['channel_account_id'];
$item['uid'] = $channel['channel_id'];
$item['item_origin'] = 1;
@@ -95,11 +94,8 @@ class Vote extends Controller {
$item['owner_xchan'] = $fetch[0]['author_xchan'];
$item['allow_cid'] = '<' . $fetch[0]['author_xchan'] . '>';
$item['item_private'] = 1;
-
-
$item['obj_type'] = 'Note';
$item['author'] = channelx_by_n($channel['channel_id']);
-
$item['obj'] = Activity::encode_item($item);
// now reset the placeholders
@@ -108,17 +104,15 @@ class Vote extends Controller {
$item['obj_type'] = 'Answer';
unset($item['author']);
-
$x = item_store($item);
-
retain_item($fetch[0]['id']);
if($x['success']) {
$itemid = $x['item_id'];
Master::Summon( [ 'Notifier', 'like', $itemid ] );
}
-
+
$r = q("select * from item where id = %d",
intval($itemid)
);
@@ -128,6 +122,7 @@ class Vote extends Controller {
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
}
}
+
$ret['success'] = true;
$ret['message'] = t('Response submitted. Updates may not appear instantly.');
json_return_and_die($ret);
diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php
index 787ed5850..bc47484be 100644
--- a/Zotlabs/Module/Webpages.php
+++ b/Zotlabs/Module/Webpages.php
@@ -15,26 +15,26 @@ require_once('include/acl_selectors.php');
class Webpages extends Controller {
function init() {
-
+
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
App::$is_sys = true;
}
}
-
+
if(argc() > 1)
$which = argv(1);
else
return;
-
+
profile_load($which);
-
+
}
-
-
+
+
function get() {
-
+
if(! App::$profile) {
notice( t('Requested profile is not available.') . EOL );
App::$error = 404;
@@ -44,22 +44,20 @@ class Webpages extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Webpages')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Webpages App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Provide managed web pages on your channel');
- return $o;
+ $papp = Apps::get_papp('Webpages');
+ return Apps::app_render($papp, 'module');
}
nav_set_selected('Webpages');
$which = argv(1);
-
+
$_SESSION['return_url'] = App::$query_string;
-
+
$uid = local_channel();
$owner = 0;
$observer = App::get_observer();
-
+
$channel = App::get_channel();
switch ($_SESSION['action']) {
@@ -74,7 +72,7 @@ class Webpages extends Controller {
'$blocks' => $_SESSION['blocks'],
));
return $o;
-
+
case 'importselected':
$_SESSION['action'] = null;
break;
@@ -85,7 +83,7 @@ class Webpages extends Controller {
break;
}
require_once('include/import.php');
-
+
$pages = get_webpage_elements($channel, 'pages');
$layouts = get_webpage_elements($channel, 'layouts');
$blocks = get_webpage_elements($channel, 'blocks');
@@ -99,13 +97,13 @@ class Webpages extends Controller {
));
$_SESSION['export'] = null;
return $o;
-
+
default :
$_SESSION['action'] = null;
break;
}
-
-
+
+
if(App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
@@ -114,7 +112,7 @@ class Webpages extends Controller {
$observer = $sys;
}
}
-
+
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
@@ -124,24 +122,24 @@ class Webpages extends Controller {
$owner = intval($r[0]['channel_id']);
}
}
-
+
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
-
+
$perms = get_all_perms($owner,$ob_hash);
-
+
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
-
+
$mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
-
+
$layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout'));
-
+
// Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages
- // Nickname is set to the observers xchan, and profile_uid to the owner's.
+ // Nickname is set to the observers xchan, and profile_uid to the owner's.
// This lets you post pages at other people's channels.
-
+
if((! $channel) && ($uid) && ($uid == App::$profile_uid)) {
$channel = App::get_channel();
}
@@ -156,12 +154,12 @@ class Webpages extends Controller {
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
-
+
$is_owner = ($uid && $uid == $owner);
$o = '';
-
+
$x = array(
'webpage' => ITEM_TYPE_WEBPAGE,
'is_owner' => true,
@@ -183,23 +181,23 @@ class Webpages extends Controller {
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
-
+
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
-
-
- // Get a list of webpages. We can't display all them because endless scroll makes that unusable,
+
+
+ // Get a list of webpages. We can't display all them because endless scroll makes that unusable,
// so just list titles and an edit link.
-
-
+
+
$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
+
+ $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)
@@ -211,14 +209,13 @@ class Webpages extends Controller {
$editor = status_editor($a,$x,false,'Webpages');
$pages = null;
-
+
if($r) {
$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'],
@@ -243,11 +240,11 @@ class Webpages extends Controller {
);
}
}
-
-
+
+
//Build the base URL for edit links
$url = z_root() . '/editwebpage/' . $which;
-
+
$o .= replace_macros(get_markup_template('webpagelist.tpl'), array(
'$listtitle' => t('Webpages'),
'$baseurl' => $url,
@@ -266,19 +263,19 @@ class Webpages extends Controller {
'$created_txt' => t('Created'),
'$edited_txt' => t('Edited')
));
-
+
return $o;
}
-
+
function post() {
$action = $_REQUEST['action'];
if( $action ){
switch ($action) {
case 'scan':
-
+
// the state of this variable tracks whether website files have been scanned (null, true, false)
- $cloud = null;
-
+ $cloud = null;
+
// Website files are to be imported from an uploaded zip file
if(($_FILES) && array_key_exists('zip_file',$_FILES) && isset($_POST['w_upload'])) {
$source = $_FILES["zip_file"]["tmp_name"];
@@ -306,8 +303,8 @@ class Webpages extends Controller {
} else {
notice( t('Error opening zip file') . EOL);
return null;
- }
- }
+ }
+ }
// Website files are to be imported from the channel cloud files
if (($_POST) && array_key_exists('path',$_POST) && isset($_POST['cloudsubmit'])) {
@@ -321,7 +318,7 @@ class Webpages extends Controller {
$cloud = true;
}
-
+
// If the website files were uploaded or specified in the cloud files, then $cloud
// should be either true or false
if ($cloud !== null) {
@@ -345,24 +342,24 @@ class Webpages extends Controller {
notice( t('No webpage elements detected.') . EOL);
$_SESSION['action'] = null;
}
-
+
}
-
+
// If the website elements were imported from a zip file, delete the temporary decompressed files
if ($cloud === false && $website && $elements) {
$_SESSION['tempimportpath'] = $website;
//rrmdir($website); // Delete the temporary decompressed files
}
-
+
break;
-
+
case 'importselected':
require_once('include/import.php');
$channel = App::get_channel();
-
+
// Import layout first so that pages that reference new layouts will find
- // the mid of layout items in the database
-
+ // the mid of layout items in the database
+
// Obtain the user-selected layouts to import and import them
$checkedlayouts = $_POST['layout'];
$layouts = [];
@@ -380,7 +377,7 @@ class Webpages extends Controller {
}
}
$_SESSION['import_layouts'] = $layouts;
-
+
// Obtain the user-selected blocks to import and import them
$checkedblocks = $_POST['block'];
$blocks = [];
@@ -398,7 +395,7 @@ class Webpages extends Controller {
}
}
$_SESSION['import_blocks'] = $blocks;
-
+
// Obtain the user-selected pages to import and import them
$checkedpages = $_POST['page'];
$pages = [];
@@ -424,9 +421,9 @@ class Webpages extends Controller {
unset($_SESSION['tempimportpath']);
}
break;
-
+
case 'exportzipfile':
-
+
if(isset($_POST['w_download'])) {
$_SESSION['action'] = 'export_select_list';
$_SESSION['export'] = 'zipfile';
@@ -436,45 +433,45 @@ class Webpages extends Controller {
$filename = 'website.zip';
}
$_SESSION['zipfilename'] = $filename;
-
+
}
-
+
break;
-
+
case 'exportcloud':
if(isset($_POST['exportcloudpath']) && $_POST['exportcloudpath'] !== '') {
$_SESSION['action'] = 'export_select_list';
$_SESSION['export'] = 'cloud';
$_SESSION['exportcloudpath'] = filter_var($_POST['exportcloudpath'], FILTER_SANITIZE_ENCODED);
}
-
+
break;
-
+
case 'cloud':
case 'zipfile':
-
+
$channel = App::get_channel();
-
+
$tmp_folder_name = random_string(10);
$zip_folder_name = random_string(10);
$zip_filename = $_SESSION['zipfilename'];
$tmp_folderpath = '/tmp/' . $tmp_folder_name;
$zip_folderpath = '/tmp/' . $zip_folder_name;
- if (!mkdir($zip_folderpath, 0770, false)) {
+ if (!mkdir($zip_folderpath, 0770, false)) {
logger('Error creating zip file export folder: ' . $zip_folderpath, LOGGER_NORMAL);
json_return_and_die(array('message' => 'Error creating zip file export folder'));
}
$zip_filepath = '/tmp/' . $zip_folder_name . '/' . $zip_filename;
-
+
$checkedblocks = $_POST['block'];
$blocks = [];
if (!empty($checkedblocks)) {
foreach ($checkedblocks as $mid) {
- $b = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
- left join item on item.id = iconfig.iid
+ $b = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
+ left join item on item.id = iconfig.iid
where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK' order by iconfig.v asc limit 1",
dbesc($mid),
- intval($channel['channel_id'])
+ intval($channel['channel_id'])
);
if($b) {
$b = $b[0];
@@ -514,25 +511,25 @@ class Webpages extends Controller {
$block_filepath = $tmp_blockfolder . '/' . $block_filename;
$blockinfo['json']['contentfile'] = $block_filename;
$block_jsonpath = $tmp_blockfolder . '/block.json';
- if (!is_dir($tmp_blockfolder) && !mkdir($tmp_blockfolder, 0770, true)) {
+ if (!is_dir($tmp_blockfolder) && !mkdir($tmp_blockfolder, 0770, true)) {
logger('Error creating temp export folder: ' . $tmp_blockfolder, LOGGER_NORMAL);
json_return_and_die(array('message' => 'Error creating temp export folder'));
}
file_put_contents($block_filepath, $blockinfo['body']);
- file_put_contents($block_jsonpath, json_encode($blockinfo['json'], JSON_UNESCAPED_SLASHES));
+ file_put_contents($block_jsonpath, json_encode($blockinfo['json'], JSON_UNESCAPED_SLASHES));
}
}
}
-
+
$checkedlayouts = $_POST['layout'];
$layouts = [];
if (!empty($checkedlayouts)) {
foreach ($checkedlayouts as $mid) {
- $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
- left join item on item.id = iconfig.iid
+ $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
+ left join item on item.id = iconfig.iid
where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1",
dbesc($mid),
- intval($channel['channel_id'])
+ intval($channel['channel_id'])
);
if($l) {
$l = $l[0];
@@ -558,38 +555,38 @@ class Webpages extends Controller {
$layout_filepath = $tmp_layoutfolder . '/' . $layout_filename;
$layoutinfo['json']['contentfile'] = $layout_filename;
$layout_jsonpath = $tmp_layoutfolder . '/layout.json';
- if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
+ if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL);
json_return_and_die(array('message' => 'Error creating temp export folder'));
}
file_put_contents($layout_filepath, $layoutinfo['body']);
- file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
+ file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
}
}
}
-
+
$checkedpages = $_POST['page'];
$pages = [];
if (!empty($checkedpages)) {
foreach ($checkedpages as $mid) {
-
- $p = q("select * from iconfig left join item on iconfig.iid = item.id
+
+ $p = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and item.mid = '%s' and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d",
intval($channel['channel_id']),
dbesc($mid),
intval(ITEM_TYPE_WEBPAGE)
);
-
+
if($p) {
foreach ($p as $pp) {
// Get the associated layout
$layoutinfo = array();
if($pp['layout_mid']) {
- $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
- left join item on item.id = iconfig.iid
+ $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig
+ left join item on item.id = iconfig.iid
where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1",
dbesc($pp['layout_mid']),
- intval($channel['channel_id'])
+ intval($channel['channel_id'])
);
if($l) {
$l = $l[0];
@@ -614,12 +611,12 @@ class Webpages extends Controller {
$layout_filepath = $tmp_layoutfolder . '/' . $layout_filename;
$layoutinfo['json']['contentfile'] = $layout_filename;
$layout_jsonpath = $tmp_layoutfolder . '/layout.json';
- if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
+ if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL);
json_return_and_die(array('message' => 'Error creating temp export folder'));
}
file_put_contents($layout_filepath, $layoutinfo['body']);
- file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
+ file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
}
}
switch ($pp['mimetype']) {
@@ -660,14 +657,14 @@ class Webpages extends Controller {
$page_filepath = $tmp_pagefolder . '/' . $page_filename;
$page_jsonpath = $tmp_pagefolder . '/page.json';
$pageinfo['json']['contentfile'] = $page_filename;
- if (!is_dir($tmp_pagefolder) && !mkdir($tmp_pagefolder, 0770, true)) {
+ if (!is_dir($tmp_pagefolder) && !mkdir($tmp_pagefolder, 0770, true)) {
logger('Error creating temp export folder: ' . $tmp_pagefolder, LOGGER_NORMAL);
json_return_and_die(array('message' => 'Error creating temp export folder'));
}
file_put_contents($page_filepath, $pageinfo['body']);
file_put_contents($page_jsonpath, json_encode($pageinfo['json'], JSON_UNESCAPED_SLASHES));
}
- }
+ }
}
}
if($action === 'zipfile') {
@@ -686,23 +683,23 @@ class Webpages extends Controller {
if(!$dirpath) {
$x = attach_mkdirp($channel, $channel['channel_hash'], array('pathname' => $cloudpath));
$folder_hash = (($x['success']) ? $x['data']['hash'] : '');
-
+
if (!$x['success']) {
logger('Failed to create cloud file folder', LOGGER_NORMAL);
}
$dirpath = get_dirpath_by_cloudpath($channel, $cloudpath);
if (!is_dir($dirpath)) {
logger('Failed to create cloud file folder', LOGGER_NORMAL);
- }
+ }
}
-
+
$success = copy_folder_to_cloudfiles($channel, $channel['channel_hash'], $tmp_folderpath, $cloudpath);
}
}
if(!$success) {
logger('Error exporting webpage elements', LOGGER_NORMAL);
}
-
+
rrmdir($zip_folderpath); rrmdir($tmp_folderpath); // delete temporary files
killme();
@@ -710,9 +707,9 @@ class Webpages extends Controller {
default :
break;
}
-
+
}
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php
index 0d7b222b8..af59b76e0 100644
--- a/Zotlabs/Module/Well_known.php
+++ b/Zotlabs/Module/Well_known.php
@@ -5,36 +5,28 @@ namespace Zotlabs\Module;
class Well_known extends \Zotlabs\Web\Controller {
function init(){
-
+
if(argc() > 1) {
-
+
$arr = array('server' => $_SERVER, 'request' => $_REQUEST);
call_hooks('well_known', $arr);
-
-
+
+
if(! check_siteallowed($_SERVER['REMOTE_ADDR'])) {
logger('well_known: site not allowed. ' . $_SERVER['REMOTE_ADDR']);
killme();
}
-
+
// from php.net re: REMOTE_HOST:
- // Note: Your web server must be configured to create this variable. For example in Apache
- // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr().
-
+ // Note: Your web server must be configured to create this variable. For example in Apache
+ // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr().
+
if(get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) {
logger('well_known: site not allowed. ' . $_SERVER['REMOTE_HOST']);
killme();
}
-
+
switch(argv(1)) {
- case 'zot-info':
- \App::$argc -= 1;
- array_shift(\App::$argv);
- \App::$argv[0] = 'zfinger';
- $module = new \Zotlabs\Module\Zfinger();
- $module->init();
- break;
-
case 'webfinger':
\App::$argc -= 1;
array_shift(\App::$argv);
@@ -42,7 +34,7 @@ class Well_known extends \Zotlabs\Web\Controller {
$module = new \Zotlabs\Module\Wfinger();
$module->init();
break;
-
+
case 'host-meta':
\App::$argc -= 1;
array_shift(\App::$argv);
@@ -63,7 +55,7 @@ class Well_known extends \Zotlabs\Web\Controller {
case 'dnt-policy.txt':
echo file_get_contents('doc/dnt-policy.txt');
killme();
-
+
case 'caldav':
case 'carddav':
if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
@@ -73,16 +65,16 @@ class Well_known extends \Zotlabs\Web\Controller {
default:
if(file_exists(\App::$cmd)) {
- echo file_get_contents(\App::$cmd);
+ echo file_get_contents(\App::$cmd);
killme();
}
elseif(file_exists(\App::$cmd . '.php'))
require_once(\App::$cmd . '.php');
break;
-
+
}
}
-
+
http_status_exit(404);
}
}
diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php
index 46da7f007..6d0e78587 100644
--- a/Zotlabs/Module/Wfinger.php
+++ b/Zotlabs/Module/Wfinger.php
@@ -1,8 +1,6 @@
<?php
namespace Zotlabs\Module;
-require_once('include/zot.php');
-
use Zotlabs\Lib\Keyutils;
use Zotlabs\Lib\Libzot;
@@ -21,7 +19,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
$scheme = 'https';
elseif(x($_SERVER,'HTTP_X_FORWARDED_PROTO') && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))
- $scheme = 'https';
+ $scheme = 'https';
$zot = intval($_REQUEST['zot']);
@@ -69,25 +67,21 @@ class Wfinger extends \Zotlabs\Web\Controller {
$channel = substr($channel,1);
$channel = substr($channel,0,-1);
$pchan = true;
- $r = q("select * from pchan left join xchan on pchan_hash = xchan_hash
+ $r = q("select * from pchan left join xchan on pchan_hash = xchan_hash
where pchan_guid = '%s' limit 1",
dbesc($channel)
);
if($r) {
- $r[0] = pchan_to_chan($r[0]);
+ $r = pchan_to_chan($r[0]);
}
}
else {
- $r = q("select * from channel left join xchan on channel_hash = xchan_hash
- where channel_address = '%s' limit 1",
- dbesc($channel)
- );
+ $r = channelx_by_nick($channel);
}
}
header('Access-Control-Allow-Origin: *');
-
if($root_resource) {
$result['subject'] = $resource;
$result['properties'] = [
@@ -109,15 +103,15 @@ class Wfinger extends \Zotlabs\Web\Controller {
if($resource && $r) {
$h = q("select hubloc_addr from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
- dbesc($r[0]['channel_hash'])
+ dbesc($r['channel_hash'])
);
$result['subject'] = $resource;
$aliases = array(
- z_root() . (($pchan) ? '/pchan/' : '/channel/') . $r[0]['channel_address'],
- z_root() . '/~' . $r[0]['channel_address'],
- z_root() . '/@' . $r[0]['channel_address']
+ z_root() . (($pchan) ? '/pchan/' : '/channel/') . $r['channel_address'],
+ z_root() . '/~' . $r['channel_address'],
+ z_root() . '/@' . $r['channel_address']
);
if($h) {
@@ -129,10 +123,10 @@ class Wfinger extends \Zotlabs\Web\Controller {
$result['aliases'] = [];
$result['properties'] = [
- 'http://webfinger.net/ns/name' => $r[0]['channel_name'],
- 'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name'],
- 'https://w3id.org/security/v1#publicKeyPem' => $r[0]['xchan_pubkey'],
- 'http://purl.org/zot/federation' => 'zot6,zot'
+ 'http://webfinger.net/ns/name' => $r['channel_name'],
+ 'http://xmlns.com/foaf/0.1/name' => $r['channel_name'],
+ 'https://w3id.org/security/v1#publicKeyPem' => $r['xchan_pubkey'],
+ 'http://purl.org/zot/federation' => 'zot6'
];
foreach($aliases as $alias)
@@ -145,18 +139,18 @@ class Wfinger extends \Zotlabs\Web\Controller {
[
'rel' => 'http://webfinger.net/rel/avatar',
- 'type' => $r[0]['xchan_photo_mimetype'],
- 'href' => $r[0]['xchan_photo_l']
+ 'type' => $r['xchan_photo_mimetype'],
+ 'href' => $r['xchan_photo_l']
],
[
'rel' => 'http://webfinger.net/rel/profile-page',
- 'href' => $r[0]['xchan_url'],
+ 'href' => $r['xchan_url'],
],
[
'rel' => 'magic-public-key',
- 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r[0]['channel_pubkey']),
+ 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r['channel_pubkey']),
]
];
@@ -169,14 +163,14 @@ class Wfinger extends \Zotlabs\Web\Controller {
[
'rel' => 'http://webfinger.net/rel/avatar',
- 'type' => $r[0]['xchan_photo_mimetype'],
- 'href' => $r[0]['xchan_photo_l']
+ 'type' => $r['xchan_photo_mimetype'],
+ 'href' => $r['xchan_photo_l']
],
[
'rel' => 'http://microformats.org/profile/hcard',
'type' => 'text/html',
- 'href' => z_root() . '/hcard/' . $r[0]['channel_address']
+ 'href' => z_root() . '/hcard/' . $r['channel_address']
],
[
@@ -186,18 +180,12 @@ class Wfinger extends \Zotlabs\Web\Controller {
[
'rel' => 'http://webfinger.net/rel/profile-page',
- 'href' => z_root() . '/profile/' . $r[0]['channel_address'],
- ],
-
- [
- 'rel' => 'http://schemas.google.com/g/2010#updates-from',
- 'type' => 'application/atom+xml',
- 'href' => z_root() . '/ofeed/' . $r[0]['channel_address']
+ 'href' => z_root() . '/profile/' . $r['channel_address'],
],
[
'rel' => 'http://webfinger.net/rel/blog',
- 'href' => z_root() . '/channel/' . $r[0]['channel_address'],
+ 'href' => z_root() . '/channel/' . $r['channel_address'],
],
[
@@ -208,12 +196,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
[
'rel' => 'http://purl.org/zot/protocol/6.0',
'type' => 'application/x-zot+json',
- 'href' => channel_url($r[0])
- ],
-
- [
- 'rel' => 'http://purl.org/zot/protocol',
- 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'],
+ 'href' => channel_url($r)
],
[
@@ -224,14 +207,14 @@ class Wfinger extends \Zotlabs\Web\Controller {
[
'rel' => 'magic-public-key',
- 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r[0]['channel_pubkey']),
+ 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r['channel_pubkey']),
]
];
}
if($zot) {
// get a zotinfo packet and return it with webfinger
- $result['zot'] = Libzot::zotinfo( [ 'address' => $r[0]['xchan_addr'] ]);
+ $result['zot'] = Libzot::zotinfo( [ 'address' => $r['xchan_addr'] ]);
}
}
@@ -240,7 +223,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
killme();
}
- $arr = [ 'channel' => $r[0], 'pchan' => $pchan, 'request' => $_REQUEST, 'result' => $result ];
+ $arr = [ 'channel' => $r, 'pchan' => $pchan, 'request' => $_REQUEST, 'result' => $result ];
call_hooks('webfinger',$arr);
json_return_and_die($arr['result'],'application/jrd+json');
diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php
index 04c1dbeaa..3d0c07492 100644
--- a/Zotlabs/Module/Wiki.php
+++ b/Zotlabs/Module/Wiki.php
@@ -48,10 +48,8 @@ class Wiki extends Controller {
if(! Apps::system_app_installed(App::$profile_uid, 'Wiki')) {
//Do not display any associated widgets at this point
App::$pdl = '';
-
- $o = '<b>' . t('Wiki App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('Provide a wiki for your channel');
- return $o;
+ $papp = Apps::get_papp('Wiki');
+ return Apps::app_render($papp, 'module');
}
@@ -68,7 +66,7 @@ class Wiki extends Controller {
$pageHistory = array();
$local_observer = null;
$resource_id = '';
-
+
// init() should have forced the URL to redirect to /wiki/channel so assume argc() > 1
$nick = argv(1);
@@ -98,9 +96,9 @@ class Wiki extends Controller {
// Initialize the ACL to the channel default permissions
$x = array(
- 'lockstate' => (( $owner['channel_allow_cid'] ||
- $owner['channel_allow_gid'] ||
- $owner['channel_deny_cid'] ||
+ 'lockstate' => (( $owner['channel_allow_cid'] ||
+ $owner['channel_allow_gid'] ||
+ $owner['channel_deny_cid'] ||
$owner['channel_deny_gid'])
? 'lock' : 'unlock'
),
@@ -113,7 +111,7 @@ class Wiki extends Controller {
);
}
else {
- // Not the channel owner
+ // Not the channel owner
$owner_acl = $x = array();
}
@@ -272,10 +270,10 @@ class Wiki extends Controller {
if(! $w['resource_id']) {
notice(t('Wiki not found') . EOL);
goaway(z_root() . '/' . argv(0) . '/' . argv(1));
- }
+ }
$resource_id = $w['resource_id'];
-
+
if(! $wiki_owner) {
// Check for observer permissions
$observer_hash = get_observer_hash();
@@ -316,7 +314,7 @@ class Wiki extends Controller {
'channel_address' => $owner['channel_address'],
'refresh' => true
]);
- //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
+ //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
notice( t('Error retrieving page content') . EOL);
//goaway(z_root() . '/' . argv(0) . '/' . argv(1) );
$renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName));
@@ -334,7 +332,7 @@ class Wiki extends Controller {
$hookinfo = ['content' => $content, 'mimetype' => $mimeType];
call_hooks('wiki_preprocess',$hookinfo);
$content = $hookinfo['content'];
-
+
// Render the Markdown-formatted page content in HTML
if($mimeType == 'text/bbcode') {
$renderedContent = zidify_links(smilies(bbcode($content)));
@@ -356,7 +354,7 @@ class Wiki extends Controller {
// default: // Strip the extraneous URL components
// goaway('/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . $pageUrlName);
}
-
+
$wikiModalID = random_string(3);
@@ -458,18 +456,18 @@ class Wiki extends Controller {
}
json_return_and_die(array('html' => $html, 'success' => true));
}
-
+
// Create a new wiki
// /wiki/channel/create/wiki
if ((argc() > 3) && (argv(2) === 'create') && (argv(3) === 'wiki')) {
- // Only the channel owner can create a wiki, at least until we create a
+ // Only the channel owner can create a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
goaway('/' . argv(0) . '/' . $nick . '/');
- }
- $wiki = array();
+ }
+ $wiki = array();
// backslashes won't work well in the javascript functions
$name = str_replace('\\','',$_POST['wikiName']);
@@ -478,12 +476,12 @@ class Wiki extends Controller {
$wiki['postVisible'] = ((intval($_POST['postVisible'])) ? 1 : 0);
$wiki['rawName'] = $name;
$wiki['htmlName'] = escape_tags($name);
- //$wiki['urlName'] = urlencode(urlencode($name));
+ //$wiki['urlName'] = urlencode(urlencode($name));
$wiki['urlName'] = NativeWiki::name_encode($name);
$wiki['mimeType'] = $_POST['mimeType'];
$wiki['typelock'] = $_POST['typelock'];
- if($wiki['urlName'] === '') {
+ if($wiki['urlName'] === '') {
notice( t('Error creating wiki. Invalid name.') . EOL);
goaway('/wiki');
return; //not reached
@@ -502,7 +500,7 @@ class Wiki extends Controller {
$r = NativeWiki::create_wiki($owner, $observer_hash, $wiki, $acl);
if($r['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']);
- $homePage = NativeWikiPage::create_page($owner['channel_id'],$observer_hash,'Home', $r['item']['resource_id'], $wiki['mimeType']);
+ $homePage = NativeWikiPage::create_page($owner, $observer_hash, 'Home', $r['item']['resource_id'], $wiki['mimeType']);
if(! $homePage['success']) {
notice( t('Wiki created, but error creating Home page.'));
goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']));
@@ -519,7 +517,7 @@ class Wiki extends Controller {
// Update a wiki
// /wiki/channel/update/wiki
if ((argc() > 3) && (argv(2) === 'update') && (argv(3) === 'wiki')) {
- // Only the channel owner can update a wiki, at least until we create a
+ // Only the channel owner can update a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
@@ -544,7 +542,7 @@ class Wiki extends Controller {
if($wiki['resource_id']) {
$arr['resource_id'] = $wiki['resource_id'];
-
+
$acl = new \Zotlabs\Access\AccessList($owner);
$acl->set_from_array($_POST);
@@ -565,18 +563,18 @@ class Wiki extends Controller {
// Delete a wiki
if ((argc() > 3) && (argv(2) === 'delete') && (argv(3) === 'wiki')) {
- // Only the channel owner can delete a wiki, at least until we create a
+ // Only the channel owner can delete a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
logger('Wiki delete permission denied.');
json_return_and_die(array('message' => t('Wiki delete permission denied.'), 'success' => false));
- }
- $resource_id = $_POST['resource_id'];
+ }
+ $resource_id = $_POST['resource_id'];
$deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id);
if ($deleted['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id);
json_return_and_die(array('message' => '', 'success' => true));
- }
+ }
else {
logger('Error deleting wiki: ' . $resource_id . ' ' . $deleted['message']);
json_return_and_die(array('message' => t('Error deleting wiki'), 'success' => false));
@@ -589,14 +587,14 @@ class Wiki extends Controller {
$mimetype = $_POST['mimetype'];
- $resource_id = $_POST['resource_id'];
+ $resource_id = $_POST['resource_id'];
// Determine if observer has permission to create a page
-
- $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash, $mimetype);
+
+ $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$name = isset($_POST['pageName']) ? $_POST['pageName'] : $_POST['missingPageName']; //Get new page name
@@ -608,12 +606,12 @@ class Wiki extends Controller {
json_return_and_die(array('message' => 'Error creating page. Invalid name (' . print_r($_POST,true) . ').', 'success' => false));
}
- $page = NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype);
+ $page = NativeWikiPage::create_page($owner, $observer_hash, $name, $resource_id, $mimetype);
if($page['item_id']) {
$commit = NativeWikiPage::commit([
- 'commit_msg' => t('New page created'),
- 'resource_id' => $resource_id,
+ 'commit_msg' => t('New page created'),
+ 'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'pageUrlName' => $name
@@ -622,10 +620,10 @@ class Wiki extends Controller {
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
//json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true));
json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true));
- }
+ }
else {
json_return_and_die(array('message' => 'Error making git commit','url' => '/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($page['wiki']['urlName']) . '/' . NativeWiki::name_encode($page['page']['urlName']),'success' => false));
- }
+ }
}
@@ -633,8 +631,8 @@ class Wiki extends Controller {
logger('Error creating page');
json_return_and_die(array('message' => 'Error creating page.', 'success' => false));
}
- }
-
+ }
+
// Fetch page list for a wiki
if((argc() === 5) && (argv(2) === 'get') && (argv(3) === 'page') && (argv(4) === 'list')) {
$resource_id = $_POST['resource_id']; // resource_id for wiki in db
@@ -642,7 +640,7 @@ class Wiki extends Controller {
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(!$perms['read']) {
logger('Wiki read permission denied.' . EOL);
- json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false));
+ json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false));
}
// @FIXME - we shouldn't invoke this if it isn't in the PDL or has been over-ridden
@@ -655,17 +653,17 @@ class Wiki extends Controller {
'channel_address' => $owner['channel_address'],
'refresh' => true
]);
- json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
+ json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
}
-
+
// Save a page
if ((argc() === 4) && (argv(2) === 'save') && (argv(3) === 'page')) {
-
- $resource_id = $_POST['resource_id'];
+
+ $resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$pageHtmlName = escape_tags($_POST['name']);
$content = $_POST['content']; //Get new content
- $commitMsg = $_POST['commitMsg'];
+ $commitMsg = $_POST['commitMsg'];
if ($commitMsg === '') {
$commitMsg = 'Updated ' . $pageHtmlName;
}
@@ -674,7 +672,7 @@ class Wiki extends Controller {
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$saved = NativeWikiPage::save_page([
@@ -687,9 +685,9 @@ class Wiki extends Controller {
if($saved['success']) {
$commit = NativeWikiPage::commit([
- 'commit_msg' => $commitMsg,
+ 'commit_msg' => $commitMsg,
'pageUrlName' => $pageUrlName,
- 'resource_id' => $resource_id,
+ 'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'revision' => (-1)
@@ -699,21 +697,21 @@ class Wiki extends Controller {
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content));
}
else {
- json_return_and_die(array('message' => 'Error making git commit','success' => false));
+ json_return_and_die(array('message' => 'Error making git commit','success' => false));
}
}
else {
- json_return_and_die(array('message' => 'Error saving page', 'success' => false));
+ json_return_and_die(array('message' => 'Error saving page', 'success' => false));
}
}
-
+
// Update page history
// /wiki/channel/history/page
if ((argc() === 4) && (argv(2) === 'history') && (argv(3) === 'page')) {
-
+
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
-
+
// Determine if observer has permission to read content
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
@@ -734,7 +732,7 @@ class Wiki extends Controller {
// Delete a page
if ((argc() === 4) && (argv(2) === 'delete') && (argv(3) === 'page')) {
- $resource_id = $_POST['resource_id'];
+ $resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
if ($pageUrlName === 'Home') {
@@ -745,13 +743,13 @@ class Wiki extends Controller {
// currently just allow page owner
if((! local_channel()) || (local_channel() != $owner['channel_id'])) {
logger('Wiki write permission denied. ' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$deleted = NativeWikiPage::delete_page([
@@ -765,14 +763,14 @@ class Wiki extends Controller {
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true));
}
else {
- json_return_and_die(array('message' => 'Error deleting page', 'success' => false));
+ json_return_and_die(array('message' => 'Error deleting page', 'success' => false));
}
}
-
+
// Revert a page
if ((argc() === 4) && (argv(2) === 'revert') && (argv(3) === 'page')) {
- $resource_id = $_POST['resource_id'];
+ $resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$commitHash = $_POST['commitHash'];
@@ -780,7 +778,7 @@ class Wiki extends Controller {
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied.' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$reverted = NativeWikiPage::revert_page([
@@ -791,16 +789,16 @@ class Wiki extends Controller {
'pageUrlName' => $pageUrlName
]);
if($reverted['success']) {
- json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true));
+ json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true));
}
else {
- json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false));
+ json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false));
}
}
-
+
// Compare page revisions
if ((argc() === 4) && (argv(2) === 'compare') && (argv(3) === 'page')) {
- $resource_id = $_POST['resource_id'];
+ $resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$compareCommit = $_POST['compareCommit'];
$currentCommit = $_POST['currentCommit'];
@@ -809,21 +807,21 @@ class Wiki extends Controller {
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(!$perms['read']) {
logger('Wiki read permission denied.' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$compare = NativeWikiPage::compare_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
if($compare['success']) {
$diffHTML = '<table class="text-center" width="100%"><tr><td class="lead" width="50%">' . t('Current Revision') . '</td><td class="lead" width="50%">' . t('Selected Revision') . '</td></tr></table>' . $compare['diff'];
- json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true));
+ json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true));
} else {
- json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false));
+ json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false));
}
}
-
+
// Rename a page
if ((argc() === 4) && (argv(2) === 'rename') && (argv(3) === 'page')) {
- $resource_id = $_POST['resource_id'];
+ $resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['oldName'];
$pageNewName = str_replace('\\','',$_POST['newName']);
if ($pageUrlName === 'Home') {
@@ -837,7 +835,7 @@ class Wiki extends Controller {
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
- json_return_and_die(array('success' => false));
+ json_return_and_die(array('success' => false));
}
$renamed = NativeWikiPage::rename_page([
@@ -850,8 +848,8 @@ class Wiki extends Controller {
if($renamed['success']) {
$commit = NativeWikiPage::commit([
'channel_id' => $owner['channel_id'],
- 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'],
- 'resource_id' => $resource_id,
+ 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'],
+ 'resource_id' => $resource_id,
'observer_hash' => $observer_hash,
'pageUrlName' => $pageNewName
]);
@@ -860,16 +858,16 @@ class Wiki extends Controller {
json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true));
}
else {
- json_return_and_die(array('message' => 'Error making git commit','success' => false));
+ json_return_and_die(array('message' => 'Error making git commit','success' => false));
}
}
else {
- json_return_and_die(array('message' => 'Error renaming page', 'success' => false));
+ json_return_and_die(array('message' => 'Error renaming page', 'success' => false));
}
}
//notice( t('You must be authenticated.'));
json_return_and_die(array('message' => t('You must be authenticated.'), 'success' => false));
-
+
}
}
diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php
index 21574eb8d..b7868c2cc 100644
--- a/Zotlabs/Module/Xrd.php
+++ b/Zotlabs/Module/Xrd.php
@@ -28,19 +28,18 @@ class Xrd extends \Zotlabs\Web\Controller {
$name = substr($local,0,strpos($local,'@'));
}
- $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1",
- dbesc($name)
- );
+ $r = channelx_by_nick($name);
+
if(! $r)
killme();
- $salmon_key = Keyutils::salmonKey($r[0]['channel_pubkey']);
+ $salmon_key = Keyutils::salmonKey($r['channel_pubkey']);
header('Access-Control-Allow-Origin: *');
header("Content-type: application/xrd+xml");
- $aliases = array('acct:' . channel_reddress($r[0]), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']);
+ $aliases = array('acct:' . channel_reddress($r), z_root() . '/channel/' . $r['channel_address'], z_root() . '/~' . $r['channel_address']);
for($x = 0; $x < count($aliases); $x ++) {
if($aliases[$x] === $resource)
@@ -48,23 +47,23 @@ class Xrd extends \Zotlabs\Web\Controller {
}
$o = replace_macros(get_markup_template('xrd_person.tpl'), array(
- '$nick' => $r[0]['channel_address'],
+ '$nick' => $r['channel_address'],
'$accturi' => $resource,
'$subject' => $subject,
'$aliases' => $aliases,
- '$channel_url' => z_root() . '/channel/' . $r[0]['channel_address'],
- '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'],
- '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'],
- '$atom' => z_root() . '/ofeed/' . $r[0]['channel_address'],
- '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'],
- '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'],
- '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'],
+ '$channel_url' => z_root() . '/channel/' . $r['channel_address'],
+ '$profile_url' => z_root() . '/channel/' . $r['channel_address'],
+ '$hcard_url' => z_root() . '/hcard/' . $r['channel_address'],
+ '$atom' => z_root() . '/ofeed/' . $r['channel_address'],
+ '$zot_post' => z_root() . '/post/' . $r['channel_address'],
+ '$poco_url' => z_root() . '/poco/' . $r['channel_address'],
+ '$photo' => z_root() . '/photo/profile/l/' . $r['channel_id'],
'$modexp' => 'data:application/magic-public-key,' . $salmon_key,
'$subscribe' => z_root() . '/follow?f=&amp;url={uri}',
));
- $arr = array('user' => $r[0], 'xml' => $o);
+ $arr = array('user' => $r, 'xml' => $o);
call_hooks('personal_xrd', $arr);
echo $arr['xml'];
diff --git a/Zotlabs/Module/Zfinger.php b/Zotlabs/Module/Zfinger.php
deleted file mode 100644
index ce7117ad8..000000000
--- a/Zotlabs/Module/Zfinger.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-namespace Zotlabs\Module;
-
-use Zotlabs\Web\HTTPSig;
-use Zotlabs\Lib\Libzot;
-
-class Zfinger extends \Zotlabs\Web\Controller {
-
- function init() {
-
- require_once('include/zot.php');
- require_once('include/crypto.php');
-
- $x = zotinfo($_REQUEST);
-
- if($x && $x['guid'] && $x['guid_sig']) {
- $chan_hash = make_xchan_hash($x['guid'],$x['guid_sig']);
- if($chan_hash) {
- $chan = channelx_by_hash($chan_hash);
- }
- }
-
- $headers = [];
- $headers['Content-Type'] = 'application/json' ;
- $ret = json_encode($x);
-
- if($chan) {
- $headers['Digest'] = HTTPSig::generate_digest_header($ret);
- $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'], channel_url($chan));
- HTTPSig::set_headers($h);
- }
- else {
- foreach($headers as $k => $v) {
- header($k . ': ' . $v);
- }
- }
-
- echo $ret;
- killme();
-
- }
-
-}
diff --git a/Zotlabs/Module/Zotfeed.php b/Zotlabs/Module/Zotfeed.php
index e47367036..0b4c3c007 100644
--- a/Zotlabs/Module/Zotfeed.php
+++ b/Zotlabs/Module/Zotfeed.php
@@ -1,124 +1,22 @@
<?php
-
namespace Zotlabs\Module;
-use App;
-use Zotlabs\Lib\Activity;
-use Zotlabs\Lib\ActivityStreams;
-use Zotlabs\Lib\Config;
-use Zotlabs\Lib\ThreadListener;
use Zotlabs\Web\Controller;
-use Zotlabs\Web\HTTPSig;
class Zotfeed extends Controller {
- function init() {
- if (ActivityStreams::is_as_request()) {
-
- if (observer_prohibited(true)) {
- killme();
- }
-
- $channel = channelx_by_nick(argv(1));
- if (!$channel) {
- killme();
- }
-
- if (intval($channel['channel_system'])) {
- killme();
- }
-
- $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
- if ($sigdata['portable_id'] && $sigdata['header_valid']) {
- $portable_id = $sigdata['portable_id'];
- if (!check_channelallowed($portable_id)) {
- http_status_exit(403, 'Permission denied');
- }
- if (!check_siteallowed($sigdata['signer'])) {
- http_status_exit(403, 'Permission denied');
- }
- observer_auth($portable_id);
- }
- elseif (Config::get('system', 'require_authenticated_fetch', false)) {
- http_status_exit(403, 'Permission denied');
- }
-
- $observer_hash = get_observer_hash();
-
- $params = [];
+ function post() {
- $params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
- $params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : '');
- $params['type'] = 'json';
- $params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0);
- $params['top'] = ((x($_REQUEST, 'top')) ? intval($_REQUEST['top']) : 0);
- $params['direction'] = ((x($_REQUEST, 'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented
- $params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : '');
- $params['compat'] = 1;
-
- $total = items_fetch(
- [
- 'total' => true,
- 'wall' => 1,
- 'datequery' => $params['end'],
- 'datequery2' => $params['begin'],
- 'direction' => dbesc($params['direction']),
- 'pages' => $params['pages'],
- 'order' => dbesc('post'),
- 'top' => $params['top'],
- 'cat' => $params['cat'],
- 'compat' => $params['compat']
- ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
- );
-
- if ($total) {
- App::set_pager_total($total);
- App::set_pager_itemspage(30);
- }
+ }
- if (App::$pager['unset'] && $total > 30) {
- $ret = Activity::paged_collection_init($total, App::$query_string);
- }
- else {
+ function get() {
- $items = items_fetch(
- [
- 'wall' => 1,
- 'datequery' => $params['end'],
- 'datequery2' => $params['begin'],
- 'records' => intval(App::$pager['itemspage']),
- 'start' => intval(App::$pager['start']),
- 'direction' => dbesc($params['direction']),
- 'pages' => $params['pages'],
- 'order' => dbesc('post'),
- 'top' => $params['top'],
- 'cat' => $params['cat'],
- 'compat' => $params['compat']
- ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module
- );
+ $outbox = new Outbox();
+ return $outbox->init();
- if ($items && $observer_hash) {
+ }
- // check to see if this observer is a connection. If not, register any items
- // belonging to this channel for notification of deletion/expiration
+}
- $x = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
- intval($channel['channel_id']),
- dbesc($observer_hash)
- );
- if (!$x) {
- foreach ($items as $item) {
- if (strpos($item['mid'], z_root()) === 0) {
- ThreadListener::store($item['mid'], $observer_hash);
- }
- }
- }
- }
- $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total);
- }
- as_return_and_die($ret, $channel);
- }
- }
-}
diff --git a/Zotlabs/Module/Zping.php b/Zotlabs/Module/Zping.php
deleted file mode 100644
index d6128fa66..000000000
--- a/Zotlabs/Module/Zping.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-namespace Zotlabs\Module; /** @file */
-
-require_once('include/zot.php');
-
-
-class Zping extends \Zotlabs\Web\Controller {
-
- function get() {
-
- // This is just a test utility function and may go away once we build these tools into
- // the address book and directory to do dead site discovery.
-
- // The response packet include the current URL and key so we can discover if the server
- // has been re-installed and clean up (e.g. get rid of) any old hublocs and xchans.
-
- // Remember to add '/post' to the url
-
- if(! local_channel())
- return;
-
- $url = $_REQUEST['url'];
-
- if(! $url)
- return;
-
-
- $m = zot_build_packet(\App::get_channel(),'ping');
- $r = zot_zot($url,$m);
- return print_r($r,true);
-
- }
-}
diff --git a/Zotlabs/Photo/PhotoDriver.php b/Zotlabs/Photo/PhotoDriver.php
index 4c4f26e32..6bdb89ab1 100644
--- a/Zotlabs/Photo/PhotoDriver.php
+++ b/Zotlabs/Photo/PhotoDriver.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Photo;
-use Zotlabs\Lib\Hashpath;
+use Zotlabs\Lib\Hashpath;
/**
* @brief Abstract photo driver class.
@@ -494,11 +494,11 @@ abstract class PhotoDriver {
( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires, profile )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']));
}
- logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r));
+ logger('Photo save imgscale ' . $p['imgscale'] . ' returned: ' . (($r) ? 1 : 0));
return $r;
}
-
+
/**
* @brief Stores thumbnail to database or filesystem.
*
@@ -530,13 +530,13 @@ abstract class PhotoDriver {
}
else
$arr['os_storage'] = 0;
-
+
if(! $this->save($arr)) {
if(array_key_exists('os_syspath', $arr))
@unlink($arr['os_syspath']);
return false;
}
-
+
return true;
}
diff --git a/Zotlabs/Render/Comanche.php b/Zotlabs/Render/Comanche.php
index 5ce05243b..230c2455e 100644
--- a/Zotlabs/Render/Comanche.php
+++ b/Zotlabs/Render/Comanche.php
@@ -572,7 +572,7 @@ class Comanche {
require_once('widget/' . trim($name) . '.php');
elseif(file_exists('widget/' . trim($name) . '/' . trim($name) . '.php'))
require_once('widget/' . trim($name) . '/' . trim($name) . '.php');
-
+
if(! function_exists($func)) {
$theme_widget = $func . '.php';
if(theme_include($theme_widget)) {
@@ -640,7 +640,8 @@ class Comanche {
$cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
- $s = str_replace($mtch[0],$this->widget(trim($mtch[1]),$mtch[2]),$s);
+
+ $s = str_replace((string)$mtch[0], (string)$this->widget(trim((string)$mtch[1]), (string)$mtch[2]), $s);
}
}
diff --git a/Zotlabs/Render/Theme.php b/Zotlabs/Render/Theme.php
index 0eebba1ba..2e6ca0c32 100644
--- a/Zotlabs/Render/Theme.php
+++ b/Zotlabs/Render/Theme.php
@@ -60,14 +60,16 @@ class Theme {
// Allow theme selection of the form 'theme_name:schema_name'
$themepair = explode(':', $chosen_theme);
-
// Check if $chosen_theme is compatible with core. If not fall back to default
$info = get_theme_info($themepair[0]);
+
$compatible = check_plugin_versions($info);
if(!$compatible) {
$chosen_theme = '';
}
+ App::$theme_info = $info;
+
if($chosen_theme && (file_exists('view/theme/' . $themepair[0] . '/css/style.css') || file_exists('view/theme/' . $themepair[0] . '/php/style.php'))) {
return($themepair);
}
diff --git a/Zotlabs/Update/_1246.php b/Zotlabs/Update/_1246.php
new file mode 100644
index 000000000..3023c45dd
--- /dev/null
+++ b/Zotlabs/Update/_1246.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1246 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ $r1 = dbq("UPDATE xchan SET xchan_deleted = 2 WHERE xchan_network = 'zot' AND xchan_deleted = 0");
+ $r2 = dbq("UPDATE hubloc SET hubloc_deleted = 2 WHERE hubloc_network = 'zot' AND hubloc_deleted = 0");
+
+ if($r1 && $r2) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1247.php b/Zotlabs/Update/_1247.php
new file mode 100644
index 000000000..e776a52f4
--- /dev/null
+++ b/Zotlabs/Update/_1247.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1247 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ $r = dbq("DELETE FROM updates WHERE ud_addr = '' OR ud_hash = '' OR ud_guid = ''");
+
+ if($r) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1248.php b/Zotlabs/Update/_1248.php
new file mode 100644
index 000000000..b61c6ed39
--- /dev/null
+++ b/Zotlabs/Update/_1248.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1248 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ // remove possible bogus entries from xconfig
+ $r = dbq("DELETE FROM xconfig WHERE xchan = ''");
+
+ // remove gnu social app - it has been moved to addons unmaintained
+ $r1 = dbq("DELETE FROM app WHERE app_plugin = 'gnusoc'");
+
+ if($r && $r1) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1249.php b/Zotlabs/Update/_1249.php
new file mode 100644
index 000000000..6d72c4de4
--- /dev/null
+++ b/Zotlabs/Update/_1249.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1249 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = dbq("ALTER TABLE abook ADD abook_role TEXT NOT NULL DEFAULT ''");
+ $r2 = dbq("CREATE INDEX \"abook_role\" ON abook (\"abook_role\")");
+ $r = ($r1 && $r2);
+ }
+ else {
+ $r = dbq("ALTER TABLE `abook` ADD `abook_role` CHAR(191) NOT NULL DEFAULT '' ,
+ ADD INDEX `abook_role` (`abook_role`)");
+ }
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1250.php b/Zotlabs/Update/_1250.php
new file mode 100644
index 000000000..bc50479d4
--- /dev/null
+++ b/Zotlabs/Update/_1250.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1250 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = dbq("ALTER TABLE atoken ADD atoken_guid VARCHAR(255) NOT NULL DEFAULT ''");
+ $r2 = dbq("CREATE INDEX \"atoken_guid\" ON atoken (\"atoken_guid\")");
+ $r = ($r1 && $r2);
+ }
+ else {
+ $r = dbq("ALTER TABLE `atoken` ADD `atoken_guid` CHAR(191) NOT NULL DEFAULT '' ,
+ ADD INDEX `atoken_guid` (`atoken_guid`)");
+ }
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1251.php b/Zotlabs/Update/_1251.php
new file mode 100644
index 000000000..ee72075d1
--- /dev/null
+++ b/Zotlabs/Update/_1251.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1251 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ $r = dbq("DELETE FROM app WHERE (app_name = 'Channel Home' OR app_name = 'Permission Categories') AND app_system = 1");
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1252.php b/Zotlabs/Update/_1252.php
new file mode 100644
index 000000000..97bb58d9d
--- /dev/null
+++ b/Zotlabs/Update/_1252.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1252 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ $r = dbq("DELETE FROM app WHERE app_plugin = 'mail' AND app_system = 1");
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Web/HTTPSig.php b/Zotlabs/Web/HTTPSig.php
index 35b18c763..4177477a1 100644
--- a/Zotlabs/Web/HTTPSig.php
+++ b/Zotlabs/Web/HTTPSig.php
@@ -2,10 +2,13 @@
namespace Zotlabs\Web;
+use DateTime;
+use DateTimeZone;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Keyutils;
use Zotlabs\Lib\Webfinger;
+use Zotlabs\Lib\Zotfinger;
use Zotlabs\Lib\Libzot;
/**
@@ -13,7 +16,6 @@ use Zotlabs\Lib\Libzot;
*
* @see https://tools.ietf.org/html/draft-cavage-http-signatures-10
*/
-
class HTTPSig {
/**
@@ -26,10 +28,10 @@ class HTTPSig {
* @return string The generated digest header string for $body
*/
- static function generate_digest_header($body,$alg = 'sha256') {
+ static function generate_digest_header($body, $alg = 'sha256') {
$digest = base64_encode(hash($alg, $body, true));
- switch($alg) {
+ switch ($alg) {
case 'sha512':
return 'SHA-512=' . $digest;
case 'sha256':
@@ -39,29 +41,29 @@ class HTTPSig {
}
}
- static function find_headers($data,&$body) {
+ static function find_headers($data, &$body) {
// decide if $data arrived via controller submission or curl
- if(is_array($data) && $data['header']) {
- if(! $data['success'])
+ if (is_array($data) && $data['header']) {
+ if (!$data['success'])
return [];
- $h = new HTTPHeaders($data['header']);
- $headers = $h->fetcharr();
- $body = $data['body'];
+ $h = new HTTPHeaders($data['header']);
+ $headers = $h->fetcharr();
+ $body = $data['body'];
$headers['(request-target)'] = $data['request_target'];
}
else {
- $headers = [];
+ $headers = [];
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
- $headers['content-type'] = $_SERVER['CONTENT_TYPE'];
- $headers['content-length'] = $_SERVER['CONTENT_LENGTH'];
+ $headers['content-type'] = $_SERVER['CONTENT_TYPE'];
+ $headers['content-length'] = $_SERVER['CONTENT_LENGTH'];
- foreach($_SERVER as $k => $v) {
- if(strpos($k,'HTTP_') === 0) {
- $field = str_replace('_','-',strtolower(substr($k,5)));
+ foreach ($_SERVER as $k => $v) {
+ if (strpos($k, 'HTTP_') === 0) {
+ $field = str_replace('_', '-', strtolower(substr($k, 5)));
$headers[$field] = $v;
}
}
@@ -77,10 +79,10 @@ class HTTPSig {
// See draft-cavage-http-signatures-10
- static function verify($data,$key = '', $keytype = '') {
+ static function verify($data, $key = '', $keytype = '') {
- $body = $data;
- $headers = null;
+ $body = $data;
+ $headers = null;
$result = [
'signer' => '',
@@ -92,21 +94,21 @@ class HTTPSig {
];
- $headers = self::find_headers($data,$body);
+ $headers = self::find_headers($data, $body);
- if(! $headers)
+ if (!$headers)
return $result;
$sig_block = null;
- if(array_key_exists('signature',$headers)) {
+ if (array_key_exists('signature', $headers)) {
$sig_block = self::parse_sigheader($headers['signature']);
}
- elseif(array_key_exists('authorization',$headers)) {
+ elseif (array_key_exists('authorization', $headers)) {
$sig_block = self::parse_sigheader($headers['authorization']);
}
- if(! $sig_block) {
+ if (!$sig_block) {
logger('no signature provided.', LOGGER_DEBUG);
return $result;
}
@@ -117,71 +119,87 @@ class HTTPSig {
$result['header_signed'] = true;
$signed_headers = $sig_block['headers'];
- if(! $signed_headers)
- $signed_headers = [ 'date' ];
+ if (!$signed_headers)
+ $signed_headers = ['date'];
$signed_data = '';
- foreach($signed_headers as $h) {
- if(array_key_exists($h,$headers)) {
+ foreach ($signed_headers as $h) {
+ if (array_key_exists($h, $headers)) {
$signed_data .= $h . ': ' . $headers[$h] . "\n";
}
- if($h === 'date') {
- $d = new \DateTime($headers[$h]);
- $d->setTimeZone(new \DateTimeZone('UTC'));
- $dplus = datetime_convert('UTC','UTC','now + 1 day');
- $dminus = datetime_convert('UTC','UTC','now - 1 day');
- $c = $d->format('Y-m-d H:i:s');
- if($c > $dplus || $c < $dminus) {
+
+ if ($h === 'date') {
+ $d = new DateTime($headers[$h]);
+ $d->setTimeZone(new DateTimeZone('UTC'));
+ $dplus = datetime_convert('UTC', 'UTC', 'now + 1 day');
+ $dminus = datetime_convert('UTC', 'UTC', 'now - 1 day');
+ $c = $d->format('Y-m-d H:i:s');
+ if ($c > $dplus || $c < $dminus) {
logger('bad time: ' . $c);
return $result;
}
}
}
- $signed_data = rtrim($signed_data,"\n");
+ $signed_data = rtrim($signed_data, "\n");
$algorithm = null;
- if($sig_block['algorithm'] === 'rsa-sha256') {
+
+ if ($sig_block['algorithm'] === 'rsa-sha256') {
$algorithm = 'sha256';
}
- if($sig_block['algorithm'] === 'rsa-sha512') {
+
+ if ($sig_block['algorithm'] === 'rsa-sha512') {
$algorithm = 'sha512';
}
- if(! array_key_exists('keyId',$sig_block))
+ if (!array_key_exists('keyId', $sig_block)) {
return $result;
+ }
$result['signer'] = $sig_block['keyId'];
- $cached_key = self::get_key($key,$keytype,$result['signer']);
+ $cached_key = self::get_key($key, $keytype, $result['signer']);
+
+ if ($sig_block['algorithm'] === 'hs2019') {
+ if (isset($cached_key['algorithm'])) {
+ if (strpos($cached_key['algorithm'], 'rsa-sha256') !== false) {
+ $algorithm = 'sha256';
+ }
+
+ if (strpos($cached_key['algorithm'], 'rsa-sha512') !== false) {
+ $algorithm = 'sha512';
+ }
+ }
+ }
- if(! ($cached_key && $cached_key['public_key'])) {
+ if (!($cached_key && $cached_key['public_key'])) {
return $result;
}
- $x = Crypto::verify($signed_data,$sig_block['signature'],$cached_key['public_key'],$algorithm);
+ $x = Crypto::verify($signed_data, $sig_block['signature'], $cached_key['public_key'], $algorithm);
logger('verified: ' . $x, LOGGER_DEBUG);
$fetched_key = '';
- if(! $x) {
+ if (!$x) {
// try again, ignoring the local actor (xchan) cache and refetching the key
// from its source
- $fetched_key = self::get_key($key,$keytype,$result['signer'],true);
+ $fetched_key = self::get_key($key, $keytype, $result['signer'], true);
if ($fetched_key && $fetched_key['public_key']) {
- $y = Crypto::verify($signed_data,$sig_block['signature'],$fetched_key['public_key'],$algorithm);
+ $y = Crypto::verify($signed_data, $sig_block['signature'], $fetched_key['public_key'], $algorithm);
logger('verified: (cache reload) ' . $x, LOGGER_DEBUG);
}
- if (! $y) {
+ if (!$y) {
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($fetched_key['public_key']) ? '' : ' no key'));
$sig_block['signature'] = base64_encode($sig_block['signature']);
- logger('affected sigblock: ' . print_r($sig_block,true));
- logger('headers: ' . print_r($headers,true));
- logger('server: ' . print_r($_SERVER,true));
+ logger('affected sigblock: ' . print_r($sig_block, true));
+ logger('headers: ' . print_r($headers, true));
+ logger('server: ' . print_r($_SERVER, true));
return $result;
}
@@ -189,59 +207,65 @@ class HTTPSig {
$key = (($fetched_key) ? $fetched_key : $cached_key);
- $result['portable_id'] = $key['portable_id'];
+ $result['portable_id'] = $key['portable_id'];
$result['header_valid'] = true;
- if(in_array('digest',$signed_headers)) {
+ if (in_array('digest', $signed_headers)) {
$result['content_signed'] = true;
- $digest = explode('=', $headers['digest'], 2);
- if($digest[0] === 'SHA-256')
+ $digest = explode('=', $headers['digest'], 2);
+ if ($digest[0] === 'SHA-256')
$hashalg = 'sha256';
- if($digest[0] === 'SHA-512')
+ if ($digest[0] === 'SHA-512')
$hashalg = 'sha512';
- if(base64_encode(hash($hashalg,$body,true)) === $digest[1]) {
+ if (base64_encode(hash($hashalg, $body, true)) === $digest[1]) {
$result['content_valid'] = true;
}
logger('Content_Valid: ' . (($result['content_valid']) ? 'true' : 'false'));
- if (! $result['content_valid']) {
- logger('invalid content signature: data ' . print_r($data,true));
- logger('invalid content signature: headers ' . print_r($headers,true));
- logger('invalid content signature: body ' . print_r($body,true));
+ if (!$result['content_valid']) {
+ logger('invalid content signature: data ' . print_r($data, true));
+ logger('invalid content signature: headers ' . print_r($headers, true));
+ logger('invalid content signature: body ' . print_r($body, true));
}
}
return $result;
}
- static function get_key($key,$keytype,$id) {
+ static function get_key($key, $keytype, $id, $force = false) {
- if(is_array($key))
- btlogger('key is array: ' . print_r($key,true));
+ if (is_array($key))
+ btlogger('key is array: ' . print_r($key, true));
- if($key) {
- if(function_exists($key)) {
+ if ($key) {
+ if (function_exists($key)) {
return $key($id);
}
- return [ 'public_key' => $key ];
+ return ['public_key' => $key];
}
- if($keytype === 'zot6') {
- $key = self::get_zotfinger_key($id);
- if($key) {
+ if ($keytype === 'zot6') {
+ $key = self::get_zotfinger_key($id, $force);
+ if ($key) {
return $key;
}
}
- if(strpos($id,'#') === false) {
- $key = self::get_webfinger_key($id);
+ if (strpos($id, '#') === false) {
+ $key = self::get_webfinger_key($id, $force);
+ if ($key) {
+ return $key;
+ }
}
- if(! $key) {
- $key = self::get_activitystreams_key($id);
+ $delete = false;
+ if ($keytype === 'delete') {
+ $delete = true;
}
+ $key = self::get_activitystreams_key($id, $force, $delete);
+
return $key;
}
@@ -249,10 +273,10 @@ class HTTPSig {
static function convertKey($key) {
- if(strstr($key,'RSA ')) {
+ if (strstr($key, 'RSA ')) {
return Keyutils::rsaToPem($key);
}
- elseif(substr($key,0,5) === 'data:') {
+ elseif (substr($key, 0, 5) === 'data:') {
return Keyutils::convertSalmonKey($key);
}
else {
@@ -263,70 +287,120 @@ class HTTPSig {
/**
- * @brief
+ * @brief get a cached key or fetch it with ActivityStreams
*
* @param string $id
- * @return boolean|string
- * false if no pub key found, otherwise return the pub key
+ * @param boolean $force (optional, default false)
+ * @return boolean|array
+ * false if no pub key found, otherwise return an array with the pub key
*/
- static function get_activitystreams_key($id) {
+ static function get_activitystreams_key($id, $force = false, $delete = false) {
- // remove fragment
+ // Check the local cache first, but remove any fragments like #main-key since these won't be present in our cached data
+ $url = ((strpos($id, '#')) ? substr($id, 0, strpos($id, '#')) : $id);
- $url = ((strpos($id,'#')) ? substr($id,0,strpos($id,'#')) : $id);
+ // $force is used to ignore the local cache and only use the remote data; for instance the cached key might be stale
+ if (!$force) {
+ $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where (hubloc_id_url = '%s' or hubloc_hash = '%s') and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
+ dbesc($url),
+ dbesc($url)
+ );
- $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' and hubloc_network in ('zot6', 'activitypub')",
- dbesc(str_replace('acct:','',$url)),
- dbesc($url)
- );
-
- $x = Libzot::zot_record_preferred($x);
+ if ($x) {
+ $best = Libzot::zot_record_preferred($x);
+ }
+ if ($best && $best['xchan_pubkey']) {
+ return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
+ }
+ }
- if($x && $x['xchan_pubkey']) {
- return [ 'portable_id' => $x['xchan_hash'], 'public_key' => $x['xchan_pubkey'] , 'hubloc' => $x ];
+ if ($delete) {
+ // If we received a delete and we do not have the record cached,
+ // we probably never saw this actor. Do not try to fetch it now.
+ return false;
}
+ // The record wasn't in cache. Fetch it now.
$r = ActivityStreams::fetch($id);
+ $signatureAlgorithm = EMPTY_STR;
+
+ if ($r) {
+ if (array_key_exists('publicKey', $r) && array_key_exists('publicKeyPem', $r['publicKey']) && array_key_exists('id', $r['publicKey'])) {
+ if ($r['publicKey']['id'] === $id || $r['id'] === $id) {
+ $portable_id = ((array_key_exists('owner', $r['publicKey'])) ? $r['publicKey']['owner'] : EMPTY_STR);
+
+ // the w3c sec context has conflicting names and no defined values for this property except
+ // "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
+
+ // Since the names conflict, it could mess up LD-signatures but we will accept both, and at this
+ // time we will only look for the substrings 'rsa-sha256' and 'rsa-sha512' within those properties.
+ // We will also accept a toplevel 'sigAlgorithm' regardless of namespace with the same constraints.
+ // Default to rsa-sha256 if we can't figure out. If they're sending 'hs2019' we have to
+ // look for something.
+
+ if (isset($r['publicKey']['signingAlgorithm'])) {
+ $signatureAlgorithm = $r['publicKey']['signingAlgorithm'];
+ set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
+ }
- if($r) {
- if(array_key_exists('publicKey',$r) && array_key_exists('publicKeyPem',$r['publicKey']) && array_key_exists('id',$r['publicKey'])) {
- if($r['publicKey']['id'] === $id || $r['id'] === $id) {
- $portable_id = ((array_key_exists('owner',$r['publicKey'])) ? $r['publicKey']['owner'] : EMPTY_STR);
- return [ 'public_key' => self::convertKey($r['publicKey']['publicKeyPem']), 'portable_id' => $portable_id, 'hubloc' => [] ];
+ if (isset($r['publicKey']['signatureAlgorithm'])) {
+ $signatureAlgorithm = $r['publicKey']['signatureAlgorithm'];
+ set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
+ }
+
+ if (isset($r['sigAlgorithm'])) {
+ $signatureAlgorithm = $r['sigAlgorithm'];
+ set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
+ }
+
+ return ['public_key' => self::convertKey($r['publicKey']['publicKeyPem']), 'portable_id' => $portable_id, 'algorithm' => (($signatureAlgorithm) ? $signatureAlgorithm : 'rsa-sha256'), 'hubloc' => []];
}
}
}
+
+ // No key was found
return false;
}
+ /**
+ * @brief get a cached key or fetch it with Webfinger
+ *
+ * @param string $id
+ * @param boolean $force (optional, default false)
+ * @return boolean|array
+ * false if no pub key found, otherwise return an array with the pub key
+ */
- static function get_webfinger_key($id) {
+ static function get_webfinger_key($id, $force = false) {
- $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s'",
- dbesc(str_replace('acct:','',$id)),
- dbesc($id)
- );
+ if (!$force) {
+ $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
+ dbesc($id)
+ );
- $x = Libzot::zot_record_preferred($x);
+ if ($x) {
+ $best = Libzot::zot_record_preferred($x);
+ }
- if($x && $x['xchan_pubkey']) {
- return [ 'portable_id' => $x['xchan_hash'], 'public_key' => $x['xchan_pubkey'] , 'hubloc' => $x ];
+ if ($best && $best['xchan_pubkey']) {
+ return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
+ }
}
- $wf = Webfinger::exec($id);
- $key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ];
+ $wf = Webfinger::exec($id);
+ $key = ['portable_id' => '', 'public_key' => '', 'hubloc' => []];
- if($wf) {
- if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) {
+ if ($wf) {
+ if (array_key_exists('properties', $wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem', $wf['properties'])) {
$key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']);
}
- if(array_key_exists('links', $wf) && is_array($wf['links'])) {
- foreach($wf['links'] as $l) {
- if(! (is_array($l) && array_key_exists('rel',$l))) {
+ if (array_key_exists('links', $wf) && is_array($wf['links'])) {
+ foreach ($wf['links'] as $l) {
+ if (!(is_array($l) && array_key_exists('rel', $l))) {
continue;
}
- if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) {
+ if ($l['rel'] === 'magic-public-key' && array_key_exists('href', $l) && $key['public_key'] === EMPTY_STR) {
$key['public_key'] = self::convertKey($l['href']);
}
}
@@ -336,51 +410,64 @@ class HTTPSig {
return (($key['public_key']) ? $key : false);
}
- static function get_zotfinger_key($id) {
+ /**
+ * @brief get a cached key or fetch it with Zotfinger
+ *
+ * @param string $id
+ * @param boolean $force (optional, default false)
+ * @return boolean|array
+ * false if no pub key found, otherwise return an array with the public key
+ */
- $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' and hubloc_network = 'zot6'",
- dbesc(str_replace('acct:','',$id)),
- dbesc($id)
- );
+ static function get_zotfinger_key($id, $force = false) {
+ if (!$force) {
+ $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network = 'zot6' order by hubloc_id desc",
+ dbesc($id)
+ );
- if($x && $x[0]['xchan_pubkey']) {
- return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
+ if ($x) {
+ $best = Libzot::zot_record_preferred($x);
+ }
+
+ if ($best && $best['xchan_pubkey']) {
+ return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
+ }
}
- $wf = Webfinger::exec($id);
- $key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ];
+ $wf = Webfinger::exec($id);
+ $key = ['portable_id' => '', 'public_key' => '', 'hubloc' => []];
- if($wf) {
- if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) {
+ if ($wf) {
+ if (array_key_exists('properties', $wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem', $wf['properties'])) {
$key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']);
}
- if(array_key_exists('links', $wf) && is_array($wf['links'])) {
- foreach($wf['links'] as $l) {
- if(! (is_array($l) && array_key_exists('rel',$l))) {
+ if (array_key_exists('links', $wf) && is_array($wf['links'])) {
+ foreach ($wf['links'] as $l) {
+ if (!(is_array($l) && array_key_exists('rel', $l))) {
continue;
}
- if($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href',$l) && $l['href'] !== EMPTY_STR) {
+ if ($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href', $l) && $l['href'] !== EMPTY_STR) {
// The third argument to Zotfinger::exec() tells it not to verify signatures
// Since we're inside a function that is fetching keys with which to verify signatures,
// this is necessary to prevent infinite loops.
- $z = \Zotlabs\Lib\Zotfinger::exec($l['href'],null,false);
- if($z) {
+ $z = Zotfinger::exec($l['href'], null, false);
+ if ($z) {
$i = Libzot::import_xchan($z['data']);
- if($i['success']) {
+ if ($i['success']) {
$key['portable_id'] = $i['hash'];
- $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network = 'zot6'",
+ $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network = 'zot6' order by hubloc_id desc",
dbesc($l['href'])
);
- if($x) {
+ if ($x) {
$key['hubloc'] = $x[0];
}
}
}
}
- if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) {
+ if ($l['rel'] === 'magic-public-key' && array_key_exists('href', $l) && $key['public_key'] === EMPTY_STR) {
$key['public_key'] = self::convertKey($l['href']);
}
}
@@ -402,39 +489,42 @@ class HTTPSig {
* @param array $encryption [ 'key', 'algorithm' ] or false
* @return array
*/
- static function create_sig($head, $prvkey, $keyid = EMPTY_STR, $auth = false, $alg = 'sha256', $encryption = false ) {
+ static function create_sig($head, $prvkey, $keyid = EMPTY_STR, $auth = false, $alg = 'sha256', $encryption = false) {
$return_headers = [];
- if($alg === 'sha256') {
+ if ($alg === 'sha256') {
$algorithm = 'rsa-sha256';
}
- if($alg === 'sha512') {
+ if ($alg === 'sha512') {
$algorithm = 'rsa-sha512';
}
- $x = self::sign($head,$prvkey,$alg);
+ $x = self::sign($head, $prvkey, $alg);
+
+ // TODO: should we default to hs2019?
+ // $headerval = 'keyId="' . $keyid . '",algorithm="' . (($algorithm === 'rsa-sha256') ? 'hs2019' : $algorithm) . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
$headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
- if($encryption) {
- $x = Crypto::encapsulate($headerval,$encryption['key'],$encryption['algorithm']);
- if(is_array($x)) {
+ if ($encryption) {
+ $x = Crypto::encapsulate($headerval, $encryption['key'], $encryption['algorithm']);
+ if (is_array($x)) {
$headerval = 'iv="' . $x['iv'] . '",key="' . $x['key'] . '",alg="' . $x['alg'] . '",data="' . $x['data'] . '"';
}
}
- if($auth) {
+ if ($auth) {
$sighead = 'Authorization: Signature ' . $headerval;
}
else {
$sighead = 'Signature: ' . $headerval;
}
- if($head) {
- foreach($head as $k => $v) {
+ if ($head) {
+ foreach ($head as $k => $v) {
// strip the request-target virtual header from the output headers
- if($k === '(request-target)') {
+ if ($k === '(request-target)') {
continue;
}
$return_headers[] = $k . ': ' . $v;
@@ -454,8 +544,8 @@ class HTTPSig {
static function set_headers($headers) {
- if($headers && is_array($headers)) {
- foreach($headers as $h) {
+ if ($headers && is_array($headers)) {
+ foreach ($headers as $h) {
header($h);
}
}
@@ -465,7 +555,7 @@ class HTTPSig {
/**
* @brief
*
- * @param array $head
+ * @param array $head
* @param string $prvkey
* @param string $alg (optional) default 'sha256'
* @return array
@@ -478,21 +568,24 @@ class HTTPSig {
$headers = '';
$fields = '';
- logger('signing: ' . print_r($head,true), LOGGER_DATA);
+ logger('signing: ' . print_r($head, true), LOGGER_DATA);
+
+ if ($head) {
+ foreach ($head as $k => $v) {
+ $k = strtolower($k);
+ $v = (($v) ? trim($v) : '');
- if($head) {
- foreach($head as $k => $v) {
- $headers .= strtolower($k) . ': ' . trim($v) . "\n";
- if($fields)
+ $headers .= $k . ': ' . $v . "\n";
+ if ($fields)
$fields .= ' ';
- $fields .= strtolower($k);
+ $fields .= $k;
}
// strip the trailing linefeed
- $headers = rtrim($headers,"\n");
+ $headers = rtrim($headers, "\n");
}
- $sig = base64_encode(Crypto::sign($headers,$prvkey,$alg));
+ $sig = base64_encode(Crypto::sign($headers, $prvkey, $alg));
$ret['headers'] = $fields;
$ret['signature'] = $sig;
@@ -513,26 +606,26 @@ class HTTPSig {
static function parse_sigheader($header) {
- $ret = [];
+ $ret = [];
$matches = [];
// if the header is encrypted, decrypt with (default) site private key and continue
- if(preg_match('/iv="(.*?)"/ism',$header,$matches))
+ if (preg_match('/iv="(.*?)"/ism', $header, $matches))
$header = self::decrypt_sigheader($header);
- if(preg_match('/keyId="(.*?)"/ism',$header,$matches))
+ if (preg_match('/keyId="(.*?)"/ism', $header, $matches))
$ret['keyId'] = $matches[1];
- if(preg_match('/algorithm="(.*?)"/ism',$header,$matches))
+ if (preg_match('/algorithm="(.*?)"/ism', $header, $matches))
$ret['algorithm'] = $matches[1];
- if(preg_match('/headers="(.*?)"/ism',$header,$matches))
+ if (preg_match('/headers="(.*?)"/ism', $header, $matches))
$ret['headers'] = explode(' ', $matches[1]);
- if(preg_match('/signature="(.*?)"/ism',$header,$matches))
- $ret['signature'] = base64_decode(preg_replace('/\s+/','',$matches[1]));
+ if (preg_match('/signature="(.*?)"/ism', $header, $matches))
+ $ret['signature'] = base64_decode(preg_replace('/\s+/', '', $matches[1]));
- if(($ret['signature']) && ($ret['algorithm']) && (! $ret['headers']))
- $ret['headers'] = [ 'date' ];
+ if (($ret['signature']) && ($ret['algorithm']) && (!$ret['headers']))
+ $ret['headers'] = ['date'];
- return $ret;
+ return $ret;
}
@@ -552,23 +645,23 @@ class HTTPSig {
$iv = $key = $alg = $data = null;
- if(! $prvkey) {
+ if (!$prvkey) {
$prvkey = get_config('system', 'prvkey');
}
$matches = [];
- if(preg_match('/iv="(.*?)"/ism',$header,$matches))
+ if (preg_match('/iv="(.*?)"/ism', $header, $matches))
$iv = $matches[1];
- if(preg_match('/key="(.*?)"/ism',$header,$matches))
+ if (preg_match('/key="(.*?)"/ism', $header, $matches))
$key = $matches[1];
- if(preg_match('/alg="(.*?)"/ism',$header,$matches))
+ if (preg_match('/alg="(.*?)"/ism', $header, $matches))
$alg = $matches[1];
- if(preg_match('/data="(.*?)"/ism',$header,$matches))
+ if (preg_match('/data="(.*?)"/ism', $header, $matches))
$data = $matches[1];
- if($iv && $key && $alg && $data) {
- return Crypto::unencapsulate([ 'encrypted' => true, 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey);
+ if ($iv && $key && $alg && $data) {
+ return Crypto::unencapsulate(['encrypted' => true, 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data], $prvkey);
}
return '';
diff --git a/Zotlabs/Web/HttpMeta.php b/Zotlabs/Web/HttpMeta.php
index ceaa82162..7cf93dda9 100644
--- a/Zotlabs/Web/HttpMeta.php
+++ b/Zotlabs/Web/HttpMeta.php
@@ -6,71 +6,108 @@ namespace Zotlabs\Web;
class HttpMeta {
private $vars = null;
- private $og = null;
+ private $og = null;
function __construct() {
- $this->vars = array();
- $this->og = array();
+ $this->vars = [];
+ $this->og = [];
+ $this->ogproperties = [];
}
- function set($property,$value) {
- if(strpos($property,'og:') === 0)
- $this->og[$property] = $value;
- else
+ //Set Meta Value
+ // Mode:
+ // 0 = Default - set if no value currently exists
+ // 1 = Overwrite - replace existing value(s)
+ // 2 = Multi - append to the array of values
+ function set($property,$value,$mode=0) {
+ $ogallowsmulti = ['image','audio','video'];
+ if (strpos($property,'og:') === 0) {
+ $count = 0;
+ foreach ($this->og as $ogk => $ogdata) {
+ if (strpos($ogdata['property'],$property) === 0) {
+ if ($mode == 1) {
+ unset($this->og[$ogk]);
+ unset($this->ogproperties[$property]);
+ }
+ elseif ($mode == 0) {
+ return;
+ }
+ elseif ($value == $ogdata['value']) {
+ return;
+ }
+ else {
+ $count++;
+ }
+ }
+ }
+
+ if ($value !== null) {
+ //mode = 1 with value === null will delete the property entirely.
+ $components = explode(':',$property);
+ $ogp=$components[1];
+
+ if (!$count || in_array($ogp,$ogallowsmulti)) {
+ $this->og[]=['property'=>$property,'value'=>$value];
+ $this->ogproperties[$property] = $property;
+ }
+ }
+ } else {
$this->vars[$property] = $value;
+ }
}
function check_required() {
- if(
- ($this->og)
- && array_key_exists('og:title',$this->og)
- && array_key_exists('og:type', $this->og)
- && array_key_exists('og:image',$this->og)
- && array_key_exists('og:url', $this->og)
- )
+ if (
+ in_array('og:title',$this->ogproperties)
+ && in_array('og:type', $this->ogproperties)
+ && (in_array('og:image',$this->ogproperties)
+ || in_array('og:image:url',$this->ogproperties))
+ && (array_key_exists('og:url', $this->ogproperties)
+ || array_key_exists('og:url:secure_url', $this->ogproperties))
+ && array_key_exists('og:description', $this->ogproperties)
+ ) {
return true;
+ }
return false;
}
function get_field($field) {
- if(strpos($field,'og:') === 0)
- $arr = $this->og;
- else
+ if (strpos($field,'og:') === 0) {
+ foreach ($this->og as $ogdata) {
+ if (strpos($ogdata['property'],$field) === 0) {
+ $arr[$field][] = $ogdata['value'];
+ }
+ }
+ }
+ else {
$arr = $this->vars;
+ }
- if($arr && array_key_exists($field,$arr) && $arr[$field])
+ if (isset($arr) && is_array($arr) && array_key_exists($field,$arr) && $arr[$field]) {
return $arr[$field];
+ }
return false;
}
function get() {
+ // use 'name' for most meta fields, and 'property' for opengraph properties
$o = '';
- if($this->vars) {
- foreach($this->vars as $k => $v) {
- $o .= '<meta property="' . $k . '" content="' . urlencode($v) . '" />' . "\r\n" ;
+ if ($this->vars) {
+ foreach ($this->vars as $k => $v) {
+ $o .= '<meta name="' . htmlspecialchars($k,ENT_COMPAT,'UTF-8',false) . '" content="' . htmlspecialchars($v,ENT_COMPAT,'UTF-8',false) . '" />' . "\r\n" ;
}
}
- if($this->check_required()) {
- $arrayproperties = [ 'og:image' ];
- foreach($this->og as $k => $v) {
- if (in_array($k,$arrayproperties)) {
- if (is_array($v)) {
- foreach ($v as $v2) {
- $o .= '<meta property="' . $k . '" content="' . $v2 . '" />' . "\r\n" ;
- }
- } else {
- $o .= '<meta property="' . $k . '" content="' . $v . '" />' . "\r\n" ;
- }
- } else {
- $o .= '<meta property="' . $k . '" content="' . $v . '" />' . "\r\n" ;
- }
+ if ($this->check_required()) {
+ foreach ($this->og as $ogdata) {
+ $o .= '<meta property="' . htmlspecialchars($ogdata['property'],ENT_COMPAT,'UTF-8',false) . '" content="' . htmlspecialchars($ogdata['value'],ENT_COMPAT,'UTF-8',false) . '" />' . "\r\n" ;
}
}
- if($o)
+ if ($o) {
return "\r\n" . $o;
+ }
return $o;
}
diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php
index 6f92a0319..443a02d20 100644
--- a/Zotlabs/Web/Session.php
+++ b/Zotlabs/Web/Session.php
@@ -25,7 +25,7 @@ class Session {
ini_set('session.cookie_httponly', 1);
$this->custom_handler = boolval(get_config('system', 'session_custom', false));
-
+
/*
* Set our session storage functions.
*/
@@ -67,23 +67,24 @@ class Session {
}
- // Force cookies to be secure (https only) if this site is SSL enabled.
+ // Force cookies to be secure (https only) if this site is SSL enabled.
// Must be done before session_start().
$arr = session_get_cookie_params();
-
+
// Note when setting cookies: set the domain to false which creates a single domain
// cookie. If you use a hostname it will create a .domain.com wildcard which will
- // have some nasty side effects if you have any other subdomains running hubzilla.
-
- session_set_cookie_params(
- ((isset($arr['lifetime'])) ? $arr['lifetime'] : 0),
- ((isset($arr['path'])) ? $arr['path'] : '/'),
- (($arr['domain']) ? $arr['domain'] : false),
- ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
- ((isset($arr['httponly'])) ? $arr['httponly'] : true)
- );
+ // have some nasty side effects if you have any other subdomains running hubzilla.
+
+ session_set_cookie_params([
+ 'lifetime' => ((isset($arr['lifetime'])) ? $arr['lifetime'] : 0),
+ 'path' => ((isset($arr['path'])) ? $arr['path'] : '/'),
+ 'domain' => (($arr['domain']) ? $arr['domain'] : false),
+ 'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
+ 'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
+ 'samesite' => 'None'
+ ]);
register_shutdown_function('session_write_close');
@@ -127,13 +128,36 @@ class Session {
$this->handler->read(session_id());
}
}
- else
+ else
logger('no session handler');
if (x($_COOKIE, 'jsdisabled')) {
- setcookie('jsdisabled', $_COOKIE['jsdisabled'], $newxtime, '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
+ setcookie(
+ 'jsdisabled',
+ $_COOKIE['jsdisabled'],
+ [
+ 'expires' => $newxtime,
+ 'path' => '/',
+ 'domain' => false,
+ 'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
+ 'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
+ 'samesite' => 'None'
+ ]
+ );
}
- setcookie(session_name(),session_id(),$newxtime, '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
+
+ setcookie(
+ session_name(),
+ session_id(),
+ [
+ 'expires' => $newxtime,
+ 'path' => '/',
+ 'domain' => false,
+ 'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
+ 'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
+ 'samesite' => 'None'
+ ]
+ );
$arr = array('expire' => $xtime);
call_hooks('new_cookie', $arr);
@@ -148,8 +172,21 @@ class Session {
$xtime = (($_SESSION['remember_me']) ? (60 * 60 * 24 * 365) : 0 );
- if($xtime)
- setcookie(session_name(),session_id(),(time() + $xtime), '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
+ if($xtime) {
+ setcookie(
+ session_name(),
+ session_id(),
+ [
+ 'expires' => time() + $xtime,
+ 'path' => '/',
+ 'domain' => false,
+ 'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
+ 'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
+ 'samesite' => 'None'
+ ]
+ );
+ }
+
$arr = array('expire' => $xtime);
call_hooks('extend_cookie', $arr);
@@ -169,8 +206,8 @@ class Session {
if($_SESSION['addr'] && $_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) {
logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
- $partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
- $partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
+ $partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
+ $partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
$paranoia = intval(get_pconfig($_SESSION['uid'], 'system', 'paranoia'));
diff --git a/Zotlabs/Web/SessionHandler.php b/Zotlabs/Web/SessionHandler.php
index 4292fdc28..6beb36795 100644
--- a/Zotlabs/Web/SessionHandler.php
+++ b/Zotlabs/Web/SessionHandler.php
@@ -6,7 +6,7 @@ namespace Zotlabs\Web;
class SessionHandler implements \SessionHandlerInterface {
- function open ($s, $n) {
+ function open ($s, $n) : bool {
return true;
}
@@ -15,7 +15,7 @@ class SessionHandler implements \SessionHandlerInterface {
// some which call read explicitly and some that do not. So we call it explicitly
// just after sid regeneration to force a record to exist.
- function read ($id) {
+ function read ($id) : string {
if($id) {
$r = q("SELECT sess_data FROM session WHERE sid= '%s'", dbesc($id));
@@ -36,7 +36,7 @@ class SessionHandler implements \SessionHandlerInterface {
}
- function write ($id, $data) {
+ function write ($id, $data) : bool {
// Pretend everything is hunky-dory, even though it isn't.
// There probably isn't anything we can do about it in any event.
@@ -49,9 +49,9 @@ class SessionHandler implements \SessionHandlerInterface {
// Unless we authenticate somehow, only keep a session for 5 minutes
// The viewer can extend this by performing any web action using the
- // original cookie, but this allows us to cleanup the hundreds or
+ // original cookie, but this allows us to cleanup the hundreds or
// thousands of empty sessions left around from web crawlers which are
- // assigned cookies on each page that they never use.
+ // assigned cookies on each page that they never use.
$expire = time() + 300;
@@ -74,19 +74,19 @@ class SessionHandler implements \SessionHandlerInterface {
return true;
}
-
- function close() {
+
+ function close() : bool {
return true;
}
- function destroy ($id) {
+ function destroy ($id) : bool {
q("DELETE FROM session WHERE sid = '%s'", dbesc($id));
return true;
}
- function gc($expire) {
+ function gc($expire) : int {
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
return true;
}
diff --git a/Zotlabs/Web/WebServer.php b/Zotlabs/Web/WebServer.php
index de0d5a883..70c6eb9b8 100644
--- a/Zotlabs/Web/WebServer.php
+++ b/Zotlabs/Web/WebServer.php
@@ -107,7 +107,8 @@ class WebServer {
$Router->Dispatch();
- $this->set_homebase();
+ // TODO: this is not used for anything atm and messes up comanche templates by adding some javascript
+ //$this->set_homebase();
// now that we've been through the module content, see if the page reported
// a permission problem and if so, a 403 response would seem to be in order.
diff --git a/Zotlabs/Widget/Activity.php b/Zotlabs/Widget/Activity.php
index 04e9fc4b1..34e0f67dc 100644
--- a/Zotlabs/Widget/Activity.php
+++ b/Zotlabs/Widget/Activity.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Activity
+ * * Description: Shows the unseen activity count per contact
+ */
+
namespace Zotlabs\Widget;
class Activity {
@@ -35,7 +40,7 @@ class Activity {
}
}
foreach($contributors as $k => $v) {
- $arr[] = [ 'author_xchan' => $k, 'total' => $v ];
+ $arr[] = [ 'author_xchan' => $k, 'total' => $v ];
}
usort($arr,'total_sort');
xchan_query($arr);
@@ -43,19 +48,19 @@ class Activity {
$x = [ 'entries' => $arr ];
call_hooks('activity_widget',$x);
- $arr = $x['entries'];
+ $arr = $x['entries'];
if($arr) {
$o .= '<div class="widget">';
- $o .= '<h3>' . t('Activity','widget') . '</h3><ul class="nav nav-pills flex-column">';
+ $o .= '<h3>' . t('Activity','widget') . '</h3><ul class="nav rounded-pill flex-column">';
foreach($arr as $rv) {
- $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&xchan=' . urlencode($rv['author_xchan']) . '" ><span class="badge badge-secondary float-right">' . ((intval($rv['total'])) ? intval($rv['total']) : '') . '</span><img src="' . $rv['author']['xchan_photo_s'] . '" class="menu-img-1" /> ' . $rv['author']['xchan_name'] . '</a></li>';
+ $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&xchan=' . urlencode($rv['author_xchan']) . '" ><span class="badge bg-secondary float-end">' . ((intval($rv['total'])) ? intval($rv['total']) : '') . '</span><img src="' . $rv['author']['xchan_photo_s'] . '" class="menu-img-1" /> ' . $rv['author']['xchan_name'] . '</a></li>';
}
$o .= '</ul></div>';
}
return $o;
}
-}
+}
diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php
index b7a69752e..daaf5fb67 100644
--- a/Zotlabs/Widget/Activity_filter.php
+++ b/Zotlabs/Widget/Activity_filter.php
@@ -1,5 +1,12 @@
<?php
+/**
+ * * Name: Activity filters
+ * * Description: Filters for the network stream
+ * * Requires: network
+ */
+
+
namespace Zotlabs\Widget;
use App;
diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php
index d3fe2a30f..e8ee11508 100644
--- a/Zotlabs/Widget/Activity_order.php
+++ b/Zotlabs/Widget/Activity_order.php
@@ -2,6 +2,12 @@
namespace Zotlabs\Widget;
+/**
+ * * Name: Activity order
+ * * Description: Order the network stream by posted date, last commented or by date unthreaded
+ * * Requires: network
+ */
+
class Activity_order {
function widget($arr) {
@@ -22,7 +28,7 @@ class Activity_order {
switch($_GET['order']){
case 'post':
$postord_active = 'active';
- set_pconfig(local_channel(), 'mod_network', 'order', 1);
+ set_pconfig(local_channel(), 'mod_network', 'order', 1);
break;
case 'comment':
$commentord_active = 'active';
diff --git a/Zotlabs/Widget/Admin.php b/Zotlabs/Widget/Admin.php
index f349377a0..0a7a6925f 100644
--- a/Zotlabs/Widget/Admin.php
+++ b/Zotlabs/Widget/Admin.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Admin menu
+ * * Requires: admin
+ */
+
namespace Zotlabs\Widget;
class Admin {
diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php
index 572af0503..e083e576c 100644
--- a/Zotlabs/Widget/Affinity.php
+++ b/Zotlabs/Widget/Affinity.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Affinity Tool
+ * * Description: Filter the network stream by affinity, requires the Affinity Tool App
+ * * Requires: network
+ */
+
namespace Zotlabs\Widget;
use Zotlabs\Lib\Apps;
@@ -13,7 +19,7 @@ class Affinity {
if(! Apps::system_app_installed(local_channel(),'Affinity Tool'))
return;
-
+
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0);
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99);
@@ -54,7 +60,7 @@ class Affinity {
'$refresh' => t('Refresh'),
'$labels' => $label_str,
));
-
+
$arr = array('html' => $x);
call_hooks('main_slider',$arr);
@@ -63,4 +69,4 @@ class Affinity {
}
}
-
+
diff --git a/Zotlabs/Widget/Album.php b/Zotlabs/Widget/Album.php
index f359e6d0f..003f6f49d 100644
--- a/Zotlabs/Widget/Album.php
+++ b/Zotlabs/Widget/Album.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Album
+ * * Description: Displays an album with a title which can be defined via the 'album' and 'title' variable
+ * * Requires: channel, articles, cards, wiki
+ */
+
namespace Zotlabs\Widget;
require_once('include/attach.php');
@@ -99,7 +105,7 @@ class Album {
'$upload_form' => $upload_form,
'$usage' => $usage_message
));
-
+
return $o;
}
}
diff --git a/Zotlabs/Widget/Appcategories.php b/Zotlabs/Widget/Appcategories.php
index aebd144d0..31fb2542e 100644
--- a/Zotlabs/Widget/Appcategories.php
+++ b/Zotlabs/Widget/Appcategories.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: App categories
+ * * Description: Shows a menu with various app categories
+ * * Requires: apps
+ */
+
namespace Zotlabs\Widget;
class Appcategories {
@@ -40,7 +46,7 @@ class Appcategories {
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('categories_widget.tpl'),array(
- '$title' => t('Categories'),
+ '$title' => t('App Categories'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
diff --git a/Zotlabs/Widget/Appcloud.php b/Zotlabs/Widget/Appcloud.php
index 2a4671eee..791d534c2 100644
--- a/Zotlabs/Widget/Appcloud.php
+++ b/Zotlabs/Widget/Appcloud.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: App cloud
+ * * Description: Shows a cloud with various app categories
+ * * Requires: apps
+ */
+
namespace Zotlabs\Widget;
class Appcloud {
diff --git a/Zotlabs/Widget/Appstore.php b/Zotlabs/Widget/Appstore.php
index 6a00ac06a..d8499152a 100644
--- a/Zotlabs/Widget/Appstore.php
+++ b/Zotlabs/Widget/Appstore.php
@@ -1,17 +1,22 @@
<?php
+/**
+ * * Name: App store menu
+ * * Description: Shows a menu with links to installed and available apps
+ * * Requires: apps
+ */
+
namespace Zotlabs\Widget;
class Appstore {
function widget($arr) {
- $store = ((argc() > 1 && argv(1) === 'available') ? 1 : 0);
- return replace_macros(get_markup_template('appstore.tpl'), [
+ return replace_macros(get_markup_template('appstore.tpl'), [
'$title' => t('App Collections'),
'$options' => [
- [ z_root() . '/apps', t('Installed apps'), 1 - $store ],
- [ z_root() . '/apps/available', t('Available Apps'), $store ]
+ [z_root() . '/apps', t('Installed apps'), ((argc() == 1 && argv(0) === 'apps') ? 1 : 0)],
+ [z_root() . '/apps/available', t('Available Apps'), ((argc() > 1 && argv(1) === 'available') ? 1 : 0)]
]
]);
}
diff --git a/Zotlabs/Widget/Archive.php b/Zotlabs/Widget/Archive.php
index 9adaac38f..e712a8236 100644
--- a/Zotlabs/Widget/Archive.php
+++ b/Zotlabs/Widget/Archive.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Archive
+ * * Description: A menu with links to content sorted by years and months
+ * * Requires: channel, articles, cards
+ */
+
namespace Zotlabs\Widget;
diff --git a/Zotlabs/Widget/Bookmarkedchats.php b/Zotlabs/Widget/Bookmarkedchats.php
index d64bbdb4b..5d6d000c1 100644
--- a/Zotlabs/Widget/Bookmarkedchats.php
+++ b/Zotlabs/Widget/Bookmarkedchats.php
@@ -1,14 +1,15 @@
<?php
+/**
+ * * Name: Bookmarked chats
+ * * Description: A menu with bookmarked chats
+ */
+
namespace Zotlabs\Widget;
class Bookmarkedchats {
function widget($arr) {
-
- if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat'))
- return '';
-
$h = get_observer_hash();
if(! $h)
return;
diff --git a/Zotlabs/Widget/Catcloud.php b/Zotlabs/Widget/Catcloud.php
index c53f9bbf6..5740caab7 100644
--- a/Zotlabs/Widget/Catcloud.php
+++ b/Zotlabs/Widget/Catcloud.php
@@ -2,6 +2,13 @@
namespace Zotlabs\Widget;
+/**
+ * * Name: Category cloud
+ * * Description: Display category links in a cloud
+ * * Requires: channel, cards, articles
+ */
+
+
class Catcloud {
function widget($arr) {
@@ -22,7 +29,7 @@ class Catcloud {
return card_catblock(\App::$profile['profile_uid'], $limit, '', \App::$profile['channel_hash']);
case 'articles':
-
+
if(! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_pages'))
return '';
diff --git a/Zotlabs/Widget/Catcloud_wall.php b/Zotlabs/Widget/Catcloud_wall.php
index 3795987cc..4ee30d023 100644
--- a/Zotlabs/Widget/Catcloud_wall.php
+++ b/Zotlabs/Widget/Catcloud_wall.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Category cloud wall
+ * * Description: Display category links in a cloud restricted to wall posts
+ * * Requires: channel
+ */
+
namespace Zotlabs\Widget;
class Catcloud_wall {
diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php
index 94ad469da..0c6996d55 100644
--- a/Zotlabs/Widget/Categories.php
+++ b/Zotlabs/Widget/Categories.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Categories
+ * * Description: Display a menu with links to categories
+ * * Requires: channel, articles, cards, cloud
+ */
+
namespace Zotlabs\Widget;
use App;
diff --git a/Zotlabs/Widget/Cdav.php b/Zotlabs/Widget/Cdav.php
index ce716b455..f84f5cb04 100644
--- a/Zotlabs/Widget/Cdav.php
+++ b/Zotlabs/Widget/Cdav.php
@@ -1,8 +1,12 @@
<?php
-namespace Zotlabs\Widget;
-
+/**
+ * * Name: CalDAV/CardDAV tools
+ * * Description: A widget with various CalDAV and CardDAV tools
+ * * Requires: cdav
+ */
+namespace Zotlabs\Widget;
class Cdav {
@@ -164,7 +168,7 @@ class Cdav {
'uri' => $sabreabook['uri'],
'displayname' => $sabreabook['{DAV:}displayname'],
'id' => $sabreabook['id']
-
+
];
}
diff --git a/Zotlabs/Widget/Chatroom_list.php b/Zotlabs/Widget/Chatroom_list.php
index e2aad0e05..d80e40bf9 100644
--- a/Zotlabs/Widget/Chatroom_list.php
+++ b/Zotlabs/Widget/Chatroom_list.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Chatroom list
+ * * Description: A menu with links to your chatrooms
+ * * Requires: chat, channel, articles, cards, wiki
+ */
+
namespace Zotlabs\Widget;
class Chatroom_list {
diff --git a/Zotlabs/Widget/Chatroom_members.php b/Zotlabs/Widget/Chatroom_members.php
index 8ed77fb3c..0846192ce 100644
--- a/Zotlabs/Widget/Chatroom_members.php
+++ b/Zotlabs/Widget/Chatroom_members.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Chatroom members
+ * * Description: A widget that shows members of a chatroom
+ * * Requires: chat
+ */
+
namespace Zotlabs\Widget;
class Chatroom_members {
diff --git a/Zotlabs/Widget/Clock.php b/Zotlabs/Widget/Clock.php
index b63b5f748..3b9751cc5 100644
--- a/Zotlabs/Widget/Clock.php
+++ b/Zotlabs/Widget/Clock.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Clock
+ * * Description: A simple widget that shows the current time
+ */
+
namespace Zotlabs\Widget;
class Clock {
diff --git a/Zotlabs/Widget/Collections.php b/Zotlabs/Widget/Collections.php
deleted file mode 100644
index bc9c812c6..000000000
--- a/Zotlabs/Widget/Collections.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-require_once('include/group.php');
-
-class Collections {
-
- function widget($args) {
-
- if(argc() < 2)
- return;
-
- $mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation');
- switch($mode) {
- case 'conversation':
- $every = argv(0);
- $each = argv(0);
- $edit = true;
- $current = $_REQUEST['gid'];
- $abook_id = 0;
- $wmode = 0;
- break;
- case 'connections':
- $every = 'connections';
- $each = 'group';
- $edit = true;
- $current = $_REQUEST['gid'];
- $abook_id = 0;
- $wmode = 0;
- case 'groups':
- $every = 'connections';
- $each = argv(0);
- $edit = false;
- $current = intval(argv(1));
- $abook_id = 0;
- $wmode = 1;
- break;
- case 'abook':
- $every = 'connections';
- $each = 'group';
- $edit = false;
- $current = 0;
- $abook_id = \App::$poi['abook_xchan'];
- $wmode = 1;
- break;
- default:
- return '';
- break;
- }
-
- return group_side($every, $each, $edit, $current, $abook_id, $wmode);
- }
-}
diff --git a/Zotlabs/Widget/Common_friends.php b/Zotlabs/Widget/Common_friends.php
index a67b9312c..6024f82f5 100644
--- a/Zotlabs/Widget/Common_friends.php
+++ b/Zotlabs/Widget/Common_friends.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Common friends
+ * * Description: Display common friends to visitors
+ * * Requires: channel, articles, cards, wiki
+ */
+
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
@@ -8,7 +14,7 @@ class Common_friends {
function widget($arr) {
- if((! \App::$profile['profile_uid'])
+ if((! \App::$profile['profile_uid'])
|| (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_contacts'))) {
return '';
}
diff --git a/Zotlabs/Widget/Conversations.php b/Zotlabs/Widget/Conversations.php
deleted file mode 100644
index 267d50fa0..000000000
--- a/Zotlabs/Widget/Conversations.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-class Conversations {
-
- function widget($arr) {
-
- if (! local_channel())
- return;
-
- if(argc() > 1) {
-
- switch(argv(1)) {
- case 'inbox':
- $mailbox = 'inbox';
- $header = t('Received Messages');
- break;
- case 'outbox':
- $mailbox = 'outbox';
- $header = t('Sent Messages');
- break;
- default:
- $mailbox = 'combined';
- $header = t('Conversations');
- break;
- }
-
- require_once('include/message.php');
-
- $o = '';
-
- // private_messages_list() can do other more complicated stuff, for now keep it simple
- $r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']);
-
- if(! $r) {
- info( t('No messages.') . EOL);
- return $o;
- }
-
- $messages = [];
-
- foreach($r as $rr) {
-
- $selected = ((argc() == 3) ? intval(argv(2)) == intval($rr['id']) : $r[0]['id'] == $rr['id']);
-
- $messages[] = [
- 'mailbox' => $mailbox,
- 'id' => $rr['id'],
- 'from_name' => $rr['from']['xchan_name'],
- 'from_url' => chanlink_hash($rr['from_xchan']),
- 'from_photo' => $rr['from']['xchan_photo_s'],
- 'to_name' => $rr['to']['xchan_name'],
- 'to_url' => chanlink_hash($rr['to_xchan']),
- 'to_photo' => $rr['to']['xchan_photo_s'],
- 'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'),
- 'delete' => t('Delete conversation'),
- 'body' => $rr['body'],
- 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], 'c'),
- 'seen' => $rr['seen'],
- 'selected' => ((argv(1) != 'new') ? $selected : '')
- ];
- }
-
- $tpl = get_markup_template('mail_head.tpl');
- $o .= replace_macros($tpl, [
- '$header' => $header,
- '$messages' => $messages
- ]);
-
- }
- return $o;
- }
-
-}
-
diff --git a/Zotlabs/Widget/Cover_photo.php b/Zotlabs/Widget/Cover_photo.php
index 97323ea8c..11d9c4715 100644
--- a/Zotlabs/Widget/Cover_photo.php
+++ b/Zotlabs/Widget/Cover_photo.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Cover photo
+ * * Description: Display a cover photo in the banner region
+ * * Requires: disabled_for_pdledit_gui
+ */
+
namespace Zotlabs\Widget;
class Cover_photo {
diff --git a/Zotlabs/Widget/Design_tools.php b/Zotlabs/Widget/Design_tools.php
index a15c0c98d..0f94577d8 100644
--- a/Zotlabs/Widget/Design_tools.php
+++ b/Zotlabs/Widget/Design_tools.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Design tools
+ * * Description: Links to useful tools for webpages
+ * * Requires: webpages
+ */
+
namespace Zotlabs\Widget;
class Design_tools {
@@ -11,4 +17,4 @@ class Design_tools {
return EMPTY_STR;
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Widget/Dirsort.php b/Zotlabs/Widget/Dirsort.php
index 2fb38b7df..569782bb9 100644
--- a/Zotlabs/Widget/Dirsort.php
+++ b/Zotlabs/Widget/Dirsort.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Dirsort
+ * * Description: Various options to provide different vies of the directory
+ * * Requires: directory
+ */
+
namespace Zotlabs\Widget;
use Zotlabs\Lib\Libzotdir;
diff --git a/Zotlabs/Widget/Dirtags.php b/Zotlabs/Widget/Dirtags.php
index f211d5942..183c2f20f 100644
--- a/Zotlabs/Widget/Dirtags.php
+++ b/Zotlabs/Widget/Dirtags.php
@@ -1,8 +1,12 @@
<?php
-namespace Zotlabs\Widget;
+/**
+ * * Name: Directory tags
+ * * Description: Show directory tags in a cloud
+ * * Requires: directory
+ */
-require_once('include/dir_fns.php');
+namespace Zotlabs\Widget;
class Dirtags {
diff --git a/Zotlabs/Widget/Eventstools.php b/Zotlabs/Widget/Eventstools.php
deleted file mode 100644
index 7efd3f72e..000000000
--- a/Zotlabs/Widget/Eventstools.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-class Eventstools {
-
- function widget($arr) {
-
- if(! local_channel())
- return;
-
- return replace_macros(get_markup_template('events_tools_side.tpl'), array(
- '$title' => t('Events Tools'),
- '$export' => t('Export Calendar'),
- '$import' => t('Import Calendar'),
- '$submit' => t('Submit')
- ));
- }
-}
diff --git a/Zotlabs/Widget/Filer.php b/Zotlabs/Widget/Filer.php
index 5d6f96a87..6c5ac47a9 100644
--- a/Zotlabs/Widget/Filer.php
+++ b/Zotlabs/Widget/Filer.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Saved folders
+ * * Description: A menu containing saved folders
+ * * Requires: network
+ */
+
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
@@ -10,7 +16,6 @@ class Filer {
if(! local_channel())
return '';
-
$selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : '');
$terms = array();
diff --git a/Zotlabs/Widget/Findpeople.php b/Zotlabs/Widget/Findpeople.php
index f450b96ae..45d62bb7f 100644
--- a/Zotlabs/Widget/Findpeople.php
+++ b/Zotlabs/Widget/Findpeople.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Find channels
+ * * Description: A simple form to search for channels in the directory
+ */
+
namespace Zotlabs\Widget;
require_once('include/contact_widgets.php');
diff --git a/Zotlabs/Widget/Follow.php b/Zotlabs/Widget/Follow.php
index c4aecc8e1..2a0abb027 100644
--- a/Zotlabs/Widget/Follow.php
+++ b/Zotlabs/Widget/Follow.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Follow
+ * * Description: A simple form which allows you to enter an address and send a follow request
+ */
+
namespace Zotlabs\Widget;
@@ -24,7 +29,7 @@ class Follow {
else {
$abook_usage_message = '';
}
-
+
return replace_macros(get_markup_template('follow.tpl'),array(
'$connect' => t('Add New Connection'),
'$desc' => t('Enter channel address'),
diff --git a/Zotlabs/Widget/Forums.php b/Zotlabs/Widget/Forums.php
index d3e2f2534..c40556273 100644
--- a/Zotlabs/Widget/Forums.php
+++ b/Zotlabs/Widget/Forums.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Forums
+ * * Description: A list of forum channels with unseen item counts
+ */
+
namespace Zotlabs\Widget;
class Forums {
@@ -21,35 +26,7 @@ class Forums {
$unseen = 1;
$perms_sql = item_permissions_sql(local_channel()) . item_normal();
-
- $xf = false;
-
- $x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = '0'",
- intval(local_channel())
- );
- if($x1) {
- $xc = ids_to_querystr($x1,'xchan',true);
-
- $x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = '1' and xchan in (" . $xc . ") ",
- intval(local_channel())
- );
-
- if($x2) {
- $xf = ids_to_querystr($x2,'xchan',true);
-
- // private forums
- $x3 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'post_wall' and v = '1' and xchan in (" . $xc . ") and not xchan in (" . $xf . ") ",
- intval(local_channel())
- );
- if($x3) {
- $xf = ids_to_querystr(array_merge($x2,$x3),'xchan',true);
- }
- }
- }
-
- $sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
-
-
+ $sql_extra = " and xchan_pubforum = 1 ";
$r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name $limit ",
intval(local_channel())
@@ -64,7 +41,7 @@ class Forums {
// There also should be a way to update this via ajax.
for($x = 0; $x < count($r1); $x ++) {
- $r = q("select sum(item_unseen) as unseen from item
+ $r = q("select sum(item_unseen) as unseen from item
where uid = %d and owner_xchan = '%s' and item_unseen = 1 $perms_sql ",
intval(local_channel()),
dbesc($r1[$x]['xchan_hash'])
@@ -109,12 +86,12 @@ class Forums {
}
}
}
-
+
if($unseen && (! intval($rr['unseen'])))
continue;
- $o .= '<li class="nav-item"><a class="nav-link" href="' . $link . '" ><span class="badge badge-secondary float-right">' . ((intval($rr['unseen'])) ? intval($rr['unseen']) : '') . '</span><img class ="menu-img-1" src="' . $rr['xchan_photo_s'] . '" /> ' . $rr['xchan_name'] . '</a></li>';
+ $o .= '<li class="nav-item"><a class="nav-link" href="' . $link . '" ><span class="badge bg-secondary float-end">' . ((intval($rr['unseen'])) ? intval($rr['unseen']) : '') . '</span><img class ="menu-img-1" src="' . $rr['xchan_photo_s'] . '" /> ' . $rr['xchan_name'] . '</a></li>';
}
$o .= '</ul></div>';
}
diff --git a/Zotlabs/Widget/Fullprofile.php b/Zotlabs/Widget/Fullprofile.php
index d7340ef40..edff88e31 100644
--- a/Zotlabs/Widget/Fullprofile.php
+++ b/Zotlabs/Widget/Fullprofile.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Full profile
+ * * Description: Profile card with extended profile info
+ * * Requires: channel, articles, cards, wiki, cloud, photos
+ */
+
namespace Zotlabs\Widget;
class Fullprofile {
@@ -11,6 +17,6 @@ class Fullprofile {
$block = observer_prohibited();
- return profile_sidebar(\App::$profile, $block);
+ return profile_sidebar(\App::$profile, $block, true, true);
}
}
diff --git a/Zotlabs/Widget/Helpindex.php b/Zotlabs/Widget/Helpindex.php
index 6c8748194..fbcd8c8b2 100644
--- a/Zotlabs/Widget/Helpindex.php
+++ b/Zotlabs/Widget/Helpindex.php
@@ -1,11 +1,18 @@
<?php
+/**
+ * * Name: Help index
+ * * Description: Help pages index
+ */
+
namespace Zotlabs\Widget;
class Helpindex {
function widget($arr) {
+ require_once('include/help.php');
+
$o .= '<div class="widget">';
$level_0 = get_help_content('sitetoc');
diff --git a/Zotlabs/Widget/Hq_controls.php b/Zotlabs/Widget/Hq_controls.php
index 0caa54a1a..7b1fe817d 100644
--- a/Zotlabs/Widget/Hq_controls.php
+++ b/Zotlabs/Widget/Hq_controls.php
@@ -1,25 +1,51 @@
<?php
+/**
+ * * Name: HQ Controls
+ * * Description: Control buttons for the HQ module
+ * * Author: Mario Vavti
+ * * Requires: hq
+ */
+
namespace Zotlabs\Widget;
+use Zotlabs\Lib\Apps;
+
+
class Hq_controls {
- function widget($arr) {
+ function widget($options) {
if (! local_channel())
return;
+ $entries = [
+ 'toggle_editor' => [
+ 'label' => t('Toggle post editor'),
+ 'href' => '#',
+ 'class' => 'btn jot-toggle',
+ 'type' => 'button',
+ 'icon' => 'pencil',
+ 'extra' => 'data-toggle="button"'
+ ]
+ ];
+
+ if(Apps::system_app_installed(local_channel(), 'Notes')) {
+ $entries['toggle_notes'] = [
+ 'label' => t('Toggle personal notes'),
+ 'href' => '#',
+ 'class' => 'btn notes-toggle',
+ 'type' => 'button',
+ 'icon' => 'sticky-note-o',
+ 'extra' => 'data-toggle="button"'
+ ];
+ }
+
return replace_macros(get_markup_template('hq_controls.tpl'),
[
- '$title' => t('HQ Control Panel'),
- '$menu' => [
- 'create' => [
- 'label' => t('Create a new post'),
- 'id' => 'jot-toggle',
- 'href' => '#',
- 'class' => ''
- ]
- ]
+ '$entries' => $entries,
+ '$wrapper_class' => $options['wrapper_class'],
+ '$entry_class' => $options['entry_class']
]
);
}
diff --git a/Zotlabs/Widget/Item.php b/Zotlabs/Widget/Item.php
index 273d5649c..9fd703dfe 100644
--- a/Zotlabs/Widget/Item.php
+++ b/Zotlabs/Widget/Item.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Item
+ * * Description: Display a webpage by title or mid,
+ * * Requires: channel, articles, cards, wiki
+ */
+
namespace Zotlabs\Widget;
require_once('include/security.php');
@@ -35,7 +41,7 @@ class Item {
);
}
else {
- $r = q("select * from item where mid = '%s' and uid = %d and item_type = "
+ $r = q("select * from item where mid = '%s' and uid = %d and item_type = "
. intval(ITEM_TYPE_WEBPAGE) . " $sql_extra limit 1",
dbesc($arr['mid']),
intval($channel_id)
diff --git a/Zotlabs/Widget/Mailmenu.php b/Zotlabs/Widget/Mailmenu.php
deleted file mode 100644
index 512f7d9c0..000000000
--- a/Zotlabs/Widget/Mailmenu.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-class Mailmenu {
-
- function widget($arr) {
-
- if (! local_channel())
- return;
-
- return replace_macros(get_markup_template('message_side.tpl'), array(
- '$title' => t('Private Mail Menu'),
- '$combined' => array(
- 'label' => t('Combined View'),
- 'url' => z_root() . '/mail/combined',
- 'sel' => (argv(1) == 'combined'),
- ),
- '$inbox' => array(
- 'label' => t('Inbox'),
- 'url' => z_root() . '/mail/inbox',
- 'sel' => (argv(1) == 'inbox'),
- ),
- '$outbox' => array(
- 'label' => t('Outbox'),
- 'url' => z_root() . '/mail/outbox',
- 'sel' => (argv(1) == 'outbox'),
- ),
- '$new' => array(
- 'label' => t('New Message'),
- 'url' => z_root() . '/mail/new',
- 'sel'=> (argv(1) == 'new'),
- )
- ));
- }
-}
diff --git a/Zotlabs/Widget/Menu_preview.php b/Zotlabs/Widget/Menu_preview.php
index 51218f6cf..ddeb4d12c 100644
--- a/Zotlabs/Widget/Menu_preview.php
+++ b/Zotlabs/Widget/Menu_preview.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Menu preview
+ * * Description: Shows a preview of the current menu
+ * * Requires: mitem
+ */
+
namespace Zotlabs\Widget;
require_once('include/menu.php');
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
new file mode 100644
index 000000000..d045ae85b
--- /dev/null
+++ b/Zotlabs/Widget/Messages.php
@@ -0,0 +1,251 @@
+<?php
+
+/**
+ * * Name: HQ Messages
+ * * Description: Quick access to messages, direct messages, starred messages (if enabled) and notifications
+ * * Author: Mario Vavti
+ * * Requires: hq
+ */
+
+
+namespace Zotlabs\Widget;
+
+use App;
+use Zotlabs\Lib\IConfig;
+
+class Messages {
+
+ public static function widget($arr) {
+ if (!local_channel())
+ return EMPTY_STR;
+
+ $page = self::get_messages_page([]);
+
+ $_SESSION['messages_loadtime'] = datetime_convert();
+
+ $tpl = get_markup_template('messages_widget.tpl');
+ $o = replace_macros($tpl, [
+ '$entries' => $page['entries'] ?? [],
+ '$offset' => $page['offset'] ?? 0,
+ '$feature_star' => feature_enabled(local_channel(), 'star_posts'),
+ '$strings' => [
+ 'messages_title' => t('Public and restricted messages'),
+ 'direct_messages_title' => t('Direct messages'),
+ 'starred_messages_title' => t('Starred messages'),
+ 'notice_messages_title' => t('Notices'),
+ 'loading' => t('Loading'),
+ 'empty' => t('No messages')
+ ]
+ ]);
+
+ return $o;
+ }
+
+ public static function get_messages_page($options) {
+ if (!local_channel())
+ return;
+
+ if (isset($options['offset']) && $options['offset'] == -1) {
+ return;
+ }
+
+ if (isset($options['type']) && $options['type'] == 'notification') {
+ return self::get_notices_page($options);
+ }
+
+ $channel = App::get_channel();
+ $item_normal = item_normal();
+ $entries = [];
+ $limit = 30;
+ $dummy_order_sql = '';
+
+ $offset = 0;
+ if ($options['offset']) {
+ $offset = intval($options['offset']);
+ }
+
+ $loadtime = (($offset) ? $_SESSION['messages_loadtime'] : datetime_convert());
+
+ switch($options['type']) {
+ case 'direct':
+ $type_sql = ' AND item_private = 2 ';
+ // $dummy_order_sql has no other meaning but to trick
+ // some mysql backends into using the right index.
+ $dummy_order_sql = ', received DESC ';
+ break;
+ case 'starred':
+ $type_sql = ' AND item_starred = 1 ';
+ break;
+ default:
+ $type_sql = ' AND item_private IN (0, 1) ';
+ }
+
+ $items = q("SELECT * FROM item WHERE uid = %d
+ AND created <= '%s'
+ $type_sql
+ AND item_thread_top = 1
+ $item_normal
+ ORDER BY created DESC $dummy_order_sql
+ LIMIT $limit OFFSET $offset",
+ intval(local_channel()),
+ dbescdate($loadtime)
+ );
+
+ xchan_query($items, false);
+
+ $i = 0;
+ $entries = [];
+
+ foreach($items as $item) {
+
+ $info = '';
+ if ($options['type'] == 'direct') {
+ $info .= self::get_dm_recipients($channel, $item);
+ }
+
+ if($item['owner_xchan'] !== $item['author_xchan']) {
+ $info .= t('via') . ' ' . $item['owner']['xchan_name'];
+ }
+
+ $summary = $item['title'];
+ if (!$summary) {
+ $summary = $item['summary'];
+ }
+
+ if (!$summary) {
+ $summary = html2plain(bbcode($item['body'], ['drop_media' => true]), 75, true);
+ if ($summary) {
+ $summary = htmlentities($summary, ENT_QUOTES, 'UTF-8', false);
+ }
+ }
+
+ if (!$summary) {
+ $summary = '...';
+ }
+ else {
+ $summary = substr_words($summary, 68);
+ }
+
+ switch(intval($item['item_private'])) {
+ case 1:
+ $icon = '<i class="fa fa-lock"></i>';
+ break;
+ case 2:
+ $icon = '<i class="fa fa-envelope-o"></i>';
+ break;
+ default:
+ $icon = '';
+ }
+
+ $entries[$i]['author_name'] = $item['author']['xchan_name'];
+ $entries[$i]['author_addr'] = (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']);
+ $entries[$i]['info'] = $info;
+ $entries[$i]['created'] = datetime_convert('UTC', date_default_timezone_get(), $item['created']);
+ $entries[$i]['summary'] = $summary;
+ $entries[$i]['b64mid'] = gen_link_id($item['mid']);
+ $entries[$i]['href'] = z_root() . '/hq/' . gen_link_id($item['mid']);
+ $entries[$i]['icon'] = $icon;
+
+ $i++;
+ }
+
+ $result = [
+ 'offset' => ((count($entries) < $limit) ? -1 : intval($offset + $limit)),
+ 'entries' => $entries
+ ];
+
+ return $result;
+ }
+
+ public static function get_dm_recipients($channel, $item) {
+
+ if($channel['channel_hash'] === $item['owner']['xchan_hash']) {
+ // we are the owner, get the recipients from the item
+ $recips = expand_acl($item['allow_cid']);
+ if (is_array($recips)) {
+ array_unshift($recips, $item['owner']['xchan_hash']);
+ $column = 'xchan_hash';
+ }
+ }
+ else {
+ $recips = IConfig::Get($item, 'activitypub', 'recips');
+ if (isset($recips['to']) && is_array($recips['to'])) {
+ $recips = $recips['to'];
+ array_unshift($recips, $item['owner']['xchan_url']);
+ $column = 'xchan_url';
+ }
+ else {
+ $hookinfo = [
+ 'item' => $item,
+ 'recips' => null,
+ 'column' => ''
+ ];
+
+ call_hooks('direct_message_recipients', $hookinfo);
+
+ $recips = $hookinfo['recips'];
+ $column = $hookinfo['column'];
+ }
+ }
+
+ if(is_array($recips)) {
+ stringify_array_elms($recips, true);
+
+ $query_str = implode(',', $recips);
+ $xchans = dbq("SELECT DISTINCT xchan_name FROM xchan WHERE $column IN ($query_str) AND xchan_deleted = 0");
+ foreach($xchans as $xchan) {
+ $recipients .= $xchan['xchan_name'] . ', ';
+ }
+ }
+
+ return trim($recipients, ', ');
+ }
+
+ public static function get_notices_page($options) {
+
+ if (!local_channel())
+ return;
+
+ $limit = 30;
+
+ $offset = 0;
+ if ($options['offset']) {
+ $offset = intval($options['offset']);
+ }
+
+ $notices = q("SELECT * FROM notify WHERE uid = %d
+ ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ intval(local_channel())
+ );
+
+ $i = 0;
+ $entries = [];
+
+ foreach($notices as $notice) {
+
+ $summary = trim(strip_tags(bbcode($notice['msg'])));
+
+ if(strpos($summary, $notice['xname']) === 0) {
+ $summary = substr($summary, strlen($notice['xname']) + 1);
+ }
+
+ $entries[$i]['author_name'] = $notice['xname'];
+ $entries[$i]['author_addr'] = $notice['url'];
+ $entries[$i]['info'] = '';
+ $entries[$i]['created'] = datetime_convert('UTC', date_default_timezone_get(), $notice['created']);
+ $entries[$i]['summary'] = $summary;
+ $entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : basename($notice['link']));
+ $entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . basename($notice['link']));
+ $entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="fa fa-user-plus"></i>' : '');
+
+ $i++;
+ }
+
+ $result = [
+ 'offset' => ((count($entries) < $limit) ? -1 : intval($offset + $limit)),
+ 'entries' => $entries
+ ];
+
+ return $result;
+ }
+}
diff --git a/Zotlabs/Widget/Newmember.php b/Zotlabs/Widget/Newmember.php
index 224f7a8a2..70a858fb0 100644
--- a/Zotlabs/Widget/Newmember.php
+++ b/Zotlabs/Widget/Newmember.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: New member
+ * * Description: Display useful links for new members to help them get started
+ */
+
namespace Zotlabs\Widget;
class Newmember {
@@ -29,7 +34,7 @@ class Newmember {
$options = [
t('Profile Creation'),
- [
+ [
'profile_photo' => t('Upload profile photo'),
'cover_photo' => t('Upload cover photo'),
'profiles' => t('Edit your profile'),
@@ -84,4 +89,4 @@ class Newmember {
}
-
+
diff --git a/Zotlabs/Widget/Notes.php b/Zotlabs/Widget/Notes.php
index 238008d81..2e8e04e93 100644
--- a/Zotlabs/Widget/Notes.php
+++ b/Zotlabs/Widget/Notes.php
@@ -1,5 +1,13 @@
<?php
+/**
+ * * Name: Notes
+ * * Description: A simple notes widget, requires the Notes App
+ * * Author: Mike Macgirvin
+ * * Author: Mario Vavti
+ * * Maintainer: Mario Vavti
+ */
+
namespace Zotlabs\Widget;
use Zotlabs\Lib\Apps;
@@ -18,10 +26,19 @@ class Notes {
$tpl = get_markup_template('notes.tpl');
$o = replace_macros($tpl, array(
- '$banner' => t('Notes'),
'$text' => $text,
- '$save' => t('Save'),
- '$app' => ((isset($arr['app'])) ? true : false)
+ '$html' => bbcode($text),
+ '$app' => ((isset($arr['app'])) ? true : false),
+ '$hidden' => ((isset($arr['hidden'])) ? true : false),
+ '$strings' => [
+ 'title' => t('Notes'),
+ 'read' => t('Read mode'),
+ 'edit' => t('Edit mode'),
+ 'editing' => t('Editing'),
+ 'saving' => t('Saving'),
+ 'saved' => t('Saved'),
+ 'dots' => '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span>'
+ ]
));
return $o;
diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php
index dd5a6cd46..0e02d5cc1 100644
--- a/Zotlabs/Widget/Notifications.php
+++ b/Zotlabs/Widget/Notifications.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Notifications
+ * * Description: Shows all kind of notifications
+ * * Author: Mario Vavti
+ */
+
namespace Zotlabs\Widget;
class Notifications {
@@ -13,11 +19,11 @@ class Notifications {
'type' => 'network',
'icon' => 'th',
'severity' => 'secondary',
- 'label' => t('New Network Activity'),
- 'title' => t('New Network Activity Notifications'),
+ 'label' => t('Network'),
+ 'title' => t('New network activity notifications'),
'viewall' => [
'url' => 'network',
- 'label' => t('View your network activity')
+ 'label' => t('Network stream')
],
'markall' => [
'label' => t('Mark all notifications read')
@@ -33,11 +39,11 @@ class Notifications {
'type' => 'home',
'icon' => 'home',
'severity' => 'danger',
- 'label' => t('New Home Activity'),
- 'title' => t('New Home Activity Notifications'),
+ 'label' => t('Home'),
+ 'title' => t('New home activity notifications'),
'viewall' => [
'url' => 'channel/' . $channel['channel_address'],
- 'label' => t('View your home activity')
+ 'label' => t('Home stream')
],
'markall' => [
'label' => t('Mark all notifications seen')
@@ -52,11 +58,11 @@ class Notifications {
'type' => 'dm',
'icon' => 'envelope',
'severity' => 'danger',
- 'label' => t('New Direct Messages'),
- 'title' => t('New Direct Messages Notifications'),
+ 'label' => t('Direct Messages'),
+ 'title' => t('New direct messages notifications'),
'viewall' => [
'url' => 'network/?dm=1',
- 'label' => t('View your direct messages')
+ 'label' => t('Direct messages stream')
],
'markall' => [
'label' => t('Mark all notifications read')
@@ -68,26 +74,11 @@ class Notifications {
];
$notifications[] = [
- 'type' => 'mail',
- 'icon' => 'envelope',
- 'severity' => 'danger',
- 'label' => t('New Mails'),
- 'title' => t('New Mails Notifications'),
- 'viewall' => [
- 'url' => 'mail/combined',
- 'label' => t('View your private mails')
- ],
- 'markall' => [
- 'label' => t('Mark all messages seen')
- ]
- ];
-
- $notifications[] = [
'type' => 'all_events',
'icon' => 'calendar',
'severity' => 'secondary',
- 'label' => t('New Events'),
- 'title' => t('New Events Notifications'),
+ 'label' => t('Events'),
+ 'title' => t('New events notifications'),
'viewall' => [
'url' => 'cdav/calendar',
'label' => t('View events')
@@ -102,7 +93,7 @@ class Notifications {
'icon' => 'users',
'severity' => 'danger',
'label' => t('New Connections'),
- 'title' => t('New Connections Notifications'),
+ 'title' => t('New connections notifications'),
'viewall' => [
'url' => 'connections',
'label' => t('View all connections')
@@ -113,8 +104,8 @@ class Notifications {
'type' => 'files',
'icon' => 'folder',
'severity' => 'danger',
- 'label' => t('New Files'),
- 'title' => t('New Files Notifications'),
+ 'label' => t('Files'),
+ 'title' => t('New files notifications'),
];
$notifications[] = [
@@ -149,8 +140,8 @@ class Notifications {
'type' => 'register',
'icon' => 'user-o',
'severity' => 'danger',
- 'label' => t('New Registrations'),
- 'title' => t('New Registrations Notifications'),
+ 'label' => t('Registrations'),
+ 'title' => t('New registrations notifications'),
];
}
@@ -160,10 +151,10 @@ class Notifications {
'icon' => 'globe',
'severity' => 'secondary',
'label' => t('Public Stream'),
- 'title' => t('Public Stream Notifications'),
+ 'title' => t('New public stream notifications'),
'viewall' => [
'url' => 'pubstream',
- 'label' => t('View the public stream')
+ 'label' => t('Public stream')
],
'markall' => [
'label' => t('Mark all notifications seen')
@@ -176,15 +167,13 @@ class Notifications {
}
$o = replace_macros(get_markup_template('notifications_widget.tpl'), [
- '$module' => \App::$module,
'$notifications' => $notifications,
'$no_notifications' => t('Sorry, you have got no notifications at the moment'),
'$loading' => t('Loading'),
- '$startpage' => ($channel ? $channel['channel_startpage'] : '')
]);
return $o;
}
}
-
+
diff --git a/Zotlabs/Widget/Permcats.php b/Zotlabs/Widget/Permcats.php
new file mode 100644
index 000000000..9226b3c71
--- /dev/null
+++ b/Zotlabs/Widget/Permcats.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * * Name: Contact roles
+ * * Description: Display a menu with all defined contact roles and contacts which are assigned to the selected role
+ * * Author: Mario Vavti
+ * * Requires: permcats
+ */
+
+namespace Zotlabs\Widget;
+
+use Zotlabs\Lib\Permcat;
+use Zotlabs\Access\PermissionLimits;
+
+class Permcats {
+
+ function widget($arr) {
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+
+ if (!$pcatlist) {
+ return;
+ }
+
+ $roles = [];
+ $active_role = '';
+
+ foreach($pcatlist as $pc) {
+ if (!$active_role) {
+ $active_role = ((argc() > 1 && $pc['name'] === hex2bin(argv(1))) ? $pc['name'] : '');
+ }
+ $roles[] = [
+ 'name' => $pc['localname'],
+ 'url' => z_root() . '/permcats/' . bin2hex($pc['name']),
+ 'active' => (argc() > 1 && $pc['name'] === hex2bin(argv(1)))
+ ];
+ }
+
+ if($active_role) {
+
+ $roles[] = [
+ 'name' => '<i class="fa fa-plus"></i>&nbsp;' . t('Add new role'),
+ 'url' => z_root() . '/permcats',
+ 'active' => ''
+ ];
+
+/* get role members based on permissions
+ $test = $pcatlist[$active]['perms'];
+
+ $role_sql = '';
+ $count = 0;
+ foreach ($test as $t) {
+ $checkinherited = PermissionLimits::Get(local_channel(),$t['name']);
+
+ if($checkinherited & PERMS_SPECIFIC) {
+ $role_sql .= "( abconfig.k = '" . dbesc($t['name']) . "' AND abconfig.v = '" . intval($t['value']) . "' ) OR ";
+ $count++;
+ }
+ }
+
+ $role_sql = rtrim($role_sql, ' OR ');
+
+ $r = q("SELECT abconfig.xchan, xchan.xchan_name, abook.abook_id FROM abconfig LEFT JOIN xchan on abconfig.xchan = xchan.xchan_hash LEFT JOIN abook ON abconfig.xchan = abook.abook_xchan WHERE xchan.xchan_deleted = 0 and abconfig.chan = %d AND abconfig.cat = 'my_perms' AND ( $role_sql ) GROUP BY abconfig.xchan HAVING count(abconfig.xchan) = %d ORDER BY xchan.xchan_name",
+ intval(local_channel()),
+ intval($count)
+ );
+*/
+
+ // get role members based on abook_role
+
+ $r = q("SELECT abook.abook_id, abook.abook_role, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM abook
+ LEFT JOIN xchan on abook.abook_xchan = xchan.xchan_hash
+ WHERE abook.abook_channel = %d AND abook.abook_role = '%s' AND abook_self = 0 AND xchan_deleted = 0
+ ORDER BY xchan.xchan_name",
+ intval(local_channel()),
+ dbesc($active_role)
+ );
+
+ $members = [];
+
+ foreach ($r as $rr) {
+ $members[] = [
+ 'name' => $rr['xchan_name'],
+ 'addr' => (($rr['xchan_addr']) ? $rr['xchan_addr'] : $rr['xchan_url']),
+ 'url' => z_root() . '/connections#' . $rr['abook_id'],
+ 'photo' => $rr['xchan_photo_s']
+ ];
+ }
+ }
+
+ $tpl = get_markup_template("permcats_widget.tpl");
+ $o .= replace_macros($tpl, [
+ '$roles_label' => t('Contact roles'),
+ '$members_label' => t('Role members'),
+ '$roles' => $roles,
+ '$members' => $members
+
+ ]);
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Widget/Photo.php b/Zotlabs/Widget/Photo.php
index 10031f028..5ad6c604c 100644
--- a/Zotlabs/Widget/Photo.php
+++ b/Zotlabs/Widget/Photo.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Photo
+ * * Description: Displays a single photo
+ */
+
+
namespace Zotlabs\Widget;
diff --git a/Zotlabs/Widget/Photo_albums.php b/Zotlabs/Widget/Photo_albums.php
index 6df8ddf3c..2ce916048 100644
--- a/Zotlabs/Widget/Photo_albums.php
+++ b/Zotlabs/Widget/Photo_albums.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Photo albums
+ * * Description: Displays a menu with links to existing photo albums
+ * * Requires: photos
+ */
+
namespace Zotlabs\Widget;
require_once('include/photos.php');
diff --git a/Zotlabs/Widget/Photo_rand.php b/Zotlabs/Widget/Photo_rand.php
index af80a3b9f..cfe026b19 100644
--- a/Zotlabs/Widget/Photo_rand.php
+++ b/Zotlabs/Widget/Photo_rand.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Random photo
+ * * Description: Display a random photo
+ */
+
namespace Zotlabs\Widget;
require_once('include/photos.php');
@@ -40,15 +45,15 @@ class Photo_rand {
if(strpos($url, 'http') !== 0)
return '';
-
+
if(array_key_exists('style', $arr) && isset($arr['style']))
$style = $arr['style'];
-
+
// ensure they can't sneak in an eval(js) function
if(strpos($style,'(') !== false)
return '';
-
+
$url = zid($url);
$o = '<div class="widget">';
diff --git a/Zotlabs/Widget/Pinned.php b/Zotlabs/Widget/Pinned.php
index cad139a91..83036e98c 100644
--- a/Zotlabs/Widget/Pinned.php
+++ b/Zotlabs/Widget/Pinned.php
@@ -1,11 +1,14 @@
<?php
namespace Zotlabs\Widget;
-/*
- * Show pinned content
- *
+/**
+ * * Name: Pinned items
+ * * Description: Display pinned items
+ * * Author: Max Kostikov
+ * * Requires: disabled_for_pdledit_gui
*/
+
class Pinned {
private $allowed_types = 0;
@@ -40,15 +43,15 @@ class Pinned {
$observer = \App::get_observer();
foreach($items as $item) {
-
- $midb64 = 'b64.' . base64url_encode($item['mid']);
-
+
+ $midb64 = gen_link_id($item['mid']);
+
if(isset($observer['xchan_hash']) && in_array($observer['xchan_hash'], get_pconfig($item['uid'], 'pinned_hide', $midb64, [])))
continue;
-
+
$author = channelx_by_hash($item['author_xchan']);
$owner = channelx_by_hash($item['owner_xchan']);
-
+
$profile_avatar = $author['xchan_photo_m'];
$profile_link = chanlink_hash($item['author_xchan']);
$profile_name = $author['xchan_name'];
@@ -71,7 +74,7 @@ class Pinned {
$isevent = true;
}
}
-
+
$consensus = (intval($item['item_consensus']) ? true : false);
if($consensus) {
$conv_responses['agree'] = [ 'title' => t('Agree','title') ];
@@ -87,7 +90,7 @@ class Pinned {
$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
$forged = ((! intval($item['item_verified']) && $item['sig']) ? t('Message signature incorrect') : '');
-
+
$shareable = ((local_channel() && \App::$profile_uid == local_channel() && $item['item_private'] != 1) ? true : false);
if ($shareable) {
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
@@ -102,9 +105,9 @@ class Pinned {
$is_new = boolval(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0);
$body = prepare_body($item,true);
-
+
$str = [
- 'item_type' => intval($item['item_type']),
+ 'item_type' => intval($item['item_type']),
'body' => $body['html'],
'tags' => $body['tags'],
'categories' => $body['categories'],
@@ -115,7 +118,7 @@ class Pinned {
'id' => $item['id'],
'mids' => json_encode([ $midb64 ]),
'isevent' => $isevent,
- 'attend' => $attend,
+ 'attend' => $attend,
'consensus' => $consensus,
'conlabels' => ($canvote ? $conlabels : []),
'canvote' => $canvote,
@@ -158,55 +161,55 @@ class Pinned {
'modal_dismiss' => t('Close'),
'responses' => $conv_responses
];
-
- $tpl = get_markup_template('pinned_item.tpl');
+
+ $tpl = get_markup_template('pinned_item.tpl');
$ret['html'] .= replace_macros($tpl, $str);
}
return $ret;
}
-
+
/*
* @brief List pinned items depend on type
*
* @param $types
* @return array of pinned items
*
- */
+ */
private function list($types) {
if(empty($types) || (! is_array($types)))
return [];
-
+
$item_types = array_intersect($this->allowed_types, $types);
if(empty($item_types))
return [];
-
+
$mids_list = [];
-
+
foreach($item_types as $type) {
-
+
$mids = get_pconfig($this->uid, 'pinned', $type, []);
foreach($mids as $mid) {
- if(! empty($mid) && strpos($mid,'b64.') === 0)
- $mids_list[] = @base64url_decode(substr($mid,4));
+ if(!empty($mid))
+ $mids_list[] = unpack_link_id($mid);
}
}
if(empty($mids_list))
return [];
-
+
$r = q("SELECT * FROM item WHERE mid IN ( '%s' ) AND uid = %d AND id = parent AND item_private = 0 ORDER BY created DESC",
dbesc(implode(",", $mids_list)),
intval($this->uid)
);
if($r)
return $r;
-
+
return [];
}
-
+
/*
* @brief List activities on item
*
@@ -214,7 +217,7 @@ class Pinned {
* @param array $conv_responses
* @return array
*
- */
+ */
private function activity($item, &$conv_responses) {
foreach(array_keys($conv_responses) as $verb) {
@@ -256,23 +259,23 @@ class Pinned {
unset($conv_responses[$verb]);
continue;
}
-
+
$conv_responses[$verb]['count'] = count($r);
$conv_responses[$verb]['button'] = get_response_button_text($verb, $conv_responses[$verb]['count']);
-
+
foreach($r as $rr) {
-
+
$author = q("SELECT * FROM xchan WHERE xchan_hash = '%s' LIMIT 1",
dbesc($rr['author_xchan'])
);
$name = (($author && $author[0]['xchan_name']) ? $author[0]['xchan_name'] : t('Unknown'));
$conv_responses[$verb]['list'][] = (($rr['author_xchan'] && $author && $author[0]['xchan_photo_s']) ?
- '<a class="dropdown-item" href="' . chanlink_hash($rr['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($author[0]['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . '</a>' :
+ '<a class="dropdown-item" href="' . chanlink_hash($rr['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($author[0]['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . '</a>' :
'<a class="dropdown-item" href="#" class="disabled">' . $name . '</a>'
);
}
}
-
+
$conv_responses['count'] = count($conv_responses);
}
}
diff --git a/Zotlabs/Widget/Portfolio.php b/Zotlabs/Widget/Portfolio.php
index 0cd043246..a06f56e30 100644
--- a/Zotlabs/Widget/Portfolio.php
+++ b/Zotlabs/Widget/Portfolio.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Portfolio
+ * * Description: Display a photo album in a portfolio style
+ * * Requires: channel, articles, cards, wiki
+ */
+
namespace Zotlabs\Widget;
require_once('include/attach.php');
@@ -8,11 +14,9 @@ class Portfolio {
function widget($args) {
-
$owner_uid = \App::$profile_uid;
$sql_extra = permissions_sql($owner_uid);
-
if(! perm_is_allowed($owner_uid,get_observer_hash(),'view_storage'))
return '';
@@ -112,7 +116,7 @@ class Portfolio {
'$upload_form' => $upload_form,
'$usage' => $usage_message
));
-
+
return $o;
}
}
diff --git a/Zotlabs/Widget/Privacygroups.php b/Zotlabs/Widget/Privacygroups.php
new file mode 100644
index 000000000..62f343ea6
--- /dev/null
+++ b/Zotlabs/Widget/Privacygroups.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * * Name: Privacy Groups
+ * * Description: Display a menu with links to existing privacy groups
+ * * Requires: group
+ */
+
+
+namespace Zotlabs\Widget;
+
+use Zotlabs\Lib\AccessList;
+
+class Privacygroups {
+
+ function widget($arr) {
+
+ $o = '';
+
+ $groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ intval(local_channel())
+ );
+
+ if (!$groups) {
+ return $o;
+ }
+
+ $menu_items = [];
+ $z_root = z_root();
+ $active = argv(1) ?? '';
+
+ foreach($groups as $group) {
+ $menu_items[] = [
+ 'href' => $z_root . '/group/' . $group['id'],
+ 'label' => $group['gname'],
+ 'title' => '',
+ 'active' => ($active === $group['id']),
+ 'count' => count(AccessList::members(local_channel(), $group['id']))
+ ];
+ }
+
+ if ($active) {
+ $menu_items[] = [
+ 'href' => $z_root . '/group',
+ 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new group'),
+ 'title' => '',
+ 'active' => '',
+ 'count' => ''
+ ];
+ }
+
+ $tpl = get_markup_template("widget_menu_count.tpl");
+ $o .= replace_macros($tpl, [
+ '$title' => t('Privacy groups'),
+ '$menu_items' => $menu_items,
+
+ ]);
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Widget/Profile.php b/Zotlabs/Widget/Profile.php
index bffd910b6..a0bb1a66a 100644
--- a/Zotlabs/Widget/Profile.php
+++ b/Zotlabs/Widget/Profile.php
@@ -1,13 +1,24 @@
<?php
+/**
+ * * Name: Profile
+ * * Description: Your profile card
+ * * Requires: channel, articles, cards, wiki, cloud, photos
+ */
+
+
namespace Zotlabs\Widget;
+use App;
class Profile {
-
function widget($args) {
+ if(!App::$profile['profile_uid']) {
+ return;
+ }
+
$block = observer_prohibited();
- return profile_sidebar(\App::$profile, $block, true);
- }
-} \ No newline at end of file
+ return profile_sidebar(App::$profile, $block, true, false);
+ }
+}
diff --git a/Zotlabs/Widget/Pubsites.php b/Zotlabs/Widget/Pubsites.php
deleted file mode 100644
index 958ba68c2..000000000
--- a/Zotlabs/Widget/Pubsites.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-class Pubsites {
-
- // used by site ratings pages to provide a return link
-
- function widget($arr) {
- if(\App::$poi)
- return;
- return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>';
- }
-}
-
-
diff --git a/Zotlabs/Widget/Pubtagcloud.php b/Zotlabs/Widget/Pubtagcloud.php
index 826e3e6ae..db7ea02e7 100644
--- a/Zotlabs/Widget/Pubtagcloud.php
+++ b/Zotlabs/Widget/Pubtagcloud.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Public stream tags
+ * * Description: Display public stream tags in a cloud
+ */
+
namespace Zotlabs\Widget;
class Pubtagcloud {
diff --git a/Zotlabs/Widget/Random_block.php b/Zotlabs/Widget/Random_block.php
index 465a51f97..9052bea03 100644
--- a/Zotlabs/Widget/Random_block.php
+++ b/Zotlabs/Widget/Random_block.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Random block
+ * * Description: Display a random block item
+ */
+
namespace Zotlabs\Widget;
class Random_block {
diff --git a/Zotlabs/Widget/Rating.php b/Zotlabs/Widget/Rating.php
index 5e09f457b..20c27ff1c 100644
--- a/Zotlabs/Widget/Rating.php
+++ b/Zotlabs/Widget/Rating.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Rating
+ * * Description: Deprecated rating tool
+ * * Requires: disabled_for_pdledit_gui
+ */
+
namespace Zotlabs\Widget;
class Rating {
diff --git a/Zotlabs/Widget/Savedsearch.php b/Zotlabs/Widget/Savedsearch.php
index 378c27139..660fd6d81 100644
--- a/Zotlabs/Widget/Savedsearch.php
+++ b/Zotlabs/Widget/Savedsearch.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Saved searches
+ * * Description: A search form which also displays saved searches if the feature is enabled
+ * * Requires: network
+ */
+
namespace Zotlabs\Widget;
class Savedsearch {
diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php
index 25b80a4b4..ef269d84b 100644
--- a/Zotlabs/Widget/Settings_menu.php
+++ b/Zotlabs/Widget/Settings_menu.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Settings menu
+ * * Description: Display the channel settings menu
+ */
+
namespace Zotlabs\Widget;
class Settings_menu {
@@ -40,6 +45,11 @@ class Settings_menu {
'selected' => ((argv(1) === 'channel') ? 'active' : ''),
),
+ array(
+ 'label' => t('Privacy settings'),
+ 'url' => z_root().'/settings/privacy',
+ 'selected' => ((argv(1) === 'privacy') ? 'active' : '')
+ )
);
$tabs[] = array(
diff --git a/Zotlabs/Widget/Shortprofile.php b/Zotlabs/Widget/Shortprofile.php
deleted file mode 100644
index 9c2a46e75..000000000
--- a/Zotlabs/Widget/Shortprofile.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-namespace Zotlabs\Widget;
-
-class Shortprofile {
-
- function widget($arr) {
-
- if(! \App::$profile['profile_uid'])
- return;
-
- $block = observer_prohibited();
-
- return profile_sidebar(\App::$profile, $block, true, true);
- }
-
-}
-
diff --git a/Zotlabs/Widget/Sitesearch.php b/Zotlabs/Widget/Sitesearch.php
index b3a25d76a..a5f1a5935 100644
--- a/Zotlabs/Widget/Sitesearch.php
+++ b/Zotlabs/Widget/Sitesearch.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Search
+ * * Description: A search form
+ * * Requires: search, network, channel
+ */
+
namespace Zotlabs\Widget;
diff --git a/Zotlabs/Widget/Suggestedchats.php b/Zotlabs/Widget/Suggestedchats.php
index 7df42944d..75df0c9e6 100644
--- a/Zotlabs/Widget/Suggestedchats.php
+++ b/Zotlabs/Widget/Suggestedchats.php
@@ -1,14 +1,18 @@
<?php
+/**
+ * * Name: Suggested chats
+ * * Description: A menu with chatroom suggestions
+ * * Requires: disabled_due_to_reasons
+ */
+
+
namespace Zotlabs\Widget;
class Suggestedchats {
function widget($arr) {
- if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat'))
- return '';
-
// There are reports that this tool does not ever remove chatrooms on dead sites,
// and also will happily link to private chats which you cannot enter.
// For those reasons, it will be disabled until somebody decides it's worth
diff --git a/Zotlabs/Widget/Suggestions.php b/Zotlabs/Widget/Suggestions.php
index b4f384e9d..e7d23bda4 100644
--- a/Zotlabs/Widget/Suggestions.php
+++ b/Zotlabs/Widget/Suggestions.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Suggestions
+ * * Description: Display suggestions for new contacts
+ */
+
namespace Zotlabs\Widget;
use Zotlabs\Lib\Apps;
@@ -12,7 +17,7 @@ class Suggestions {
function widget($arr) {
- if((! local_channel()) || (! Apps::system_app_installed(local_channel(), 'Suggest Channels')))
+ if(! local_channel())
return EMPTY_STR;
$r = suggestion_query(local_channel(),get_observer_hash(),0,20);
@@ -23,14 +28,14 @@ class Suggestions {
$arr = array();
- // Get two random entries from the top 20 returned.
+ // Get four random entries from the top 20 returned.
// We'll grab the first one and the one immediately following.
// This will throw some entropy intot he situation so you won't
// be looking at the same two mug shots every time the widget runs
- $index = ((count($r) > 2) ? mt_rand(0,count($r) - 2) : 0);
+ $index = ((count($r) > 4) ? mt_rand(0,count($r) - 4) : 0);
- for($x = $index; $x <= ($index+1); $x ++) {
+ for($x = $index; $x <= ($index+3); $x ++) {
$rr = $r[$x];
if(! $rr['xchan_url'])
break;
diff --git a/Zotlabs/Widget/Tagcloud.php b/Zotlabs/Widget/Tagcloud.php
index f79bd59ad..00456f24f 100644
--- a/Zotlabs/Widget/Tagcloud.php
+++ b/Zotlabs/Widget/Tagcloud.php
@@ -2,6 +2,11 @@
namespace Zotlabs\Widget;
+/**
+ * * Name: Tag cloud
+ * * Description: Display hashtags of your network items in a cloud
+ * * Requires: network, hq
+ */
class Tagcloud {
diff --git a/Zotlabs/Widget/Tagcloud_wall.php b/Zotlabs/Widget/Tagcloud_wall.php
index 7cff6ce09..20def4ab1 100644
--- a/Zotlabs/Widget/Tagcloud_wall.php
+++ b/Zotlabs/Widget/Tagcloud_wall.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Tag cloud wall
+ * * Description: Display hashtags of your channel wall items in a cloud if the feature is enabled
+ * * Requires: channel
+ */
+
namespace Zotlabs\Widget;
class Tagcloud_wall {
diff --git a/Zotlabs/Widget/Tasklist.php b/Zotlabs/Widget/Tasklist.php
index 56342bd17..5ecfd5a27 100644
--- a/Zotlabs/Widget/Tasklist.php
+++ b/Zotlabs/Widget/Tasklist.php
@@ -1,8 +1,11 @@
<?php
-namespace Zotlabs\Widget;
+/**
+ * * Name: Task list
+ * * Description: Simple task list mangager
+ */
-require_once('include/event.php');
+namespace Zotlabs\Widget;
class Tasklist {
@@ -20,7 +23,7 @@ class Tasklist {
}
</script>';
- $o .= '<div class="widget">' . '<h3>' . t('Tasks') . '</h3><div class="tasklist-tasks">';
+ $o .= '<div class="widget">' . '<h3>' . t('Tasks') . '</h3><div class="tasklist-tasks mb-1">';
$o .= '</div><form id="tasklist-new-form" action="" ><input class="form-control" id="tasklist-new-summary" type="text" name="summary" value="" /></form>';
$o .= '</div>';
return $o;
diff --git a/Zotlabs/Widget/Tokens.php b/Zotlabs/Widget/Tokens.php
new file mode 100644
index 000000000..69452d628
--- /dev/null
+++ b/Zotlabs/Widget/Tokens.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * * Name: Tokens
+ * * Description: Display a menu with links to existing guest access tokens
+ * * Requires: tokens
+ */
+
+namespace Zotlabs\Widget;
+
+class Tokens {
+
+ function widget($arr) {
+
+ $o = '';
+
+ $tokens = q("SELECT atoken_id, atoken_name FROM atoken WHERE atoken_uid = %d",
+ intval(local_channel())
+ );
+
+ if (!$tokens) {
+ return $o;
+ }
+
+ $menu_items = [];
+ $z_root = z_root();
+ $active = argv(1) ?? '';
+
+ foreach($tokens as $token) {
+ $menu_items[] = [
+ 'href' => $z_root . '/tokens/' . $token['atoken_id'],
+ 'label' => $token['atoken_name'],
+ 'title' => '',
+ 'active' => ($active === $token['atoken_id'])
+ ];
+ }
+
+ if ($active) {
+ $menu_items[] = [
+ 'href' => $z_root . '/tokens',
+ 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new guest'),
+ 'title' => '',
+ 'active' => ''
+ ];
+ }
+
+ $tpl = get_markup_template("widget_menu.tpl");
+ $o .= replace_macros($tpl, [
+ '$title' => t('Guest access'),
+ '$menu_items' => $menu_items,
+
+ ]);
+
+ return $o;
+
+ }
+}
diff --git a/Zotlabs/Widget/Vcard.php b/Zotlabs/Widget/Vcard.php
index cab05dfdd..25bb8592c 100644
--- a/Zotlabs/Widget/Vcard.php
+++ b/Zotlabs/Widget/Vcard.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Vcard
+ * * Description: Your default profile card
+ */
+
namespace Zotlabs\Widget;
class Vcard {
diff --git a/Zotlabs/Widget/Website_portation_tools.php b/Zotlabs/Widget/Website_portation_tools.php
index 1cf3bb78a..61fe48169 100644
--- a/Zotlabs/Widget/Website_portation_tools.php
+++ b/Zotlabs/Widget/Website_portation_tools.php
@@ -1,7 +1,12 @@
<?php
-namespace Zotlabs\Widget;
+/**
+ * * Name: Website import/export
+ * * Description: Tools to import and export websites
+ * * Requires: website
+ */
+namespace Zotlabs\Widget;
class Website_portation_tools {
diff --git a/Zotlabs/Widget/Wiki_list.php b/Zotlabs/Widget/Wiki_list.php
index 64c988ee7..217ab8706 100644
--- a/Zotlabs/Widget/Wiki_list.php
+++ b/Zotlabs/Widget/Wiki_list.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Wiki list
+ * * Description: A list of existing wikis
+ */
+
namespace Zotlabs\Widget;
class Wiki_list {
diff --git a/Zotlabs/Widget/Wiki_page_history.php b/Zotlabs/Widget/Wiki_page_history.php
index dbb322dc3..3c9f5ed1a 100644
--- a/Zotlabs/Widget/Wiki_page_history.php
+++ b/Zotlabs/Widget/Wiki_page_history.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Wiki page history
+ * * Description: History of an existing wiki page
+ * * Requires: wiki
+ */
+
namespace Zotlabs\Widget;
class Wiki_page_history {
@@ -10,7 +16,7 @@ class Wiki_page_history {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = \Zotlabs\Lib\NativeWikiPage::page_history([
- 'channel_id' => \App::$profile_uid,
+ 'channel_id' => \App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
diff --git a/Zotlabs/Widget/Wiki_pages.php b/Zotlabs/Widget/Wiki_pages.php
index dee0a2229..ece712334 100644
--- a/Zotlabs/Widget/Wiki_pages.php
+++ b/Zotlabs/Widget/Wiki_pages.php
@@ -1,5 +1,11 @@
<?php
+/**
+ * * Name: Wiki pages
+ * * Description: A list of existing pages of a wiki
+ * * Requires: wiki
+ */
+
namespace Zotlabs\Widget;
use Zotlabs\Lib\NativeWiki;
@@ -34,7 +40,7 @@ class Wiki_pages {
'$addnew' => t('Add new page'),
'$typelock' => $typelock,
'$lockedtype' => $w['mimeType'],
- '$mimetype' => mimetype_select(0,$w['mimeType'],
+ '$mimetype' => mimetype_select(0,$w['mimeType'],
[ 'text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$pageName' => array('missingPageName', 'Create Page' , $pageName),
'$refresh' => $arr['refresh'],
@@ -91,7 +97,7 @@ class Wiki_pages {
'$addnew' => t('Add new page'),
'$typelock' => $typelock,
'$lockedtype' => $w['mimeType'],
- '$mimetype' => mimetype_select(0,$w['mimeType'],
+ '$mimetype' => mimetype_select(0,$w['mimeType'],
[ 'text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$pageName' => array('pageName', t('Page name')),
'$refresh' => $arr['refresh'],
diff --git a/Zotlabs/Widget/Zcard.php b/Zotlabs/Widget/Zcard.php
index 12e53eaab..35362c50e 100644
--- a/Zotlabs/Widget/Zcard.php
+++ b/Zotlabs/Widget/Zcard.php
@@ -1,5 +1,10 @@
<?php
+/**
+ * * Name: Zcard
+ * * Description: Your default profile card including your cover photo
+ */
+
namespace Zotlabs\Widget;
class Zcard {
diff --git a/Zotlabs/Zot/Auth.php b/Zotlabs/Zot/Auth.php
deleted file mode 100644
index 6ce2174f7..000000000
--- a/Zotlabs/Zot/Auth.php
+++ /dev/null
@@ -1,363 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot;
-
-use Zotlabs\Lib\Crypto;
-
-class Auth {
-
- protected $test;
- protected $test_results;
- protected $debug_msg;
-
- protected $address;
- protected $desturl;
- protected $sec;
- protected $version;
- protected $delegate;
- protected $success;
- protected $delegate_success;
-
- protected $remote;
- protected $remote_service_class;
- protected $remote_level;
- protected $remote_hub;
- protected $dnt;
-
- function __construct($req) {
-
-
- $this->test = ((array_key_exists('test',$req)) ? intval($req['test']) : 0);
- $this->test_results = array('success' => false);
- $this->debug_msg = '';
-
- $this->success = false;
- $this->address = $req['auth'];
- $this->desturl = $req['dest'];
- $this->sec = $req['sec'];
- $this->version = $req['version'];
- $this->delegate = $req['delegate'];
-
- $c = get_sys_channel();
- if(! $c) {
- logger('unable to obtain response (sys) channel');
- $this->Debug('no local channels found.');
- $this->Finalise();
- }
-
- if(strpbrk($this->sec,'.:')) {
- logger('illegal security context');
- $this->Debug('illegal security context.');
- $this->Finalise();
- }
-
- $x = $this->GetHublocs($this->address);
-
- if($x) {
- foreach($x as $xx) {
- if($this->Verify($c,$xx))
- break;
- }
- }
-
- /**
- * @FIXME we really want to save the return_url in the session before we
- * visit rmagic. This does however prevent a recursion if you visit
- * rmagic directly, as it would otherwise send you back here again.
- * But z_root() probably isn't where you really want to go.
- */
-
- if(strstr($this->desturl,z_root() . '/rmagic'))
- goaway(z_root());
-
- $this->Finalise();
-
- }
-
- function GetHublocs($address) {
-
- // Try and find a hubloc for the person attempting to auth.
- // Since we're matching by address, we have to return all entries
- // some of which may be from re-installed hubs; and we'll need to
- // try each sequentially to see if one can pass the test
-
- $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
- where hubloc_addr = '%s' order by hubloc_id desc",
- dbesc($address)
- );
-
- if(! $x) {
- // finger them if they can't be found.
- $j = Finger::run($address, null);
- if ($j['success']) {
- import_xchan($j);
- $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
- where hubloc_addr = '%s' order by hubloc_id desc",
- dbesc($address)
- );
- }
- }
- if(! $x) {
- logger('mod_zot: auth: unable to finger ' . $address);
- $this->Debug('no hubloc found for ' . $address . ' and probing failed.');
- $this->Finalise();
- }
-
- return $x;
- }
-
-
- function Verify($channel,$hubloc) {
-
- logger('auth request received from ' . $hubloc['hubloc_addr'] );
-
- $this->remote = remote_channel();
- $this->remote_service_class = '';
- $this->remote_level = 0;
- $this->remote_hub = $hubloc['hubloc_url'];
- $this->dnt = 0;
-
- if(! $this->sec) {
- logger('missing security context.');
- if($this->test)
- $this->Debug('missing security context.');
- return false;
- }
-
-
- // check credentials and access
-
- // If they are already authenticated and haven't changed credentials,
- // we can save an expensive network round trip and improve performance.
-
- // Also check that they are coming from the same site as they authenticated with originally.
-
- $already_authed = (((remote_channel()) && ($hubloc['hubloc_hash'] == remote_channel())
- && ($hubloc['hubloc_url'] === $_SESSION['remote_hub'])) ? true : false);
-
- if($this->delegate && $this->delegate !== $_SESSION['delegate_channel'])
- $already_authed = false;
-
- if($already_authed)
- return true;
-
- if(local_channel()) {
-
- // tell them to logout if they're logged in locally as anything but the target remote account
- // in which case just shut up because they don't need to be doing this at all.
-
- if (\App::$channel['channel_hash'] == $hubloc['xchan_hash']) {
- return true;
- }
- else {
- logger('already authenticated locally as somebody else.');
- notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL);
- if($this->test) {
- $this->Debug('already logged in locally with a conflicting identity.');
- return false;
- }
- }
- return false;
- }
-
- // Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the
- // site private key
- // The actual channel sending the packet ($c[0]) is not important, but this provides a
- // generic zot packet with a sender which can be verified
-
- $x = q("select site_crypto from site where site_url = '%s' limit 1",
- dbesc($hubloc['hubloc_url'])
- );
-
- $p = zot_build_packet($channel,$type = 'auth_check',
- array(array('guid' => $hubloc['hubloc_guid'],'guid_sig' => $hubloc['hubloc_guid_sig'])),
- $hubloc['hubloc_sitekey'], (($x) ? $x[0]['site_crypto'] : ''), $this->sec);
-
- $this->Debug('auth check packet created using sitekey ' . $hubloc['hubloc_sitekey']);
- $this->Debug('packet contents: ' . $p);
-
- $result = zot_zot($hubloc['hubloc_callback'],$p);
- if(! $result['success']) {
- logger('auth_check callback failed.');
- if($this->test)
- $this->Debug('auth check request to your site returned .' . print_r($result, true));
- return false;
- }
-
- $j = json_decode($result['body'], true);
- if(! $j) {
- logger('auth_check json data malformed.');
- if($this->test)
- $this->Debug('json malformed: ' . $result['body']);
- return false;
- }
-
- $this->Debug('auth check request returned ' . print_r($j, true));
-
- if(! $j['success'])
- return false;
-
- // legit response, but we do need to check that this wasn't answered by a man-in-middle
-
- if (! Crypto::verify($this->sec . $hubloc['xchan_hash'],base64url_decode($j['confirm']),$hubloc['xchan_pubkey'])) {
- logger('final confirmation failed.');
- if($this->test)
- $this->Debug('final confirmation failed. ' . $sec . print_r($j,true) . print_r($hubloc,true));
- return false;
- }
-
- if (array_key_exists('service_class',$j))
- $this->remote_service_class = $j['service_class'];
- if (array_key_exists('level',$j))
- $this->remote_level = $j['level'];
- if (array_key_exists('DNT',$j))
- $this->dnt = $j['DNT'];
-
-
- // log them in
-
- if ($this->test) {
- // testing only - return the success result
- $this->test_results['success'] = true;
- $this->Debug('Authentication Success!');
- $this->Finalise();
- }
-
- $_SESSION['authenticated'] = 1;
-
- // check for delegation and if all is well, log them in locally with delegation restrictions
-
- $this->delegate_success = false;
-
- if($this->delegate) {
- $r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1",
- dbesc($this->delegate)
- );
- if ($r && intval($r[0]['channel_id'])) {
- $allowed = perm_is_allowed($r[0]['channel_id'],$hubloc['xchan_hash'],'delegate');
- if($allowed) {
- $_SESSION['delegate_channel'] = $r[0]['channel_id'];
- $_SESSION['delegate'] = $hubloc['xchan_hash'];
- $_SESSION['account_id'] = intval($r[0]['channel_account_id']);
- require_once('include/security.php');
- // this will set the local_channel authentication in the session
- change_channel($r[0]['channel_id']);
- $this->delegate_success = true;
- }
- }
- }
-
- if (! $this->delegate_success) {
- // normal visitor (remote_channel) login session credentials
- $_SESSION['visitor_id'] = $hubloc['xchan_hash'];
- $_SESSION['my_url'] = $hubloc['xchan_url'];
- $_SESSION['my_address'] = $this->address;
- $_SESSION['remote_service_class'] = $this->remote_service_class;
- $_SESSION['remote_level'] = $this->remote_level;
- $_SESSION['remote_hub'] = $this->remote_hub;
- $_SESSION['DNT'] = $this->dnt;
- }
-
- $arr = array('xchan' => $hubloc, 'url' => $this->desturl, 'session' => $_SESSION);
- call_hooks('magic_auth_success',$arr);
- \App::set_observer($hubloc);
- require_once('include/security.php');
- \App::set_groups(init_groups_visitor($_SESSION['visitor_id']));
- info(sprintf( t('Welcome %s. Remote authentication successful.'),$hubloc['xchan_name']));
- logger('mod_zot: auth success from ' . $hubloc['xchan_addr']);
- $this->success = true;
- return true;
- }
-
- function Debug($msg) {
- $this->debug_msg .= $msg . EOL;
- }
-
-
- function Finalise() {
-
- if($this->test) {
- $this->test_results['message'] = $this->debug_msg;
- json_return_and_die($this->test_results);
- }
-
- goaway($this->desturl);
- }
-
-}
-
-
-/**
- *
- * Magic Auth
- * ==========
- *
- * So-called "magic auth" takes place by a special exchange. On the site where the "channel to be authenticated" lives (e.g. $mysite),
- * a redirection is made via $mysite/magic to the zot endpoint of the remote site ($remotesite) with special GET parameters.
- *
- * The endpoint is typically https://$remotesite/post - or whatever was specified as the callback url in prior communications
- * (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist)
- *
- * Five GET parameters are supplied:
- * * auth => the urlencoded webbie (channel@host.domain) of the channel requesting access
- * * dest => the desired destination URL (urlencoded)
- * * sec => a random string which is also stored on $mysite for use during the verification phase.
- * * version => the zot revision
- * * delegate => optional urlencoded webbie of a local channel to invoke delegation rights for
- *
- * * test => (optional 1 or 0 - debugs the authentication exchange and returns a json response instead of redirecting the browser session)
- *
- * When this packet is received, an "auth-check" zot message is sent to $mysite.
- * (e.g. if $_GET['auth'] is foobar@podunk.edu, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post)
- * If no information has been recorded about the requesting identity a zot information packet will be retrieved before
- * continuing.
- *
- * The sender of this packet is an arbitrary/random site channel. The recipients will be a single recipient corresponding
- * to the guid and guid_sig we have associated with the requesting auth identity
- *
- * \code{.json}
- * {
- * "type":"auth_check",
- * "sender":{
- * "guid":"kgVFf_...",
- * "guid_sig":"PT9-TApz...",
- * "url":"http:\/\/podunk.edu",
- * "url_sig":"T8Bp7j...",
- * "sitekey":"aMtgKTiirXrICP..."
- * },
- * "recipients":{
- * {
- * "guid":"ZHSqb...",
- * "guid_sig":"JsAAXi..."
- * }
- * }
- * "callback":"\/post",
- * "version":1,
- * "secret":"1eaa661",
- * "secret_sig":"eKV968b1..."
- * }
- * \endcode
- *
- * auth_check messages MUST use encapsulated encryption. This message is sent to the origination site, which checks the 'secret' to see
- * if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the
- * destination channel's private key and base64url encoded. If everything checks out, a json packet is returned:
- *
- * \code{.json}
- * {
- * "success":1,
- * "confirm":"q0Ysovd1u...",
- * "service_class":(optional)
- * "level":(optional)
- * "DNT": (optional do-not-track - 1 or 0)
- * }
- * \endcode
- *
- * 'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the
- * base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key.
- * This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful
- * verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login.
- * Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is
- * a string whose contents are not defined by protocol. Example: "basic" or "gold".
- *
- * @param[in,out] \App &$a
- */
diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php
deleted file mode 100644
index cadde5415..000000000
--- a/Zotlabs/Zot/Finger.php
+++ /dev/null
@@ -1,155 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot;
-
-use Zotlabs\Lib\Crypto;
-use Zotlabs\Web\HTTPSig;
-
-/**
- * @brief Finger
- *
- */
-class Finger {
-
- static private $token;
-
- /**
- * @brief Look up information about channel.
- *
- * @param string $webbie
- * does not have to be host qualified e.g. 'foo' is treated as 'foo\@thishub'
- * @param array $channel
- * (optional), if supplied permissions will be enumerated specifically for $channel
- * @param boolean $autofallback
- * fallback/failover to http if https connection cannot be established. Default is true.
- *
- * @return zotinfo array (with 'success' => true) or array('success' => false);
- */
-
- static public function run($webbie, $channel = null, $autofallback = true) {
-
- $ret = array('success' => false);
-
- self::$token = random_string();
-
- if (strpos($webbie, '@') === false) {
- $address = $webbie;
- $host = \App::get_hostname();
- } else {
- $address = substr($webbie,0,strpos($webbie,'@'));
- $host = substr($webbie,strpos($webbie,'@')+1);
- if(strpos($host,'/'))
- $host = substr($host,0,strpos($host,'/'));
- }
-
- $xchan_addr = $address . '@' . $host;
-
- if ((! $address) || (! $xchan_addr)) {
- logger('zot_finger: no address :' . $webbie);
-
- return $ret;
- }
-
- logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG);
-
- // potential issue here; the xchan_addr points to the primary hub.
- // The webbie we were called with may not, so it might not be found
- // unless we query for hubloc_addr instead of xchan_addr
-
- $r = q("select xchan.*, hubloc.* from xchan
- left join hubloc on xchan_hash = hubloc_hash
- where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 and hubloc_network = 'zot' limit 1",
- dbesc($xchan_addr)
- );
-
- if($r) {
- $url = $r[0]['hubloc_url'];
-
- if($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
- logger('zot_finger: alternate network: ' . $webbie);
- logger('url: ' . $url . ', net: ' . var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
- return $ret;
- }
- } else {
- $url = 'https://' . $host;
- }
-
- $m = parse_url($url);
- if($m) {
- $parsed_host = strtolower($m['host']);
- }
-
- $rhs = '/.well-known/zot-info';
- $https = ((strpos($url,'https://') === 0) ? true : false);
-
- logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG);
-
- if ($channel) {
- $postvars = array(
- 'address' => $address,
- 'target' => $channel['channel_guid'],
- 'target_sig' => $channel['channel_guid_sig'],
- 'key' => $channel['channel_pubkey'],
- 'token' => self::$token
- );
-
- $headers = [];
- $headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname();
- $headers['X-Zot-Nonce'] = random_string();
- $headers['Host'] = $parsed_host;
-
- $xhead = HTTPSig::create_sig($headers,$channel['channel_prvkey'],'acct:' . channel_reddress($channel));
-
- $retries = 0;
-
- $result = z_post_url($url . $rhs,$postvars,$retries, [ 'headers' => $xhead ]);
-
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_post_url('http://' . $host . $rhs,$postvars, $retries, [ 'headers' => $xhead ]);
- }
- }
- }
- else {
- $rhs .= '?f=&address=' . urlencode($address) . '&token=' . self::$token;
-
- $result = z_fetch_url($url . $rhs);
- if((! $result['success']) && ($autofallback)) {
- if($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_fetch_url('http://' . $host . $rhs);
- }
- }
- }
-
- if(! $result['success']) {
- logger('zot_finger: no results');
-
- return $ret;
- }
-
- $x = json_decode($result['body'], true);
-
- $verify = HTTPSig::verify($result,(($x) ? $x['key'] : ''));
-
- if($x && (! $verify['header_valid'])) {
- $signed_token = ((is_array($x) && array_key_exists('signed_token', $x)) ? $x['signed_token'] : null);
- if($signed_token) {
- $valid = Crypto::verify('token.' . self::$token, base64url_decode($signed_token), $x['key']);
- if(! $valid) {
- logger('invalid signed token: ' . $url . $rhs, LOGGER_NORMAL, LOG_ERR);
-
- return $ret;
- }
- }
- else {
- logger('No signed token from ' . $url . $rhs, LOGGER_NORMAL, LOG_WARNING);
- return $ret;
- }
- }
-
- return $x;
- }
-
-}
diff --git a/Zotlabs/Zot/IHandler.php b/Zotlabs/Zot/IHandler.php
deleted file mode 100644
index dd82f5be6..000000000
--- a/Zotlabs/Zot/IHandler.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot;
-
-interface IHandler {
-
- function Ping();
-
- function Pickup($data);
-
- function Notify($data);
-
- function Request($data);
-
- function Rekey($sender,$data);
-
- function AuthCheck($data,$encrypted);
-
- function Purge($sender,$recipients);
-
- function Refresh($sender,$recipients);
-
-}
-
diff --git a/Zotlabs/Zot/Receiver.php b/Zotlabs/Zot/Receiver.php
deleted file mode 100644
index f0378b650..000000000
--- a/Zotlabs/Zot/Receiver.php
+++ /dev/null
@@ -1,304 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot;
-
-use Zotlabs\Lib\Crypto;
-
-class Receiver {
-
- protected $data;
- protected $encrypted;
- protected $error;
- protected $messagetype;
- protected $sender;
- protected $validated;
- protected $recipients;
- protected $response;
- protected $handler;
-
- function __construct($data,$prvkey,$handler) {
-
- $this->error = false;
- $this->validated = false;
- $this->messagetype = '';
- $this->response = array('success' => false);
-
- $this->handler = $handler;
-
- if(! is_array($data))
- $data = json_decode($data,true);
-
- if($data && is_array($data)) {
- $this->encrypted = ((array_key_exists('iv',$data)) ? true : false);
-
- if($this->encrypted) {
- $data['encrypted'] = true;
- $this->data = @json_decode(@Crypto::unencapsulate($data,$prvkey),true);
- }
- if(! $this->data)
- $this->data = $data;
-
- if($this->data && is_array($this->data) && array_key_exists('type',$this->data))
- $this->messagetype = $this->data['type'];
- }
- if(! $this->messagetype)
- $this->error = true;
-
- if($this->data) {
- $this->sender = ((array_key_exists('sender',$this->data)) ? $this->data['sender'] : null);
- $this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
- }
-
- if($this->sender)
- $this->ValidateSender();
-
- $this->Dispatch();
- }
-
- function ValidateSender() {
- $hubs = zot_gethub($this->sender,true);
- if (! $hubs) {
-
- /* Have never seen this guid or this guid coming from this location. Check it and register it. */
- /* (!!) this will validate the sender. */
-
- $result = zot_register_hub($this->sender);
-
- if ((! $result['success']) || (! ($hubs = zot_gethub($this->sender,true)))) {
- $this->response['message'] = 'Hub not available.';
- json_return_and_die($this->response);
- }
- }
- foreach($hubs as $hub) {
- update_hub_connected($hub,((array_key_exists('sitekey',$this->sender)) ? $this->sender['sitekey'] : ''));
- }
- $this->validated = true;
- }
-
-
- function Dispatch() {
-
- /* Handle tasks which don't require sender validation */
-
- switch($this->messagetype) {
- case 'ping':
- /* no validation needed */
- $this->handler->Ping();
- break;
- case 'pickup':
- /* perform site validation, as opposed to sender validation */
- $this->handler->Pickup($this->data);
- break;
-
- default:
- if(! $this->validated) {
- $this->response['message'] = 'Sender not valid';
- json_return_and_die($this->response);
- }
- break;
- }
-
- /* Now handle tasks which require sender validation */
-
- switch($this->messagetype) {
-
- case 'auth_check':
- $this->handler->AuthCheck($this->data,$this->encrypted);
- break;
-
- case 'request':
- $this->handler->Request($this->data);
- break;
-
- case 'purge':
- $this->handler->Purge($this->sender,$this->recipients);
- break;
-
- case 'refresh':
- case 'force_refresh':
- $this->handler->Refresh($this->sender,$this->recipients);
- break;
-
- case 'notify':
- $this->handler->Notify($this->data);
- break;
-
- case 'rekey':
- $this->handler->Rekey($this->sender, $this->data);
- break;
-
- default:
- $this->response['message'] = 'Not implemented';
- json_return_and_die($this->response);
- break;
- }
-
- }
-}
-
-
-
-/**
- * @brief zot communications and messaging.
- *
- * Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet.
- * This packet is optionally encrypted, which we will discover if the json has an 'iv' element.
- * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data);
- * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded.
- *
- * Once decrypted, one will find the normal json_encoded zot message packet.
- *
- * Defined packet types are: notify, purge, refresh, force_refresh, auth_check, ping, and pickup
- *
- * Standard packet: (used by notify, purge, refresh, force_refresh, and auth_check)
- * \code{.json}
- * {
- * "type": "notify",
- * "sender":{
- * "guid":"kgVFf_1...",
- * "guid_sig":"PT9-TApzp...",
- * "url":"http:\/\/podunk.edu",
- * "url_sig":"T8Bp7j5...",
- * },
- * "recipients": { optional recipient array },
- * "callback":"\/post",
- * "version":"1.2",
- * "encryption":["aes256cbc"],
- * "secret":"1eaa...",
- * "secret_sig": "df89025470fac8..."
- * }
- * \endcode
- *
- * Signature fields are all signed with the sender channel private key and base64url encoded.
- * Recipients are arrays of guid and guid_sig, which were previously signed with the recipients private
- * key and base64url encoded and later obtained via channel discovery. Absence of recipients indicates
- * a public message or visible to all potential listeners on this site.
- *
- * "pickup" packet:
- * The pickup packet is sent in response to a notify packet from another site
- * \code{.json}
- * {
- * "type":"pickup",
- * "url":"http:\/\/example.com",
- * "callback":"http:\/\/example.com\/post",
- * "callback_sig":"teE1_fLI...",
- * "secret":"1eaa...",
- * "secret_sig":"O7nB4_..."
- * }
- * \endcode
- *
- * In the pickup packet, the sig fields correspond to the respective data
- * element signed with this site's system private key and then base64url encoded.
- * The "secret" is the same as the original secret from the notify packet.
- *
- * If verification is successful, a json structure is returned containing a
- * success indicator and an array of type 'pickup'.
- * Each pickup element contains the original notify request and a message field
- * whose contents are dependent on the message type.
- *
- * This JSON array is AES encapsulated using the site public key of the site
- * that sent the initial zot pickup packet.
- * Using the above example, this would be example.com.
- *
- * \code{.json}
- * {
- * "success":1,
- * "pickup":{
- * "notify":{
- * "type":"notify",
- * "sender":{
- * "guid":"kgVFf_...",
- * "guid_sig":"PT9-TApz...",
- * "url":"http:\/\/z.podunk.edu",
- * "url_sig":"T8Bp7j5D..."
- * },
- * "callback":"\/post",
- * "version":1,
- * "secret":"1eaa661..."
- * },
- * "message":{
- * "type":"activity",
- * "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
- * "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
- * "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
- * "created":"2012-11-20 04:04:16",
- * "edited":"2012-11-20 04:04:16",
- * "title":"",
- * "body":"Hi Nickordo",
- * "app":"",
- * "verb":"post",
- * "object_type":"",
- * "target_type":"",
- * "permalink":"",
- * "location":"",
- * "longlat":"",
- * "owner":{
- * "name":"Indigo",
- * "address":"indigo@podunk.edu",
- * "url":"http:\/\/podunk.edu",
- * "photo":{
- * "mimetype":"image\/jpeg",
- * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5"
- * },
- * "guid":"kgVFf_...",
- * "guid_sig":"PT9-TAp...",
- * },
- * "author":{
- * "name":"Indigo",
- * "address":"indigo@podunk.edu",
- * "url":"http:\/\/podunk.edu",
- * "photo":{
- * "mimetype":"image\/jpeg",
- * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5"
- * },
- * "guid":"kgVFf_...",
- * "guid_sig":"PT9-TAp..."
- * }
- * }
- * }
- * }
- * \endcode
- *
- * Currently defined message types are 'activity', 'mail', 'profile', 'location'
- * and 'channel_sync', which each have different content schemas.
- *
- * Ping packet:
- * A ping packet does not require any parameters except the type. It may or may
- * not be encrypted.
- *
- * \code{.json}
- * {
- * "type": "ping"
- * }
- * \endcode
- *
- * On receipt of a ping packet a ping response will be returned:
- *
- * \code{.json}
- * {
- * "success" : 1,
- * "site" {
- * "url": "http:\/\/podunk.edu",
- * "url_sig": "T8Bp7j5...",
- * "sitekey": "-----BEGIN PUBLIC KEY-----
- * MIICIjANBgkqhkiG9w0BAQE..."
- * }
- * }
- * \endcode
- *
- * The ping packet can be used to verify that a site has not been re-installed, and to
- * initiate corrective action if it has. The url_sig is signed with the site private key
- * and base64url encoded - and this should verify with the enclosed sitekey. Failure to
- * verify indicates the site is corrupt or otherwise unable to communicate using zot.
- * This return packet is not otherwise verified, so should be compared with other
- * results obtained from this site which were verified prior to taking action. For instance
- * if you have one verified result with this signature and key, and other records for this
- * url which have different signatures and keys, it indicates that the site was re-installed
- * and corrective action may commence (remove or mark invalid any entries with different
- * signatures).
- * If you have no records which match this url_sig and key - no corrective action should
- * be taken as this packet may have been returned by an imposter.
- *
- * @param[in,out] App &$a
- */
-
diff --git a/Zotlabs/Zot/ZotHandler.php b/Zotlabs/Zot/ZotHandler.php
deleted file mode 100644
index ab8815b3d..000000000
--- a/Zotlabs/Zot/ZotHandler.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot;
-
-class ZotHandler implements IHandler {
-
- function Ping() {
- zot_reply_ping();
- }
-
- function Pickup($data) {
- zot_reply_pickup($data);
- }
-
- function Notify($data) {
- zot_reply_notify($data);
- }
-
- function Request($data) {
- zot_reply_message_request($data);
- }
-
- function Rekey($sender,$data) {
- zot_rekey_request($sender,$data);
- }
-
- function AuthCheck($data,$encrypted) {
- zot_reply_auth_check($data,$encrypted);
- }
-
- function Purge($sender,$recipients) {
- zot_reply_purge($sender,$recipients);
- }
-
- function Refresh($sender,$recipients) {
- zot_reply_refresh($sender,$recipients);
- }
-
-}
diff --git a/Zotlabs/Zot6/Finger.php b/Zotlabs/Zot6/Finger.php
deleted file mode 100644
index cec3f98ab..000000000
--- a/Zotlabs/Zot6/Finger.php
+++ /dev/null
@@ -1,145 +0,0 @@
-<?php
-
-namespace Zotlabs\Zot6;
-
-/**
- * @brief Finger
- *
- */
-class Finger {
-
- static private $token;
-
- /**
- * @brief Look up information about channel.
- *
- * @param string $webbie
- * does not have to be host qualified e.g. 'foo' is treated as 'foo\@thishub'
- * @param array $channel
- * (optional), if supplied permissions will be enumerated specifically for $channel
- * @param boolean $autofallback
- * fallback/failover to http if https connection cannot be established. Default is true.
- *
- * @return zotinfo array (with 'success' => true) or array('success' => false);
- */
-
- static public function run($webbie, $channel = null, $autofallback = true) {
-
- $ret = array('success' => false);
-
- self::$token = random_string();
-
- if (strpos($webbie, '@') === false) {
- $address = $webbie;
- $host = \App::get_hostname();
- } else {
- $address = substr($webbie,0,strpos($webbie,'@'));
- $host = substr($webbie,strpos($webbie,'@')+1);
- if(strpos($host,'/'))
- $host = substr($host,0,strpos($host,'/'));
- }
-
- $xchan_addr = $address . '@' . $host;
-
- if ((! $address) || (! $xchan_addr)) {
- logger('zot_finger: no address :' . $webbie);
-
- return $ret;
- }
-
- logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG);
-
- // potential issue here; the xchan_addr points to the primary hub.
- // The webbie we were called with may not, so it might not be found
- // unless we query for hubloc_addr instead of xchan_addr
-
- $r = q("select xchan.*, hubloc.* from xchan
- left join hubloc on xchan_hash = hubloc_hash
- where xchan_addr = '%s' and hubloc_primary = 1 limit 1",
- dbesc($xchan_addr)
- );
-
- if($r) {
- $url = $r[0]['hubloc_url'];
-
- if($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
- logger('zot_finger: alternate network: ' . $webbie);
- logger('url: ' . $url . ', net: ' . var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
- return $ret;
- }
- } else {
- $url = 'https://' . $host;
- }
-
- $rhs = '/.well-known/zot-info';
- $https = ((strpos($url,'https://') === 0) ? true : false);
-
- logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG);
-
- if ($channel) {
- $postvars = array(
- 'address' => $address,
- 'target' => $channel['channel_guid'],
- 'target_sig' => $channel['channel_guid_sig'],
- 'key' => $channel['channel_pubkey'],
- 'token' => self::$token
- );
-
- $headers = [];
- $headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname();
- $headers['X-Zot-Nonce'] = random_string();
- $xhead = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel));
-
- $retries = 0;
-
- $result = z_post_url($url . $rhs,$postvars,$retries, [ 'headers' => $xhead ]);
-
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_post_url('http://' . $host . $rhs,$postvars, $retries, [ 'headers' => $xhead ]);
- }
- }
- }
- else {
- $rhs .= '?f=&address=' . urlencode($address) . '&token=' . self::$token;
-
- $result = z_fetch_url($url . $rhs);
- if((! $result['success']) && ($autofallback)) {
- if($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_fetch_url('http://' . $host . $rhs);
- }
- }
- }
-
- if(! $result['success']) {
- logger('zot_finger: no results');
-
- return $ret;
- }
-
- $x = json_decode($result['body'], true);
-
- $verify = HTTPSig::verify($result,(($x) ? $x['key'] : ''));
-
- if($x && (! $verify['header_valid'])) {
- $signed_token = ((is_array($x) && array_key_exists('signed_token', $x)) ? $x['signed_token'] : null);
- if($signed_token) {
- $valid = zot_verify('token.' . self::$token, base64url_decode($signed_token), $x['key']);
- if(! $valid) {
- logger('invalid signed token: ' . $url . $rhs, LOGGER_NORMAL, LOG_ERR);
-
- return $ret;
- }
- }
- else {
- logger('No signed token from ' . $url . $rhs, LOGGER_NORMAL, LOG_WARNING);
- return $ret;
- }
- }
-
- return $x;
- }
-
-}
diff --git a/Zotlabs/Zot6/IHandler.php b/Zotlabs/Zot6/IHandler.php
index 53b6caa89..4e7738926 100644
--- a/Zotlabs/Zot6/IHandler.php
+++ b/Zotlabs/Zot6/IHandler.php
@@ -4,15 +4,13 @@ namespace Zotlabs\Zot6;
interface IHandler {
- function Notify($data,$hub);
+ function Notify($data, $hub);
- function Request($data,$hub);
+ function Rekey($sender, $data, $hub);
- function Rekey($sender,$data,$hub);
+ function Refresh($sender, $recipients, $hub, $force);
- function Refresh($sender,$recipients,$hub);
-
- function Purge($sender,$recipients,$hub);
+ function Purge($sender, $recipients, $hub);
}
diff --git a/Zotlabs/Zot6/Receiver.php b/Zotlabs/Zot6/Receiver.php
index 6440c5da5..964c61651 100644
--- a/Zotlabs/Zot6/Receiver.php
+++ b/Zotlabs/Zot6/Receiver.php
@@ -7,7 +7,6 @@ use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
use Zotlabs\Web\HTTPSig;
-
class Receiver {
protected $data;
@@ -174,21 +173,20 @@ class Receiver {
function Dispatch() {
switch ($this->messagetype) {
-
- case 'request':
- $this->response = $this->handler->Request($this->data,$this->hub);
- break;
-
case 'purge':
- $this->response = $this->handler->Purge($this->sender,$this->recipients,$this->hub);
+ $this->response = $this->handler->Purge($this->sender, $this->recipients, $this->hub);
break;
case 'refresh':
- $this->response = $this->handler->Refresh($this->sender,$this->recipients,$this->hub);
+ $this->response = $this->handler->Refresh($this->sender, $this->recipients, $this->hub, false);
+ break;
+
+ case 'force_refresh':
+ $this->response = $this->handler->Refresh($this->sender, $this->recipients, $this->hub, true);
break;
case 'rekey':
- $this->response = $this->handler->Rekey($this->sender, $this->data,$this->hub);
+ $this->response = $this->handler->Rekey($this->sender, $this->data, $this->hub);
break;
case 'activity':
@@ -196,7 +194,7 @@ class Receiver {
case 'sync':
default:
if ($this->sender) {
- $this->response = $this->handler->Notify($this->data,$this->hub);
+ $this->response = $this->handler->Notify($this->data, $this->hub);
}
break;
diff --git a/Zotlabs/Zot6/Zot6Handler.php b/Zotlabs/Zot6/Zot6Handler.php
index bd321c4b1..4dc410f52 100644
--- a/Zotlabs/Zot6/Zot6Handler.php
+++ b/Zotlabs/Zot6/Zot6Handler.php
@@ -7,24 +7,20 @@ use Zotlabs\Lib\Queue;
class Zot6Handler implements IHandler {
- function Notify($data,$hub) {
- return self::reply_notify($data,$hub);
+ function Notify($data, $hub) {
+ return self::reply_notify($data, $hub);
}
- function Request($data,$hub) {
- return self::reply_message_request($data,$hub);
+ function Rekey($sender, $data, $hub) {
+ return self::reply_rekey_request($sender, $data, $hub);
}
- function Rekey($sender,$data,$hub) {
- return self::reply_rekey_request($sender,$data,$hub);
+ function Refresh($sender, $recipients, $hub, $force) {
+ return self::reply_refresh($sender, $recipients, $hub, $force);
}
- function Refresh($sender,$recipients,$hub) {
- return self::reply_refresh($sender,$recipients,$hub);
- }
-
- function Purge($sender,$recipients,$hub) {
- return self::reply_purge($sender,$recipients,$hub);
+ function Purge($sender, $recipients, $hub) {
+ return self::reply_purge($sender, $recipients, $hub);
}
@@ -38,7 +34,7 @@ class Zot6Handler implements IHandler {
logger('notify received from ' . $hub['hubloc_url']);
- $x = Libzot::fetch($data);
+ $x = Libzot::fetch($data, $hub);
$ret['delivery_report'] = $x;
@@ -62,7 +58,7 @@ class Zot6Handler implements IHandler {
*
* @return array
*/
- static function reply_refresh($sender, $recipients, $hub) {
+ static function reply_refresh($sender, $recipients, $hub, $force) {
$ret = array('success' => false);
if($recipients) {
@@ -75,87 +71,18 @@ class Zot6Handler implements IHandler {
where xchan_hash ='%s' limit 1",
dbesc($recip)
);
- /// @FIXME $msgtype is undefined
- $x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], $r[0], (($msgtype === 'force_refresh') ? true : false));
+ $x = Libzot::refresh([ 'hubloc_id_url' => $hub['hubloc_id_url']], $r[0], $force);
}
}
else {
// system wide refresh
- /// @FIXME $msgtype is undefined
- $x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], null, (($msgtype === 'force_refresh') ? true : false));
+ $x = Libzot::refresh(['hubloc_id_url' => $hub['hubloc_id_url']], null, $force);
}
$ret['success'] = true;
return $ret;
}
-
-
- /**
- * @brief Process a message request.
- *
- * If a site receives a comment to a post but finds they have no parent to attach it with, they
- * may send a 'request' packet containing the message_id of the missing parent. This is the handler
- * for that packet. We will create a message_list array of the entire conversation starting with
- * the missing parent and invoke delivery to the sender of the packet.
- *
- * Zotlabs/Daemon/Deliver.php (for local delivery) and
- * mod/post.php???? @fixme (for web delivery) detect the existence of
- * this 'message_list' at the destination and split it into individual messages which are
- * processed/delivered in order.
- *
- * @param array $data
- * @param array $hub
- * @return array
- */
- static function reply_message_request($data, $hub) {
- $ret = [ 'success' => false ];
-
- $message_id = EMPTY_STR;
-
- if(array_key_exists('data',$data))
- $ptr = $data['data'];
- if(is_array($ptr) && array_key_exists(0,$ptr)) {
- $ptr = $ptr[0];
- }
- if(is_string($ptr)) {
- $message_id = $ptr;
- }
- if(is_array($ptr) && array_key_exists('id',$ptr)) {
- $message_id = $ptr['id'];
- }
-
- if (! $message_id) {
- $ret['message'] = 'no message_id';
- logger('no message_id');
- return $ret;
- }
-
- $sender = $hub['hubloc_hash'];
-
- /*
- * Find the local channel in charge of this post (the first and only recipient of the request packet)
- */
-
- $arr = $data['recipients'][0];
-
- $c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1",
- dbesc($arr['portable_id'])
- );
- if (! $c) {
- logger('recipient channel not found.');
- $ret['message'] .= 'recipient not found.' . EOL;
- return $ret;
- }
-
- /*
- * fetch the requested conversation
- */
- $messages = zot_feed($c[0]['channel_id'], $sender, [ 'message_id' => $data['message_id'], 'encoding' => 'activitystreams' ]);
-
- return (($messages) ? : [] );
- }
-
static function rekey_request($sender,$data,$hub) {
$ret = array('success' => false);
@@ -174,7 +101,7 @@ class Zot6Handler implements IHandler {
$old = null;
if(Libzot::verify($data['old_guid'],$data['old_guid_sig'],$data['old_key'])) {
- $oldhash = make_xchan_hash($data['old_guid'],$data['old_key']);
+ $oldhash = Libzot::make_xchan_hash($data['old_guid'],$data['old_key']);
$old = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($oldhash)
);
@@ -223,6 +150,10 @@ class Zot6Handler implements IHandler {
$ret = array('success' => false);
+ if (! $sender) {
+ return $ret;
+ }
+
if ($recipients) {
// basically this means "unfriend"
foreach ($recipients as $recip) {