aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/ActivityStreams/ASObject.php776
-rw-r--r--Zotlabs/ActivityStreams/Activity.php122
-rw-r--r--Zotlabs/ActivityStreams/Actor.php428
-rw-r--r--Zotlabs/ActivityStreams/AssertionMethod.php87
-rw-r--r--Zotlabs/ActivityStreams/Collection.php124
-rw-r--r--Zotlabs/ActivityStreams/CollectionPage.php73
-rw-r--r--Zotlabs/ActivityStreams/IntransitiveActivity.php104
-rw-r--r--Zotlabs/ActivityStreams/Link.php183
-rw-r--r--Zotlabs/ActivityStreams/OrderedCollection.php8
-rw-r--r--Zotlabs/ActivityStreams/OrderedCollectionPage.php92
-rw-r--r--Zotlabs/ActivityStreams/Place.php125
-rw-r--r--Zotlabs/ActivityStreams/Profile.php29
-rw-r--r--Zotlabs/ActivityStreams/PublicKey.php68
-rw-r--r--Zotlabs/ActivityStreams/Question.php67
-rw-r--r--Zotlabs/ActivityStreams/Relationship.php67
-rw-r--r--Zotlabs/ActivityStreams/Signature.php65
-rw-r--r--Zotlabs/ActivityStreams/Tombstone.php48
-rw-r--r--Zotlabs/ActivityStreams/UnhandledElementException.php8
-rw-r--r--Zotlabs/Daemon/Channel_purge.php2
-rw-r--r--Zotlabs/Daemon/Content_importer.php12
-rw-r--r--Zotlabs/Daemon/Cron.php53
-rw-r--r--Zotlabs/Daemon/Expire.php4
-rw-r--r--Zotlabs/Daemon/File_importer.php8
-rw-r--r--Zotlabs/Daemon/Importdoc.php21
-rw-r--r--Zotlabs/Daemon/Notifier.php43
-rw-r--r--Zotlabs/Entity/Account.php352
-rw-r--r--Zotlabs/Entity/Channel.php714
-rw-r--r--Zotlabs/Entity/Item.php1498
-rw-r--r--Zotlabs/Lib/Activity.php608
-rw-r--r--Zotlabs/Lib/BaseObject.php80
-rw-r--r--Zotlabs/Lib/Chatroom.php2
-rw-r--r--Zotlabs/Lib/Connect.php8
-rw-r--r--Zotlabs/Lib/DB_Upgrade.php31
-rw-r--r--Zotlabs/Lib/Enotify.php36
-rw-r--r--Zotlabs/Lib/Libsync.php2
-rw-r--r--Zotlabs/Lib/Libzot.php167
-rw-r--r--Zotlabs/Lib/Mailer.php86
-rw-r--r--Zotlabs/Lib/PermissionDescription.php14
-rw-r--r--Zotlabs/Lib/QueueWorker.php4
-rw-r--r--Zotlabs/Lib/SuperCurl.php127
-rw-r--r--Zotlabs/Lib/ThreadItem.php122
-rw-r--r--Zotlabs/Lib/Traits/HelpHelperTrait.php47
-rw-r--r--Zotlabs/Lib/XConfig.php2
-rw-r--r--Zotlabs/Module/Achievements.php44
-rw-r--r--Zotlabs/Module/Activity.php4
-rw-r--r--Zotlabs/Module/Admin/Account_edit.php11
-rw-r--r--Zotlabs/Module/Admin/Accounts.php258
-rw-r--r--Zotlabs/Module/Admin/Addons.php285
-rw-r--r--Zotlabs/Module/Admin/Channels.php2
-rw-r--r--Zotlabs/Module/Admin/Features.php5
-rw-r--r--Zotlabs/Module/Admin/Site.php3
-rw-r--r--Zotlabs/Module/Admin/Themes.php2
-rw-r--r--Zotlabs/Module/Api.php3
-rw-r--r--Zotlabs/Module/Appman.php28
-rw-r--r--Zotlabs/Module/Apporder.php4
-rw-r--r--Zotlabs/Module/Apps.php4
-rw-r--r--Zotlabs/Module/Authorize.php9
-rw-r--r--Zotlabs/Module/Authtest.php4
-rw-r--r--Zotlabs/Module/Changeaddr.php40
-rw-r--r--Zotlabs/Module/Channel_calendar.php30
-rw-r--r--Zotlabs/Module/Chatsvc.php2
-rw-r--r--Zotlabs/Module/Cloud.php8
-rw-r--r--Zotlabs/Module/Conversation.php13
-rw-r--r--Zotlabs/Module/Cover_photo.php9
-rw-r--r--Zotlabs/Module/Dav.php1
-rw-r--r--Zotlabs/Module/Display.php7
-rw-r--r--Zotlabs/Module/Dreport.php8
-rw-r--r--Zotlabs/Module/Editpost.php1
-rw-r--r--Zotlabs/Module/Fbrowser.php2
-rw-r--r--Zotlabs/Module/Filer.php63
-rw-r--r--Zotlabs/Module/Go.php4
-rw-r--r--Zotlabs/Module/Help.php18
-rw-r--r--Zotlabs/Module/Home.php15
-rw-r--r--Zotlabs/Module/Hq.php1
-rw-r--r--Zotlabs/Module/Impel.php4
-rw-r--r--Zotlabs/Module/Import.php3
-rw-r--r--Zotlabs/Module/Import_progress.php20
-rw-r--r--Zotlabs/Module/Item.php557
-rw-r--r--Zotlabs/Module/Like.php23
-rw-r--r--Zotlabs/Module/Lockview.php2
-rw-r--r--Zotlabs/Module/Login.php13
-rw-r--r--Zotlabs/Module/Magic.php70
-rw-r--r--Zotlabs/Module/Mitem.php30
-rw-r--r--Zotlabs/Module/Moderate.php2
-rw-r--r--Zotlabs/Module/Network.php25
-rw-r--r--Zotlabs/Module/Notes.php30
-rw-r--r--Zotlabs/Module/Notify.php4
-rw-r--r--Zotlabs/Module/OAuth2TestVehicle.php8
-rw-r--r--Zotlabs/Module/Oauth.php12
-rw-r--r--Zotlabs/Module/Oauth2.php12
-rw-r--r--Zotlabs/Module/Owa.php186
-rw-r--r--Zotlabs/Module/Page.php4
-rw-r--r--Zotlabs/Module/Pdledit.php2
-rw-r--r--Zotlabs/Module/Permcat.php4
-rw-r--r--Zotlabs/Module/Photos.php4
-rw-r--r--Zotlabs/Module/Profperm.php2
-rw-r--r--Zotlabs/Module/Pubsites.php8
-rw-r--r--Zotlabs/Module/Pubstream.php8
-rw-r--r--Zotlabs/Module/React.php3
-rw-r--r--Zotlabs/Module/Removeaccount.php20
-rw-r--r--Zotlabs/Module/Removeme.php6
-rw-r--r--Zotlabs/Module/Rmagic.php4
-rw-r--r--Zotlabs/Module/Search_ac.php7
-rw-r--r--Zotlabs/Module/Settings/Account.php4
-rw-r--r--Zotlabs/Module/Settings/Calendar.php5
-rw-r--r--Zotlabs/Module/Settings/Channel_home.php5
-rw-r--r--Zotlabs/Module/Settings/Connections.php5
-rw-r--r--Zotlabs/Module/Settings/Conversation.php21
-rw-r--r--Zotlabs/Module/Settings/Directory.php5
-rw-r--r--Zotlabs/Module/Settings/Editor.php5
-rw-r--r--Zotlabs/Module/Settings/Events.php5
-rw-r--r--Zotlabs/Module/Settings/Features.php7
-rw-r--r--Zotlabs/Module/Settings/Manage.php5
-rw-r--r--Zotlabs/Module/Settings/Network.php5
-rw-r--r--Zotlabs/Module/Settings/Photos.php5
-rw-r--r--Zotlabs/Module/Settings/Profiles.php5
-rw-r--r--Zotlabs/Module/Setup.php5
-rw-r--r--Zotlabs/Module/Share.php14
-rw-r--r--Zotlabs/Module/Snap.php20
-rw-r--r--Zotlabs/Module/Sse.php94
-rw-r--r--Zotlabs/Module/Sse_bs.php26
-rw-r--r--Zotlabs/Module/Subthread.php2
-rw-r--r--Zotlabs/Module/Tagger.php6
-rw-r--r--Zotlabs/Module/Tagrm.php98
-rw-r--r--Zotlabs/Module/Thing.php46
-rw-r--r--Zotlabs/Module/Vote.php9
-rw-r--r--Zotlabs/Module/Wall_attach.php6
-rw-r--r--Zotlabs/Module/Webfinger.php14
-rw-r--r--Zotlabs/Module/Webpages.php5
-rw-r--r--Zotlabs/Module/Zot_probe.php8
-rw-r--r--Zotlabs/Photo/PhotoGd.php30
-rw-r--r--Zotlabs/Render/SmartyInterface.php8
-rw-r--r--Zotlabs/Storage/Browser.php1
-rw-r--r--Zotlabs/Storage/GitRepo.php159
-rw-r--r--Zotlabs/Thumbs/Epubthumb.php183
-rw-r--r--Zotlabs/Update/_1007.php4
-rw-r--r--Zotlabs/Update/_1151.php4
-rw-r--r--Zotlabs/Web/HttpMeta.php13
-rw-r--r--Zotlabs/Web/WebServer.php6
-rw-r--r--Zotlabs/Widget/Activity.php2
-rw-r--r--Zotlabs/Widget/Activity_filter.php12
-rw-r--r--Zotlabs/Widget/Album.php8
-rw-r--r--Zotlabs/Widget/Channel_activities.php8
-rw-r--r--Zotlabs/Widget/Helpindex.php4
-rw-r--r--Zotlabs/Widget/Hq_controls.php4
-rw-r--r--Zotlabs/Widget/Item.php2
-rw-r--r--Zotlabs/Widget/Messages.php67
-rw-r--r--Zotlabs/Widget/Notes.php9
-rw-r--r--Zotlabs/Widget/Notifications.php16
-rw-r--r--Zotlabs/Widget/Permcats.php2
-rw-r--r--Zotlabs/Widget/Pinned.php3
-rw-r--r--Zotlabs/Widget/Portfolio.php6
-rw-r--r--Zotlabs/Widget/Privacygroups.php2
-rw-r--r--Zotlabs/Widget/Rating.php6
-rw-r--r--Zotlabs/Widget/Tagcloud.php3
-rw-r--r--Zotlabs/Widget/Tasklist.php2
-rw-r--r--Zotlabs/Widget/Tokens.php2
-rw-r--r--Zotlabs/Zot6/Zot6Handler.php8
158 files changed, 7361 insertions, 2126 deletions
diff --git a/Zotlabs/ActivityStreams/ASObject.php b/Zotlabs/ActivityStreams/ASObject.php
new file mode 100644
index 000000000..1006943af
--- /dev/null
+++ b/Zotlabs/ActivityStreams/ASObject.php
@@ -0,0 +1,776 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+
+use Zotlabs\Lib\BaseObject;
+
+class ASObject extends BaseObject
+{
+ public $id;
+ public $type;
+ public $attachment;
+ public $attributedTo;
+ public $audience;
+ public $content;
+ public $context;
+ public $name;
+ public $endTime;
+ public $generator;
+ public $icon;
+ public $image;
+ public $inReplyTo;
+ public $location;
+ public $preview;
+ public $published;
+ public $replies;
+ public $startTime;
+ public $summary;
+ public $tag;
+ public $updated;
+ public $url;
+ public $to;
+ public $bto;
+ public $cc;
+ public $bcc;
+ public $mediaType;
+ public $duration;
+ public $source;
+
+
+ // Extension properties
+
+ public $signature;
+ public $proof;
+ public $sensitive;
+ public $replyTo;
+ public $wall;
+ public $isContainedConversation;
+ public $expires;
+ public $canReply;
+ public $canSearch;
+ public $directMessage;
+ public $commentPolicy;
+
+ /**
+ * @return mixed
+ */
+ public function getDirectMessage()
+ {
+ return $this->directMessage;
+ }
+
+ /**
+ * @param mixed $directMessage
+ * @return ASObject
+ */
+ public function setDirectMessage($directMessage)
+ {
+ $this->directMessage = $directMessage;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSignature()
+ {
+ return $this->signature;
+ }
+
+ /**
+ * @param mixed $signature
+ * @return ASObject
+ */
+ public function setSignature($signature)
+ {
+ $this->signature = $signature;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getProof()
+ {
+ return $this->proof;
+ }
+
+ /**
+ * @param mixed $proof
+ * @return ASObject
+ */
+ public function setProof($proof)
+ {
+ $this->proof = $proof;
+ return $this;
+ }
+
+
+ /**
+ * @return mixed
+ */
+ public function getSensitive()
+ {
+ return $this->sensitive;
+ }
+
+ /**
+ * @param mixed $sensitive
+ * @return ASObject
+ */
+ public function setSensitive($sensitive)
+ {
+ $this->sensitive = $sensitive;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getReplyTo()
+ {
+ return $this->replyTo;
+ }
+
+ /**
+ * @param mixed $replyTo
+ * @return ASObject
+ */
+ public function setReplyTo($replyTo)
+ {
+ $this->replyTo = $replyTo;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWall()
+ {
+ return $this->wall;
+ }
+
+ /**
+ * @param mixed $wall
+ * @return ASObject
+ */
+ public function setWall($wall)
+ {
+ $this->wall = $wall;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getIsContainedConversation()
+ {
+ return $this->isContainedConversation;
+ }
+
+ /**
+ * @param mixed $isContainedConversation
+ * @return ASObject
+ */
+ public function setIsContainedConversation($isContainedConversation)
+ {
+ $this->isContainedConversation = $isContainedConversation;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExpires()
+ {
+ return $this->expires;
+ }
+
+ /**
+ * @param mixed $expires
+ * @return ASObject
+ */
+ public function setExpires($expires)
+ {
+ $this->expires = $expires;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCanReply()
+ {
+ return $this->canReply;
+ }
+
+ /**
+ * @param mixed $canReply
+ * @return ASObject
+ */
+ public function setCanReply($canReply)
+ {
+ $this->canReply = $canReply;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCanSearch()
+ {
+ return $this->canSearch;
+ }
+
+ /**
+ * @param mixed $canSearch
+ * @return ASObject
+ */
+ public function setCanSearch($canSearch)
+ {
+ $this->canSearch = $canSearch;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCommentPolicy()
+ {
+ return $this->commentPolicy;
+ }
+
+ /**
+ * @param mixed $commentPolicy
+ * @return ASObject
+ */
+ public function setCommentPolicy($commentPolicy)
+ {
+ $this->commentPolicy = $commentPolicy;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @param mixed $id
+ * @return ASObject
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param mixed $type
+ * @return ASObject
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAttachment()
+ {
+ return $this->attachment;
+ }
+
+ /**
+ * @param mixed $attachment
+ * @return ASObject
+ */
+ public function setAttachment($attachment)
+ {
+ $this->attachment = $attachment;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAttributedTo()
+ {
+ return $this->attributedTo;
+ }
+
+ /**
+ * @param mixed $attributedTo
+ * @return ASObject
+ */
+ public function setAttributedTo($attributedTo)
+ {
+ $this->attributedTo = $attributedTo;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAudience()
+ {
+ return $this->audience;
+ }
+
+ /**
+ * @param mixed $audience
+ * @return ASObject
+ */
+ public function setAudience($audience)
+ {
+ $this->audience = $audience;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * @param mixed $content
+ * @return ASObject
+ */
+ public function setContent($content)
+ {
+ $this->content = $content;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getContext()
+ {
+ return $this->context;
+ }
+
+ /**
+ * @param mixed $context
+ * @return ASObject
+ */
+ public function setContext($context)
+ {
+ $this->context = $context;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param mixed $name
+ * @return ASObject
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEndTime()
+ {
+ return $this->endTime;
+ }
+
+ /**
+ * @param mixed $endTime
+ * @return ASObject
+ */
+ public function setEndTime($endTime)
+ {
+ $this->endTime = $endTime;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getGenerator()
+ {
+ return $this->generator;
+ }
+
+ /**
+ * @param mixed $generator
+ * @return ASObject
+ */
+ public function setGenerator($generator)
+ {
+ $this->generator = $generator;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getIcon()
+ {
+ return $this->icon;
+ }
+
+ /**
+ * @param mixed $icon
+ * @return ASObject
+ */
+ public function setIcon($icon)
+ {
+ $this->icon = $icon;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getImage()
+ {
+ return $this->image;
+ }
+
+ /**
+ * @param mixed $image
+ * @return ASObject
+ */
+ public function setImage($image)
+ {
+ $this->image = $image;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getInReplyTo()
+ {
+ return $this->inReplyTo;
+ }
+
+ /**
+ * @param mixed $inReplyTo
+ * @return ASObject
+ */
+ public function setInReplyTo($inReplyTo)
+ {
+ $this->inReplyTo = $inReplyTo;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLocation()
+ {
+ return $this->location;
+ }
+
+ /**
+ * @param mixed $location
+ * @return ASObject
+ */
+ public function setLocation($location)
+ {
+ $this->location = $location;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPreview()
+ {
+ return $this->preview;
+ }
+
+ /**
+ * @param mixed $preview
+ * @return ASObject
+ */
+ public function setPreview($preview)
+ {
+ $this->preview = $preview;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPublished()
+ {
+ return $this->published;
+ }
+
+ /**
+ * @param mixed $published
+ * @return ASObject
+ */
+ public function setPublished($published)
+ {
+ $this->published = $published;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getReplies()
+ {
+ return $this->replies;
+ }
+
+ /**
+ * @param mixed $replies
+ * @return ASObject
+ */
+ public function setReplies($replies)
+ {
+ $this->replies = $replies;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getStartTime()
+ {
+ return $this->startTime;
+ }
+
+ /**
+ * @param mixed $startTime
+ * @return ASObject
+ */
+ public function setStartTime($startTime)
+ {
+ $this->startTime = $startTime;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSummary()
+ {
+ return $this->summary;
+ }
+
+ /**
+ * @param mixed $summary
+ * @return ASObject
+ */
+ public function setSummary($summary)
+ {
+ $this->summary = $summary;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTag()
+ {
+ return $this->tag;
+ }
+
+ /**
+ * @param mixed $tag
+ * @return ASObject
+ */
+ public function setTag($tag)
+ {
+ $this->tag = $tag;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+ /**
+ * @param mixed $updated
+ * @return ASObject
+ */
+ public function setUpdated($updated)
+ {
+ $this->updated = $updated;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * @param mixed $url
+ * @return ASObject
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTo()
+ {
+ return $this->to;
+ }
+
+ /**
+ * @param mixed $to
+ * @return ASObject
+ */
+ public function setTo($to)
+ {
+ $this->to = $to;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getBto()
+ {
+ return $this->bto;
+ }
+
+ /**
+ * @param mixed $bto
+ * @return ASObject
+ */
+ public function setBto($bto)
+ {
+ $this->bto = $bto;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCc()
+ {
+ return $this->cc;
+ }
+
+ /**
+ * @param mixed $cc
+ * @return ASObject
+ */
+ public function setCc($cc)
+ {
+ $this->cc = $cc;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getBcc()
+ {
+ return $this->bcc;
+ }
+
+ /**
+ * @param mixed $bcc
+ * @return ASObject
+ */
+ public function setBcc($bcc)
+ {
+ $this->bcc = $bcc;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMediaType()
+ {
+ return $this->mediaType;
+ }
+
+ /**
+ * @param mixed $mediaType
+ * @return ASObject
+ */
+ public function setMediaType($mediaType)
+ {
+ $this->mediaType = $mediaType;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDuration()
+ {
+ return $this->duration;
+ }
+
+ /**
+ * @param mixed $duration
+ * @return ASObject
+ */
+ public function setDuration($duration)
+ {
+ $this->duration = $duration;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSource()
+ {
+ return $this->source;
+ }
+
+ /**
+ * @param mixed $source
+ * @return ASObject
+ */
+ public function setSource($source)
+ {
+ $this->source = $source;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/Activity.php b/Zotlabs/ActivityStreams/Activity.php
new file mode 100644
index 000000000..3fccfb964
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Activity.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Activity extends ASObject
+{
+ public $actor;
+ public $object;
+ public $target;
+ public $result;
+ public $origin;
+ public $instrument;
+
+ /**
+ * @return mixed
+ */
+ public function getActor()
+ {
+ return $this->actor;
+ }
+
+ /**
+ * @param mixed $actor
+ * @return Activity
+ */
+ public function setActor($actor)
+ {
+ $this->actor = $actor;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getObject()
+ {
+ return $this->object;
+ }
+
+ /**
+ * @param mixed $object
+ * @return Activity
+ */
+ public function setObject($object)
+ {
+ $this->object = $object;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTarget()
+ {
+ return $this->target;
+ }
+
+ /**
+ * @param mixed $target
+ * @return Activity
+ */
+ public function setTarget($target)
+ {
+ $this->target = $target;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getResult()
+ {
+ return $this->result;
+ }
+
+ /**
+ * @param mixed $result
+ * @return Activity
+ */
+ public function setResult($result)
+ {
+ $this->result = $result;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOrigin()
+ {
+ return $this->origin;
+ }
+
+ /**
+ * @param mixed $origin
+ * @return Activity
+ */
+ public function setOrigin($origin)
+ {
+ $this->origin = $origin;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getInstrument()
+ {
+ return $this->instrument;
+ }
+
+ /**
+ * @param mixed $instrument
+ * @return Activity
+ */
+ public function setInstrument($instrument)
+ {
+ $this->instrument = $instrument;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/Actor.php b/Zotlabs/ActivityStreams/Actor.php
new file mode 100644
index 000000000..4efa2f6b1
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Actor.php
@@ -0,0 +1,428 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Actor extends ASObject
+{
+ public $inbox;
+ public $outbox;
+ public $followers;
+ public $following;
+ public $permissions; /* extension property */
+ public $endpoints;
+ public $publicKey;
+ public $preferredUsername;
+ public $alsoKnownAs;
+
+ // Extension properties
+
+ public $movedTo;
+ public $copiedTo;
+ public $discoverable;
+ public $manuallyApprovesFollowers;
+ public $webfinger;
+ public $canSearch;
+ public $indexable;
+ public $assertionMethod;
+ public $gateways;
+ public $openwebauth;
+ public $authredirect;
+
+ /**
+ * @return mixed
+ */
+ public function getAlsoKnownAs()
+ {
+ return $this->alsoKnownAs;
+ }
+
+ /**
+ * @param mixed $alsoKnownAs
+ * @return Actor
+ */
+ public function setAlsoKnownAs($alsoKnownAs)
+ {
+ $this->alsoKnownAs = $alsoKnownAs;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMovedTo()
+ {
+ return $this->movedTo;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCopiedTo()
+ {
+ return $this->copiedTo;
+ }
+
+ /**
+ * @param mixed $copiedTo
+ * @return Actor
+ */
+ public function setCopiedTo($copiedTo)
+ {
+ $this->copiedTo = $copiedTo;
+ return $this;
+ }
+
+ /**
+ * @param mixed $movedTo
+ * @return Actor
+ */
+ public function setMovedTo($movedTo)
+ {
+ $this->movedTo = $movedTo;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDiscoverable()
+ {
+ return $this->discoverable;
+ }
+
+ /**
+ * @param mixed $discoverable
+ * @return Actor
+ */
+ public function setDiscoverable($discoverable)
+ {
+ $this->discoverable = $discoverable;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getManuallyApprovesFollowers()
+ {
+ return $this->manuallyApprovesFollowers;
+ }
+
+ /**
+ * @param mixed $manuallyApprovesFollowers
+ * @return Actor
+ */
+ public function setManuallyApprovesFollowers($manuallyApprovesFollowers)
+ {
+ $this->manuallyApprovesFollowers = $manuallyApprovesFollowers;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPreferredUsername()
+ {
+ return $this->preferredUsername;
+ }
+
+ /**
+ * @param mixed $preferredUsername
+ * @return Actor
+ */
+ public function setPreferredUsername($preferredUsername)
+ {
+ $this->preferredUsername = $preferredUsername;
+ return $this;
+ }
+
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @param mixed $id
+ * @return Actor
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param mixed $type
+ * @return Actor
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getInbox()
+ {
+ return $this->inbox;
+ }
+
+ /**
+ * @param mixed $inbox
+ * @return Actor
+ */
+ public function setInbox($inbox)
+ {
+ $this->inbox = $inbox;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOutbox()
+ {
+ return $this->outbox;
+ }
+
+ /**
+ * @param mixed $outbox
+ * @return Actor
+ */
+ public function setOutbox($outbox)
+ {
+ $this->outbox = $outbox;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFollowers()
+ {
+ return $this->followers;
+ }
+
+ /**
+ * @param mixed $followers
+ * @return Actor
+ */
+ public function setFollowers($followers)
+ {
+ $this->followers = $followers;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFollowing()
+ {
+ return $this->following;
+ }
+
+ /**
+ * @param mixed $following
+ * @return Actor
+ */
+ public function setFollowing($following)
+ {
+ $this->following = $following;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEndpoints()
+ {
+ return $this->endpoints;
+ }
+
+ /**
+ * @param mixed $endpoints
+ * @return Actor
+ */
+ public function setEndpoints($endpoints)
+ {
+ $this->endpoints = $endpoints;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPublicKey()
+ {
+ return $this->publicKey;
+ }
+
+ /**
+ * @param mixed $publicKey
+ * @return Actor
+ */
+ public function setPublicKey($publicKey)
+ {
+ $this->publicKey = $publicKey;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWebfinger()
+ {
+ return $this->webfinger;
+ }
+
+ /**
+ * @param mixed $webfinger
+ * @return Actor
+ */
+ public function setWebfinger($webfinger)
+ {
+ $this->webfinger = $webfinger;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCanSearch()
+ {
+ return $this->canSearch;
+ }
+
+ /**
+ * @param mixed $canSearch
+ * @return Actor
+ */
+ public function setCanSearch($canSearch)
+ {
+ $this->canSearch = $canSearch;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getIndexable()
+ {
+ return $this->indexable;
+ }
+
+ /**
+ * @param mixed $indexable
+ * @return Actor
+ */
+ public function setIndexable($indexable)
+ {
+ $this->indexable = $indexable;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssertionMethod()
+ {
+ return $this->assertionMethod;
+ }
+
+ /**
+ * @param mixed $assertionMethod
+ * @return Actor
+ */
+ public function setAssertionMethod($assertionMethod)
+ {
+ $this->assertionMethod = $assertionMethod;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getGateways()
+ {
+ return $this->gateways;
+ }
+
+ /**
+ * @param mixed $gateways
+ * @return Actor
+ */
+ public function setGateways($gateways)
+ {
+ $this->gateways = $gateways;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPermissions()
+ {
+ return $this->permissions;
+ }
+
+ /**
+ * @param mixed $permissions
+ * @return Actor
+ */
+ public function setPermissions($permissions)
+ {
+ $this->permissions = $permissions;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOpenwebauth()
+ {
+ return $this->openwebauth;
+ }
+
+ /**
+ * @param mixed $openwebauth
+ * @return Actor
+ */
+ public function setOpenwebauth($openwebauth)
+ {
+ $this->openwebauth = $openwebauth;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAuthredirect()
+ {
+ return $this->authredirect;
+ }
+
+ /**
+ * @param mixed $authredirect
+ * @return Actor
+ */
+ public function setAuthredirect($authredirect)
+ {
+ $this->authredirect = $authredirect;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/AssertionMethod.php b/Zotlabs/ActivityStreams/AssertionMethod.php
new file mode 100644
index 000000000..d34f0332c
--- /dev/null
+++ b/Zotlabs/ActivityStreams/AssertionMethod.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class AssertionMethod extends ASObject
+{
+ public $id;
+ public $type;
+ public $controller;
+ public $publicKeyMultibase;
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @param mixed $id
+ * @return AssertionMethod
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param mixed $type
+ * @return AssertionMethod
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getController()
+ {
+ return $this->controller;
+ }
+
+ /**
+ * @param mixed $controller
+ * @return AssertionMethod
+ */
+ public function setController($controller)
+ {
+ $this->controller = $controller;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPublicKeyMultibase()
+ {
+ return $this->publicKeyMultibase;
+ }
+
+ /**
+ * @param mixed $publicKeyMultibase
+ * @return AssertionMethod
+ */
+ public function setPublicKeyMultibase($publicKeyMultibase)
+ {
+ $this->publicKeyMultibase = $publicKeyMultibase;
+ return $this;
+ }
+
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/Collection.php b/Zotlabs/ActivityStreams/Collection.php
new file mode 100644
index 000000000..f005166a8
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Collection.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Collection extends ASObject
+{
+ public int $totalItems;
+ public string $current;
+ public string $first;
+ public string $last;
+ public array $items;
+
+ public mixed $collectionOf;
+
+ /**
+ * @return int
+ */
+ public function getTotalItems(): int
+ {
+ return $this->totalItems;
+ }
+
+ /**
+ * @param mixed $totalItems
+ * @return Collection
+ */
+ public function setTotalItems(mixed $totalItems): static
+ {
+ $this->totalItems = $totalItems;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCurrent(): string
+ {
+ return $this->current;
+ }
+
+ /**
+ * @param mixed $current
+ * @return Collection
+ */
+ public function setCurrent(mixed $current): static
+ {
+ $this->current = $current;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFirst(): string
+ {
+ return $this->first;
+ }
+
+ /**
+ * @param mixed $first
+ * @return Collection
+ */
+ public function setFirst(mixed $first): static
+ {
+ $this->first = $first;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLast(): string
+ {
+ return $this->last;
+ }
+
+ /**
+ * @param mixed $last
+ * @return Collection
+ */
+ public function setLast(mixed $last): static
+ {
+ $this->last = $last;
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getItems(): array
+ {
+ return $this->items;
+ }
+
+ /**
+ * @param mixed $items
+ * @return Collection
+ */
+ public function setItems(mixed $items): static
+ {
+ $this->items = $items;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCollectionOf(): mixed
+ {
+ return $this->collectionOf;
+ }
+
+ /**
+ * @param mixed $collectionOf
+ * @return Collection
+ */
+ public function setCollectionOf(mixed $collectionOf): static
+ {
+ $this->collectionOf = $collectionOf;
+ return $this;
+ }
+
+
+}
diff --git a/Zotlabs/ActivityStreams/CollectionPage.php b/Zotlabs/ActivityStreams/CollectionPage.php
new file mode 100644
index 000000000..4bdedc93e
--- /dev/null
+++ b/Zotlabs/ActivityStreams/CollectionPage.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class CollectionPage extends Collection
+{
+ public $partOf;
+ public $next;
+ public $prev;
+
+ // startIndex only applies for OrderedCollectionPage. See
+ // https://www.w3.org/ns/activitystreams#OrderedCollectionPage
+ // It is provided here to avoid multiple inheritance
+
+ public $startIndex;
+
+ /**
+ * @return mixed
+ */
+ public function getPartOf()
+ {
+ return $this->partOf;
+ }
+
+ /**
+ * @param mixed $partOf
+ * @return CollectionPage
+ */
+ public function setPartOf($partOf)
+ {
+ $this->partOf = $partOf;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNext()
+ {
+ return $this->next;
+ }
+
+ /**
+ * @param mixed $next
+ * @return CollectionPage
+ */
+ public function setNext($next)
+ {
+ $this->next = $next;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPrev()
+ {
+ return $this->prev;
+ }
+
+ /**
+ * @param mixed $prev
+ * @return CollectionPage
+ */
+ public function setPrev($prev)
+ {
+ $this->prev = $prev;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/IntransitiveActivity.php b/Zotlabs/ActivityStreams/IntransitiveActivity.php
new file mode 100644
index 000000000..62e83f63c
--- /dev/null
+++ b/Zotlabs/ActivityStreams/IntransitiveActivity.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+
+class IntransitiveActivity extends ASObject
+{
+ public $actor;
+ public $target;
+ public $result;
+ public $origin;
+ public $instrument;
+
+ /**
+ * @return mixed
+ */
+ public function getActor()
+ {
+ return $this->actor;
+ }
+
+ /**
+ * @param mixed $actor
+ * @return IntransitiveActivity
+ */
+ public function setActor($actor)
+ {
+ $this->actor = $actor;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTarget()
+ {
+ return $this->target;
+ }
+
+ /**
+ * @param mixed $target
+ * @return IntransitiveActivity
+ */
+ public function setTarget($target)
+ {
+ $this->target = $target;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getResult()
+ {
+ return $this->result;
+ }
+
+ /**
+ * @param mixed $result
+ * @return IntransitiveActivity
+ */
+ public function setResult($result)
+ {
+ $this->result = $result;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOrigin()
+ {
+ return $this->origin;
+ }
+
+ /**
+ * @param mixed $origin
+ * @return IntransitiveActivity
+ */
+ public function setOrigin($origin)
+ {
+ $this->origin = $origin;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getInstrument()
+ {
+ return $this->instrument;
+ }
+
+ /**
+ * @param mixed $instrument
+ * @return IntransitiveActivity
+ */
+ public function setInstrument($instrument)
+ {
+ $this->instrument = $instrument;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/Link.php b/Zotlabs/ActivityStreams/Link.php
new file mode 100644
index 000000000..904b354da
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Link.php
@@ -0,0 +1,183 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+use Zotlabs\Lib\BaseObject;
+
+class Link extends BaseObject
+{
+ public $type;
+ public $href;
+ public $rel;
+ public $mediaType;
+ public $name;
+ public $hreflang;
+ public $height;
+ public $width;
+ public $preview;
+
+
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param mixed $type
+ * @return Link
+ */
+ public function setType($type)
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHref()
+ {
+ return $this->href;
+ }
+
+ /**
+ * @param mixed $href
+ * @return Link
+ */
+ public function setHref($href)
+ {
+ $this->href = $href;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRel()
+ {
+ return $this->rel;
+ }
+
+ /**
+ * @param mixed $rel
+ * @return Link
+ */
+ public function setRel($rel)
+ {
+ $this->rel = $rel;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMediaType()
+ {
+ return $this->mediaType;
+ }
+
+ /**
+ * @param mixed $mediaType
+ * @return Link
+ */
+ public function setMediaType($mediaType)
+ {
+ $this->mediaType = $mediaType;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param mixed $name
+ * @return Link
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHreflang()
+ {
+ return $this->hreflang;
+ }
+
+ /**
+ * @param mixed $hreflang
+ * @return Link
+ */
+ public function setHreflang($hreflang)
+ {
+ $this->hreflang = $hreflang;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHeight()
+ {
+ return $this->height;
+ }
+
+ /**
+ * @param mixed $height
+ * @return Link
+ */
+ public function setHeight($height)
+ {
+ $this->height = $height;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWidth()
+ {
+ return $this->width;
+ }
+
+ /**
+ * @param mixed $width
+ * @return Link
+ */
+ public function setWidth($width)
+ {
+ $this->width = $width;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPreview()
+ {
+ return $this->preview;
+ }
+
+ /**
+ * @param mixed $preview
+ * @return Link
+ */
+ public function setPreview($preview)
+ {
+ $this->preview = $preview;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/OrderedCollection.php b/Zotlabs/ActivityStreams/OrderedCollection.php
new file mode 100644
index 000000000..95f5036f7
--- /dev/null
+++ b/Zotlabs/ActivityStreams/OrderedCollection.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class OrderedCollection extends Collection
+{
+
+}
diff --git a/Zotlabs/ActivityStreams/OrderedCollectionPage.php b/Zotlabs/ActivityStreams/OrderedCollectionPage.php
new file mode 100644
index 000000000..664802eff
--- /dev/null
+++ b/Zotlabs/ActivityStreams/OrderedCollectionPage.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+/**
+ * According to the specification, OrderedCollectionPage extends
+ * both OrderedCollection and CollectionPage, but PHP is still a bit awkward
+ * when it comes to multiple inheritance. Rather than try and do this with
+ * traits, we'll just include the CollectionPage elements here - as this only
+ * consists of three properties.
+ */
+
+class OrderedCollectionPage extends OrderedCollection
+{
+ public $partOf;
+ public $next;
+ public $prev;
+ public $startIndex;
+
+ /**
+ * @return mixed
+ */
+ public function getPartOf()
+ {
+ return $this->partOf;
+ }
+
+ /**
+ * @param mixed $partOf
+ * @return OrderedCollectionPage
+ */
+ public function setPartOf($partOf)
+ {
+ $this->partOf = $partOf;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNext()
+ {
+ return $this->next;
+ }
+
+ /**
+ * @param mixed $next
+ * @return OrderedCollectionPage
+ */
+ public function setNext($next)
+ {
+ $this->next = $next;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPrev()
+ {
+ return $this->prev;
+ }
+
+ /**
+ * @param mixed $prev
+ * @return OrderedCollectionPage
+ */
+ public function setPrev($prev)
+ {
+ $this->prev = $prev;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getStartIndex()
+ {
+ return $this->startIndex;
+ }
+
+ /**
+ * @param mixed $startIndex
+ * @return OrderedCollectionPage
+ */
+ public function setStartIndex($startIndex)
+ {
+ $this->startIndex = $startIndex;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/Place.php b/Zotlabs/ActivityStreams/Place.php
new file mode 100644
index 000000000..5aadc1c73
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Place.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Place extends ASObject
+{
+
+ public $accuracy;
+ public $altitude;
+ public $latitude;
+ public $longitude;
+ public $radius;
+ public $units;
+
+ /**
+ * @return mixed
+ */
+ public function getAccuracy()
+ {
+ return $this->accuracy;
+ }
+
+ /**
+ * @param mixed $accuracy
+ * @return Place
+ */
+ public function setAccuracy($accuracy)
+ {
+ $this->accuracy = $accuracy;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAltitude()
+ {
+ return $this->altitude;
+ }
+
+ /**
+ * @param mixed $altitude
+ * @return Place
+ */
+ public function setAltitude($altitude)
+ {
+ $this->altitude = $altitude;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLatitude()
+ {
+ return $this->latitude;
+ }
+
+ /**
+ * @param mixed $latitude
+ * @return Place
+ */
+ public function setLatitude($latitude)
+ {
+ $this->latitude = $latitude;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLongitude()
+ {
+ return $this->longitude;
+ }
+
+ /**
+ * @param mixed $longitude
+ * @return Place
+ */
+ public function setLongitude($longitude)
+ {
+ $this->longitude = $longitude;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRadius()
+ {
+ return $this->radius;
+ }
+
+ /**
+ * @param mixed $radius
+ * @return Place
+ */
+ public function setRadius($radius)
+ {
+ $this->radius = $radius;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUnits()
+ {
+ return $this->units;
+ }
+
+ /**
+ * @param mixed $units
+ * @return Place
+ */
+ public function setUnits($units)
+ {
+ $this->units = $units;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/Profile.php b/Zotlabs/ActivityStreams/Profile.php
new file mode 100644
index 000000000..817f4a817
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Profile.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Profile extends ASObject
+{
+
+ public $describes;
+
+ /**
+ * @return mixed
+ */
+ public function getDescribes()
+ {
+ return $this->describes;
+ }
+
+ /**
+ * @param mixed $describes
+ * @return Profile
+ */
+ public function setDescribes($describes)
+ {
+ $this->describes = $describes;
+ return $this;
+ }
+
+
+}
diff --git a/Zotlabs/ActivityStreams/PublicKey.php b/Zotlabs/ActivityStreams/PublicKey.php
new file mode 100644
index 000000000..d5e7b9522
--- /dev/null
+++ b/Zotlabs/ActivityStreams/PublicKey.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class PublicKey extends ASObject
+{
+ public $owner;
+ public $signatureAlgorithm;
+ public $publicKeyPem;
+
+ /**
+ * @return mixed
+ */
+ public function getOwner()
+ {
+ return $this->owner;
+ }
+
+ /**
+ * @param mixed $owner
+ * @return PublicKey
+ */
+ public function setOwner($owner)
+ {
+ $this->owner = $owner;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSignatureAlgorithm()
+ {
+ return $this->signatureAlgorithm;
+ }
+
+ /**
+ * @param mixed $signatureAlgorithm
+ * @return PublicKey
+ */
+ public function setSignatureAlgorithm($signatureAlgorithm)
+ {
+ $this->signatureAlgorithm = $signatureAlgorithm;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPublicKeyPem()
+ {
+ return $this->publicKeyPem;
+ }
+
+ /**
+ * @param mixed $publicKeyPem
+ * @return PublicKey
+ */
+ public function setPublicKeyPem($publicKeyPem)
+ {
+ $this->publicKeyPem = $publicKeyPem;
+ return $this;
+ }
+
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/Question.php b/Zotlabs/ActivityStreams/Question.php
new file mode 100644
index 000000000..63f642eaa
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Question.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Question extends ASObject
+{
+ public $oneOf;
+ public $anyOf;
+ public $closed;
+
+ /**
+ * @return mixed
+ */
+ public function getOneOf()
+ {
+ return $this->oneOf;
+ }
+
+ /**
+ * @param mixed $oneOf
+ * @return Question
+ */
+ public function setOneOf($oneOf)
+ {
+ $this->oneOf = $oneOf;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAnyOf()
+ {
+ return $this->anyOf;
+ }
+
+ /**
+ * @param mixed $anyOf
+ * @return Question
+ */
+ public function setAnyOf($anyOf)
+ {
+ $this->anyOf = $anyOf;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getClosed()
+ {
+ return $this->closed;
+ }
+
+ /**
+ * @param mixed $closed
+ * @return Question
+ */
+ public function setClosed($closed)
+ {
+ $this->closed = $closed;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/Relationship.php b/Zotlabs/ActivityStreams/Relationship.php
new file mode 100644
index 000000000..29669a200
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Relationship.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Relationship extends ASObject
+{
+ public $subject;
+ public $object;
+ public $relationship;
+
+ /**
+ * @return mixed
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * @param mixed $subject
+ * @return Relationship
+ */
+ public function setSubject($subject)
+ {
+ $this->subject = $subject;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getObject()
+ {
+ return $this->object;
+ }
+
+ /**
+ * @param mixed $object
+ * @return Relationship
+ */
+ public function setObject($object)
+ {
+ $this->object = $object;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRelationship()
+ {
+ return $this->relationship;
+ }
+
+ /**
+ * @param mixed $relationship
+ * @return Relationship
+ */
+ public function setRelationship($relationship)
+ {
+ $this->relationship = $relationship;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/Signature.php b/Zotlabs/ActivityStreams/Signature.php
new file mode 100644
index 000000000..e115dd331
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Signature.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Signature extends ASObject
+{
+ public $nonce;
+ public $creator;
+ public $signatureValue;
+
+ /**
+ * @return mixed
+ */
+ public function getCreator()
+ {
+ return $this->creator;
+ }
+
+ /**
+ * @param mixed $creator
+ * @return Signature
+ */
+ public function setCreator($creator)
+ {
+ $this->creator = $creator;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSignatureValue()
+ {
+ return $this->signatureValue;
+ }
+
+ /**
+ * @param mixed $signatureValue
+ * @return Signature
+ */
+ public function setSignatureValue($signatureValue)
+ {
+ $this->signatureValue = $signatureValue;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNonce()
+ {
+ return $this->nonce;
+ }
+
+ /**
+ * @param mixed $nonce
+ * @return Signature
+ */
+ public function setNonce($nonce)
+ {
+ $this->nonce = $nonce;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/ActivityStreams/Tombstone.php b/Zotlabs/ActivityStreams/Tombstone.php
new file mode 100644
index 000000000..54a6ab76c
--- /dev/null
+++ b/Zotlabs/ActivityStreams/Tombstone.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class Tombstone extends ASObject
+{
+ public $formerType;
+ public $deleted;
+
+ /**
+ * @return mixed
+ */
+ public function getFormerType()
+ {
+ return $this->formerType;
+ }
+
+ /**
+ * @param mixed $formerType
+ * @return Tombstone
+ */
+ public function setFormerType($formerType)
+ {
+ $this->formerType = $formerType;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDeleted()
+ {
+ return $this->deleted;
+ }
+
+ /**
+ * @param mixed $deleted
+ * @return Tombstone
+ */
+ public function setDeleted($deleted)
+ {
+ $this->deleted = $deleted;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/ActivityStreams/UnhandledElementException.php b/Zotlabs/ActivityStreams/UnhandledElementException.php
new file mode 100644
index 000000000..f8b71693d
--- /dev/null
+++ b/Zotlabs/ActivityStreams/UnhandledElementException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Zotlabs\ActivityStreams;
+
+class UnhandledElementException extends \Exception
+{
+
+}
diff --git a/Zotlabs/Daemon/Channel_purge.php b/Zotlabs/Daemon/Channel_purge.php
index 9fceb0fb9..7286a791a 100644
--- a/Zotlabs/Daemon/Channel_purge.php
+++ b/Zotlabs/Daemon/Channel_purge.php
@@ -24,7 +24,7 @@ class Channel_purge {
);
if ($r) {
foreach ($r as $rv) {
- drop_item($rv['id'], false);
+ drop_item($rv['id'], uid: $channel_id);
}
}
} while ($r);
diff --git a/Zotlabs/Daemon/Content_importer.php b/Zotlabs/Daemon/Content_importer.php
index 67f1c8e80..b98a1f10d 100644
--- a/Zotlabs/Daemon/Content_importer.php
+++ b/Zotlabs/Daemon/Content_importer.php
@@ -38,7 +38,13 @@ class Content_importer {
$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 ]);
+ $redirects = 0;
+ $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));
@@ -47,9 +53,9 @@ class Content_importer {
killme();
}
- $j = json_decode($x['body'],true);
+ $j = json_decode($x['body'], true);
- if(! is_array($j['item']) || ! count($j['item'])) {
+ if($j && empty($j['item'])) {
PConfig::Set($channel['channel_id'], 'import', 'content_completed', 1);
return;
}
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index d2c863572..a38809f45 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -69,18 +69,18 @@ class Cron {
// expire any expired items
- $r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
+ $r = q("select id, uid, item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
and item_deleted = 0 ",
db_utcnow()
);
+
if ($r) {
- require_once('include/items.php');
foreach ($r as $rr) {
- drop_item($rr['id'], false, (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
+ // pass uid of the message for permission check as we are running as a daemon process with no session.
+ drop_item($rr['id'], (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL), uid: intval($rr['uid']));
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon(['Notifier', 'drop', $rr['id']]);
-
if ($interval) {
usleep($interval);
}
@@ -147,40 +147,29 @@ class Cron {
// (time travel posts). Restrict to items that have come of age in the last
// couple of days to limit the query to something reasonable.
- $r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
+ $r = q("select * from item where item_delayed = 1 and created <= %s and created > '%s' ",
db_utcnow(),
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
);
- if ($r) {
- foreach ($r as $rr) {
- $x = q("update item set item_delayed = 0 where id = %d",
- intval($rr['id'])
- );
- if ($x) {
- $z = q("select * from item where id = %d",
- intval($rr['id'])
- );
- if ($z) {
- xchan_query($z);
- $sync_item = fetch_post_tags($z);
- Libsync::build_sync_packet($sync_item[0]['uid'],
- [
- 'item' => [encode_item($sync_item[0], true)]
- ]
- );
- }
- Master::Summon(array('Notifier', 'wall-new', $rr['id']));
- if ($interval) {
- usleep($interval);
+ if ($r) {
+ xchan_query($r);
+ $items = fetch_post_tags($r);
+ foreach ($items as $item) {
+ $item['item_delayed'] = 0;
+ $post = item_store_update($item);
+
+ if($post['success']) {
+ Master::Summon(['Notifier', 'wall-new', $post['item_id']]);
+ if (!empty($post['approval_id'])) {
+ Master::Summon(['Notifier', 'wall-new', $post['approval_id']]);
}
}
- }
- }
-
- require_once('include/attach.php');
- attach_upgrade();
-
+ if ($interval) {
+ usleep($interval);
+ }
+ }
+ }
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
diff --git a/Zotlabs/Daemon/Expire.php b/Zotlabs/Daemon/Expire.php
index ad52a6b71..dae585578 100644
--- a/Zotlabs/Daemon/Expire.php
+++ b/Zotlabs/Daemon/Expire.php
@@ -23,13 +23,13 @@ class Expire {
// perform final cleanup on previously delete items
- $r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
+ $r = q("select id, uid from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('10 DAY')
);
if ($r) {
foreach ($r as $rr) {
- drop_item($rr['id'], false, DROPITEM_PHASE2);
+ drop_item($rr['id'], DROPITEM_PHASE2, uid: $rr['uid']);
}
}
diff --git a/Zotlabs/Daemon/File_importer.php b/Zotlabs/Daemon/File_importer.php
index 7067e152d..1ddab60f0 100644
--- a/Zotlabs/Daemon/File_importer.php
+++ b/Zotlabs/Daemon/File_importer.php
@@ -38,7 +38,13 @@ class File_importer {
$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 ]);
+ $redirects = 0;
+ $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']) {
diff --git a/Zotlabs/Daemon/Importdoc.php b/Zotlabs/Daemon/Importdoc.php
index c5a81e50c..de571848e 100644
--- a/Zotlabs/Daemon/Importdoc.php
+++ b/Zotlabs/Daemon/Importdoc.php
@@ -11,6 +11,21 @@ class Importdoc {
self::update_docs_dir('doc/*');
+ $sys = get_sys_channel();
+
+ // remove old files that weren't updated (indicates they were most likely deleted).
+ $i = q("select id from item where uid = %d and item_type = 5 and edited < %s - INTERVAL %s",
+ intval($sys['channel_id']),
+ db_utcnow(),
+ db_quoteinterval('14 DAY')
+ );
+
+ if ($i) {
+ foreach ($i as $iv) {
+ drop_item($iv['id'], uid: $sys['channel_id']);
+ }
+ }
+
return;
}
@@ -18,9 +33,13 @@ class Importdoc {
static public function update_docs_dir($s) {
$f = basename($s);
$d = dirname($s);
- if ($s === 'doc/html')
+
+ if ($s === 'doc/html') {
return;
+ }
+
$files = glob("$d/$f");
+
if ($files) {
foreach ($files as $fi) {
if ($fi === 'doc/html') {
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index 20134b8fe..9fdb1defb 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -241,11 +241,6 @@ class Notifier {
$target_item = $r[0];
- if (in_array($target_item['author']['xchan_network'], ['rss', 'anon', 'token'])) {
- logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
- return;
- }
-
if (intval($target_item['item_deleted'])) {
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
}
@@ -268,22 +263,9 @@ class Notifier {
}
- // Check for non published items, but allow an exclusion for transmitting hidden file activities
-
- if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
- intval($target_item['item_blocked']) || intval($target_item['item_hidden'])) {
- logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
- return;
- }
-
- // follow/unfollow is for internal use only
- if (in_array($target_item['verb'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
- logger('not fowarding follow/unfollow note activity');
- return;
- }
-
- if (strpos($target_item['postopts'], 'nodeliver') !== false) {
- logger('notifier: target item is undeliverable', LOGGER_DEBUG);
+ if (!item_forwardable($target_item)) {
+ //hz_syslog(print_r($target_item,true));
+ logger('notifier: target item not forwardable', LOGGER_DEBUG);
return;
}
@@ -299,7 +281,7 @@ class Notifier {
return;
}
- if ($target_item['verb'] === ACTIVITY_SHARE) {
+ if (in_array($target_item['verb'], [ACTIVITY_SHARE])) {
// Provide correct representation across the wire. Internally this is treated as a comment.
$target_item['parent_mid'] = $target_item['thr_parent'] = $target_item['mid'];
}
@@ -341,7 +323,13 @@ class Notifier {
self::$encoded_item = json_decode($m, true);
}
else {
- self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
+ $activity = Activity::encode_activity($target_item);
+
+ if (!$activity) {
+ return;
+ }
+
+ self::$encoded_item = Activity::build_packet($activity, self::$channel, false);
}
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
@@ -358,6 +346,10 @@ class Notifier {
$relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
+ if (self::$channel['channel_hash'] === $target_item['owner_xchan']) {
+ $relay_to_owner = 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
@@ -374,7 +366,6 @@ class Notifier {
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
- // If the Parent item is an Announce the real owner is the parent author
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
self::$recipients = [$sendto];
self::$private = true;
@@ -389,7 +380,7 @@ class Notifier {
logger('normal (downstream) distribution', LOGGER_DEBUG);
}
- if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
+ if (($parent_item && $parent_item['item_private'] !== $target_item['item_private']) || (intval($target_item['item_restrict']) & 1)) {
logger('conversation privacy mismatch - downstream delivery prevented');
return;
}
@@ -589,8 +580,6 @@ class Notifier {
foreach ($dhubs as $hub) {
- logger('notifier_hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
-
if ($hub['hubloc_network'] !== 'zot6') {
$narr = [
'channel' => self::$channel,
diff --git a/Zotlabs/Entity/Account.php b/Zotlabs/Entity/Account.php
new file mode 100644
index 000000000..2d3af5e4b
--- /dev/null
+++ b/Zotlabs/Entity/Account.php
@@ -0,0 +1,352 @@
+<?php
+
+namespace Zotlabs\Entity;
+
+use Zotlabs\Lib\BaseObject;
+
+class Account extends BaseObject
+{
+ public $account_id;
+ public $account_parent;
+ public $account_default_channel;
+ public $account_salt;
+ public $account_password;
+ public $account_email;
+ public $account_external;
+ public $account_language;
+ public $account_created;
+ public $account_lastlog;
+ public $account_flags;
+ public $account_roles;
+ public $account_reset;
+ public $account_expires;
+ public $account_expire_notified;
+ public $account_service_class;
+ public $account_level;
+ public $account_password_change;
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->account_id;
+ }
+
+ /**
+ * @param mixed $account_id
+ * @return Account
+ */
+ public function setId($account_id)
+ {
+ $this->account_id = $account_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getParent()
+ {
+ return $this->account_parent;
+ }
+
+ /**
+ * @param mixed $account_parent
+ * @return Account
+ */
+ public function setParent($account_parent)
+ {
+ $this->account_parent = $account_parent;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDefaultChannel()
+ {
+ return $this->account_default_channel;
+ }
+
+ /**
+ * @param mixed $account_default_channel
+ * @return Account
+ */
+ public function setDefaultChannel($account_default_channel)
+ {
+ $this->account_default_channel = $account_default_channel;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSalt()
+ {
+ return $this->account_salt;
+ }
+
+ /**
+ * @param mixed $account_salt
+ * @return Account
+ */
+ public function setSalt($account_salt)
+ {
+ $this->account_salt = $account_salt;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPassword()
+ {
+ return $this->account_password;
+ }
+
+ /**
+ * @param mixed $account_password
+ * @return Account
+ */
+ public function setPassword($account_password)
+ {
+ $this->account_password = $account_password;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEmail()
+ {
+ return $this->account_email;
+ }
+
+ /**
+ * @param mixed $account_email
+ * @return Account
+ */
+ public function setEmail($account_email)
+ {
+ $this->account_email = $account_email;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExternal()
+ {
+ return $this->account_external;
+ }
+
+ /**
+ * @param mixed $account_external
+ * @return Account
+ */
+ public function setExternal($account_external)
+ {
+ $this->account_external = $account_external;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLanguage()
+ {
+ return $this->account_language;
+ }
+
+ /**
+ * @param mixed $account_language
+ * @return Account
+ */
+ public function setLanguage($account_language)
+ {
+ $this->account_language = $account_language;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->account_created;
+ }
+
+ /**
+ * @param mixed $account_created
+ * @return Account
+ */
+ public function setCreated($account_created)
+ {
+ $this->account_created = $account_created;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLastlog()
+ {
+ return $this->account_lastlog;
+ }
+
+ /**
+ * @param mixed $account_lastlog
+ * @return Account
+ */
+ public function setLastlog($account_lastlog)
+ {
+ $this->account_lastlog = $account_lastlog;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlags()
+ {
+ return $this->account_flags;
+ }
+
+ /**
+ * @param mixed $account_flags
+ * @return Account
+ */
+ public function setFlags($account_flags)
+ {
+ $this->account_flags = $account_flags;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRoles()
+ {
+ return $this->account_roles;
+ }
+
+ /**
+ * @param mixed $account_roles
+ * @return Account
+ */
+ public function setRoles($account_roles)
+ {
+ $this->account_roles = $account_roles;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getReset()
+ {
+ return $this->account_reset;
+ }
+
+ /**
+ * @param mixed $account_reset
+ * @return Account
+ */
+ public function setReset($account_reset)
+ {
+ $this->account_reset = $account_reset;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExpires()
+ {
+ return $this->account_expires;
+ }
+
+ /**
+ * @param mixed $account_expires
+ * @return Account
+ */
+ public function setExpires($account_expires)
+ {
+ $this->account_expires = $account_expires;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExpireNotified()
+ {
+ return $this->account_expire_notified;
+ }
+
+ /**
+ * @param mixed $account_expire_notified
+ * @return Account
+ */
+ public function setExpireNotified($account_expire_notified)
+ {
+ $this->account_expire_notified = $account_expire_notified;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getServiceClass()
+ {
+ return $this->account_service_class;
+ }
+
+ /**
+ * @param mixed $account_service_class
+ * @return Account
+ */
+ public function setServiceClass($account_service_class)
+ {
+ $this->account_service_class = $account_service_class;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLevel()
+ {
+ return $this->account_level;
+ }
+
+ /**
+ * @param mixed $account_level
+ * @return Account
+ */
+ public function setLevel($account_level)
+ {
+ $this->account_level = $account_level;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPasswordChange()
+ {
+ return $this->account_password_change;
+ }
+
+ /**
+ * @param mixed $account_password_change
+ * @return Account
+ */
+ public function setPasswordChange($account_password_change)
+ {
+ $this->account_password_change = $account_password_change;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/Entity/Channel.php b/Zotlabs/Entity/Channel.php
new file mode 100644
index 000000000..e9f7dc14f
--- /dev/null
+++ b/Zotlabs/Entity/Channel.php
@@ -0,0 +1,714 @@
+<?php
+
+namespace Zotlabs\Entity;
+
+use Zotlabs\Lib\BaseObject;
+
+class Channel extends BaseObject
+{
+ public $channel_id;
+ public $channel_account_id;
+ public $channel_primary;
+ public $channel_name;
+ public $channel_parent;
+ public $channel_address;
+ public $channel_guid;
+ public $channel_guid_sig;
+ public $channel_hash;
+ public $channel_timezone;
+ public $channel_location;
+ public $channel_theme;
+ public $channel_startpage;
+ public $channel_pubkey;
+ public $channel_prvkey;
+ public $channel_epubkey;
+ public $channel_eprvkey;
+ public $channel_notifyflags;
+ public $channel_pageflags;
+ public $channel_dirdate;
+ public $channel_lastpost;
+ public $channel_deleted;
+ public $channel_active;
+ public $channel_max_anon_mail;
+ public $channel_max_friend_req;
+ public $channel_expire_days;
+ public $channel_passwd_reset;
+ public $channel_default_group;
+ public $channel_allow_cid;
+ public $channel_allow_gid;
+ public $channel_deny_cid;
+ public $channel_deny_gid;
+ public $channel_removed;
+ public $channel_system;
+ public $channel_moved;
+ public $channel_password;
+ public $channel_salt;
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->channel_id;
+ }
+
+ /**
+ * @param mixed $channel_id
+ * @return Channel
+ */
+ public function setId($channel_id)
+ {
+ $this->channel_id = $channel_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAccountId()
+ {
+ return $this->channel_account_id;
+ }
+
+ /**
+ * @param mixed $channel_account_id
+ * @return Channel
+ */
+ public function setAccountId($channel_account_id)
+ {
+ $this->channel_account_id = $channel_account_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPrimary()
+ {
+ return $this->channel_primary;
+ }
+
+ /**
+ * @param mixed $channel_primary
+ * @return Channel
+ */
+ public function setPrimary($channel_primary)
+ {
+ $this->channel_primary = $channel_primary;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->channel_name;
+ }
+
+ /**
+ * @param mixed $channel_name
+ * @return Channel
+ */
+ public function setName($channel_name)
+ {
+ $this->channel_name = $channel_name;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getParent()
+ {
+ return $this->channel_parent;
+ }
+
+ /**
+ * @param mixed $channel_parent
+ * @return Channel
+ */
+ public function setParent($channel_parent)
+ {
+ $this->channel_parent = $channel_parent;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAddress()
+ {
+ return $this->channel_address;
+ }
+
+ /**
+ * @param mixed $channel_address
+ * @return Channel
+ */
+ public function setAddress($channel_address)
+ {
+ $this->channel_address = $channel_address;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getGuid()
+ {
+ return $this->channel_guid;
+ }
+
+ /**
+ * @param mixed $channel_guid
+ * @return Channel
+ */
+ public function setGuid($channel_guid)
+ {
+ $this->channel_guid = $channel_guid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getGuidSig()
+ {
+ return $this->channel_guid_sig;
+ }
+
+ /**
+ * @param mixed $channel_guid_sig
+ * @return Channel
+ */
+ public function setGuidSig($channel_guid_sig)
+ {
+ $this->channel_guid_sig = $channel_guid_sig;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHash()
+ {
+ return $this->channel_hash;
+ }
+
+ /**
+ * @param mixed $channel_hash
+ * @return Channel
+ */
+ public function setHash($channel_hash)
+ {
+ $this->channel_hash = $channel_hash;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTimezone()
+ {
+ return $this->channel_timezone;
+ }
+
+ /**
+ * @param mixed $channel_timezone
+ * @return Channel
+ */
+ public function setTimezone($channel_timezone)
+ {
+ $this->channel_timezone = $channel_timezone;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLocation()
+ {
+ return $this->channel_location;
+ }
+
+ /**
+ * @param mixed $channel_location
+ * @return Channel
+ */
+ public function setLocation($channel_location)
+ {
+ $this->channel_location = $channel_location;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTheme()
+ {
+ return $this->channel_theme;
+ }
+
+ /**
+ * @param mixed $channel_theme
+ * @return Channel
+ */
+ public function setTheme($channel_theme)
+ {
+ $this->channel_theme = $channel_theme;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getStartpage()
+ {
+ return $this->channel_startpage;
+ }
+
+ /**
+ * @param mixed $channel_startpage
+ * @return Channel
+ */
+ public function setStartpage($channel_startpage)
+ {
+ $this->channel_startpage = $channel_startpage;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPubkey()
+ {
+ return $this->channel_pubkey;
+ }
+
+ /**
+ * @param mixed $channel_pubkey
+ * @return Channel
+ */
+ public function setPubkey($channel_pubkey)
+ {
+ $this->channel_pubkey = $channel_pubkey;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPrvkey()
+ {
+ return $this->channel_prvkey;
+ }
+
+ /**
+ * @param mixed $channel_prvkey
+ * @return Channel
+ */
+ public function setPrvkey($channel_prvkey)
+ {
+ $this->channel_prvkey = $channel_prvkey;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEpubkey()
+ {
+ return $this->channel_epubkey;
+ }
+
+ /**
+ * @param mixed $channel_epubkey
+ * @return Channel
+ */
+ public function setEpubkey($channel_epubkey)
+ {
+ $this->channel_epubkey = $channel_epubkey;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEprvkey()
+ {
+ return $this->channel_eprvkey;
+ }
+
+ /**
+ * @param mixed $channel_eprvkey
+ * @return Channel
+ */
+ public function setEprvkey($channel_eprvkey)
+ {
+ $this->channel_eprvkey = $channel_eprvkey;
+ return $this;
+ }
+
+
+ /**
+ * @return mixed
+ */
+ public function getNotifyflags()
+ {
+ return $this->channel_notifyflags;
+ }
+
+ /**
+ * @param mixed $channel_notifyflags
+ * @return Channel
+ */
+ public function setNotifyflags($channel_notifyflags)
+ {
+ $this->channel_notifyflags = $channel_notifyflags;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPageflags()
+ {
+ return $this->channel_pageflags;
+ }
+
+ /**
+ * @param mixed $channel_pageflags
+ * @return Channel
+ */
+ public function setPageflags($channel_pageflags)
+ {
+ $this->channel_pageflags = $channel_pageflags;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDirdate()
+ {
+ return $this->channel_dirdate;
+ }
+
+ /**
+ * @param mixed $channel_dirdate
+ * @return Channel
+ */
+ public function setDirdate($channel_dirdate)
+ {
+ $this->channel_dirdate = $channel_dirdate;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLastpost()
+ {
+ return $this->channel_lastpost;
+ }
+
+ /**
+ * @param mixed $channel_lastpost
+ * @return Channel
+ */
+ public function setLastpost($channel_lastpost)
+ {
+ $this->channel_lastpost = $channel_lastpost;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDeleted()
+ {
+ return $this->channel_deleted;
+ }
+
+ /**
+ * @param mixed $channel_deleted
+ * @return Channel
+ */
+ public function setDeleted($channel_deleted)
+ {
+ $this->channel_deleted = $channel_deleted;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getActive()
+ {
+ return $this->channel_active;
+ }
+
+ /**
+ * @param mixed $channel_active
+ * @return Channel
+ */
+ public function setActive($channel_active)
+ {
+ $this->channel_active = $channel_active;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMaxAnonMail()
+ {
+ return $this->channel_max_anon_mail;
+ }
+
+ /**
+ * @param mixed $channel_max_anon_mail
+ * @return Channel
+ */
+ public function setMaxAnonMail($channel_max_anon_mail)
+ {
+ $this->channel_max_anon_mail = $channel_max_anon_mail;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMaxFriendReq()
+ {
+ return $this->channel_max_friend_req;
+ }
+
+ /**
+ * @param mixed $channel_max_friend_req
+ * @return Channel
+ */
+ public function setMaxFriendReq($channel_max_friend_req)
+ {
+ $this->channel_max_friend_req = $channel_max_friend_req;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExpireDays()
+ {
+ return $this->channel_expire_days;
+ }
+
+ /**
+ * @param mixed $channel_expire_days
+ * @return Channel
+ */
+ public function setExpireDays($channel_expire_days)
+ {
+ $this->channel_expire_days = $channel_expire_days;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPasswdReset()
+ {
+ return $this->channel_passwd_reset;
+ }
+
+ /**
+ * @param mixed $channel_passwd_reset
+ * @return Channel
+ */
+ public function setPasswdReset($channel_passwd_reset)
+ {
+ $this->channel_passwd_reset = $channel_passwd_reset;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDefaultGroup()
+ {
+ return $this->channel_default_group;
+ }
+
+ /**
+ * @param mixed $channel_default_group
+ * @return Channel
+ */
+ public function setDefaultGroup($channel_default_group)
+ {
+ $this->channel_default_group = $channel_default_group;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAllowCid()
+ {
+ return $this->channel_allow_cid;
+ }
+
+ /**
+ * @param mixed $channel_allow_cid
+ * @return Channel
+ */
+ public function setAllowCid($channel_allow_cid)
+ {
+ $this->channel_allow_cid = $channel_allow_cid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAllowGid()
+ {
+ return $this->channel_allow_gid;
+ }
+
+ /**
+ * @param mixed $channel_allow_gid
+ * @return Channel
+ */
+ public function setAllowGid($channel_allow_gid)
+ {
+ $this->channel_allow_gid = $channel_allow_gid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDenyCid()
+ {
+ return $this->channel_deny_cid;
+ }
+
+ /**
+ * @param mixed $channel_deny_cid
+ * @return Channel
+ */
+ public function setDenyCid($channel_deny_cid)
+ {
+ $this->channel_deny_cid = $channel_deny_cid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDenyGid()
+ {
+ return $this->channel_deny_gid;
+ }
+
+ /**
+ * @param mixed $channel_deny_gid
+ * @return Channel
+ */
+ public function setDenyGid($channel_deny_gid)
+ {
+ $this->channel_deny_gid = $channel_deny_gid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRemoved()
+ {
+ return $this->channel_removed;
+ }
+
+ /**
+ * @param mixed $channel_removed
+ * @return Channel
+ */
+ public function setRemoved($channel_removed)
+ {
+ $this->channel_removed = $channel_removed;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSystem()
+ {
+ return $this->channel_system;
+ }
+
+ /**
+ * @param mixed $channel_system
+ * @return Channel
+ */
+ public function setSystem($channel_system)
+ {
+ $this->channel_system = $channel_system;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMoved()
+ {
+ return $this->channel_moved;
+ }
+
+ /**
+ * @param mixed $channel_moved
+ * @return Channel
+ */
+ public function setMoved($channel_moved)
+ {
+ $this->channel_moved = $channel_moved;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPassword()
+ {
+ return $this->channel_password;
+ }
+
+ /**
+ * @param mixed $channel_password
+ * @return Channel
+ */
+ public function setPassword($channel_password)
+ {
+ $this->channel_password = $channel_password;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSalt()
+ {
+ return $this->channel_salt;
+ }
+
+ /**
+ * @param mixed $channel_salt
+ * @return Channel
+ */
+ public function setSalt($channel_salt)
+ {
+ $this->channel_salt = $channel_salt;
+ return $this;
+ }
+
+}
diff --git a/Zotlabs/Entity/Item.php b/Zotlabs/Entity/Item.php
new file mode 100644
index 000000000..76ff8b150
--- /dev/null
+++ b/Zotlabs/Entity/Item.php
@@ -0,0 +1,1498 @@
+<?php
+
+namespace Zotlabs\Entity;
+
+use Zotlabs\Lib\BaseObject;
+
+class Item extends BaseObject
+{
+ // primary index auto-increment
+ public $id;
+ // id of the thread top-level parent
+ public $parent;
+
+ // account id of the owner of this record
+ public $aid;
+ // channel id of the owner of this record
+ public $uid;
+
+ // UUID-V4 // If no UUID is provided UUID-V5 of the message id
+ public $uuid;
+
+ // message id
+ public $mid;
+
+ // message id of top-level parent
+ public $parent_mid;
+ // message id of immediate parent
+ public $thr_parent;
+
+ // int thread depth
+ public $item_level;
+
+ // url pointing to the local copy of this item
+ public $llink;
+
+ // url pointing to permalink or this item origin
+ public $plink;
+
+ // UTC datetime the item was created
+ public $created;
+ // UTC datetime the item was changed
+ public $edited;
+ // UTC datetime the item will self-destruct
+ public $expires;
+ // UTC datetime last comment
+ public $commented;
+ // UTC datetime received here
+ public $received;
+ // UTC datetime this record last modified
+ public $changed;
+ // UTC datetime comments will be refused
+ public $comments_closed;
+
+ // portable id of channel that initiated this conversation thread
+ public $owner_xchan;
+ // portable id of item creator
+ public $author_xchan;
+ // portable id of real (upstream) author if relayed
+ public $source_xchan;
+ // MIME type of item body
+ public $mimetype;
+
+ // ISO language string
+ public $lang;
+ // Name of publishing software
+ public $app;
+ // Title of item
+ public $title;
+ // Sommary of item
+ public $summary;
+ // body of item
+ public $body;
+ // html representation
+ public $html;
+ // Activity type
+ public $verb;
+ // Activity object type
+ public $obj_type;
+ // Activity object content JSON
+ public $obj;
+ // Activity target type
+ public $tgt_type;
+ // Activity target content JSON
+ public $target;
+ // attachments
+ public $attach;
+ // signature information
+ public $sig;
+
+ // version of this item
+ public $revision;
+ // message id of controlling layout (CMS use)
+ public $layout_mid;
+ // shared storage for delivery addons
+ public $postopts;
+ // delivery relay tracking
+ public $route;
+ // UUID of attached resource
+ public $resource_id;
+ // table type of attacched resource
+ public $resource_type;
+
+ // free-form text location
+ public $location;
+ // combined coordinates (text)
+ public $coord;
+ // string public policy
+ public $public_policy;
+ // string comment policy
+ public $comment_policy;
+ // string encoded array of portable ids
+ public $allow_cid;
+ // string encoded array of access group UUIDs
+ public $allow_gid;
+ // string encoded array blocked portable ids
+ public $deny_cid;
+ // string encoded array blocked access group UUIDs
+ public $deny_gid;
+ public $item_restrict;
+ public $item_flags;
+ public $item_private;
+ public $item_origin;
+ public $item_unseen;
+ public $item_starred;
+ public $item_uplink;
+ public $item_consensus;
+ public $item_wall;
+ public $item_thread_top;
+ public $item_notshown;
+ public $item_nsfw;
+ public $item_relay;
+ public $item_mentionsme;
+ public $item_nocomment;
+ public $item_obscured;
+ public $item_verified;
+ public $item_retained;
+ public $item_rss;
+ public $item_deleted;
+ public $item_type;
+ public $item_hidden;
+ public $item_unpublished;
+ public $item_delayed;
+ public $item_pending_remove;
+ public $item_blocked;
+
+ /**
+ * @return mixed
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @param mixed $id
+ * @return Item
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMid()
+ {
+ return $this->mid;
+ }
+
+ /**
+ * @param mixed $mid
+ * @return Item
+ */
+ public function setMid($mid)
+ {
+ $this->mid = $mid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUuid()
+ {
+ return $this->uuid;
+ }
+
+ /**
+ * @param mixed $uuid
+ * @return Item
+ */
+ public function setUuid($uuid)
+ {
+ $this->uuid = $uuid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAid()
+ {
+ return $this->aid;
+ }
+
+ /**
+ * @param mixed $aid
+ * @return Item
+ */
+ public function setAid($aid)
+ {
+ $this->aid = $aid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUid()
+ {
+ return $this->uid;
+ }
+
+ /**
+ * @param mixed $uid
+ * @return Item
+ */
+ public function setUid($uid)
+ {
+ $this->uid = $uid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getParent()
+ {
+ return $this->parent;
+ }
+
+ /**
+ * @param mixed $parent
+ * @return Item
+ */
+ public function setParent($parent)
+ {
+ $this->parent = $parent;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getParentMid()
+ {
+ return $this->parent_mid;
+ }
+
+ /**
+ * @param mixed $parent_mid
+ * @return Item
+ */
+ public function setParentMid($parent_mid)
+ {
+ $this->parent_mid = $parent_mid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getThrParent()
+ {
+ return $this->thr_parent;
+ }
+
+ /**
+ * @param mixed $thr_parent
+ * @return Item
+ */
+ public function setThrParent($thr_parent)
+ {
+ $this->thr_parent = $thr_parent;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLevel()
+ {
+ return $this->item_level;
+ }
+
+ /**
+ * @param mixed $item_level
+ * @return Item
+ */
+ public function setLevel($item_level)
+ {
+ $this->item_level = $item_level;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * @param mixed $created
+ * @return Item
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEdited()
+ {
+ return $this->edited;
+ }
+
+ /**
+ * @param mixed $edited
+ * @return Item
+ */
+ public function setEdited($edited)
+ {
+ $this->edited = $edited;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getExpires()
+ {
+ return $this->expires;
+ }
+
+ /**
+ * @param mixed $expires
+ * @return Item
+ */
+ public function setExpires($expires)
+ {
+ $this->expires = $expires;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCommented()
+ {
+ return $this->commented;
+ }
+
+ /**
+ * @param mixed $commented
+ * @return Item
+ */
+ public function setCommented($commented)
+ {
+ $this->commented = $commented;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getReceived()
+ {
+ return $this->received;
+ }
+
+ /**
+ * @param mixed $received
+ * @return Item
+ */
+ public function setReceived($received)
+ {
+ $this->received = $received;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getChanged()
+ {
+ return $this->changed;
+ }
+
+ /**
+ * @param mixed $changed
+ * @return Item
+ */
+ public function setChanged($changed)
+ {
+ $this->changed = $changed;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCommentsClosed()
+ {
+ return $this->comments_closed;
+ }
+
+ /**
+ * @param mixed $comments_closed
+ * @return Item
+ */
+ public function setCommentsClosed($comments_closed)
+ {
+ $this->comments_closed = $comments_closed;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOwnerXchan()
+ {
+ return $this->owner_xchan;
+ }
+
+ /**
+ * @param mixed $owner_xchan
+ * @return Item
+ */
+ public function setOwnerXchan($owner_xchan)
+ {
+ $this->owner_xchan = $owner_xchan;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAuthorXchan()
+ {
+ return $this->author_xchan;
+ }
+
+ /**
+ * @param mixed $author_xchan
+ * @return Item
+ */
+ public function setAuthorXchan($author_xchan)
+ {
+ $this->author_xchan = $author_xchan;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSourceXchan()
+ {
+ return $this->source_xchan;
+ }
+
+ /**
+ * @param mixed $source_xchan
+ * @return Item
+ */
+ public function setSourceXchan($source_xchan)
+ {
+ $this->source_xchan = $source_xchan;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMimetype()
+ {
+ return $this->mimetype;
+ }
+
+ /**
+ * @param mixed $mimetype
+ * @return Item
+ */
+ public function setMimetype($mimetype)
+ {
+ $this->mimetype = $mimetype;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * @param mixed $title
+ * @return Item
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSummary()
+ {
+ return $this->summary;
+ }
+
+ /**
+ * @param mixed $summary
+ * @return Item
+ */
+ public function setSummary($summary)
+ {
+ $this->summary = $summary;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getBody()
+ {
+ return $this->body;
+ }
+
+ /**
+ * @param mixed $body
+ * @return Item
+ */
+ public function setBody($body)
+ {
+ $this->body = $body;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHtml()
+ {
+ return $this->html;
+ }
+
+ /**
+ * @param mixed $html
+ * @return Item
+ */
+ public function setHtml($html)
+ {
+ $this->html = $html;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getApp()
+ {
+ return $this->app;
+ }
+
+ /**
+ * @param mixed $app
+ * @return Item
+ */
+ public function setApp($app)
+ {
+ $this->app = $app;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLang()
+ {
+ return $this->lang;
+ }
+
+ /**
+ * @param mixed $lang
+ * @return Item
+ */
+ public function setLang($lang)
+ {
+ $this->lang = $lang;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRevision()
+ {
+ return $this->revision;
+ }
+
+ /**
+ * @param mixed $revision
+ * @return Item
+ */
+ public function setRevision($revision)
+ {
+ $this->revision = $revision;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getVerb()
+ {
+ return $this->verb;
+ }
+
+ /**
+ * @param mixed $verb
+ * @return Item
+ */
+ public function setVerb($verb)
+ {
+ $this->verb = $verb;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getObjType()
+ {
+ return $this->obj_type;
+ }
+
+ /**
+ * @param mixed $obj_type
+ * @return Item
+ */
+ public function setObjType($obj_type)
+ {
+ $this->obj_type = $obj_type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getObj()
+ {
+ return $this->obj;
+ }
+
+ /**
+ * @param mixed $obj
+ * @return Item
+ */
+ public function setObj($obj)
+ {
+ $this->obj = $obj;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTgtType()
+ {
+ return $this->tgt_type;
+ }
+
+ /**
+ * @param mixed $tgt_type
+ * @return Item
+ */
+ public function setTgtType($tgt_type)
+ {
+ $this->tgt_type = $tgt_type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTarget()
+ {
+ return $this->target;
+ }
+
+ /**
+ * @param mixed $target
+ * @return Item
+ */
+ public function setTarget($target)
+ {
+ $this->target = $target;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLayoutMid()
+ {
+ return $this->layout_mid;
+ }
+
+ /**
+ * @param mixed $layout_mid
+ * @return Item
+ */
+ public function setLayoutMid($layout_mid)
+ {
+ $this->layout_mid = $layout_mid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPostopts()
+ {
+ return $this->postopts;
+ }
+
+ /**
+ * @param mixed $postopts
+ * @return Item
+ */
+ public function setPostopts($postopts)
+ {
+ $this->postopts = $postopts;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRoute()
+ {
+ return $this->route;
+ }
+
+ /**
+ * @param mixed $route
+ * @return Item
+ */
+ public function setRoute($route)
+ {
+ $this->route = $route;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLlink()
+ {
+ return $this->llink;
+ }
+
+ /**
+ * @param mixed $llink
+ * @return Item
+ */
+ public function setLlink($llink)
+ {
+ $this->llink = $llink;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPlink()
+ {
+ return $this->plink;
+ }
+
+ /**
+ * @param mixed $plink
+ * @return Item
+ */
+ public function setPlink($plink)
+ {
+ $this->plink = $plink;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getResourceId()
+ {
+ return $this->resource_id;
+ }
+
+ /**
+ * @param mixed $resource_id
+ * @return Item
+ */
+ public function setResourceId($resource_id)
+ {
+ $this->resource_id = $resource_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getResourceType()
+ {
+ return $this->resource_type;
+ }
+
+ /**
+ * @param mixed $resource_type
+ * @return Item
+ */
+ public function setResourceType($resource_type)
+ {
+ $this->resource_type = $resource_type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAttach()
+ {
+ return $this->attach;
+ }
+
+ /**
+ * @param mixed $attach
+ * @return Item
+ */
+ public function setAttach($attach)
+ {
+ $this->attach = $attach;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSig()
+ {
+ return $this->sig;
+ }
+
+ /**
+ * @param mixed $sig
+ * @return Item
+ */
+ public function setSig($sig)
+ {
+ $this->sig = $sig;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLocation()
+ {
+ return $this->location;
+ }
+
+ /**
+ * @param mixed $location
+ * @return Item
+ */
+ public function setLocation($location)
+ {
+ $this->location = $location;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCoord()
+ {
+ return $this->coord;
+ }
+
+ /**
+ * @param mixed $coord
+ * @return Item
+ */
+ public function setCoord($coord)
+ {
+ $this->coord = $coord;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPublicPolicy()
+ {
+ return $this->public_policy;
+ }
+
+ /**
+ * @param mixed $public_policy
+ * @return Item
+ */
+ public function setPublicPolicy($public_policy)
+ {
+ $this->public_policy = $public_policy;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCommentPolicy()
+ {
+ return $this->comment_policy;
+ }
+
+ /**
+ * @param mixed $comment_policy
+ * @return Item
+ */
+ public function setCommentPolicy($comment_policy)
+ {
+ $this->comment_policy = $comment_policy;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAllowCid()
+ {
+ return $this->allow_cid;
+ }
+
+ /**
+ * @param mixed $allow_cid
+ * @return Item
+ */
+ public function setAllowCid($allow_cid)
+ {
+ $this->allow_cid = $allow_cid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAllowGid()
+ {
+ return $this->allow_gid;
+ }
+
+ /**
+ * @param mixed $allow_gid
+ * @return Item
+ */
+ public function setAllowGid($allow_gid)
+ {
+ $this->allow_gid = $allow_gid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDenyCid()
+ {
+ return $this->deny_cid;
+ }
+
+ /**
+ * @param mixed $deny_cid
+ * @return Item
+ */
+ public function setDenyCid($deny_cid)
+ {
+ $this->deny_cid = $deny_cid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDenyGid()
+ {
+ return $this->deny_gid;
+ }
+
+ /**
+ * @param mixed $deny_gid
+ * @return Item
+ */
+ public function setDenyGid($deny_gid)
+ {
+ $this->deny_gid = $deny_gid;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRestrict()
+ {
+ return $this->item_restrict;
+ }
+
+ /**
+ * @param mixed $item_restrict
+ * @return Item
+ */
+ public function setRestrict($item_restrict)
+ {
+ $this->item_restrict = $item_restrict;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlags()
+ {
+ return $this->item_flags;
+ }
+
+ /**
+ * @param mixed $item_flags
+ * @return Item
+ */
+ public function setFlags($item_flags)
+ {
+ $this->item_flags = $item_flags;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPrivate()
+ {
+ return $this->item_private;
+ }
+
+ /**
+ * @param mixed $item_private
+ * @return Item
+ */
+ public function setPrivate($item_private)
+ {
+ $this->item_private = $item_private;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getOrigin()
+ {
+ return $this->item_origin;
+ }
+
+ /**
+ * @param mixed $item_origin
+ * @return Item
+ */
+ public function setOrigin($item_origin)
+ {
+ $this->item_origin = $item_origin;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUnseen()
+ {
+ return $this->item_unseen;
+ }
+
+ /**
+ * @param mixed $item_unseen
+ * @return Item
+ */
+ public function setUnseen($item_unseen)
+ {
+ $this->item_unseen = $item_unseen;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getStarred()
+ {
+ return $this->item_starred;
+ }
+
+ /**
+ * @param mixed $item_starred
+ * @return Item
+ */
+ public function setStarred($item_starred)
+ {
+ $this->item_starred = $item_starred;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUplink()
+ {
+ return $this->item_uplink;
+ }
+
+ /**
+ * @param mixed $item_uplink
+ * @return Item
+ */
+ public function setUplink($item_uplink)
+ {
+ $this->item_uplink = $item_uplink;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getConsensus()
+ {
+ return $this->item_consensus;
+ }
+
+ /**
+ * @param mixed $item_consensus
+ * @return Item
+ */
+ public function setConsensus($item_consensus)
+ {
+ $this->item_consensus = $item_consensus;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWall()
+ {
+ return $this->item_wall;
+ }
+
+ /**
+ * @param mixed $item_wall
+ * @return Item
+ */
+ public function setWall($item_wall)
+ {
+ $this->item_wall = $item_wall;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getThreadTop()
+ {
+ return $this->item_thread_top;
+ }
+
+ /**
+ * @param mixed $item_thread_top
+ * @return Item
+ */
+ public function setThreadTop($item_thread_top)
+ {
+ $this->item_thread_top = $item_thread_top;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNotshown()
+ {
+ return $this->item_notshown;
+ }
+
+ /**
+ * @param mixed $item_notshown
+ * @return Item
+ */
+ public function setNotshown($item_notshown)
+ {
+ $this->item_notshown = $item_notshown;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNsfw()
+ {
+ return $this->item_nsfw;
+ }
+
+ /**
+ * @param mixed $item_nsfw
+ * @return Item
+ */
+ public function setNsfw($item_nsfw)
+ {
+ $this->item_nsfw = $item_nsfw;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRelay()
+ {
+ return $this->item_relay;
+ }
+
+ /**
+ * @param mixed $item_relay
+ * @return Item
+ */
+ public function setRelay($item_relay)
+ {
+ $this->item_relay = $item_relay;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMentionsme()
+ {
+ return $this->item_mentionsme;
+ }
+
+ /**
+ * @param mixed $item_mentionsme
+ * @return Item
+ */
+ public function setMentionsme($item_mentionsme)
+ {
+ $this->item_mentionsme = $item_mentionsme;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNocomment()
+ {
+ return $this->item_nocomment;
+ }
+
+ /**
+ * @param mixed $item_nocomment
+ * @return Item
+ */
+ public function setNocomment($item_nocomment)
+ {
+ $this->item_nocomment = $item_nocomment;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getObscured()
+ {
+ return $this->item_obscured;
+ }
+
+ /**
+ * @param mixed $item_obscured
+ * @return Item
+ */
+ public function setObscured($item_obscured)
+ {
+ $this->item_obscured = $item_obscured;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getVerified()
+ {
+ return $this->item_verified;
+ }
+
+ /**
+ * @param mixed $item_verified
+ * @return Item
+ */
+ public function setVerified($item_verified)
+ {
+ $this->item_verified = $item_verified;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRetained()
+ {
+ return $this->item_retained;
+ }
+
+ /**
+ * @param mixed $item_retained
+ * @return Item
+ */
+ public function setRetained($item_retained)
+ {
+ $this->item_retained = $item_retained;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRss()
+ {
+ return $this->item_rss;
+ }
+
+ /**
+ * @param mixed $item_rss
+ * @return Item
+ */
+ public function setRss($item_rss)
+ {
+ $this->item_rss = $item_rss;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDeleted()
+ {
+ return $this->item_deleted;
+ }
+
+ /**
+ * @param mixed $item_deleted
+ * @return Item
+ */
+ public function setDeleted($item_deleted)
+ {
+ $this->item_deleted = $item_deleted;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->item_type;
+ }
+
+ /**
+ * @param mixed $item_type
+ * @return Item
+ */
+ public function setType($item_type)
+ {
+ $this->item_type = $item_type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHidden()
+ {
+ return $this->item_hidden;
+ }
+
+ /**
+ * @param mixed $item_hidden
+ * @return Item
+ */
+ public function setHidden($item_hidden)
+ {
+ $this->item_hidden = $item_hidden;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUnpublished()
+ {
+ return $this->item_unpublished;
+ }
+
+ /**
+ * @param mixed $item_unpublished
+ * @return Item
+ */
+ public function setUnpublished($item_unpublished)
+ {
+ $this->item_unpublished = $item_unpublished;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDelayed()
+ {
+ return $this->item_delayed;
+ }
+
+ /**
+ * @param mixed $item_delayed
+ * @return Item
+ */
+ public function setDelayed($item_delayed)
+ {
+ $this->item_delayed = $item_delayed;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPendingRemove()
+ {
+ return $this->item_pending_remove;
+ }
+
+ /**
+ * @param mixed $item_pending_remove
+ * @return Item
+ */
+ public function setPendingRemove($item_pending_remove)
+ {
+ $this->item_pending_remove = $item_pending_remove;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getBlocked()
+ {
+ return $this->item_blocked;
+ }
+
+ /**
+ * @param mixed $item_blocked
+ * @return Item
+ */
+ public function setBlocked($item_blocked)
+ {
+ $this->item_blocked = $item_blocked;
+ return $this;
+ }
+
+
+
+}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 9178dac39..1f7d4be0c 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -8,6 +8,7 @@ use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\Permissions;
use Zotlabs\Daemon\Master;
use Zotlabs\Web\HTTPSig;
+use Zotlabs\Entity\Item;
require_once('include/event.php');
require_once('include/html2plain.php');
@@ -503,15 +504,21 @@ class Activity {
$ret['diaspora:guid'] = $i['uuid'];
$images = [];
+ $audios = [];
+ $videos = [];
+
$has_images = preg_match_all('/\[[zi]mg(.*?)](.*?)\[/ism', $i['body'], $images, PREG_SET_ORDER);
+ $has_audios = preg_match_all('/\[zaudio](.*?)\[/ism', $i['body'], $audios, PREG_SET_ORDER);
+ $has_videos = preg_match_all('/\[zvideo](.*?)\[/ism', $i['body'], $videos, PREG_SET_ORDER);
// provide ocap access token for private media.
// set this for descendants even if the current item is not private
// because it may have been relayed from a private item.
$token = IConfig::Get($i, 'ocap', 'relay');
+ $matches_processed = [];
+
if ($token && $has_images) {
- $matches_processed = [];
for ($n = 0; $n < count($images); $n++) {
$match = $images[$n];
if (str_starts_with($match[1], '=http') && str_contains($match[1], z_root() . '/photo/') && !in_array($match[1], $matches_processed)) {
@@ -526,6 +533,28 @@ class Activity {
}
}
+ if ($token && $has_audios) {
+ for ($n = 0; $n < count($audios); $n++) {
+ $match = $audios[$n];
+ if (str_contains($match[1], z_root() . '/attach/') && !in_array($match[1], $matches_processed)) {
+ $i['body'] = str_replace($match[1], $match[1] . '?token=' . $token, $i['body']);
+ $audios[$n][1] = $match[1] . '?token=' . $token;
+ $matches_processed[] = $match[1];
+ }
+ }
+ }
+
+ if ($token && $has_videos) {
+ for ($n = 0; $n < count($videos); $n++) {
+ $match = $videos[$n];
+ if (str_contains($match[1], z_root() . '/attach/') && !in_array($match[1], $matches_processed)) {
+ $i['body'] = str_replace($match[1], $match[1] . '?token=' . $token, $i['body']);
+ $videos[$n][1] = $match[1] . '?token=' . $token;
+ $matches_processed[] = $match[1];
+ }
+ }
+ }
+
if ($i['title'])
$ret['name'] = unescape_tags($i['title']);
@@ -570,6 +599,26 @@ class Activity {
if ($i['mid'] !== $i['parent_mid']) {
$ret['inReplyTo'] = ((strpos($i['thr_parent'], 'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
+
+ $cnv = IConfig::Get($i['parent'], 'activitypub', 'context');
+ if (!$cnv) {
+ $cnv = $i['parent_mid'];
+ }
+ }
+
+ if (empty($cnv)) {
+ $cnv = IConfig::Get($i, 'activitypub', 'context');
+ if (!$cnv) {
+ $cnv = $i['parent_mid'];
+ }
+ }
+
+ if (!empty($cnv)) {
+ if (is_string($cnv) && str_starts_with($cnv, z_root())) {
+ $cnv = str_replace(['/item/', '/activity/'], ['/conversation/', '/conversation/'], $cnv);
+ $ret['contextHistory'] = $cnv;
+ }
+ $ret['context'] = $cnv;
}
if ($i['mimetype'] === 'text/bbcode') {
@@ -589,6 +638,12 @@ class Activity {
$t = self::encode_taxonomy($i);
if ($t) {
+ foreach($t as $tag) {
+ if (strcasecmp($tag['name'], '#nsfw') === 0 || strcasecmp($tag['name'], '#sensitive') === 0) {
+ $ret['sensitive'] = true;
+ }
+ }
+
$ret['tag'] = $t;
}
@@ -596,7 +651,20 @@ class Activity {
if ($a) {
$ret['attachment'] = $a;
}
-
+/*
+ if ($i['target']) {
+ if (is_string($i['target'])) {
+ $tmp = json_decode($i['target'], true);
+ if ($tmp !== null) {
+ $i['target'] = $tmp;
+ }
+ }
+ $tgt = self::encode_object($i['target']);
+ if ($tgt) {
+ $ret['target'] = $tgt;
+ }
+ }
+*/
if (intval($i['item_private']) === 0) {
$ret['to'] = [ACTIVITY_PUBLIC_INBOX];
}
@@ -694,6 +762,8 @@ class Activity {
$ret = [];
+ $token = IConfig::Get($item, 'ocap', 'relay');
+
if (!$iconfig && array_key_exists('attach', $item)) {
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
if ($atts) {
@@ -702,11 +772,17 @@ class Activity {
continue;
}
- if (isset($att['type']) && strpos($att['type'], 'image')) {
- $ret[] = ['type' => 'Image', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href']];
+ if (str_starts_with($att['type'], 'image')) {
+ $ret[] = ['type' => 'Image', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
+ }
+ elseif (str_starts_with($att['type'], 'audio')) {
+ $ret[] = ['type' => 'Audio', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
+ }
+ elseif (str_starts_with($att['type'], 'video')) {
+ $ret[] = ['type' => 'Video', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
}
else {
- $ret[] = ['type' => 'Link', 'mediaType' => $att['type'], 'name' => $att['title'], 'href' => $att['href']];
+ $ret[] = ['type' => 'Link', 'mediaType' => $att['type'], 'name' => $att['title'], 'href' => $att['href'] . (($token) ? '?token=' . $token : '')];
}
}
}
@@ -727,7 +803,7 @@ class Activity {
$ret = [];
- if (isset($item['attachment'])) {
+ if (isset($item['attachment']) && is_array($item['attachment'])) {
$ptr = $item['attachment'];
if (!array_key_exists(0, $ptr)) {
$ptr = [$ptr];
@@ -807,12 +883,32 @@ class Activity {
$ret['type'] = self::activity_mapper($i['verb']);
if ((isset($i['item_deleted']) && intval($i['item_deleted'])) && !$recurse) {
- $is_response = false;
- if (ActivityStreams::is_response_activity($ret['type'])) {
+ if ($i['verb'] === 'Add' && str_contains($i['tgt_type'], 'Collection')) {
+ $ret['id'] = str_replace('/item/', '/activity/', $i['mid']) . '#Remove';
+ $ret['type'] = 'Remove';
+ if (is_string($i['obj'])) {
+ $obj = json_decode($i['obj'], true);
+ }
+ elseif(is_array($i['obj'])) {
+ $obj = $i['obj'];
+ }
+ if (isset($obj['id'])) {
+ $ret['object'] = $obj['id'];
+ }
+ else {
+ $ret['object'] = str_replace('/item/', '/activity/', $i['mid']);
+ }
+ $ret['target'] = is_array($i['target']) ? $i['target'] : json_decode($i['target'], true);
+
+ return $ret;
+ }
+
+ $is_response = ActivityStreams::is_response_activity($ret['type']);
+
+ if ($is_response) {
$ret['type'] = 'Undo';
$fragment = 'undo';
- $is_response = true;
}
else {
$ret['type'] = 'Delete';
@@ -935,9 +1031,29 @@ class Activity {
// inReplyTo needs to be set in the activity for followup actions (Like, Dislike, Announce, etc.),
// but *not* for comments and RSVPs, where it should only be present in the object
- if (!in_array($ret['type'], ['Create', 'Update', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject'])) {
+ if (!in_array($ret['type'], ['Create', 'Update', 'Add', 'Remove', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject'])) {
$ret['inReplyTo'] = ((strpos($i['thr_parent'], 'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
}
+
+ $cnv = IConfig::Get($i['parent'], 'activitypub', 'context');
+ if (!$cnv) {
+ $cnv = $i['parent_mid'];
+ }
+ }
+
+ if (empty($cnv)) {
+ $cnv = IConfig::Get($i, 'activitypub', 'context');
+ if (!$cnv) {
+ $cnv = $i['parent_mid'];
+ }
+ }
+
+ if (!empty($cnv)) {
+ if (is_string($cnv) && str_starts_with($cnv, z_root())) {
+ $cnv = str_replace(['/item/', '/activity/'], ['/conversation/', '/conversation/'], $cnv);
+ $ret['contextHistory'] = $cnv;
+ }
+ $ret['context'] = $cnv;
}
$actor = self::encode_person($i['author'], false);
@@ -1010,6 +1126,7 @@ class Activity {
call_hooks('encode_activity', $hookinfo);
return $hookinfo['encoded'];
+
}
// Returns an array of URLS for any mention tags found in the item array $i.
@@ -1253,81 +1370,6 @@ class Activity {
// return false;
}
- 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/stop-following' => 'Unfollow',
- 'http://purl.org/zot/activity/attendyes' => 'Accept',
- 'http://purl.org/zot/activity/attendno' => 'Reject',
- 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
- 'Announce' => 'Announce',
- 'Invite' => 'Invite',
- 'Delete' => 'Delete',
- 'Undo' => 'Undo',
- 'Add' => 'Add',
- 'Remove' => 'Remove'
- ];
-
- call_hooks('activity_decode_mapper', $acts);
-
- foreach ($acts as $k => $v) {
- if ($verb === $v) {
- return $k;
- }
- }
-
- logger('Unmapped activity: ' . $verb);
- return 'Create';
-
- }
-
- static function activity_obj_decode_mapper($obj) {
-
- $objs = [
- 'http://activitystrea.ms/schema/1.0/note' => 'Note',
- 'http://activitystrea.ms/schema/1.0/note' => 'Article',
- 'http://activitystrea.ms/schema/1.0/comment' => 'Note',
- 'http://activitystrea.ms/schema/1.0/person' => 'Person',
- 'http://purl.org/zot/activity/profile' => 'Profile',
- 'http://activitystrea.ms/schema/1.0/photo' => 'Image',
- 'http://activitystrea.ms/schema/1.0/profile-photo' => 'Icon',
- 'http://activitystrea.ms/schema/1.0/event' => 'Event',
- 'http://purl.org/zot/activity/location' => 'Place',
- 'http://purl.org/zot/activity/chessgame' => 'Game',
- 'http://purl.org/zot/activity/tagterm' => 'zot:Tag',
- 'http://purl.org/zot/activity/thing' => 'Object',
- 'http://purl.org/zot/activity/file' => 'zot:File',
- 'http://purl.org/zot/activity/mood' => 'zot:Mood',
- 'Invite' => 'Invite',
- 'Question' => 'Question',
- 'Document' => 'Document',
- 'Audio' => 'Audio',
- 'Video' => 'Video',
- 'Delete' => 'Delete',
- 'Undo' => 'Undo'
- ];
-
- call_hooks('activity_obj_decode_mapper', $objs);
-
- foreach ($objs as $k => $v) {
- if ($obj === $v) {
- return $k;
- }
- }
-
- logger('Unmapped activity object: ' . $obj);
- return 'Note';
- }
-
static function activity_obj_mapper($obj) {
$objs = [
@@ -1606,9 +1648,9 @@ class Activity {
}
if (in_array($observer, [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
- drop_item($r[0]['id'], false, (($r[0]['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
+ drop_item($r[0]['id'], (($r[0]['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL), observer_hash: $observer);
} elseif (in_array($act->actor['id'], [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
- drop_item($r[0]['id'], false, (($r[0]['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
+ drop_item($r[0]['id'], (($r[0]['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
}
sync_an_item($channel['channel_id'], $r[0]['id']);
@@ -1676,9 +1718,9 @@ class Activity {
return;
}
- $name = $person_obj['name'] ?? '';
+ $name = ((isset($person_obj['name'])) ? escape_tags($person_obj['name']) : '');
if (!$name) {
- $name = $person_obj['preferredUsername'] ?? '';
+ $name = ((isset($person_obj['preferredUsername'])) ? escape_tags($person_obj['preferredUsername']) : '');
}
if (!$name) {
$name = t('Unknown');
@@ -1687,13 +1729,11 @@ class Activity {
$webfinger_addr = ((isset($person_obj['webfinger'])) ? str_replace('acct:', '', $person_obj['webfinger']) : '');
$hostname = '';
$baseurl = '';
- $site_url = '';
$m = parse_url($url);
if ($m) {
- $hostname = $m['host'];
- $baseurl = $m['scheme'] . '://' . $m['host'] . ((isset($m['port'])) ? ':' . $m['port'] : '');
- $site_url = $m['scheme'] . '://' . $m['host'];
+ $hostname = unparse_url($m, ['host']);
+ $baseurl = unparse_url($m, ['scheme', 'host', 'port']);
}
if (!$webfinger_addr && !empty($person_obj['preferredUsername']) && $hostname) {
@@ -1795,7 +1835,7 @@ class Activity {
q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s'",
dbesc(datetime_convert()),
- dbesc($site_url)
+ dbesc($baseurl)
);
// update existing xchan record
@@ -1906,129 +1946,173 @@ class Activity {
}
- static function update_poll($item_id, $post) {
+ static function update_poll($pollItem, $response) {
+
+ logger('updating poll');
+
+ $multi = false;
- $multi = false;
- $mid = $post['mid'];
- $content = $post['title'];
+ if (!$pollItem) {
+ logger('no item');
+ return false;
+ }
- if (!$item_id) {
+ if (intval($pollItem['item_blocked']) === ITEM_MODERATED) {
+ logger('item blocked');
return false;
}
- if (intval($post['item_blocked']) === ITEM_MODERATED) {
+ $channel = channelx_by_n($pollItem['uid']);
+ if (!$channel) {
+ logger('no channel');
return false;
}
+ $relatedItem = find_related($pollItem);
+
+ $ids = (($relatedItem) ? $pollItem['id'] . ',' . $relatedItem['id'] : $pollItem['id']);
+
dbq("START TRANSACTION");
+ // Using the provided items as is will produce desastrous race conditions
+ // in case of multiple choice polls - hence:
- $item = q("SELECT * FROM item WHERE id = %d FOR UPDATE",
- intval($item_id)
- );
+ $items = dbq("SELECT * FROM item WHERE id in ($ids) FOR UPDATE");
- if (!$item) {
- dbq("COMMIT");
- return false;
+ foreach ($items as $item) {
+ if ($item['id'] === $pollItem['id']) {
+ $pollItem = $item;
+ }
+ if (!empty($relatedItem['id']) && $item['id'] === $relatedItem['id']) {
+ $relatedItem = $item;
+ }
}
- $item = $item[0];
+ $o = json_decode($pollItem['obj'], true);
- $o = json_decode($item['obj'], true);
if ($o && array_key_exists('anyOf', $o)) {
$multi = true;
}
- $r = q("select mid, title from item where parent_mid = '%s' and author_xchan = '%s'",
- dbesc($item['mid']),
- dbesc($post['author_xchan'])
- );
+ if ($response) {
+ $mid = $response['mid'];
+ $content = trim($response['title']);
- // prevent any duplicate votes by same author for oneOf and duplicate votes with same author and same answer for anyOf
+ $r = q("select mid, title from item where parent_mid = '%s' and author_xchan = '%s' and mid != parent_mid ",
+ dbesc($pollItem['mid']),
+ dbesc($response['author_xchan'])
+ );
- if ($r) {
- if ($multi) {
- foreach ($r as $rv) {
- if ($rv['title'] === $content && $rv['mid'] !== $mid) {
- return false;
+ // prevent any duplicate votes by same author for oneOf and duplicate votes with same author and same answer for anyOf
+
+ if ($r) {
+ if ($multi) {
+ foreach ($r as $rv) {
+ if (trim($rv['title']) === $content && $rv['mid'] !== $mid) {
+ logger('already voted multi');
+ return false;
+ }
}
- }
- }
- else {
- foreach ($r as $rv) {
- if ($rv['mid'] !== $mid) {
- return false;
+ } else {
+ foreach ($r as $rv) {
+ if ($rv['mid'] !== $mid && $content) {
+ logger('already voted');
+ return false;
+ }
}
}
}
- }
- $answer_found = false;
- $found = false;
- if ($multi) {
- for ($c = 0; $c < count($o['anyOf']); $c++) {
- if ($o['anyOf'][$c]['name'] === $content) {
- $answer_found = true;
- if (is_array($o['anyOf'][$c]['replies'])) {
- foreach ($o['anyOf'][$c]['replies'] as $reply) {
- if (is_array($reply) && array_key_exists('id', $reply) && $reply['id'] === $mid) {
- $found = true;
+ $answer_found = false;
+ $foundPrevious = false;
+ if ($multi) {
+ for ($c = 0; $c < count($o['anyOf']); $c++) {
+ if (trim($o['anyOf'][$c]['name']) === $content) {
+ $answer_found = true;
+
+
+ if (is_array($o['anyOf'][$c]['replies'])) {
+ foreach ($o['anyOf'][$c]['replies'] as $reply) {
+ if (is_array($reply) && array_key_exists('id', $reply) && $reply['id'] === $mid) {
+ $foundPrevious = true;
+ }
}
}
- }
- if (!$found) {
- $o['anyOf'][$c]['replies']['totalItems']++;
- $o['anyOf'][$c]['replies']['items'][] = ['id' => $mid, 'type' => 'Note'];
+ if (!$foundPrevious) {
+ $o['anyOf'][$c]['replies']['totalItems']++;
+ $o['anyOf'][$c]['replies']['items'][] = ['id' => $mid, 'type' => 'Note'];
+ }
}
}
- }
- }
- else {
- for ($c = 0; $c < count($o['oneOf']); $c++) {
- if ($o['oneOf'][$c]['name'] === $content) {
- $answer_found = true;
- if (is_array($o['oneOf'][$c]['replies'])) {
- foreach ($o['oneOf'][$c]['replies'] as $reply) {
- if (is_array($reply) && array_key_exists('id', $reply) && $reply['id'] === $mid) {
- $found = true;
+ } else {
+ for ($c = 0; $c < count($o['oneOf']); $c++) {
+ if (trim($o['oneOf'][$c]['name']) === $content) {
+ $answer_found = true;
+ if (is_array($o['oneOf'][$c]['replies'])) {
+ foreach ($o['oneOf'][$c]['replies'] as $reply) {
+ if (is_array($reply) && array_key_exists('id', $reply) && $reply['id'] === $mid) {
+ $foundPrevious = true;
+ }
}
}
- }
- if (!$found) {
- $o['oneOf'][$c]['replies']['totalItems']++;
- $o['oneOf'][$c]['replies']['items'][] = ['id' => $mid, 'type' => 'Note'];
+ if (!$foundPrevious) {
+ $o['oneOf'][$c]['replies']['totalItems']++;
+ $o['oneOf'][$c]['replies']['items'][] = ['id' => $mid, 'type' => 'Note'];
+ }
}
}
}
}
- logger('updated_poll: ' . print_r($o, true), LOGGER_DATA);
- if ($answer_found && !$found) {
- $u = q("update item set obj = '%s', edited = '%s' where id = %d",
- dbesc(json_encode($o)),
- dbesc(datetime_convert()),
- intval($item['id'])
- );
+ if ($pollItem['comments_closed'] > NULL_DATE) {
+ if ($pollItem['comments_closed'] > datetime_convert()) {
+ $o['closed'] = datetime_convert('UTC', 'UTC', $pollItem['comments_closed'], ATOM_TIME);
+ // set this to force an update
+ $answer_found = true;
+ }
+ }
- if ($u) {
- dbq("COMMIT");
+ // A change was made locally
+ if ($response && $answer_found && !$foundPrevious) {
- if ($multi) {
- // wait some seconds for possible multiple answers to be processed
- // before calling the notifier
- sleep(3);
- }
+ // update this copy
+ $i = [$pollItem];
+ xchan_query($i, true);
+ $i = fetch_post_tags($i);
+ $i[0]['obj'] = $o;
- Master::Summon(['Notifier', 'wall-new', $item['id']]);
- return true;
- }
+ $edited = datetime_convert();
+ $i[0]['edited'] = $edited;
- dbq("ROLLBACK");
+ // create the new object
+ $newObj = self::build_packet(self::encode_activity($i[0]), $channel, true);
+ // and immediately update the db
+ $u = q("UPDATE item
+ SET obj = (
+ CASE
+ WHEN item.id = %d THEN '%s'
+ WHEN item.id = %d THEN '%s'
+ END
+ ),
+ edited = '%s'
+ WHERE id IN ($ids)",
+ intval($pollItem['id']),
+ dbesc(json_encode($o)),
+ intval($relatedItem['id']),
+ dbesc($newObj),
+ dbesc($edited)
+ );
+
+ dbq("COMMIT");
+
+ Master::Summon(['Notifier', 'edit_post', $pollItem['id'], $response['mid']]);
+ if (!empty($relatedItem['id'])) {
+ Master::Summon(['Notifier', 'edit_post', $relatedItem['id'], $response['mid']]);
+ }
}
- dbq("COMMIT");
- return false;
+ return true;
}
static function decode_note($act) {
@@ -2116,6 +2200,13 @@ class Activity {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
}
+ if ($act->objprop('location')) {
+ $s['location'] = ((isset($act->objprop('location')['name'])) ? html2plain(purify_html($act->objprop('location')['name'])) : '');
+ if (isset($act->objprop('location')['latitude'], $act->objprop('location')['longitude'])) {
+ $s['coord'] = floatval($act->objprop('location')['latitude']) . ' ' . floatval($act->objprop('location')['longitude']);
+ }
+ }
+
if (in_array($act->type, ['Invite', 'Create']) && $act->objprop('type') === 'Event') {
$s['mid'] = $s['parent_mid'] = $act->id;
}
@@ -2218,6 +2309,8 @@ class Activity {
if ($s['mid'] === $s['parent_mid']) {
$s['item_thread_top'] = 1;
+ $s['item_nocomment'] = 0;
+ $s['comments_closed'] = NULL_DATE;
// it is a parent node - decode the comment policy info if present
if ($act->objprop('commentPolicy')) {
@@ -2225,7 +2318,7 @@ class Activity {
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;
+ $s['item_nocomment'] = 1;
}
}
@@ -2277,6 +2370,16 @@ class Activity {
$s['obj']['actor'] = $s['obj']['actor']['id'];
}
+ if (is_array($act->tgt) && $act->tgt) {
+ if (array_key_exists('type', $act->tgt)) {
+ $s['tgt_type'] = self::activity_obj_mapper($act->tgt['type']);
+ }
+ // We shouldn't need to store collection contents which could be large. We will often only require the meta-data
+ if (isset($s['tgt_type']) && str_contains($s['tgt_type'], 'Collection')) {
+ $s['target'] = ['id' => $act->tgt['id'], 'type' => $s['tgt_type'], 'attributedTo' => $act->tgt['attributedTo'] ?? $act->tgt['actor']];
+ }
+ }
+
$generator = $act->get_property_obj('generator');
if ((!$generator) && (!$response_activity)) {
$generator = $act->get_property_obj('generator', $act->obj);
@@ -2582,6 +2685,7 @@ class Activity {
}
}
+
if (!$ap_rawmsg && array_key_exists('signed', $raw_arr)) {
// zap
$ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
@@ -2615,8 +2719,7 @@ class Activity {
return $hookinfo['s'];
}
-
- static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false) {
+ static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false, $is_collection_operation = false) {
$is_sys_channel = is_sys_channel($channel['channel_id']);
$is_child_node = false;
$parent = null;
@@ -2647,6 +2750,8 @@ class Activity {
}
$allowed = false;
+ $relay = false;
+
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system','permit_all_mentions') && i_am_mentioned($channel, $item));
if ($is_child_node) {
@@ -2673,13 +2778,22 @@ class Activity {
return;
}
+ $relay = $channel['channel_hash'] === $parent[0]['owner_xchan'];
+
+ if (str_contains($parent[0]['tgt_type'], 'Collection') && !$relay && !$isCollectionOperation) {
+ logger('not a collection activity');
+ return;
+ }
+
if ($parent[0]['obj_type'] === 'Question') {
if (in_array($item['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $item['title'] && (!$item['body'])) {
$item['obj_type'] = 'Answer';
+ $item['item_hidden'] = 1;
}
}
if ($parent[0]['item_wall']) {
+
// set the owner to the owner of the parent
$item['owner_xchan'] = $parent[0]['owner_xchan'];
@@ -2860,6 +2974,13 @@ class Activity {
// This isn't perfect but the best we can do for now.
$item['comment_policy'] = ((isset($act->data['commentPolicy'])) ? $act->data['commentPolicy'] : 'authenticated');
+ if (!empty($act->obj['contextHistory'])) {
+ IConfig::Set($item, 'activitypub', 'context', $act->obj['contextHistory'], 1);
+ }
+ elseif (!empty($act->obj['context'])) {
+ IConfig::Set($item, 'activitypub', 'context', $act->obj['context'], 1);
+ }
+
IConfig::Set($item, 'activitypub', 'recips', $act->raw_recips);
if (intval($act->sigok)) {
@@ -2930,17 +3051,48 @@ class Activity {
dbesc($item['mid']),
intval($item['uid'])
);
+
if ($r) {
if ($item['edited'] > $r[0]['edited']) {
$item['id'] = $r[0]['id'];
- $x = item_store_update($item);
+ $x = item_store_update($item, deliver: false);
}
else {
return;
}
}
else {
- $x = item_store($item);
+ $x = item_store($item, deliver: false, addAndSync: false);
+ }
+
+ if ($x['success']) {
+
+ if ($relay && $channel['channel_hash'] === $x['item']['owner_xchan'] && $x['item']['verb'] !== 'Add' && !$isCollectionOperation) {
+ $approval = Activity::addToCollection($channel, $act->data, $x['item']['parent_mid'], $x['item'], deliver: false);
+ }
+
+ if (check_item_source($channel['channel_id'], $x['item']) && in_array($x['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
+ event_addtocal($x['item_id'], $channel['channel_id']);
+ }
+
+ tag_deliver($channel['channel_id'], $x['item_id']);
+
+ if ($relay && $is_child_node) {
+ // We are the owner of this conversation, so send all received comments back downstream
+ Master::Summon(['Notifier', 'comment-import', $x['item_id']]);
+ if (!empty($approval['item_id'])) {
+ Master::Summon(['Notifier', 'comment-import', $approval['item_id']]);
+ }
+ }
+
+ $r = q("select * from item where id = %d limit 1",
+ intval($x['item_id'])
+ );
+
+ if ($r) {
+ send_status_notifications($x['item_id'], $r[0]);
+ }
+ sync_an_item($channel['channel_id'], $x['item_id']);
}
if ($fetch_parents && $parent && !intval($parent[0]['item_private'])) {
@@ -2967,28 +3119,6 @@ class Activity {
}
}
}
-
- if ($x['success']) {
-
- if (check_item_source($channel['channel_id'], $x['item']) && in_array($x['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
- event_addtocal($x['item_id'], $channel['channel_id']);
- }
-
- if ($is_child_node) {
- if ($item['owner_xchan'] === $channel['channel_hash']) {
- // We are the owner of this conversation, so send all received comments back downstream
- Master::Summon(['Notifier', 'comment-import', $x['item_id']]);
- }
- $r = q("select * from item where id = %d limit 1",
- intval($x['item_id'])
- );
- if ($r) {
- send_status_notifications($x['item_id'], $r[0]);
- }
- }
- sync_an_item($channel['channel_id'], $x['item_id']);
- }
-
}
/**
@@ -3271,7 +3401,7 @@ class Activity {
return $content;
}
- if ($act['type'] === 'Event') {
+ if (isset($act['type']) && $act['type'] === 'Event') {
$adjust = false;
$event = [];
$event['event_hash'] = $act['id'];
@@ -3464,7 +3594,7 @@ class Activity {
$ret[$collection] = $actor_record[$collection];
}
}
- if (array_path_exists('endpoints/sharedInbox', $actor_record) && $actor_record['endpoints']['sharedInbox']) {
+ if (!empty($actor_record['endpoints']['sharedInbox'])) {
$ret['sharedInbox'] = $actor_record['endpoints']['sharedInbox'];
}
@@ -3567,6 +3697,8 @@ class Activity {
return [
'zot' => z_root() . '/apschema#',
+
+ 'contextHistory' => 'https://w3id.org/fep/171b/contextHistory',
'schema' => 'http://schema.org#',
'ostatus' => 'http://ostatus.org#',
'diaspora' => 'https://diasporafoundation.org/ns/',
@@ -3590,7 +3722,6 @@ class Activity {
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'Hashtag' => 'as:Hashtag'
-
];
}
@@ -3669,5 +3800,76 @@ class Activity {
}
}
+ public static function addToCollection($channel, $object, $target, $sourceItem = null, $deliver = true) {
+ if (!isset($channel['xchan_hash'])) {
+ $channel = channelx_by_hash($channel['channel_hash']);
+ }
+
+ $item = ((new Item())
+ ->setUid($channel['channel_id'])
+ ->setVerb('Add')
+ ->setAuthorXchan($channel['channel_hash'])
+ ->setOwnerXchan($channel['channel_hash'])
+ ->setObj($object)
+ ->setObjType($object['type'])
+ ->setParentMid(str_replace('/conversation/','/item/', $target))
+ ->setThrParent(str_replace('/conversation/','/item/', $target))
+ ->setTgtType('Collection')
+ ->setTarget([
+ 'id' => str_replace('/item/','/conversation/', $target),
+ 'type' => 'Collection',
+ 'attributedTo' => z_root() . '/channel/' . $channel['channel_address'],
+ ])
+ );
+ if ($sourceItem) {
+ $item->setSourceXchan($sourceItem['source_xchan'])
+ ->setAllowCid($sourceItem['allow_cid'])
+ ->setAllowGid($sourceItem['allow_gid'])
+ ->setDenyCid($sourceItem['deny_cid'])
+ ->setDenyGid($sourceItem['deny_gid'])
+ ->setPrivate($sourceItem['item_private'])
+ ->setRestrict($sourceItem['item_restrict'])
+ ->setHidden($sourceItem['item_hidden'])
+ ->setDelayed($sourceItem['item_delayed'])
+ ->setUnpublished($sourceItem['item_unpublished'])
+ ->setBlocked($sourceItem['item_blocked'])
+ ->setType($sourceItem['item_type'])
+ ->setCommentPolicy($sourceItem['comment_policy'])
+ ->setPublicPolicy($sourceItem['public_policy'])
+ ->setPostopts($sourceItem['postopts']);
+ }
+ $result = post_activity_item($item->toArray(), deliver: $deliver, channel: $channel, observer: $channel, addAndSync: false);
+ logger('addToCollection: ' . print_r($result, true));
+
+ return $result;
+ }
+
+ public static function removeFromCollection($channel, $object, $target, $deliver = true) {
+ if (!isset($channel['xchan_hash'])) {
+ $channel = channelx_by_hash($channel['channel_hash']);
+ }
+
+ $item = ((new Item())
+ ->setUid($channel['channel_id'])
+ ->setVerb('Remove')
+ ->setAuthorXchan($channel['channel_hash'])
+ ->setOwnerXchan($channel['channel_hash'])
+ ->setObj($object)
+ ->setObjType($object['type'])
+ ->setParentMid(str_replace('/conversation/','/item/', $target))
+ ->setThrParent(str_replace('/conversation/','/item/', $target))
+ ->setReplyto(z_root() . '/channel/' . $channel['channel_address'])
+ ->setTgtType('Collection')
+ ->setTarget([
+ 'id' => str_replace('/item/','/conversation/', $target),
+ 'type' => 'Collection',
+ 'attributedTo' => z_root() . '/channel/' . $channel['channel_address']
+ ])
+ );
+
+ $result = post_activity_item($item->toArray(), deliver: $deliver, channel: $channel, observer: $channel, addAndSync: false);
+ logger('removeFromCollection: ' . print_r($result, true));
+ return $result;
+ }
}
diff --git a/Zotlabs/Lib/BaseObject.php b/Zotlabs/Lib/BaseObject.php
new file mode 100644
index 000000000..7125d34cb
--- /dev/null
+++ b/Zotlabs/Lib/BaseObject.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+use Zotlabs\ActivityStreams\UnhandledElementException;
+
+class BaseObject
+{
+
+ public $string;
+ public $ldContext;
+
+ /**
+ * @param $input
+ * @param $strict
+ * @throws UnhandledElementException if $strict
+ */
+
+ public function __construct($input = null, $strict = false)
+ {
+ if (isset($input)) {
+ if (is_string($input)) {
+ $this->string = $input;
+ }
+ elseif(is_array($input)) {
+ foreach ($input as $key => $value) {
+ $key = ($key === '@context') ? 'ldContext' : $key;
+ if ($strict && !property_exists($this, $key)) {
+ throw new UnhandledElementException("Unhandled element: $key");
+ }
+ $this->{$key} = $value;
+ }
+ }
+ }
+ return $this;
+ }
+
+ public function getDataType($element, $object = null)
+ {
+ $object = $object ?? $this;
+ $type = gettype($object[$element]);
+ if ($type === 'array' && array_is_list($object[$element])) {
+ return 'list';
+ }
+ return $type;
+ }
+
+ public function toArray()
+ {
+ if ($this->string) {
+ return $this->string;
+ }
+ $returnValue = [];
+ foreach ((array) $this as $key => $value) {
+ if (isset($value)) {
+ $key = ($key === 'ldContext') ? '@context' : $key;
+ $returnValue[$key] = (($value instanceof BaseObject) ? $value->toArray() : $value);
+ }
+ }
+ return $returnValue;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLdContext()
+ {
+ return $this->ldContext;
+ }
+
+ /**
+ * @param mixed $ldContext
+ * @return BaseObject
+ */
+ public function setLdContext($ldContext)
+ {
+ $this->ldContext = $ldContext;
+ return $this;
+ }
+}
diff --git a/Zotlabs/Lib/Chatroom.php b/Zotlabs/Lib/Chatroom.php
index 34853b6ab..ee16d0002 100644
--- a/Zotlabs/Lib/Chatroom.php
+++ b/Zotlabs/Lib/Chatroom.php
@@ -181,7 +181,7 @@ class Chatroom {
}
- function leave($observer_xchan, $room_id, $client) {
+ public static function leave($observer_xchan, $room_id, $client) {
if(! $room_id || ! $observer_xchan)
return;
diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php
index b8e7a5c4e..9f6d077b4 100644
--- a/Zotlabs/Lib/Connect.php
+++ b/Zotlabs/Lib/Connect.php
@@ -24,10 +24,16 @@ class Connect {
$uid = $channel['channel_id'];
- if (strpos($url,'@') === false && strpos($url,'/') === false) {
+ // If we get just a channel name and it is not an URL turn it into a local webbie
+ if (!str_contains($url, '@') && strpos($url,'/') === false) {
$url = $url . '@' . App::get_hostname();
}
+ // Remove a possible leading @
+ if (str_starts_with($url, '@')) {
+ $url = ltrim($url, '@');
+ }
+
$result = [ 'success' => false, 'message' => '' ];
$my_perms = false;
diff --git a/Zotlabs/Lib/DB_Upgrade.php b/Zotlabs/Lib/DB_Upgrade.php
index 981c354a4..e11c2eb10 100644
--- a/Zotlabs/Lib/DB_Upgrade.php
+++ b/Zotlabs/Lib/DB_Upgrade.php
@@ -1,18 +1,35 @@
<?php
+/**
+ * A class to handle database schema upgrades.
+ *
+ * SPDX-FileCopyrightText: 2024 Hubzilla Community
+ * SPDX-FileContributor: Harald Eilertsen
+ *
+ * SPDX-License-Identifier: MIT
+ */
namespace Zotlabs\Lib;
use Zotlabs\Lib\Config;
+/**
+ * Upgrade the database schema if necessary.
+ *
+ * Compares the currently active database schema version with the version
+ * required for this version of Hubzilla, and performs the upgrade if needed.
+ *
+ * If the difference consists of more than one revision of the schema, each of
+ * the intermediate upgrades are performed in turn.
+ */
class DB_Upgrade {
- public $config_name = '';
- public $func_prefix = '';
-
- function __construct($db_revision) {
-
- $this->config_name = 'db_version';
- $this->func_prefix = '_';
+ /**
+ * Check the installed and required schema versions and perform the upgrade
+ * if necessary.
+ *
+ * @param int $db_version The required DB schema version.
+ */
+ public static function run(int $db_revision): void {
$build = Config::Get('system', 'db_version', 0);
if(! intval($build))
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index 121ad9b09..6820091d5 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -213,28 +213,36 @@ class Enotify {
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
- $dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
+ $dest_str = sprintf(
+ t('%1$s %2$s [zrl=%3$s]a %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
- $item_post_type);
+ $item_post_type
+ );
// "George Bull's post"
- if($p)
- $dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
+ if($p) {
+ $dest_str = sprintf(
+ t('%1$s %2$s [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
- $p[0]['author']['xchan_name'],
- $item_post_type);
+ $parent_item['author']['xchan_name'],
+ $item_post_type
+ );
+ }
// "your post"
- if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
- $dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
+ if ($parent_item['owner']['xchan_hash'] === $recip['channel_hash'] && intval($parent_item['item_wall'])) {
+ $dest_str = sprintf(
+ t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$action,
$itemlink,
- $item_post_type);
+ $item_post_type
+ );
+ }
// Some mail softwares relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
@@ -308,7 +316,6 @@ class Enotify {
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
-
$parent_item = $p[0];
//$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
@@ -321,13 +328,14 @@ class Enotify {
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
// "your post"
- if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
+ if ($parent_item['author']['xchan_hash'] === $recip['channel_hash']) {
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$verb,
$itemlink,
$item_post_type
);
+ }
else {
pop_lang();
return;
@@ -406,6 +414,7 @@ class Enotify {
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSHARE) {
+ $itemlink = $params['link'];
$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]') ,
@@ -415,7 +424,6 @@ class Enotify {
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_INTRO) {
@@ -433,6 +441,7 @@ class Enotify {
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_SUGGEST) {
+ $itemlink = $params['link'];
$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.'),
@@ -447,7 +456,6 @@ class Enotify {
$sitelink = t('Please visit %s to approve or reject the suggestion.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
- $itemlink = $params['link'];
}
elseif (isset($params['type']) && $params['type'] === NOTIFY_CONFIRM) {
@@ -595,7 +603,7 @@ class Enotify {
// send email notification if notification preferences permit
- require_once('bbcode.php');
+ require_once('include/bbcode.php');
if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
logger('notification: sending notification email');
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index a7e33ba6b..c6b149738 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -885,7 +885,7 @@ class Libsync {
dbesc($t)
);
- q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s'",
+ q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' and hubloc_network = 'zot6'",
dbesc($r[0]['hubloc_url']),
dbesc($r[0]['hubloc_sitekey'])
);
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index bc944c97c..57c110d8b 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -655,6 +655,11 @@ class Libzot {
return $ret;
}
+ if (empty($arr['primary_location']['address'])) {
+ logger('Empty primary location address: ' . print_r($arr, true), LOGGER_DEBUG);
+ return $ret;
+ }
+
/**
* @hooks import_xchan
* Called when processing the result of zot_finger() to store the result
@@ -1134,6 +1139,7 @@ class Libzot {
}
$message_request = false;
+ $is_collection_operation = false;
$has_data = array_key_exists('data', $env) && $env['data'];
@@ -1141,15 +1147,33 @@ class Libzot {
$AS = null;
+
if ($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data);
- if (!$AS->is_valid()) {
- logger('Activity rejected: ' . print_r($data, true));
- return;
+
+ // process add/remove from collection separately, as it requires a target.
+ // use the data object, as it will not include actor expansion
+ if (in_array($AS->type, ['Add', 'Remove'])
+ && is_array($AS->obj)
+ && array_key_exists('object', $AS->obj)
+ && array_key_exists('actor', $AS->obj)
+ && !empty($AS->tgt)) {
+
+ logger('relayed collection operation', LOGGER_DEBUG);
+ $is_collection_operation = true;
+
+ $original_id = $AS->id;
+ $original_type = $AS->type;
+
+ $raw_activity = $AS->data;
+
+ $AS = new ActivityStreams($raw_activity['object'], portable_id: $env['sender']);
}
+
if (is_array($AS->obj)) {
$item = Activity::decode_note($AS);
+
if (!$item) {
logger('Could not decode activity: ' . print_r($AS, true));
return;
@@ -1158,6 +1182,12 @@ class Libzot {
else {
$item = [];
}
+
+ if (!$AS->is_valid()) {
+ logger('Activity rejected: ' . print_r($data, true));
+ return;
+ }
+
logger($AS->debug(), LOGGER_DATA);
}
@@ -1198,7 +1228,6 @@ class Libzot {
logger('public post');
-
// Public post. look for any site members who are or may be accepting posts from this sender
// and who are allowed to see them based on the sender's permissions
// @fixme;
@@ -1265,25 +1294,6 @@ class Libzot {
$item['item_private'] = 1;
}
- if ($item['mid'] === $item['parent_mid']) {
- if (is_array($AS->obj) && array_key_exists('commentPolicy', $AS->obj)) {
- $p = strstr($AS->obj['commentPolicy'], 'until=');
- if ($p !== false) {
- $comments_closed_at = datetime_convert('UTC', 'UTC', substr($p, 6));
- if ($comments_closed_at === $item['created']) {
- $item['item_nocomment'] = 1;
- }
- else {
- $item['comments_closed'] = $comments_closed_at;
- $aritemr['comment_policy'] = trim(str_replace($p, '', $AS->obj['commentPolicy']));
- }
- }
- else {
- $item['comment_policy'] = $AS->obj['commentPolicy'];
- }
- }
- }
-
if (!empty($AS->meta['hubloc']) || $AS->sigok) {
$item['item_verified'] = true;
}
@@ -1301,7 +1311,7 @@ class Libzot {
$relay = (($env['type'] === 'response') ? true : false);
- $result = self::process_delivery($env['sender'], $AS, $item, $deliveries, $relay, false, $message_request);
+ $result = self::process_delivery($env['sender'], $AS, $item, $deliveries, $relay, false, $message_request, false, $is_collection_operation);
Activity::init_background_fetch($env['sender']);
}
@@ -1517,7 +1527,7 @@ class Libzot {
* @return array
*/
- static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) {
+ static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false, $is_collection_operation = false) {
$result = [];
// We've validated the sender. Now make sure that the sender is the owner or author
@@ -1545,6 +1555,14 @@ class Libzot {
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+ $conversation_operation = $is_collection_operation && isset($arr['target']['attributedTo']);
+
+ if (isset($arr['tgt_type']) && str_contains($arr['tgt_type'], 'Collection') && !$relay && !$conversation_operation) {
+ $DR->update('not a collection activity');
+ $result[] = $DR->get();
+ continue;
+ }
+
if (($act) && ($act->obj) && (!is_array($act->obj))) {
// The initial object fetch failed using the sys channel credentials.
// Try again using the delivery channel credentials.
@@ -1578,6 +1596,8 @@ class Libzot {
*
*/
+
+
if ($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && !str_starts_with($arr['mid'], z_root())) {
$DR->update('self delivery ignored');
$result[] = $DR->get();
@@ -1624,22 +1644,24 @@ class Libzot {
if (intval($channel['channel_system']) && (!$arr['item_private']) && (!$relay)) {
$local_public = true;
- $r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
- dbesc($sender)
- );
- // don't import sys channel posts from selfcensored authors
- if ($r && (intval($r[0]['xchan_selfcensored']))) {
+ $incl = Config::Get('system','pubstream_incl');
+ $excl = Config::Get('system','pubstream_excl');
+
+ if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
$local_public = false;
continue;
}
- $incl = Config::Get('system','pubstream_incl');
- $excl = Config::Get('system','pubstream_excl');
+ $r = q("select xchan_selfcensored, xchan_censored from xchan where xchan_hash = '%s'",
+ dbesc($sender)
+ );
- if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
+ // don't import sys channel posts from selfcensored or censored authors
+ if ($r && ($r[0]['xchan_selfcensored'] || $r[0]['xchan_censored'])) {
$local_public = false;
continue;
}
+
}
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
@@ -1701,6 +1723,7 @@ class Libzot {
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
if (in_array($arr['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $arr['title'] && (!$arr['body'])) {
$arr['obj_type'] = 'Answer';
+ $arr['item_hidden'] = 1;
}
}
@@ -1826,11 +1849,12 @@ class Libzot {
dbesc($arr['author_xchan'])
);
- // reactions such as like and dislike could have an mid with /activity/ in it.
+ // Reactions such as like and dislike could have an mid with /activity/ in it.
// Check for both forms in order to prevent duplicates.
- $r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
+
+ $r = q("select * from item where mid in ('%s', '%s') and uid = %d limit 1",
dbesc($arr['mid']),
- dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
+ dbesc(reverse_activity_mid($arr['mid'])),
intval($channel['channel_id'])
);
@@ -1859,21 +1883,29 @@ class Libzot {
$DR->update('update ignored');
$result[] = $DR->get();
}
+
+ if ($relay && $channel['channel_hash'] === $item_result['item']['owner_xchan'] && $item_result['item']['verb'] !== 'Add' && !$is_collection_operation) {
+ $approval = Activity::addToCollection($channel, $act->data, $item_result['item']['parent_mid'], $item_result['item'], deliver: false);
+ }
+
}
else {
$DR->update('update ignored');
$result[] = $DR->get();
- // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit),
+ // We need this line to ensure wall-to-wall comments and add/remove activities are relayed (by falling through to the relay bit),
// and at the same time not relay any other relayable posts more than once, because to do so is very wasteful.
if (!intval($r[0]['item_origin']))
continue;
}
+
+
}
else {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
+
// if it's a sourced post, call the post_local hooks as if it were
// posted locally so that crosspost connectors will be triggered.
$item_source = check_item_source($arr['uid'], $arr);
@@ -1902,10 +1934,15 @@ class Libzot {
}
if (post_is_importable($arr['uid'], $arr, $abook)) {
- $item_result = item_store($arr);
+ $item_result = item_store($arr, addAndSync: false);
+
if ($item_result['success']) {
$item_id = $item_result['item_id'];
+ if ($relay && $channel['channel_hash'] === $item_result['item']['owner_xchan'] && $item_result['item']['verb'] !== 'Add' && !$is_collection_operation) {
+ $approval = Activity::addToCollection($channel, $act->data, $item_result['item']['parent_mid'], $item_result['item'], deliver: false);
+ }
+
if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
event_addtocal($item_id, $channel['channel_id']);
}
@@ -1948,12 +1985,16 @@ class Libzot {
if ((is_array($stored)) && ($stored['id'] != $stored['parent'])
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
- retain_item($stored['item']['parent']);
+ retain_item($stored['parent']);
}
- if ($relay && $item_id && $stored['item_blocked'] !== ITEM_MODERATED) {
+ if ($relay && $item_id && item_forwardable($stored)) {
logger('Invoking relay');
Master::Summon(['Notifier', 'relay', intval($item_id)]);
+ if (!empty($approval) && $approval['item_id']) {
+ Master::Summon(['Notifier', 'relay', intval($approval['item_id'])]);
+ }
+
$DR->addto_update('relayed');
$result[] = $DR->get();
}
@@ -2006,6 +2047,7 @@ class Libzot {
foreach ($items as $activity) {
$AS = new ActivityStreams($activity);
+
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object', $AS->obj) && array_key_exists('actor', $AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
@@ -2014,6 +2056,30 @@ class Libzot {
$AS = new ActivityStreams($AS->obj);
}
+ // process add/remove from collection separately, as it requires a target.
+ // use the raw object, as it will not include actor expansion
+ if (in_array($AS->type, ['Add', 'Remove'])
+ && is_array($AS->obj)
+ && array_key_exists('object', $AS->obj)
+ && array_key_exists('actor', $AS->obj)
+ && !empty($AS->tgt)) {
+
+ logger('relayed collection operation', LOGGER_DEBUG);
+
+ $is_collection_operation = true;
+
+ $original_id = $AS->id;
+ $original_type = $AS->type;
+
+ $raw_activity = $AS->data;
+
+ $AS = new ActivityStreams($raw_activity['object']);
+
+ // Store the original activity id and type for later usage
+ $AS->meta['original_id'] = $original_id;
+ $AS->meta['original_type'] = $original_type;
+ }
+
if (!$AS->is_valid()) {
logger('Fetched activity rejected: ' . print_r($activity, true));
continue;
@@ -2207,7 +2273,7 @@ class Libzot {
}
- $x = item_store_update($item);
+ $x = item_store_update($item, addAndSync: false);
// If we're updating an event that we've saved locally, we store the item info first
// because event_addtocal will parse the body to get the 'new' event details
@@ -2323,21 +2389,20 @@ class Libzot {
);
}
} else {
- if ($stored['id'] !== $stored['parent']) {
- q(
- "update item set commented = '%s', changed = '%s' where id = %d",
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval($stored['parent'])
- );
- }
- }
+ if ($stored['id'] !== $stored['parent']) {
+ q("update item set commented = '%s', changed = '%s' where id = %d",
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($stored['parent'])
+ );
+ }
+ }
// Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
// and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2).
- drop_item($post_id, false, DROPITEM_PHASE1);
+ drop_item($post_id, DROPITEM_PHASE1, uid: $uid);
tag_deliver($uid, $post_id);
}
diff --git a/Zotlabs/Lib/Mailer.php b/Zotlabs/Lib/Mailer.php
new file mode 100644
index 000000000..ca2d84d0d
--- /dev/null
+++ b/Zotlabs/Lib/Mailer.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Mailer class for sending emails from Hubzilla.
+ *
+ * SPDX-FileCopyrightText: 2024 Hubzilla Community
+ * SPDX-FileContributor: Harald Eilertsen
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+namespace Zotlabs\Lib;
+
+use App;
+
+/**
+ * A class for sending emails.
+ *
+ * Based on the previous `z_mail` function, but adaped and made more
+ * robust and usable as a class.
+ */
+class Mailer {
+
+ public function __construct(private array $params = []) {
+ }
+
+ public function deliver(): bool {
+
+ if(empty($this->params['fromEmail'])) {
+ $this->params['fromEmail'] = Config::Get('system','from_email');
+ if(empty($this->params['fromEmail'])) {
+ $this->params['fromEmail'] = 'Administrator@' . App::get_hostname();
+ }
+ }
+
+ if(empty($this->params['fromName'])) {
+ $this->params['fromName'] = Config::Get('system','from_email_name');
+ if(empty($this->params['fromName'])) {
+ $this->params['fromName'] = System::get_site_name();
+ }
+ }
+
+ if(empty($this->params['replyTo'])) {
+ $this->params['replyTo'] = Config::Get('system','reply_address');
+ if(empty($this->params['replyTo'])) {
+ $this->params['replyTo'] = 'noreply@' . App::get_hostname();
+ }
+ }
+
+ if (!isset($this->params['additionalMailHeader'])) {
+ $this->params['additionalMailHeader'] = '';
+ }
+
+ $this->params['sent'] = false;
+ $this->params['result'] = false;
+
+ /**
+ * @hooks email_send
+ * * \e params @see z_mail()
+ */
+ call_hooks('email_send', $this->params);
+
+ if($this->params['sent']) {
+ logger('notification: z_mail returns ' . (($this->params['result']) ? 'success' : 'failure'), LOGGER_DEBUG);
+ return $this->params['result'];
+ }
+
+ $fromName = email_header_encode(html_entity_decode($this->params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
+ $messageSubject = email_header_encode(html_entity_decode($this->params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
+
+ $messageHeader =
+ $this->params['additionalMailHeader'] .
+ "From: $fromName <{$this->params['fromEmail']}>" . PHP_EOL .
+ "Reply-To: $fromName <{$this->params['replyTo']}>" . PHP_EOL .
+ "Content-Type: text/plain; charset=UTF-8";
+
+ // send the message
+ $res = mail(
+ $this->params['toEmail'], // send to address
+ $messageSubject, // subject
+ $this->params['textVersion'],
+ $messageHeader // message headers
+ );
+ logger('notification: z_mail returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
+ return $res;
+ }
+}
diff --git a/Zotlabs/Lib/PermissionDescription.php b/Zotlabs/Lib/PermissionDescription.php
index 51d5f890d..13df60b60 100644
--- a/Zotlabs/Lib/PermissionDescription.php
+++ b/Zotlabs/Lib/PermissionDescription.php
@@ -117,7 +117,7 @@ class PermissionDescription {
}
/**
- * Returns an icon css class name if an appropriate one is available, e.g. "fa-globe" for Public,
+ * Returns an icon css class name if an appropriate one is available, e.g. "bi-globe" for Public,
* otherwise returns empty string.
*
* @return string icon css class name (often FontAwesome)
@@ -125,12 +125,12 @@ class PermissionDescription {
public function get_permission_icon() {
switch($this->channel_perm) {
- case 0:/* only me */ return 'fa-eye-slash';
- case PERMS_PUBLIC: return 'fa-globe';
- case PERMS_NETWORK: return 'fa-share-alt-square'; // fa-share-alt-square is very similiar to the hubzilla logo, but we should create our own logo class to use
- case PERMS_SITE: return 'fa-sitemap';
- case PERMS_CONTACTS: return 'fa-group';
- case PERMS_SPECIFIC: return 'fa-list';
+ case 0:/* only me */ return 'bi-eye-slash';
+ case PERMS_PUBLIC: return 'bi-globe';
+ case PERMS_NETWORK: return 'bi-share'; // bi-share is very similiar to the hubzilla logo, but we should create our own logo class to use
+ case PERMS_SITE: return 'bi-geo';
+ case PERMS_CONTACTS: return 'bi-people';
+ case PERMS_SPECIFIC: return 'bi-list-ul';
case PERMS_AUTHED: return '';
case PERMS_PENDING: return '';
default: return '';
diff --git a/Zotlabs/Lib/QueueWorker.php b/Zotlabs/Lib/QueueWorker.php
index 24114438e..9e28999c9 100644
--- a/Zotlabs/Lib/QueueWorker.php
+++ b/Zotlabs/Lib/QueueWorker.php
@@ -59,7 +59,7 @@ class QueueWorker {
$transaction = new \DbaTransaction(\DBA::$dba);
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
intval($priority),
- $workinfo_json,
+ dbesc($workinfo_json),
dbesc($uuid),
dbesc($argv[0])
);
@@ -105,7 +105,7 @@ class QueueWorker {
$transaction = new \DbaTransaction(\DBA::$dba);
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
intval($priority),
- $workinfo_json,
+ dbesc($workinfo_json),
dbesc($uuid),
dbesc($argv[0])
);
diff --git a/Zotlabs/Lib/SuperCurl.php b/Zotlabs/Lib/SuperCurl.php
deleted file mode 100644
index 462a62b36..000000000
--- a/Zotlabs/Lib/SuperCurl.php
+++ /dev/null
@@ -1,127 +0,0 @@
-<?php
-
-namespace Zotlabs\Lib;
-
-/**
- * @brief wrapper for z_fetch_url() which can be instantiated with several built-in parameters and
- * these can be modified and re-used. Useful for CalDAV and other processes which need to authenticate
- * and set lots of CURL options (many of which stay the same from one call to the next).
- */
-
-
-
-
-class SuperCurl {
-
-
- private $auth;
- private $url;
-
- private $curlopt = array();
-
- private $headers = null;
- public $filepos = 0;
- public $filehandle = 0;
- public $request_data = '';
-
- private $request_method = 'GET';
- private $upload = false;
- private $cookies = false;
-
-
- private function set_data($s) {
- $this->request_data = $s;
- $this->filepos = 0;
- }
-
- public function curl_read($ch,$fh,$size) {
-
- if($this->filepos < 0) {
- unset($fh);
- return '';
- }
-
- $s = substr($this->request_data,$this->filepos,$size);
-
- if(strlen($s) < $size)
- $this->filepos = (-1);
- else
- $this->filepos = $this->filepos + $size;
-
- return $s;
- }
-
-
- public function __construct($opts = array()) {
- $this->set($opts);
- }
-
- private function set($opts = array()) {
- if($opts) {
- foreach($opts as $k => $v) {
- switch($k) {
- case 'http_auth':
- $this->auth = $v;
- break;
- case 'magicauth':
- // currently experimental
- $this->magicauth = $v;
- \Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]);
- break;
- case 'custom':
- $this->request_method = $v;
- break;
- case 'url':
- $this->url = $v;
- break;
- case 'data':
- $this->set_data($v);
- if($v) {
- $this->upload = true;
- }
- else {
- $this->upload = false;
- }
- break;
- case 'headers':
- $this->headers = $v;
- break;
- default:
- $this->curlopts[$k] = $v;
- break;
- }
- }
- }
- }
-
- function exec() {
- $opts = $this->curlopts;
- $url = $this->url;
- if($this->auth)
- $opts['http_auth'] = $this->auth;
- if($this->magicauth) {
- $opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth;
- $opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth;
- $opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth));
- $c = channelx_by_n($this->magicauth);
- if($c)
- $url = zid($this->url,channel_reddress($c));
- }
- if($this->custom)
- $opts['custom'] = $this->custom;
- if($this->headers)
- $opts['headers'] = $this->headers;
- if($this->upload) {
- $opts['upload'] = true;
- $opts['infile'] = $this->filehandle;
- $opts['infilesize'] = strlen($this->request_data);
- $opts['readfunc'] = [ $this, 'curl_read' ] ;
- }
-
- $recurse = 0;
- return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null));
-
- }
-
-
-}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 1082bf642..e0db98eb3 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -93,7 +93,7 @@ class ThreadItem {
$buttons = '';
$dropping = false;
$star = false;
- $isstarred = "unstarred fa-star-o";
+ $isstarred = "unstarred bi-star";
$is_comment = false;
$is_item = false;
$osparkle = '';
@@ -123,13 +123,13 @@ class ThreadItem {
$locktype = 0;
}
- $shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0)) ? true : false);
+ $shareable = ((local_channel() && $conv->get_profile_owner() == local_channel()) && (intval($item['item_private']) === 0));
// allow an exemption for sharing stuff from your private feeds
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
- $repeatable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0) && (in_array($item['author']['xchan_network'], ['zot6', 'activitypub']))) ? true : false);
+ $repeatable = ((local_channel() && $conv->get_profile_owner() == local_channel()) && intval($item['item_private']) === 0 && in_array($item['author']['xchan_network'], ['zot6', 'activitypub']));
// @fixme
// Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
@@ -187,7 +187,7 @@ class ThreadItem {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
- $filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
+ $filer = (((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_s'];
$profile_link = chanlink_hash($item['author_xchan']);
@@ -204,9 +204,11 @@ class ThreadItem {
$response_verbs[] = 'dislike';
}
- $response_verbs[] = 'announce';
+ if ($repeatable) {
+ $response_verbs[] = 'announce';
+ }
- if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
+ if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
@@ -216,60 +218,21 @@ class ThreadItem {
}
}
- if($item['obj_type'] === 'Question') {
+ if ($item['obj_type'] === 'Question') {
$response_verbs[] = 'answer';
}
- if(! feature_enabled($conv->get_profile_owner(),'dislike'))
+ if (!feature_enabled($conv->get_profile_owner(),'dislike')) {
unset($conv_responses['dislike']);
+ }
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$my_responses = [];
foreach($response_verbs as $v) {
-
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
}
-/*
-
- $like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
- $like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
- if (($like_list) && (count($like_list) > MAX_LIKERS)) {
- $like_list_part = array_slice($like_list, 0, MAX_LIKERS);
- array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $like_list_part = '';
- }
- $like_button_label = tt('Like','Likes',$like_count,'noun');
-
- $repeat_count = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid']] : '');
- $repeat_list = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid'] . '-l'] : '');
- if (($repeat_list) && (count($repeat_list) > MAX_LIKERS)) {
- $repeat_list_part = array_slice($repeat_list, 0, MAX_LIKERS);
- array_push($repeat_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#repeatModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $repeat_list_part = '';
- }
- $repeat_button_label = tt('Repeat','Repeats',$repeat_count,'noun');
-
- $showdislike = '';
- if (feature_enabled($conv->get_profile_owner(),'dislike')) {
- $dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
- $dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
- $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
- if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
- $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
- array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $dislike_list_part = '';
- }
-
- $showdislike = ((x($conv_responses['dislike'],$item['mid'])) ? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
- }
-
- $showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
-*/
/*
* We should avoid doing this all the time, but it depends on the conversation mode
@@ -327,11 +290,13 @@ class ThreadItem {
$like = [];
$dislike = [];
$reply_to = [];
+ $reactions_allowed = false;
if($this->is_commentable() && $observer) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
- $reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
+ $reply_to = array( t("Reply to this comment"), t("reply"), t("Reply to"));
+ $reactions_allowed = true;
}
$share = [];
@@ -411,7 +376,6 @@ class ThreadItem {
'template' => $this->get_template(),
'mode' => $mode,
'item_type' => intval($item['item_type']),
- //'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'body' => $body['html'],
'tags' => $body['tags'],
'categories' => $body['categories'],
@@ -446,16 +410,15 @@ class ThreadItem {
'sparkle' => $sparkle,
'title' => $item['title'],
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
- //'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t('from %s'), $item['app']),
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
- 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
- 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
- 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
+ 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created']),
+ 'editedtime' => (($item['edited'] != $item['created']) ? sprintf(t('Last edited %s'), relative_time($item['edited'])) : ''),
+ 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf(t('Expires %s'), relative_time($item['expires'])) : ''),
'lock' => $lock,
'locktype' => $locktype,
- 'delayed' => $item['item_delayed'],
+ 'delayed' => (($item['item_delayed']) ? sprintf(t('Published %s'), relative_time($item['created'])) : ''),
'privacy_warning' => $privacy_warning,
'verified' => $verified,
'unverified' => $unverified,
@@ -475,7 +438,7 @@ class ThreadItem {
'event' => $body['event'],
'has_tags' => $has_tags,
'reactions' => $this->reactions,
-// Item toolbar buttons
+ // Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
@@ -485,7 +448,7 @@ class ThreadItem {
'embed' => $embed,
'rawmid' => $item['mid'],
'plink' => get_plink($item),
- 'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
+ 'edpost' => $edpost,
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
@@ -496,7 +459,7 @@ class ThreadItem {
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'dropdown_extras' => $dropdown_extras,
-// end toolbar buttons
+ // end toolbar buttons
'unseen_comments' => $unseen_comments,
'comment_count' => $total_children,
'comment_count_txt' => $comment_count_txt,
@@ -504,30 +467,9 @@ class ThreadItem {
'markseen' => t('Mark all comments seen'),
'responses' => $responses,
'my_responses' => $my_responses,
- /*
- 'like_count' => $like_count,
- 'like_list' => $like_list,
- 'like_list_part' => $like_list_part,
- 'like_button_label' => $like_button_label,
- 'like_modal_title' => t('Likes','noun'),
-
- 'repeat_count' => $repeat_count,
- 'repeat_list' => $repeat_list,
- 'repeat_list_part' => $repeat_list_part,
- 'repeat_button_label' => $repeat_button_label,
- 'repeat_modal_title' => t('Repeats','noun'),
-
-
- 'dislike_modal_title' => t('Dislikes','noun'),
- 'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
- 'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
- 'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
- 'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
-*/
'modal_dismiss' => t('Close'),
- // 'showlike' => $showlike,
- // 'showdislike' => $showdislike,
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
+ 'no_comment' => (($item['item_thread_top'] && $item['item_nocomment'])? t('Comments disabled') : ''),
'previewing' => ($conv->is_preview() ? true : false ),
'preview_lbl' => t('This is an unsaved preview'),
'wait' => t('Please wait'),
@@ -539,6 +481,9 @@ class ThreadItem {
'moderate_approve' => t('Approve'),
'moderate_delete' => t('Delete'),
'rtl' => in_array($item['lang'], rtl_languages()),
+ 'reactions_allowed' => $reactions_allowed,
+ 'reaction_str' => [t('Add yours'), t('Remove yours')],
+ 'is_contained' => $this->is_toplevel() && str_contains($item['tgt_type'], 'Collection')
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -549,15 +494,7 @@ class ThreadItem {
$result['children'] = array();
$nb_children = count($children);
- $visible_comments = Config::Get('system','expanded_comments');
- if($visible_comments === false)
- $visible_comments = 3;
-
-// needed for scroll to comment from notification but needs more work
-// as we do not want to open all comments unless there is actually an #item_xx anchor
-// and the url fragment is not sent to the server.
-// if(in_array(\App::$module,['display','update_display']))
-// $visible_comments = 99999;
+ $visible_comments = Config::Get('system', 'expanded_comments', 3);
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
foreach($children as $child) {
@@ -567,7 +504,7 @@ class ThreadItem {
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
- $result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
+ $result['children'][0]['hide_text'] = t('show all');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
}
@@ -862,6 +799,7 @@ class ThreadItem {
'$submit' => t('Submit'),
'$edbold' => t('Bold'),
'$editalic' => t('Italic'),
+ '$edhighlighter' => t('Highlight selected text'),
'$eduline' => t('Underline'),
'$edquote' => t('Quote'),
'$edcode' => t('Code'),
@@ -869,7 +807,7 @@ class ThreadItem {
'$edatt' => t('Attach/Upload file'),
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
- '$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
+ '$preview' => t('Preview'),
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()),
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
@@ -890,7 +828,7 @@ class ThreadItem {
}
/**
- * Check if we are a wall to wall item and set the relevant properties
+ * Check if we are a wall to wall or announce item and set the relevant properties
*/
protected function check_wall_to_wall() {
$conv = $this->get_conversation();
diff --git a/Zotlabs/Lib/Traits/HelpHelperTrait.php b/Zotlabs/Lib/Traits/HelpHelperTrait.php
index b7711bbd5..63b0eb22e 100644
--- a/Zotlabs/Lib/Traits/HelpHelperTrait.php
+++ b/Zotlabs/Lib/Traits/HelpHelperTrait.php
@@ -15,6 +15,15 @@ trait HelpHelperTrait {
private string $file_type = '';
/**
+ * Associative array containing the detected language.
+ */
+ private array $lang = [
+ 'language' => 'en', //! Detected language, 2-letter ISO 639-1 code ("en")
+ 'from_url' => false, //! true if language from URL overrides browser default
+ 'missing' => false, //! true if topic not found in detected language
+ ];
+
+ /**
* Determines help language.
*
* If the language was specified in the URL, override the language preference
@@ -28,17 +37,15 @@ trait HelpHelperTrait {
$languages = $language_repository->getList();
if(array_key_exists(argv(1), $languages)) {
- $lang = argv(1);
- $from_url = true;
+ $this->lang['language'] = argv(1);
+ $this->lang['from_url'] = true;
} else {
- $lang = \App::$language;
- if(! isset($lang))
- $lang = 'en';
+ if(isset(\App::$language)) {
+ $this->lang['language'] = \App::$language;
+ }
- $from_url = false;
+ $this->lang['from_url'] = false;
}
-
- $this->lang = array('language' => $lang, 'from_url' => $from_url);
}
/**
@@ -53,10 +60,10 @@ trait HelpHelperTrait {
// Use local variable until we can use trait constants.
$valid_file_ext = ['md', 'bb', 'html'];
- $base_path = "doc/{$lang}/${base_path}";
+ $base_path_with_lang = "doc/{$lang}/${base_path}";
foreach ($valid_file_ext as $ext) {
- $path = "{$base_path}.{$ext}";
+ $path = "{$base_path_with_lang}.{$ext}";
if (file_exists($path)) {
$this->file_name = $path;
$this->file_type = $ext;
@@ -64,5 +71,25 @@ trait HelpHelperTrait {
break;
}
}
+
+ if (empty($this->file_name) && $lang !== 'en') {
+ $this->lang['missing'] = true;
+ $this->find_help_file($base_path, 'en');
+ }
+ }
+
+ public function missing_translation(): bool {
+ return !!$this->lang['missing'];
+ }
+
+ public function missing_translation_message(): string {
+ $prefered_language_name = get_language_name(
+ $this->lang['language'],
+ $this->lang['language']
+ );
+
+ return bbcode(
+ t("This page is not yet available in {$prefered_language_name}. See [observer.baseurl]/help/developer/developer_guide#Translations for information about how to help.")
+ );
}
}
diff --git a/Zotlabs/Lib/XConfig.php b/Zotlabs/Lib/XConfig.php
index 76ac8dc7a..5eed9224e 100644
--- a/Zotlabs/Lib/XConfig.php
+++ b/Zotlabs/Lib/XConfig.php
@@ -83,7 +83,7 @@ class XConfig {
return $default;
if(! array_key_exists($xchan, \App::$config))
- load_xconfig($xchan);
+ self::Load($xchan);
if((! array_key_exists($family, \App::$config[$xchan])) || (! array_key_exists($key, \App::$config[$xchan][$family])))
return $default;
diff --git a/Zotlabs/Module/Achievements.php b/Zotlabs/Module/Achievements.php
index 1529448d3..a16294039 100644
--- a/Zotlabs/Module/Achievements.php
+++ b/Zotlabs/Module/Achievements.php
@@ -8,25 +8,25 @@ class Achievements extends \Zotlabs\Web\Controller {
// This doesn't work, so
if (! is_developer())
return;
-
+
if(argc() > 1)
$which = argv(1);
else {
notice( t('Requested profile is not available.') . EOL );
return;
}
-
+
$profile = 0;
- $profile = argv(1);
+ $profile = argv(1);
profile_load($which,$profile);
-
+
$r = q("select channel_id from channel where channel_address = '%s'",
dbesc($which)
);
if($r) {
$owner = intval($r[0]['channel_id']);
}
-
+
$observer = \App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
@@ -34,60 +34,60 @@ class Achievements extends \Zotlabs\Web\Controller {
notice( t('Permission denied.') . EOL);
return;
}
-
+
$newmembertext = t('Some blurb about what to do when you\'re new here');
-
-
+
+
// By default, all badges are false
$contactbadge = false;
$profilebadge = false;
$keywordsbadge = false;
-
+
// Check number of contacts. Award a badge if over 10
- // We'll figure these out on each page load instead of
+ // We'll figure these out on each page load instead of
// writing them to the DB because that will mean one needs
// to retain their achievements - eg, you can't add
// a bunch of channels just to get your badge, and then
// delete them all again. If these become popular or
// used in profiles or something, we may need to reconsider
// and add a table for this - because this won't scale.
-
+
$r = q("select * from abook where abook_channel = %d",
intval($owner)
);
-
+
if (count($r))
$contacts = count($r);
// We're checking for 11 to adjust for the abook record for self
if ($contacts >= 11)
$contactbadge = true;
-
+
// Check if an about field in the profile has been created.
-
+
$r = q("select * from profile where uid = %d and about <> ''",
intval($owner)
);
-
+
if ($r)
$profilebadge = 1;
-
+
// Check if keywords have been set
-
+
$r = q("select * from profile where uid = %d and keywords <> ''",
intval($owner)
);
-
+
if($r)
$keywordsbadge = 1;
-
+
return replace_macros(get_markup_template("achievements.tpl"), array(
'$newmembertext' => $newmembertext,
'$profilebadge' => $profilebadge,
'$contactbadge' => $contactbadge,
'$keywordsbadge' => $keywordsbadge,
- '$channelsbadge' => $channelsbadge
+ '$channelsbadge' => null,
));
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Activity.php b/Zotlabs/Module/Activity.php
index 133312e28..85b9f3e7c 100644
--- a/Zotlabs/Module/Activity.php
+++ b/Zotlabs/Module/Activity.php
@@ -30,7 +30,7 @@ class Activity extends Controller {
dbesc(ACTIVITY_UNFOLLOW)
);
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
$i = null;
@@ -191,7 +191,7 @@ class Activity extends Controller {
dbesc(ACTIVITY_UNFOLLOW)
);
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
diff --git a/Zotlabs/Module/Admin/Account_edit.php b/Zotlabs/Module/Admin/Account_edit.php
index 0300fb10c..35a15133f 100644
--- a/Zotlabs/Module/Admin/Account_edit.php
+++ b/Zotlabs/Module/Admin/Account_edit.php
@@ -8,6 +8,11 @@ class Account_edit {
function post() {
+ // Validate CSRF token
+ //
+ // We terminate with a 403 Forbidden status if the check fails.
+ check_form_security_token_ForbiddenOnErr('admin_account_edit', 'security');
+
$account_id = $_REQUEST['aid'];
if(! $account_id)
@@ -18,7 +23,7 @@ class Account_edit {
if($pass1 && $pass2 && ($pass1 === $pass2)) {
$salt = random_string(32);
$password_encoded = hash('whirlpool', $salt . $pass1);
- $r = q("update account set account_salt = '%s', account_password = '%s',
+ $r = q("update account set account_salt = '%s', account_password = '%s',
account_password_changed = '%s' where account_id = %d",
dbesc($salt),
dbesc($password_encoded),
@@ -34,7 +39,7 @@ class Account_edit {
$account_level = 5;
$account_language = trim($_REQUEST['account_language']);
- $r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
+ $r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
where account_id = %d",
dbesc($service_class),
intval($account_level),
@@ -62,8 +67,8 @@ class Account_edit {
return '';
}
-
$a = replace_macros(get_markup_template('admin_account_edit.tpl'), [
+ '$security' => get_form_security_token('admin_account_edit'),
'$account' => $x[0],
'$title' => t('Account Edit'),
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],
diff --git a/Zotlabs/Module/Admin/Accounts.php b/Zotlabs/Module/Admin/Accounts.php
index 6f7cb0311..108231d7d 100644
--- a/Zotlabs/Module/Admin/Accounts.php
+++ b/Zotlabs/Module/Admin/Accounts.php
@@ -6,133 +6,33 @@ use Zotlabs\Lib\Config;
class Accounts {
- /**
- * @brief Handle POST actions on accounts admin page.
- *
- * This function is called when on the admin user/account page the form was
- * submitted to handle multiple operations at once. If one of the icons next
- * to an entry are pressed the function admin_page_accounts() will handle this.
- *
- */
const MYP = 'ZAR'; // ZAR2x
const VERSION = '2.0.0';
- function post() {
+ /**
+ * Handle POST actions on accounts admin page.
+ */
+ public function post() {
- $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
- $users = ( x($_POST, 'user') ? $_POST['user'] : array() );
- $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
+ $pending = x($_POST, 'pending') ? $_POST['pending'] : array();
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
- $isajax = is_ajax();
- $rc = 0;
-
- If (!is_site_admin()) {
- if ($isajax) {
- killme();
- exit;
- }
- goaway(z_root() . '/');
- }
-
- if ($isajax) {
- //$debug = print_r($_SESSION[self::MYP],true);
- $zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
- ? $_POST['zardo'] : '';
- // zarat arrives with leading underscore _n
- $zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
- ? substr($_POST['zarat'],1) : '';
- $zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
- ? hex2bin($_POST['zarse']) : '';
-
- if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
-
- //
- if ($zarop == 'd') {
- $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
- intval($_SESSION[self::MYP]['i'][$zarat]),
- dbesc($_SESSION[self::MYP]['h'][$zarat])
- );
- $rc = '×';
- }
- elseif ($zarop == 'a') {
- // approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
- $rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
- . " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
- . " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
- intval($_SESSION[self::MYP]['i'][$zarat]),
- dbesc($_SESSION[self::MYP]['h'][$zarat])
- );
- $rc = 0;
- $rs = q("SELECT * from register WHERE reg_id = %d ",
- intval($_SESSION[self::MYP]['i'][$zarat])
- );
- if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
- // create account
- $rc = 'ok'.$rs[0]['reg_id'];
- $ac = create_account_from_register($rs[0]);
- if ( $ac['success'] ) {
- $rc .= '✔';
-
- $auto_create = Config::Get('system','auto_channel_create',1);
-
- if($auto_create) {
- $reonar = json_decode($rs[0]['reg_stuff'], true);
- // prepare channel creation
- if($reonar['chan.name'])
- set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
-
- if($reonar['chan.did1'])
- set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
-
- $permissions_role = Config::Get('system','default_permissions_role');
- if($permissions_role)
- set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
-
- // create channel
- $new_channel = auto_channel_create($ac['account']['account_id']);
-
- if($new_channel['success']) {
- $rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
- }
- else {
- $rc .= ' c ×';
- }
- }
-
-
- }
- } else {
- $rc='oh ×';
- }
- }
- echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
- }
+ if (is_ajax()) {
+ $this->handle_ajax_request();
killme();
- exit;
}
// change to switch structure?
// account block/unblock button was submitted
if (x($_POST, 'page_accounts_block')) {
- for ($i = 0; $i < count($users); $i++) {
- // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
- $op = ($blocked[$i]) ? '& ~' : '| ';
- q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
- intval(ACCOUNT_BLOCKED),
- intval($users[$i])
- );
- }
- notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
+ $this->block_unblock_accounts();
}
+
// account delete button was submitted
if (x($_POST, 'page_accounts_delete')) {
- foreach ($users as $uid){
- account_remove($uid, true, false);
- }
- notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
+ $this->delete_accounts();
}
// registration approved button was submitted
if (x($_POST, 'page_accounts_approve')) {
@@ -351,5 +251,143 @@ class Accounts {
return $o;
}
+ private function handle_ajax_request(): void {
+ //$debug = print_r($_SESSION[self::MYP],true);
+ $zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
+ ? $_POST['zardo'] : '';
+ // zarat arrives with leading underscore _n
+ $zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
+ ? substr($_POST['zarat'],1) : '';
+ $zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
+ ? hex2bin($_POST['zarse']) : '';
+
+ if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
+
+ //
+ if ($zarop == 'd') {
+ $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
+ intval($_SESSION[self::MYP]['i'][$zarat]),
+ dbesc($_SESSION[self::MYP]['h'][$zarat])
+ );
+ $rc = '×';
+ }
+ elseif ($zarop == 'a') {
+ // approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
+ $rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
+ . " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
+ . " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
+ intval($_SESSION[self::MYP]['i'][$zarat]),
+ dbesc($_SESSION[self::MYP]['h'][$zarat])
+ );
+ $rc = 0;
+ $rs = q("SELECT * from register WHERE reg_id = %d ",
+ intval($_SESSION[self::MYP]['i'][$zarat])
+ );
+ if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
+ // create account
+ $rc = 'ok'.$rs[0]['reg_id'];
+ $ac = create_account_from_register($rs[0]);
+ if ( $ac['success'] ) {
+ $rc .= '✔';
+
+ $auto_create = Config::Get('system','auto_channel_create',1);
+
+ if($auto_create) {
+ $reonar = json_decode($rs[0]['reg_stuff'], true);
+ // prepare channel creation
+ if($reonar['chan.name'])
+ set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
+
+ if($reonar['chan.did1'])
+ set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
+
+ $permissions_role = Config::Get('system','default_permissions_role');
+ if($permissions_role)
+ set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
+
+ // create channel
+ $new_channel = auto_channel_create($ac['account']['account_id']);
+
+ if($new_channel['success']) {
+ $rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
+ }
+ else {
+ $rc .= ' c ×';
+ }
+ }
+
+
+ }
+ } else {
+ $rc='oh ×';
+ }
+ }
+ echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
+ }
+ }
+
+ /**
+ * Block or unblock accounts given by the `user` and `blocked` POST params.
+ *
+ * The post params `user` and `blocked` must be present and arrays of equal
+ * lengths. The `user` array should contain account id's or the accounts to
+ * process, and the `blocked` array holds a corresponding boolean value to
+ * indicate that the account at the same offset in the `user` array is or is
+ * not blocked.
+ *
+ * An account that is _not_ blocked will be blocked, and accounts that _are_
+ * blocked will be unblocked.
+ *
+ * @SuppressWarnings(PHPMD.ShortVariable)
+ */
+ private function block_unblock_accounts(): void {
+ if (!isset($_POST['user']) || !isset($_POST['blocked'])) {
+ return;
+ }
+
+ $users = $_POST['user'];
+ $blocked = $_POST['blocked'];
+
+ if (!is_array($users) || !is_array($blocked)) {
+ return;
+ }
+
+ foreach($users as $i => $id) {
+ // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
+ $op = $blocked[$i] ? '& ~' : '| ';
+
+ q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
+ intval(ACCOUNT_BLOCKED),
+ intval($id)
+ );
+ }
+
+ $count = count($users);
+ $fmt = tt("%s account blocked/unblocked", "%s account blocked/unblocked", $count);
+ notice(sprintf($fmt, $count));
+ }
+
+ /**
+ * Delete multiple accounts given by the `user` POST param.
+ */
+ private function delete_accounts(): void {
+ if (!isset($_POST['user'])) {
+ return;
+ }
+
+ $users = $_POST['user'];
+
+ if (!is_array($users)) {
+ return;
+ }
+
+ foreach ($users as $uid){
+ account_remove($uid, true, false);
+ }
+
+ $count = count($users);
+ $fmt = tt("%s account deleted", "%s accounts deleted", $count);
+ notice(sprintf($fmt, $count));
+ }
}
diff --git a/Zotlabs/Module/Admin/Addons.php b/Zotlabs/Module/Admin/Addons.php
index b7cfb651c..0cb173e7c 100644
--- a/Zotlabs/Module/Admin/Addons.php
+++ b/Zotlabs/Module/Admin/Addons.php
@@ -3,9 +3,8 @@
namespace Zotlabs\Module\Admin;
use App;
-use \Zotlabs\Lib\Config;
-use \Zotlabs\Storage\GitRepo;
-use \Michelf\MarkdownExtra;
+use Zotlabs\Lib\Config;
+use Michelf\MarkdownExtra;
class Addons {
@@ -24,227 +23,6 @@ class Addons {
goaway(z_root() . '/admin/addons/' . argv(2) );
}
- elseif(argc() > 2) {
- switch(argv(2)) {
- case 'updaterepo':
- if (array_key_exists('repoName', $_REQUEST)) {
- $repoName = $_REQUEST['repoName'];
- }
- else {
- json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
- }
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- }
- else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- $repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
- if (!is_dir($repoDir)) {
- logger('Repo directory does not exist: ' . $repoDir);
- json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
- }
- if (!is_writable($repoDir)) {
- logger('Repo directory not writable to web server: ' . $repoDir);
- json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
- }
- $git = new GitRepo('sys', null, false, $repoName, $repoDir);
- try {
- if ($git->pull()) {
- $files = array_diff(scandir($repoDir), array('.', '..'));
- foreach ($files as $file) {
- if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
- $source = '../extend/addon/' . $repoName . '/' . $file;
- $target = realpath('addon/') . '/' . $file;
- unlink($target);
- if (!symlink($source, $target)) {
- logger('Error linking addons to /addon');
- json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
- }
- }
- }
- json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
- }
- } catch (\PHPGit\Exception\GitException $e) {
- json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
- }
- break;
- case 'removerepo':
- if (array_key_exists('repoName', $_REQUEST)) {
- $repoName = $_REQUEST['repoName'];
- } else {
- json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
- }
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- $repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
- if (!is_dir($repoDir)) {
- logger('Repo directory does not exist: ' . $repoDir);
- json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
- }
- if (!is_writable($repoDir)) {
- logger('Repo directory not writable to web server: ' . $repoDir);
- json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
- }
- /// @TODO remove directory and unlink /addon/files
- if (rrmdir($repoDir)) {
- json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
- }
- break;
- case 'installrepo':
- if (array_key_exists('repoURL', $_REQUEST)) {
- require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
- $repoURL = $_REQUEST['repoURL'];
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- if (!is_writable($extendDir)) {
- logger('Directory not writable to web server: ' . $extendDir);
- json_return_and_die(array('message' => 'Directory not writable to web server.', 'success' => false));
- }
- $repoName = null;
- if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
- $repoName = $_REQUEST['repoName'];
- } else {
- $repoName = GitRepo::getRepoNameFromURL($repoURL);
- }
- if (!$repoName) {
- logger('Invalid git repo');
- json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
- }
- $repoDir = $addonDir . '/' . $repoName;
- $tempRepoBaseDir = 'store/[data]/git/sys/temp/';
- $tempAddonDir = $tempRepoBaseDir . $repoName;
-
- if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
- logger('Temp repo directory or /extend/addon not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Temp repo directory not writable to web server.', 'success' => false));
- }
- rename($tempAddonDir, $repoDir);
-
- if (!is_writable(realpath('addon/'))) {
- logger('/addon directory not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => '/addon directory not writable to web server.', 'success' => false));
- }
- $files = array_diff(scandir($repoDir), array('.', '..'));
- foreach ($files as $file) {
- if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
- $source = '../extend/addon/' . $repoName . '/' . $file;
- $target = realpath('addon/') . '/' . $file;
- unlink($target);
- if (!symlink($source, $target)) {
- logger('Error linking addons to /addon');
- json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
- }
- }
- }
- $git = new GitRepo('sys', $repoURL, false, $repoName, $repoDir);
- $repo = $git->probeRepo();
- json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
- }
- break;
- case 'addrepo':
- if (array_key_exists('repoURL', $_REQUEST)) {
- require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
- $repoURL = $_REQUEST['repoURL'];
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- $tempAddonDir = realpath('store/[data]') . '/git/sys/temp';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- if (!is_dir($tempAddonDir)) {
- if (!mkdir($tempAddonDir, 0770, true)) {
- logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
- }
- }
- $repoName = null;
- if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
- $repoName = $_REQUEST['repoName'];
- } else {
- $repoName = GitRepo::getRepoNameFromURL($repoURL);
- }
- if (!$repoName) {
- logger('Invalid git repo');
- json_return_and_die(array('message' => 'Invalid git repo: ' . $repoName, 'success' => false));
- }
- $repoDir = $tempAddonDir . '/' . $repoName;
- if (!is_writable($tempAddonDir)) {
- logger('Temporary directory for new addon repo is not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Temporary directory for new addon repo is not writable to web server.', 'success' => false));
- }
- // clone the repo if new automatically
- $git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
-
- $remotes = $git->git->remote();
- $fetchURL = $remotes['origin']['fetch'];
- if ($fetchURL !== $git->url) {
- if (rrmdir($repoDir)) {
- $git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
- } else {
- json_return_and_die(array('message' => 'Error deleting existing addon repo.', 'success' => false));
- }
- }
- $repo = $git->probeRepo();
- $repo['readme'] = $repo['manifest'] = null;
- foreach ($git->git->tree('master') as $object) {
- if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
- $repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
- } else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
- $repo['manifest'] = $git->git->cat->blob($object['hash']);
- }
- }
- json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'No repo URL provided', 'success' => false));
- }
- break;
- default:
- break;
- }
- }
}
/**
@@ -408,37 +186,6 @@ class Addons {
usort($plugins,'self::plugin_sort');
- $allowManageRepos = false;
- if(is_writable('extend/addon') && is_writable('store/[data]')) {
- $allowManageRepos = true;
- }
-
- $admin_plugins_add_repo_form= replace_macros(
- get_markup_template('admin_plugins_addrepo.tpl'), array(
- '$post' => 'admin/addons/addrepo',
- '$desc' => t('Enter the public git repository URL of the addon repo.'),
- '$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''),
- '$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')),
- '$submit' => t('Download Addon Repo')
- )
- );
- $newRepoModalID = random_string(3);
- $newRepoModal = replace_macros(
- get_markup_template('generic_modal.tpl'), array(
- '$id' => $newRepoModalID,
- '$title' => t('Install new repo'),
- '$ok' => t('Install'),
- '$cancel' => t('Cancel')
- )
- );
-
- $reponames = $this->listAddonRepos();
- $addonrepos = [];
- foreach($reponames as $repo) {
- $addonrepos[] = array('name' => $repo, 'description' => '');
- /// @TODO Parse repo info to provide more information about repos
- }
-
$t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@@ -449,37 +196,9 @@ class Addons {
'$plugins' => $plugins,
'$disabled' => t('Disabled - version incompatibility'),
'$form_security_token' => get_form_security_token('admin_addons'),
- '$allowManageRepos' => $allowManageRepos,
- '$managerepos' => t('Manage Repos'),
- '$installedtitle' => t('Installed Addon Repositories'),
- '$addnewrepotitle' => t('Install a New Addon Repository'),
- '$expandform' => false,
- '$form' => $admin_plugins_add_repo_form,
- '$newRepoModal' => $newRepoModal,
- '$newRepoModalID' => $newRepoModalID,
- '$addonrepos' => $addonrepos,
- '$repoUpdateButton' => t('Update'),
- '$repoBranchButton' => t('Switch branch'),
- '$repoRemoveButton' => t('Remove')
));
}
- function listAddonRepos() {
- $addonrepos = [];
- $addonDir = 'extend/addon/';
- if(is_dir($addonDir)) {
- if ($handle = opendir($addonDir)) {
- while (false !== ($entry = readdir($handle))) {
- if ($entry != "." && $entry != "..") {
- $addonrepos[] = $entry;
- }
- }
- closedir($handle);
- }
- }
- return $addonrepos;
- }
-
static public function plugin_sort($a,$b) {
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
}
diff --git a/Zotlabs/Module/Admin/Channels.php b/Zotlabs/Module/Admin/Channels.php
index 52b661420..cd1d2b6fe 100644
--- a/Zotlabs/Module/Admin/Channels.php
+++ b/Zotlabs/Module/Admin/Channels.php
@@ -126,7 +126,7 @@ class Channels {
goaway(z_root() . '/admin/channels' );
}
- $key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
+ $key = ((isset($_REQUEST['key']) && $_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
$dir = 'asc';
if(array_key_exists('dir',$_REQUEST))
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
diff --git a/Zotlabs/Module/Admin/Features.php b/Zotlabs/Module/Admin/Features.php
index e0b3a3fd4..eb82ae1ff 100644
--- a/Zotlabs/Module/Admin/Features.php
+++ b/Zotlabs/Module/Admin/Features.php
@@ -59,14 +59,13 @@ class Features {
}
$tpl = get_markup_template("admin_settings_features.tpl");
- $o .= replace_macros($tpl, array(
+
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("admin_manage_features"),
'$title' => t('Manage Additional Features'),
'$features' => $arr,
'$submit' => t('Submit'),
));
-
- return $o;
}
}
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index abc56d298..9ef5dc20f 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -6,6 +6,8 @@ use Zotlabs\Lib\Config;
class Site {
+ private string $eol;
+ private string $joo;
/**
* @brief POST handler for Admin Site Page.
@@ -208,7 +210,6 @@ class Site {
//Config::Set('system','force_queue_threshold', $force_queue);
Config::Set('system','no_community_page', $no_community_page);
- Config::Set('system','no_utf', $no_utf);
Config::Set('system','sse_enabled', $sse_enabled);
diff --git a/Zotlabs/Module/Admin/Themes.php b/Zotlabs/Module/Admin/Themes.php
index 6793f56b1..09fec9725 100644
--- a/Zotlabs/Module/Admin/Themes.php
+++ b/Zotlabs/Module/Admin/Themes.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Module\Admin;
-use \Michelf\MarkdownExtra;
+use Michelf\MarkdownExtra;
use Zotlabs\Lib\Config;
/**
diff --git a/Zotlabs/Module/Api.php b/Zotlabs/Module/Api.php
index 8574ae1cd..c3337b501 100644
--- a/Zotlabs/Module/Api.php
+++ b/Zotlabs/Module/Api.php
@@ -108,6 +108,9 @@ class Api extends \Zotlabs\Web\Controller {
echo api_call();
killme();
+
+ // not reached
+ return;
}
function oauth_get_client($request){
diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php
index 5f72d771b..8a842feda 100644
--- a/Zotlabs/Module/Appman.php
+++ b/Zotlabs/Module/Appman.php
@@ -16,21 +16,21 @@ class Appman extends \Zotlabs\Web\Controller {
if(isset($_POST['url']) && $_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
- 'url' => escape_tags($_REQUEST['url']),
- 'guid' => escape_tags($_REQUEST['guid']),
- 'author' => escape_tags($_REQUEST['author']),
- 'addr' => escape_tags($_REQUEST['addr']),
- 'name' => escape_tags($_REQUEST['name']),
- 'desc' => escape_tags($_REQUEST['desc']),
- 'photo' => escape_tags($_REQUEST['photo']),
- 'version' => escape_tags($_REQUEST['version']),
- 'price' => escape_tags($_REQUEST['price']),
- 'page' => escape_tags($_REQUEST['page']),
- 'requires' => escape_tags($_REQUEST['requires']),
+ 'url' => escape_tags($_REQUEST['url'] ?? ''),
+ 'guid' => escape_tags($_REQUEST['guid'] ?? ''),
+ 'author' => escape_tags($_REQUEST['author'] ?? ''),
+ 'addr' => escape_tags($_REQUEST['addr'] ?? ''),
+ 'name' => escape_tags($_REQUEST['name'] ?? ''),
+ 'desc' => escape_tags($_REQUEST['desc'] ?? ''),
+ 'photo' => escape_tags($_REQUEST['photo'] ?? ''),
+ 'version' => escape_tags($_REQUEST['version'] ?? ''),
+ 'price' => escape_tags($_REQUEST['price'] ?? ''),
+ 'page' => escape_tags($_REQUEST['page'] ?? ''),
+ 'requires' => escape_tags($_REQUEST['requires'] ?? ''),
'system' => intval($_REQUEST['system']),
- 'plugin' => escape_tags($_REQUEST['plugin']),
- 'sig' => escape_tags($_REQUEST['sig']),
- 'categories' => escape_tags($_REQUEST['categories'])
+ 'plugin' => escape_tags($_REQUEST['plugin'] ?? ''),
+ 'sig' => escape_tags($_REQUEST['sig'] ?? ''),
+ 'categories' => escape_tags($_REQUEST['categories'] ?? '')
);
$_REQUEST['appid'] = Apps::app_install(local_channel(),$arr);
diff --git a/Zotlabs/Module/Apporder.php b/Zotlabs/Module/Apporder.php
index 313c2df50..579ca738c 100644
--- a/Zotlabs/Module/Apporder.php
+++ b/Zotlabs/Module/Apporder.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Module;
-use \Zotlabs\Lib as Zlib;
+use Zotlabs\Lib as Zlib;
class Apporder extends \Zotlabs\Web\Controller {
@@ -25,7 +25,7 @@ class Apporder extends \Zotlabs\Web\Controller {
$syslist[] = Zlib\Apps::app_encode($li);
}
}
-
+
Zlib\Apps::translate_system_apps($syslist);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php
index a8817111e..97e1b237f 100644
--- a/Zotlabs/Module/Apps.php
+++ b/Zotlabs/Module/Apps.php
@@ -1,8 +1,8 @@
<?php
namespace Zotlabs\Module;
-use \Zotlabs\Lib\Config;
-use \Zotlabs\Lib as Zlib;
+use Zotlabs\Lib\Config;
+use Zotlabs\Lib as Zlib;
class Apps extends \Zotlabs\Web\Controller {
diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php
index c6709f602..b015c3284 100644
--- a/Zotlabs/Module/Authorize.php
+++ b/Zotlabs/Module/Authorize.php
@@ -9,7 +9,7 @@ class Authorize extends \Zotlabs\Web\Controller {
function get() {
if (! local_channel()) {
return login();
- }
+ }
else {
$name = $_REQUEST['client_name'];
@@ -25,7 +25,7 @@ class Authorize extends \Zotlabs\Web\Controller {
$link = (($app['url']) ? '<a style="float: none;" href="' . $app['url'] . '">' . $app['name'] . '</a> ' : $app['name']);
- $o .= replace_macros(get_markup_template('oauth_authorize.tpl'), [
+ return replace_macros(get_markup_template('oauth_authorize.tpl'), [
'$title' => t('Authorize'),
'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), $link ),
'$app' => $app,
@@ -35,7 +35,6 @@ class Authorize extends \Zotlabs\Web\Controller {
'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
]);
- return $o;
}
}
@@ -50,7 +49,7 @@ class Authorize extends \Zotlabs\Web\Controller {
// TODO: The automatic client registration protocol below should adhere more
// closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined
// at https://tools.ietf.org/html/rfc7591
-
+
// If no client_id was provided, generate a new one.
if (x($_POST, 'client_id')) {
$client_id = $_POST['client_id'];
@@ -67,7 +66,7 @@ class Authorize extends \Zotlabs\Web\Controller {
$request = \OAuth2\Request::createFromGlobals();
$response = new \OAuth2\Response();
- // Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string.
+ // Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string.
$channel = channelx_by_n(local_channel());
$user_id = $channel['channel_id'];
diff --git a/Zotlabs/Module/Authtest.php b/Zotlabs/Module/Authtest.php
index d85af09dc..bf199ccf6 100644
--- a/Zotlabs/Module/Authtest.php
+++ b/Zotlabs/Module/Authtest.php
@@ -7,7 +7,7 @@ class Authtest extends \Zotlabs\Web\Controller {
$auth_success = false;
- $o .= '<h3>Magic-Auth Diagnostic</h3>';
+ $o = '<h3>Magic-Auth Diagnostic</h3>';
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
@@ -27,7 +27,7 @@ class Authtest extends \Zotlabs\Web\Controller {
$_REQUEST['test'] = 1;
$mod = new Magic();
- $x = $mod->init($a);
+ $x = $mod->init();
$o .= 'Local Setup returns: ' . print_r($x,true);
diff --git a/Zotlabs/Module/Changeaddr.php b/Zotlabs/Module/Changeaddr.php
index ed139c9f9..f8a045727 100644
--- a/Zotlabs/Module/Changeaddr.php
+++ b/Zotlabs/Module/Changeaddr.php
@@ -5,30 +5,30 @@ namespace Zotlabs\Module;
class Changeaddr 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();
$channel = \App::get_channel();
-
+
$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) {
@@ -36,7 +36,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
return;
}
}
-
+
$new_address = trim($_POST['newname']);
if($new_address === $channel['channel_address'])
@@ -55,23 +55,23 @@ class Changeaddr extends \Zotlabs\Web\Controller {
channel_change_address($channel,$new_address);
goaway(z_root() . '/changeaddr');
-
+
}
-
-
+
+
function get() {
-
+
if(! local_channel())
goaway(z_root());
-
+
$channel = \App::get_channel();
$hash = random_string();
-
+
$_SESSION['remove_account_verify'] = $hash;
-
+
$tpl = get_markup_template('channel_rename.tpl');
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$basedir' => z_root(),
'$hash' => $hash,
'$title' => t('Change channel nickname/address'),
@@ -80,9 +80,5 @@ class Changeaddr extends \Zotlabs\Web\Controller {
'$newname' => array('newname', t('New channel address'),$channel['channel_address'], ''),
'$submit' => t('Rename Channel')
));
-
- return $o;
-
}
-
}
diff --git a/Zotlabs/Module/Channel_calendar.php b/Zotlabs/Module/Channel_calendar.php
index 289e3a734..30683404b 100644
--- a/Zotlabs/Module/Channel_calendar.php
+++ b/Zotlabs/Module/Channel_calendar.php
@@ -179,26 +179,14 @@ class Channel_calendar extends Controller {
if ($post_tags)
$datarray['term'] = $post_tags;
- $item_id = event_store_item($datarray, $event);
+ $post = 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) {
- Libsync::build_sync_packet($channel['channel_id'], array('event_item' => array(encode_item($sync_item[0], true)), 'event' => $z));
- }
- }
+ if (!empty($post['item_id'])) {
+ Master::Summon(['Notifier', 'event', $post['item_id']]);
+ }
+ if (!empty($post['approval_id'])) {
+ Master::Summon(['Notifier', 'event', $post['approval_id']]);
}
-
- Master::Summon(array('Notifier', 'event', $item_id));
killme();
@@ -470,13 +458,14 @@ class Channel_calendar extends Controller {
}
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'], DROPITEM_PHASE1);
$complex = true;
}
$ii = q("select * from item where id = %d",
intval($i[0]['id'])
);
+
if ($ii) {
xchan_query($ii);
$sync_item = fetch_post_tags($ii);
@@ -485,6 +474,9 @@ class Channel_calendar extends Controller {
if ($complex) {
tag_deliver($i[0]['uid'], $i[0]['id']);
+ if (intval($i[0]['item_wall'])) {
+ Master::Summon(['Notifier', 'drop', $i[0]['id']]);
+ }
}
}
}
diff --git a/Zotlabs/Module/Chatsvc.php b/Zotlabs/Module/Chatsvc.php
index 2f2784fc4..e9dfb2a4b 100644
--- a/Zotlabs/Module/Chatsvc.php
+++ b/Zotlabs/Module/Chatsvc.php
@@ -4,7 +4,7 @@ namespace Zotlabs\Module;
require_once('include/security.php');
-use \Zotlabs\Lib as Zlib;
+use Zotlabs\Lib as Zlib;
class Chatsvc extends \Zotlabs\Web\Controller {
diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php
index 527b06b3a..510f91c1e 100644
--- a/Zotlabs/Module/Cloud.php
+++ b/Zotlabs/Module/Cloud.php
@@ -8,10 +8,10 @@ namespace Zotlabs\Module;
*/
use Sabre\DAV as SDAV;
-use \Zotlabs\Web\Controller;
-use \Zotlabs\Storage\BasicAuth;
-use \Zotlabs\Storage\Directory;
-use \Zotlabs\Storage\Browser;
+use Zotlabs\Web\Controller;
+use Zotlabs\Storage\BasicAuth;
+use Zotlabs\Storage\Directory;
+use Zotlabs\Storage\Browser;
// composer autoloader for SabreDAV
diff --git a/Zotlabs/Module/Conversation.php b/Zotlabs/Module/Conversation.php
index aa8349f55..0a1ba87d1 100644
--- a/Zotlabs/Module/Conversation.php
+++ b/Zotlabs/Module/Conversation.php
@@ -16,7 +16,7 @@ class Conversation extends Controller {
public function init() {
- if (ActivityStreams::is_as_request()) {
+ if (ActivityStreams::is_as_request() || Libzot::is_zot_request()) {
$item_id = argv(1);
if (!$item_id) {
@@ -30,14 +30,13 @@ class Conversation extends Controller {
dbesc(ACTIVITY_UNFOLLOW)
);
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
$i = null;
// do we have the item (at all)?
- $r = q("select parent_mid from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
- dbesc(z_root() . '/item/' . $item_id),
+ $r = q("select parent_mid from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc($item_id)
);
@@ -77,16 +76,16 @@ class Conversation extends Controller {
}
}
}
- elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ 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
// with a bias towards those items owned by channels on this site (item_wall = 1)
- $sql_extra = item_permissions_sql(0);
-
if (!$i) {
+ $sql_extra = item_permissions_sql(0);
+
$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'])
);
diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php
index aa2464ac2..2d2ffd52d 100644
--- a/Zotlabs/Module/Cover_photo.php
+++ b/Zotlabs/Module/Cover_photo.php
@@ -371,7 +371,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$tpl = get_markup_template('cover_photo.tpl');
- $o .= replace_macros($tpl,array(
+ $output = replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$info' => t('Your cover photo may be visible to anybody on the internet'),
'$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850),
@@ -397,15 +397,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
));
- call_hooks('cover_photo_content_end', $o);
+ call_hooks('cover_photo_content_end', $output);
- return $o;
+ return $output;
}
else {
$filename = \App::$data['imagecrop'] . '-3';
$resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
- $o .= replace_macros($tpl,array(
+ return replace_macros($tpl,array(
'$filename' => $filename,
'$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3',
@@ -415,7 +415,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
'$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing')
));
- return $o;
}
}
diff --git a/Zotlabs/Module/Dav.php b/Zotlabs/Module/Dav.php
index 96fe2c898..5254d436d 100644
--- a/Zotlabs/Module/Dav.php
+++ b/Zotlabs/Module/Dav.php
@@ -9,6 +9,7 @@
namespace Zotlabs\Module;
use Sabre\DAV as SDAV;
+use Zotlabs\Lib\Libzot;
use Zotlabs\Storage;
use Zotlabs\Web\HTTPSig;
diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php
index 451ddeb1f..090e0c92e 100644
--- a/Zotlabs/Module/Display.php
+++ b/Zotlabs/Module/Display.php
@@ -344,7 +344,12 @@ class Display extends Controller {
'$profile_page' => xmlify(z_root() . '/display/' . gen_link_id($target_item['mid'])),
));
- $x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
+ $x = [
+ 'xml' => $atom,
+ 'channel' => $channel,
+ 'observer_hash' => $observer_hash,
+ 'params' => [],
+ ];
call_hooks('atom_feed_top',$x);
$atom = $x['xml'];
diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php
index 5db607545..d1ffb8027 100644
--- a/Zotlabs/Module/Dreport.php
+++ b/Zotlabs/Module/Dreport.php
@@ -19,7 +19,7 @@ class Dreport extends \Zotlabs\Web\Controller {
$table = 'push';
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 )) ",
+ $i = q("select * 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']),
dbesc($channel['channel_hash']),
@@ -27,6 +27,12 @@ class Dreport extends \Zotlabs\Web\Controller {
);
if($i) {
\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $i[0]['id'] ]);
+
+ $relatedItem = find_related($i[0]);
+ if (isset($relatedItem['id'])) {
+ \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $relatedItem['id'] ]);
+ }
+
}
}
sleep(3);
diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php
index 6f524cdb8..678ceb207 100644
--- a/Zotlabs/Module/Editpost.php
+++ b/Zotlabs/Module/Editpost.php
@@ -86,6 +86,7 @@ class Editpost extends \Zotlabs\Web\Controller {
'bbco_autocomplete'=> 'bbcode',
'return_path' => 'hq',
'button' => t('Submit'),
+ 'disable_comments' => (($itm[0]['item_thread_top']) ? false : true),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
diff --git a/Zotlabs/Module/Fbrowser.php b/Zotlabs/Module/Fbrowser.php
index 3bac81c5a..e8517e095 100644
--- a/Zotlabs/Module/Fbrowser.php
+++ b/Zotlabs/Module/Fbrowser.php
@@ -6,6 +6,8 @@ namespace Zotlabs\Module;
* @author Fabio Comuni <fabrixxm@kirgroup.com>
*/
+use function Zotlabs\Render\template_escape;
+
require_once('include/photo/photo_driver.php');
/**
diff --git a/Zotlabs/Module/Filer.php b/Zotlabs/Module/Filer.php
index c2747e6c2..bf472eb67 100644
--- a/Zotlabs/Module/Filer.php
+++ b/Zotlabs/Module/Filer.php
@@ -1,43 +1,54 @@
<?php
namespace Zotlabs\Module;
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
+use App;
class Filer extends \Zotlabs\Web\Controller {
function get() {
-
- if(! local_channel()) {
+
+ if(!local_channel()) {
killme();
}
-
- $term = unxmlify(trim($_GET['term']));
- $item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
-
+
+ $term = unxmlify(trim($_GET['term'] ?? ''));
+ $item_id = ((App::$argc > 1) ? intval(App::$argv[1]) : 0);
+
logger('filer: tag ' . $term . ' item ' . $item_id);
-
+
if($item_id && strlen($term)){
+
+ $sys = get_sys_channel();
+
+ $r = q("SELECT * FROM item WHERE (uid = %d OR uid = %d) AND id = %d
+ and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
+ and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
+ intval(local_channel()),
+ intval($sys['channel_id']),
+ intval($item_id)
+ );
+
+ if ($r && $r[0]['uid'] === $sys['channel_id']) {
+ $r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
+ }
+
+ if(!$r) {
+ killme();
+ }
+
+ $item_id = $r[0]['id'];
+
// file item
store_item_tag(local_channel(),$item_id,TERM_OBJ_POST,TERM_FILE,$term,'');
-
+
// protect the entire conversation from periodic expiration
-
- $r = q("select parent from item where id = %d and uid = %d limit 1",
- intval($item_id),
+
+ q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
+ dbesc(datetime_convert()),
+ intval($r[0]['parent']),
intval(local_channel())
);
- if($r) {
- $x = q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
- dbesc(datetime_convert()),
- intval($r[0]['parent']),
- intval(local_channel())
- );
- }
- }
+ }
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
@@ -55,10 +66,10 @@ class Filer extends \Zotlabs\Web\Controller {
'$title' => t('Save to Folder'),
'$cancel' => t('Cancel')
));
-
+
echo $o;
}
killme();
}
-
+
}
diff --git a/Zotlabs/Module/Go.php b/Zotlabs/Module/Go.php
index ec528fb1a..77a3ffac6 100644
--- a/Zotlabs/Module/Go.php
+++ b/Zotlabs/Module/Go.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Module;
-use Zorlabs\Lib\Config;
+use Zotlabs\Lib\Config;
class Go extends \Zotlabs\Web\Controller {
@@ -19,7 +19,7 @@ class Go extends \Zotlabs\Web\Controller {
function get() {
if(! local_channel()) {
- notify( t('This page is available only to site members') . EOL);
+ notice( t('This page is available only to site members') . EOL);
}
$channel = \App::get_channel();
diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php
index fd5cacee6..fc0ef2708 100644
--- a/Zotlabs/Module/Help.php
+++ b/Zotlabs/Module/Help.php
@@ -6,6 +6,7 @@ use Michelf\MarkdownExtra;
/**
* You can create local site resources in doc/Site.md and either link to doc/Home.md for the standard resources
* or use our include mechanism to include it on your local page.
+ *
*@code
* #include doc/Home.md;
*@endcode
@@ -19,14 +20,6 @@ class Help extends \Zotlabs\Web\Controller {
private string $heading_slug = '';
/**
- * Associative array containing the detected language.
- */
- public array $lang = [
- 'language' => 'en', //! Detected language, 2-letter ISO 639-1 code ("en")
- 'from_url' => false, //! true if language from URL overrides browser default
- ];
-
- /**
* Pre-check before processing request.
*
* Determine language requested, and ensure that a topic was requested.
@@ -36,8 +29,8 @@ class Help extends \Zotlabs\Web\Controller {
public function init() {
$this->determine_help_language();
- if (argc() === 1) {
- goaway("/help/{$this->lang['language']}/about/about");
+ if (empty($_REQUEST['search']) && argc() === 1) {
+ goaway("/help/about/about");
killme();
}
}
@@ -69,6 +62,7 @@ class Help extends \Zotlabs\Web\Controller {
$o .= '</div>';
$o .= '<div class="section-content-wrapper">';
+ require_once('include/help.php');
$r = search_doc_files($_REQUEST['search']);
if($r) {
$o .= '<ul class="help-searchlist">';
@@ -160,6 +154,10 @@ class Help extends \Zotlabs\Web\Controller {
array_shift($args);
}
+ if (empty($args)) {
+ goaway("/help/about/about");
+ }
+
// Keep the first remaining arg as the heading slug
$this->heading_slug = $args[0];
diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php
index 691ca1af9..3ac445f9f 100644
--- a/Zotlabs/Module/Home.php
+++ b/Zotlabs/Module/Home.php
@@ -100,14 +100,25 @@ class Home extends Controller {
goaway($frontpage);
}
+ $o .= '<div class="generic-content-wrapper">';
+
$sitename = Config::Get('system', 'sitename');
- if ($sitename)
- $o .= '<h1 class="home-welcome">' . sprintf(t('Welcome to %s'), $sitename) . '</h1>';
+ if ($sitename) {
+ $o .= '<div class="section-title-wrapper">';
+ $o .= '<h2 class="">' . sprintf(t('Welcome to %s'), $sitename) . '</h2>';
+ $o .= '</div>';
+
+ }
+
+ $o .= '<div class="section-content-wrapper">';
$loginbox = Config::Get('system', 'login_on_homepage');
if (intval($loginbox) || $loginbox === false)
$o .= login(true);
+ $o .= '</div>';
+ $o .= '</div>';
+
return $o;
}
diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php
index c8e6efe38..51caa179c 100644
--- a/Zotlabs/Module/Hq.php
+++ b/Zotlabs/Module/Hq.php
@@ -230,6 +230,7 @@ class Hq extends \Zotlabs\Web\Controller {
$options['offset'] = $_REQUEST['offset'] ?? 0;
$options['type'] = $_REQUEST['type'] ?? '';
$options['author'] = ((isset($_REQUEST['author'])) ? urldecode($_REQUEST['author']) : '');
+ $options['file'] = ((isset($_REQUEST['file'])) ? urldecode($_REQUEST['file']) : '');
$ret = Messages::get_messages_page($options);
diff --git a/Zotlabs/Module/Impel.php b/Zotlabs/Module/Impel.php
index 869de2669..0e07ab71c 100644
--- a/Zotlabs/Module/Impel.php
+++ b/Zotlabs/Module/Impel.php
@@ -164,7 +164,7 @@ class Impel extends \Zotlabs\Web\Controller {
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if($arr['edited'] > $i[0]['edited'])
- $x = item_store_update($arr,$execflag);
+ $x = item_store_update($arr, $execflag , deliver: false, addAndSync: false);
}
else {
if(($i) && (intval($i[0]['item_deleted']))) {
@@ -175,7 +175,7 @@ class Impel extends \Zotlabs\Web\Controller {
);
}
else
- $x = item_store($arr,$execflag);
+ $x = item_store($arr, $execflag, deliver: false, addAndSync: false);
}
if($x && $x['success']) {
diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php
index 5ace4e72d..7aed6469e 100644
--- a/Zotlabs/Module/Import.php
+++ b/Zotlabs/Module/Import.php
@@ -534,6 +534,7 @@ class Import extends Controller {
if ($api_path) {
$parsed = parse_url($api_path);
unset($parsed['path']);
+ unset($parsed['query']);
// store the import host so we can manually kick off item/file sync later in case anything did not work out
set_pconfig($channel['channel_id'], 'import', 'host', $parsed['host']);
@@ -551,7 +552,7 @@ class Import extends Controller {
$until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day');
//$poll_interval = Config::Get('system', 'poll_interval', 3);
- $page = 0;
+ $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)]);
diff --git a/Zotlabs/Module/Import_progress.php b/Zotlabs/Module/Import_progress.php
index d9b13e8a8..0afb6faed 100644
--- a/Zotlabs/Module/Import_progress.php
+++ b/Zotlabs/Module/Import_progress.php
@@ -29,14 +29,14 @@ class Import_progress extends \Zotlabs\Web\Controller {
$c = PConfig::Get(local_channel(), 'import', 'content_progress');
if ($c) {
- $total_cpages = floor(intval($c['items_total']) / intval($c['items_page']));
+ $total_cpages = round(intval($c['items_total']) / intval($c['items_page']));
if(!$total_cpages) {
- $total_cpages = 1; // because of floor
+ $total_cpages = 1; // because of round
}
$cpage = $c['last_page'] + 1; // because page count start at 0
- $cprogress = intval(floor((intval($cpage) * 100) / $total_cpages));
+ $cprogress = intval(round((intval($cpage) * 100) / $total_cpages));
$ccompleted_str = t('Item sync completed!');
if(argv(1) === 'resume_itemsync' && $cprogress < 100) {
@@ -50,6 +50,7 @@ class Import_progress extends \Zotlabs\Web\Controller {
if ($alive) {
$parsed = parse_url($alive);
unset($parsed['path']);
+ unset($parsed['query']);
$hz_server = unparse_url($parsed);
$since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00');
@@ -79,14 +80,14 @@ class Import_progress extends \Zotlabs\Web\Controller {
$f = PConfig::Get(local_channel(), 'import', 'files_progress');
if ($f) {
- $total_fpages = floor(intval($f['files_total']) / intval($f['files_page']));
+ $total_fpages = round(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));
+ $fprogress = intval(round((intval($fpage) * 100) / $total_fpages));
$fcompleted_str = t('File sync completed!');
if(argv(1) === 'resume_filesync' && $fprogress < 100) {
@@ -120,6 +121,7 @@ class Import_progress extends \Zotlabs\Web\Controller {
}
$fcompleted_str = t('File sync completed but no files were found!');
+
}
$fprogress_str = ((intval($fprogress)) ? $fprogress . '%' : $fprogress);
@@ -127,13 +129,15 @@ class Import_progress extends \Zotlabs\Web\Controller {
if(is_ajax()) {
$ret = [
'cprogress' => $cprogress,
- 'fprogress' => $fprogress
+ 'ccompleted_str' => $ccompleted_str,
+ 'fprogress' => $fprogress,
+ 'fcompleted_str' => $fcompleted_str
];
json_return_and_die($ret);
}
- $o = replace_macros(get_markup_template("import_progress.tpl"), [
+ return 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'),
@@ -147,8 +151,6 @@ class Import_progress extends \Zotlabs\Web\Controller {
'$resume_str' => t('Resume'),
'$resume_helper_str' => t('Only resume if sync stalled!')
]);
-
- return $o;
}
}
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 3d13655d2..ea561ee25 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -44,253 +44,30 @@ class Item extends Controller {
function init() {
if (Libzot::is_zot_request()) {
-
- $item_id = argv(1);
-
- if (!$item_id)
- http_status_exit(404, 'Not found');
-
- $portable_id = EMPTY_STR;
-
- $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
- dbesc(ACTIVITY_FOLLOW),
- dbesc(ACTIVITY_UNFOLLOW)
- );
-
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
-
- $i = null;
-
- // do we have the item (at all)?
-
- $r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
- dbesc($item_id)
- );
-
- if (!$r) {
- http_status_exit(404, 'Not found');
- }
-
- // process an authenticated fetch
-
- $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);
-
- $i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
- dbesc($r[0]['parent_mid']),
- dbesc($portable_id)
- );
- }
- 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
- // with a bias towards those items owned by channels on this site (item_wall = 1)
-
- $sql_extra = item_permissions_sql(0);
-
- if (!$i) {
- $i = q("select id as item_id, uid, item_private 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');
- }
-
- $chan = channelx_by_n($i[0]['uid']);
-
- if (!$chan) {
- http_status_exit(404, 'Not found');
- }
-
- if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
- http_status_exit(403, 'Forbidden');
- }
-
- $parents_str = ids_to_querystr($i, 'item_id');
-
- // We won't need to check for privacy mismatches if the verified observer is also owner
- $parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
-
- $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
- intval($parents_str)
- );
-
- App::set_pager_total($total[0]['count']);
- App::set_pager_itemspage(30);
-
- if (App::$pager['total'] > App::$pager['itemspage']) {
- // let mod conversation handle this request
- App::$query_string = str_replace('item', 'conversation', App::$query_string);
- $i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
- as_return_and_die($i ,$chan);
- }
- else {
- $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
- intval($parents_str)
- );
-
- xchan_query($items, true);
- $items = fetch_post_tags($items, true);
-
- $i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
- }
-
- 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) {
- ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
- }
- }
-
- as_return_and_die($i ,$chan);
+ $this->init_zot_request();
}
if (ActivityStreams::is_as_request()) {
-
- $item_id = argv(1);
- if (!$item_id)
- http_status_exit(404, 'Not found');
-
- $portable_id = EMPTY_STR;
-
- $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
- dbesc(ACTIVITY_FOLLOW),
- dbesc(ACTIVITY_UNFOLLOW)
- );
-
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
-
- $i = null;
-
- // do we have the item (at all)?
- // add preferential bias to item owners (item_wall = 1)
-
- $r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
- dbesc($item_id)
- );
-
- if (!$r) {
- http_status_exit(404, 'Not found');
- }
-
- // process an authenticated fetch
-
- $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);
-
- $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ",
- dbesc($r[0]['parent_mid']),
- dbesc($portable_id)
- );
- }
- 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
- // with a bias towards those items owned by channels on this site (item_wall = 1)
-
- $sql_extra = item_permissions_sql(0);
-
- 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'])
- );
- }
-
- $bear = Activity::token_from_request();
- if ($bear) {
- logger('bear: ' . $bear, LOGGER_DEBUG);
- if (!$i) {
- $t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
- dbesc($bear)
- );
- if ($t) {
- $i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
- dbesc($item_id),
- intval($t[0]['iid'])
- );
- }
- }
- }
-
- 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);
-
- $chan = channelx_by_n($items[0]['uid']);
-
- if (!$chan)
- http_status_exit(404, 'Not found');
-
- if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
- http_status_exit(403, 'Forbidden');
-
- $i = Activity::encode_item($items[0]);
-
- if (!$i)
- http_status_exit(404, 'Not found');
-
- 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) {
- ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
- }
- }
-
- as_return_and_die($i ,$chan);
-
+ $this->init_as_request();
}
if (argc() > 1 && argv(1) !== 'drop') {
- $x = q("select uid, item_wall, llink, mid, uuid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
- dbesc(z_root() . '/item/' . argv(1)),
- dbesc(z_root() . '/activity/' . argv(1)),
+ $x = q("select uid, item_wall, llink, uuid from item where uuid = '%s' order by item_wall desc",
dbesc(argv(1))
);
+
if ($x) {
- foreach ($x as $xv) {
- if (intval($xv['item_wall'])) {
- $c = channelx_by_n($xv['uid']);
- if ($c) {
- goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $xv['uuid']);
- }
+ if ($x[0]['item_wall']) {
+ $c = channelx_by_n($x[0]['uid']);
+ if ($c) {
+ goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $x[0]['uuid']);
}
}
+
goaway($x[0]['llink']);
}
+
http_status_exit(404, 'Not found');
}
@@ -323,7 +100,6 @@ class Item extends Controller {
$item_deleted = false;
$item_hidden = false;
$item_unpublished = false;
- $item_delayed = false;
$item_pending_remove = false;
$item_blocked = false;
@@ -401,6 +177,7 @@ class Item extends Controller {
$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);
+ $item_delayed = ((x($_REQUEST, 'delayed')) ? intval($_REQUEST['delayed']) : 0);
$pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : '');
$layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
$plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
@@ -430,7 +207,6 @@ class Item extends Controller {
$expires = NULL_DATE;
- $comments_closed = NULL_DATE;
$route = '';
$parent_item = null;
@@ -607,6 +383,7 @@ class Item extends Controller {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($channel['channel_hash'])
);
+
if ($r && count($r)) {
$owner_xchan = $r[0];
}
@@ -677,7 +454,7 @@ class Item extends Controller {
$title = escape_tags(trim($_REQUEST['title']));
$summary = escape_tags(trim($_REQUEST['summary']));
$body = trim($_REQUEST['body']);
- $item_flags = $orig_post['item_flags'];
+ $item_flags = $orig_post['item_flags'];
$item_origin = $orig_post['item_origin'];
$item_unseen = $orig_post['item_unseen'];
$item_starred = $orig_post['item_starred'];
@@ -691,7 +468,7 @@ class Item extends Controller {
$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_verified = $orig_post['item_verified'];
$item_retained = $orig_post['item_retained'];
$item_rss = $orig_post['item_rss'];
$item_deleted = $orig_post['item_deleted'];
@@ -710,6 +487,7 @@ class Item extends Controller {
$thr_parent = $orig_post['thr_parent'];
$parent_mid = $orig_post['parent_mid'];
$plink = $orig_post['plink'];
+ $owner_hash = $orig_post['owner_xchan'];
}
else {
if (!$walltowall) {
@@ -837,8 +615,10 @@ class Item extends Controller {
if ($results) {
- // Set permissions based on tag replacements
- set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ // Set permissions based on tag replacements only if not editing an existing post
+ if (!$orig_post) {
+ set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ }
foreach ($results as $result) {
$success = $result['success'];
@@ -1014,6 +794,7 @@ class Item extends Controller {
$item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
+ $comments_closed = (($nocomment) ? $comments_closed : NULL_DATE);
// determine if this is a wall post
@@ -1027,18 +808,42 @@ class Item extends Controller {
}
- if ($moderated)
+ if ($moderated) {
$item_blocked = ITEM_MODERATED;
+ }
- if (!strlen($verb))
+ if (!strlen($verb)) {
$verb = 'Create';
+ }
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
$uuid = $uuid ?? $message_id ?? item_message_id();
$mid = $mid ?? z_root() . '/item/' . $uuid;
+
+ if (empty($owner_hash)) {
+ $owner_hash = $owner_xchan['xchan_hash'];
+ }
+
+ // Set the conversation target.
+ if ($owner_hash === $channel['channel_hash']) {
+ $attributedTo = z_root() . '/channel/' . $channel['channel_address'];
+
+ $conversation = isset($parent_item) ? $parent_item['mid'] : $mid;
+ $datarray['target'] = [
+ 'id' => str_replace('/item/', '/conversation/', $conversation),
+ 'type' => 'Collection',
+ 'attributedTo' => $attributedTo,
+ ];
+ $datarray['tgt_type'] = 'Collection';
+ }
+ elseif (!empty($parent_item['target'])) {
+ $datarray['target'] = $parent_item['target'];
+ $datarray['tgt_type'] = $parent_item['tgt_type'];
+ }
+
if ($is_poll) {
$poll = [
'question' => $body,
@@ -1058,7 +863,7 @@ class Item extends Controller {
$obj['id'] = $mid;
$obj['diaspora:guid'] = $uuid;
$obj['attributedTo'] = channel_url($channel);
- $obj['published'] = $created;
+ $obj['published'] = datetime_convert('UTC', 'UTC', $created, ATOM_TIME);
$obj['name'] = $title;
$datarray['obj'] = $obj;
@@ -1080,19 +885,13 @@ class Item extends Controller {
if ($parent_item)
$parent_mid = $parent_item['mid'];
-
// Fallback so that we always have a thr_parent
if (!$thr_parent)
$thr_parent = $mid;
-
$item_thread_top = ((!$parent) ? 1 : 0);
- if ((!$plink) && ($item_thread_top)) {
- $plink = $mid;
- }
-
if (isset($datarray['obj']) && $datarray['obj']) {
$datarray['obj']['id'] = $mid;
}
@@ -1155,7 +954,7 @@ class Item extends Controller {
$datarray['public_policy'] = $public_policy;
$datarray['comment_policy'] = map_scope($comment_policy);
$datarray['term'] = array_unique($post_tags, SORT_REGULAR);
- $datarray['plink'] = $plink;
+ $datarray['plink'] = $plink ?? $mid;
$datarray['route'] = $route;
// A specific ACL over-rides public_policy completely
@@ -1243,6 +1042,7 @@ class Item extends Controller {
$this->add_listeners($datarray);
}
+ /* sync this is done in item_store_update()
if (!$parent) {
$r = q("select * from item where id = %d",
intval($post_id)
@@ -1253,9 +1053,14 @@ class Item extends Controller {
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 (intval($x['approval_id'])) {
+ Master::Summon(['Notifier', 'edit_post', $x['approval_id']]);
+ }
+ }
if ($api_source)
return ($x);
@@ -1279,6 +1084,7 @@ class Item extends Controller {
}
$post_id = $post['item_id'];
+ $approval_id = $post['approval_id'] ?? 0;
$datarray = $post['item'];
@@ -1353,6 +1159,7 @@ class Item extends Controller {
killme();
}
+ /* sync this is done in item_store_update()
if ($parent || $datarray['item_private'] == 1) {
$r = q("select * from item where id = %d",
intval($post_id)
@@ -1363,6 +1170,7 @@ class Item extends Controller {
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
}
+ */
$datarray['id'] = $post_id;
$datarray['llink'] = z_root() . '/display/' . $datarray['uuid'];
@@ -1373,8 +1181,12 @@ class Item extends Controller {
$nopush = false;
}
- if (!$nopush)
+ if (!$nopush) {
Master::Summon(['Notifier', $notify_type, $post_id]);
+ if ($approval_id) {
+ Master::Summon(['Notifier', $notify_type, $approval_id]);
+ }
+ }
logger('post_complete');
@@ -1427,10 +1239,7 @@ class Item extends Controller {
if ((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
- require_once('include/items.php');
-
-
- $i = q("select id, uid, item_origin, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1",
+ $i = q("select * from item where id = %d limit 1",
intval(argv(2))
);
@@ -1457,7 +1266,6 @@ class Item extends Controller {
$can_delete = true;
}
-
if (!($can_delete || $local_delete)) {
notice(t('Permission denied.') . EOL);
return;
@@ -1473,13 +1281,14 @@ class Item extends Controller {
}
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'], DROPITEM_PHASE1);
$complex = true;
}
$r = q("select * from item where id = %d",
intval($i[0]['id'])
);
+
if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
@@ -1488,6 +1297,9 @@ class Item extends Controller {
if ($complex) {
tag_deliver($i[0]['uid'], $i[0]['id']);
+ if (intval($i[0]['item_wall']) || $i[0]['mid'] !== $i[0]['parent_mid']) {
+ Master::Summon(['Notifier', 'drop', $i[0]['id']]);
+ }
}
}
@@ -1671,5 +1483,234 @@ class Item extends Controller {
}
}
+ private function init_zot_request() {
+
+ $item_id = argv(1);
+
+ if (!$item_id)
+ http_status_exit(404, 'Not found');
+
+ $portable_id = EMPTY_STR;
+
+ $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
+
+ $i = null;
+
+ // do we have the item (at all)?
+
+ $r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
+ dbesc($item_id)
+ );
+
+ if (!$r) {
+ http_status_exit(404, 'Not found');
+ }
+
+ // process an authenticated fetch
+
+ $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);
+
+ $i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
+ dbesc($r[0]['parent_mid']),
+ dbesc($portable_id)
+ );
+ }
+ 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
+ // with a bias towards those items owned by channels on this site (item_wall = 1)
+
+ $sql_extra = item_permissions_sql(0);
+
+ if (!$i) {
+ $i = q("select id as item_id, uid, item_private 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');
+ }
+
+ $chan = channelx_by_n($i[0]['uid']);
+
+ if (!$chan) {
+ http_status_exit(404, 'Not found');
+ }
+
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ $parents_str = ids_to_querystr($i, 'item_id');
+
+ // We won't need to check for privacy mismatches if the verified observer is also owner
+ $parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
+
+ $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
+ intval($parents_str)
+ );
+
+ App::set_pager_total($total[0]['count']);
+ App::set_pager_itemspage(30);
+
+ if (App::$pager['total'] > App::$pager['itemspage']) {
+ // let mod conversation handle this request
+ App::$query_string = str_replace('item', 'conversation', App::$query_string);
+ $i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
+ as_return_and_die($i ,$chan);
+ }
+ else {
+ $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
+ intval($parents_str)
+ );
+
+ xchan_query($items, true);
+ $items = fetch_post_tags($items, true);
+
+ $i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
+ }
+
+ 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) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
+ }
+
+ as_return_and_die($i ,$chan);
+ }
+
+ private function init_as_request() {
+
+ $item_id = argv(1);
+ if (!$item_id)
+ http_status_exit(404, 'Not found');
+
+ $portable_id = EMPTY_STR;
+
+ $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
+
+ $i = null;
+
+ // do we have the item (at all)?
+ // add preferential bias to item owners (item_wall = 1)
+
+ $r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
+ dbesc($item_id)
+ );
+
+ if (!$r) {
+ http_status_exit(404, 'Not found');
+ }
+
+ // process an authenticated fetch
+
+ $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);
+
+ $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ",
+ dbesc($r[0]['parent_mid']),
+ dbesc($portable_id)
+ );
+ }
+ 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
+ // with a bias towards those items owned by channels on this site (item_wall = 1)
+
+ $sql_extra = item_permissions_sql(0);
+
+ 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'])
+ );
+ }
+
+ $bear = Activity::token_from_request();
+ if ($bear) {
+ logger('bear: ' . $bear, LOGGER_DEBUG);
+ if (!$i) {
+ $t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
+ dbesc($bear)
+ );
+ if ($t) {
+ $i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
+ dbesc($item_id),
+ intval($t[0]['iid'])
+ );
+ }
+ }
+ }
+
+ 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);
+
+ $chan = channelx_by_n($items[0]['uid']);
+
+ if (!$chan)
+ http_status_exit(404, 'Not found');
+
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
+ http_status_exit(403, 'Forbidden');
+
+ $i = Activity::encode_item($items[0]);
+
+ if (!$i)
+ http_status_exit(404, 'Not found');
+
+ 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) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
+ }
+
+ as_return_and_die($i ,$chan);
+
+ }
}
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
index 4460900a8..2fb3fab83 100644
--- a/Zotlabs/Module/Like.php
+++ b/Zotlabs/Module/Like.php
@@ -284,7 +284,7 @@ class Like extends Controller {
intval($ch[0]['channel_id'])
);
if ($r)
- drop_item($r[0]['id'], false);
+ drop_item($r[0]['id']);
if ($interactive) {
notice(t('Previous action reversed.') . EOL);
return $o;
@@ -387,17 +387,20 @@ class Like extends Controller {
// already liked it. Drop that item.
require_once('include/items.php');
foreach ($r as $rr) {
- drop_item($rr['id'], false, DROPITEM_PHASE1);
+ drop_item($rr['id'], DROPITEM_PHASE1);
+
// set the changed timestamp on the parent so we'll see the update without a page reload
q("update item set changed = '%s' where id = %d and uid = %d",
dbesc(datetime_convert()),
intval($rr['parent']),
intval($rr['uid'])
);
+
// Prior activity was a duplicate of the one we're submitting, just undo it;
// don't fall through and create another
- if (activity_match($rr['verb'], $activity))
+ if (activity_match($rr['verb'], $activity)) {
$multi_undo = false;
+ }
$d = q("select * from item where id = %d",
intval($rr['id'])
@@ -559,6 +562,7 @@ class Like extends Controller {
$post = item_store($arr);
$post_id = $post['item_id'];
+ $approval_id = $post['approval_id'] ?? 0;
// save the conversation from expiration
@@ -569,6 +573,12 @@ class Like extends Controller {
call_hooks('post_local_end', $arr);
+ if ($is_rsvp && in_array($verb, ['attendyes', 'attendmaybe'])) {
+ event_addtocal($item_id, local_channel());
+ }
+
+
+/* Item sync is now done in item_store()
$r = q("select * from item where id = %d",
intval($post_id)
);
@@ -577,7 +587,7 @@ class Like extends Controller {
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
-
+*/
if ($extended_like) {
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
@@ -604,7 +614,10 @@ class Like extends Controller {
}
- Master::Summon(array('Notifier', 'like', $post_id));
+ Master::Summon(['Notifier', 'like', $post_id]);
+ if ($approval_id) {
+ Master::Summon(['Notifier', 'like', $approval_id]);
+ }
if ($interactive) {
notice(t('Action completed.') . EOL);
diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php
index f3ae07f74..4b708a1aa 100644
--- a/Zotlabs/Module/Lockview.php
+++ b/Zotlabs/Module/Lockview.php
@@ -227,7 +227,7 @@ class Lockview extends Controller {
$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); toast(\'' . t('Link copied') . '\', \'info\');"><span>' . $atoken['xchan_name'] . '</span><i class="fa fa-copy p-1"></i></div>';
+ $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); toast(\'' . t('Link copied') . '\', \'info\');"><span>' . $atoken['xchan_name'] . '</span><i class="bi bi-copy p-1"></i></div>';
}
}
}
diff --git a/Zotlabs/Module/Login.php b/Zotlabs/Module/Login.php
index 6430939b4..269990a54 100644
--- a/Zotlabs/Module/Login.php
+++ b/Zotlabs/Module/Login.php
@@ -10,7 +10,16 @@ class Login extends \Zotlabs\Web\Controller {
if(remote_channel() && $_SESSION['atoken'])
goaway(z_root());
- return login(true);
+ $o = '<div class="generic-content-wrapper">';
+ $o .= '<div class="section-title-wrapper">';
+ $o .= '<h2 class="">' . t('Login') . '</h2>';
+ $o .= '</div>';
+ $o .= '<div class="section-content-wrapper">';
+ $o .= login(true);
+ $o .= '</div>';
+ $o .= '</div>';
+
+ return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php
index 8259f7d39..732488002 100644
--- a/Zotlabs/Module/Magic.php
+++ b/Zotlabs/Module/Magic.php
@@ -11,37 +11,43 @@ class Magic extends Controller {
function init() {
- $ret = [
- 'success' => false,
- 'url' => '',
- 'message' => ''
- ];
-
logger('mod_magic: invoked', LOGGER_DEBUG);
- logger('args: ' . print_r($_REQUEST,true),LOGGER_DATA);
+ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $data = $_POST;
+ } elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
+ $data = $_GET;
+ } else {
+ http_status_exit(405, 'Method Not Allowed');
+ }
+
+ logger('request method: ' . print_r($_SERVER['REQUEST_METHOD'], true), LOGGER_DATA);
+ logger('args: ' . print_r($data, true), LOGGER_DATA);
- $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : '');
- $bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : '');
- $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
- $rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
- $owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0);
- $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : '');
+ $bdest = $data['bdest'] ?? '';
+ $owa = $data['owa'] ?? 0;
+ $delegate = $data['delegate'] ?? '';
// bdest is preferred as it is hex-encoded and can survive url rewrite and argument parsing
- if ($bdest) {
- $dest = hex2bin($bdest);
+ if (!$bdest) {
+ http_status_exit(400, 'Bad Request');
}
+ $dest = hex2bin($bdest);
$parsed = parse_url($dest);
- if (! $parsed) {
- goaway($dest);
+ if (!$parsed) {
+ http_status_exit(400, 'Bad Request');
}
- $basepath = $parsed['scheme'] . '://' . $parsed['host'] . (isset($parsed['port']) ? ':' . $parsed['port'] : '');
- $owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa');
+ $basepath = unparse_url(array_filter(
+ $parsed,
+ fn (string $key) => in_array($key, ['scheme', 'host', 'port']),
+ ARRAY_FILTER_USE_KEY
+ ));
+
+ $owapath = SConfig::get($basepath, 'system', 'openwebauth', $basepath . '/owa');
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
// By default, we'll proceed without asking.
@@ -53,12 +59,14 @@ class Magic extends Controller {
];
call_hooks('magic_auth',$arr);
+
$dest = $arr['destination'];
- if (! $arr['proceed']) {
+
+ if (!$arr['proceed']) {
goaway($dest);
}
- if((get_observer_hash()) && (stripos($dest,z_root()) === 0)) {
+ if (get_observer_hash() && str_starts_with($dest, z_root())) {
// We are already authenticated on this site and a registered observer.
// First check if this is a delegate request on the local system and process accordingly.
@@ -106,29 +114,41 @@ class Magic extends Controller {
$headers['Content-Type'] = 'application/x-zot+json' ;
$headers['X-Open-Web-Auth'] = random_string();
$headers['Host'] = $parsed['host'];
- $headers['(request-target)'] = 'get ' . '/owa';
+ $headers['(request-target)'] = 'get /owa';
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$redirects = 0;
+
$x = z_fetch_url($owapath, false, $redirects, ['headers' => $headers]);
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
+
if ($x['success']) {
$j = json_decode($x['body'],true);
if ($j['success'] && $j['encrypted_token']) {
// decrypt the token using our private key
$token = '';
- openssl_private_decrypt(base64url_decode($j['encrypted_token']),$token,$channel['channel_prvkey']);
+ openssl_private_decrypt(base64url_decode($j['encrypted_token']), $token, $channel['channel_prvkey']);
$x = strpbrk($dest,'?&');
// redirect using the encrypted token which will be exchanged for an authenticated session
- $args = (($x) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
+ $args = (($x) ? '&owt=' . $token : '?owt=' . $token) . (($delegate) ? '&delegate=1' : '');
goaway($dest . $args);
}
+ else {
+ $o = '<h1>OWA ERROR</h1>';
+ if (!empty($j['message'])) {
+ $o .= '<h2>' . $j['message'] . '</h2>';
+ }
+ $o .= '<a href=' . $dest . '>' . $dest . '</a>';
+
+ echo $o;
+ }
}
}
}
- goaway($dest);
+ killme();
+
}
}
diff --git a/Zotlabs/Module/Mitem.php b/Zotlabs/Module/Mitem.php
index ac7470e13..81787f8c4 100644
--- a/Zotlabs/Module/Mitem.php
+++ b/Zotlabs/Module/Mitem.php
@@ -184,8 +184,8 @@ class Mitem extends \Zotlabs\Web\Controller {
'$nick' => $which,
'$sys' => \App::$is_sys
));
-
- $o .= replace_macros(get_markup_template('mitemlist.tpl'),array(
+
+ return replace_macros(get_markup_template('mitemlist.tpl'),array(
'$title' => t('Menu:'),
'$create' => $create,
'$nametitle' => t('Link Name'),
@@ -204,29 +204,27 @@ class Mitem extends \Zotlabs\Web\Controller {
'$hintedit' => t('Edit this menu item'),
'$nick' => $which,
));
-
- return $o;
}
-
-
+
+
if(argc() > 3) {
if(intval(argv(3))) {
-
+
$m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1",
intval(argv(3)),
intval($owner)
);
-
+
if(! $m) {
notice( t('Menu item not found.') . EOL);
goaway(z_root() . '/menu/'. $which . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
-
+
$mitem = $m[0];
-
+
$lockstate = (($mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid']) ? 'lock' : 'unlock');
-
+
if(argc() == 5 && argv(4) == 'drop') {
menu_sync_packet($owner,get_observer_hash(),$mitem['mitem_menu_id']);
$r = menu_del_item($mitem['mitem_menu_id'], $owner, intval(argv(3)));
@@ -235,12 +233,12 @@ class Mitem extends \Zotlabs\Web\Controller {
info( t('Menu item deleted.') . EOL);
else
notice( t('Menu item could not be deleted.'). EOL);
-
+
goaway(z_root() . '/mitem/' . $which . '/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : ''));
}
-
+
// edit menu item
- $o = replace_macros(get_markup_template('mitemedit.tpl'), array(
+ return replace_macros(get_markup_template('mitemedit.tpl'), array(
'$header' => t('Edit Menu Element'),
'$menu_id' => \App::$data['menu']['menu_id'],
'$permissions' => t('Menu Item Permissions'),
@@ -261,10 +259,8 @@ class Mitem extends \Zotlabs\Web\Controller {
'$menu_names' => $menu_names,
'$nick' => $which
));
-
- return $o;
}
}
}
-
+
}
diff --git a/Zotlabs/Module/Moderate.php b/Zotlabs/Module/Moderate.php
index ed2a1e4f9..2103684ab 100644
--- a/Zotlabs/Module/Moderate.php
+++ b/Zotlabs/Module/Moderate.php
@@ -74,7 +74,7 @@ class Moderate extends \Zotlabs\Web\Controller {
// let the sender know we received their comment but we don't permit spam here.
// Activity::send_rejection_activity(App::get_channel(), $item['author_xchan'], $item);
- drop_item($post_id,false);
+ drop_item($post_id);
notice( t('Item deleted') . EOL);
}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index 3ea813547..09a0a6ccc 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -278,32 +278,11 @@ class Network extends \Zotlabs\Web\Controller {
$likes_sql = " AND verb NOT IN ('Like', 'Dislike', '" . 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_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 ";
+ $sql_extra = " AND item.parent IN (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) AND item_unseen = 1 AND verb != 'Announce' $likes_sql ";
}
else {
// 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 = 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');
- if(! $p_str)
- killme();
-
- $sql_extra = " AND item.parent IN ( $p_str ) ";
+ $sql_extra = " AND item.parent IN (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) ";
}
}
diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php
index 2fd719f25..ba693e4f2 100644
--- a/Zotlabs/Module/Notes.php
+++ b/Zotlabs/Module/Notes.php
@@ -13,31 +13,34 @@ class Notes extends Controller {
function post() {
- if(! local_channel())
- return EMPTY_STR;
+ if(!local_channel()) {
+ return;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Notes'))
- return EMPTY_STR;
+ if(!Apps::system_app_installed(local_channel(), 'Notes')) {
+ return;
+ }
$ret = [
'success' => false,
'html' => ''
];
-
- if(array_key_exists('note_text',$_REQUEST)) {
+ if (array_key_exists('note_text',$_REQUEST)) {
$body = escape_tags($_REQUEST['note_text']);
// I've had my notes vanish into thin air twice in four years.
// Provide a backup copy if there were contents previously
// and there are none being saved now.
- if(! $body) {
- $old_text = get_pconfig(local_channel(),'notes','text');
- if($old_text)
- set_pconfig(local_channel(),'notes','text.bak',$old_text);
+ if(!$body) {
+ $old_text = get_pconfig(local_channel(), 'notes', 'text');
+ if ($old_text) {
+ set_pconfig(local_channel(), 'notes', 'text.bak', $old_text);
+ }
}
- set_pconfig(local_channel(),'notes','text',$body);
+
+ set_pconfig(local_channel(), 'notes', 'text', $body);
$ret['html'] = bbcode($body, ['tryoembed' => false]);
$ret['success'] = true;
@@ -55,8 +58,9 @@ class Notes extends Controller {
}
function get() {
- if(! local_channel())
+ if(!local_channel()) {
return EMPTY_STR;
+ }
if(! Apps::system_app_installed(local_channel(), 'Notes')) {
//Do not display any associated widgets at this point
@@ -65,6 +69,8 @@ class Notes extends Controller {
return Apps::app_render($papp, 'module');
}
+ App::$profile_uid = local_channel();
+
$w = new \Zotlabs\Widget\Notes;
$arr = ['app' => true];
diff --git a/Zotlabs/Module/Notify.php b/Zotlabs/Module/Notify.php
index 0af2ec93a..7a7becbc8 100644
--- a/Zotlabs/Module/Notify.php
+++ b/Zotlabs/Module/Notify.php
@@ -1,8 +1,8 @@
<?php
namespace Zotlabs\Module;
-use \Zotlabs\Lib\PConfig;
-use \Zotlabs\Web\Controller;
+use Zotlabs\Lib\PConfig;
+use Zotlabs\Web\Controller;
class Notify extends Controller {
diff --git a/Zotlabs/Module/OAuth2TestVehicle.php b/Zotlabs/Module/OAuth2TestVehicle.php
index 5ae278e8c..57cda3c28 100644
--- a/Zotlabs/Module/OAuth2TestVehicle.php
+++ b/Zotlabs/Module/OAuth2TestVehicle.php
@@ -31,8 +31,8 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller {
$_SESSION['api_response'] = (x($_SESSION, 'api_response') ? $_SESSION['api_response'] : '');
}
function get() {
-
- $o .= replace_macros(get_markup_template('oauth2testvehicle.tpl'), array(
+
+ $output = replace_macros(get_markup_template('oauth2testvehicle.tpl'), array(
'$baseurl' => z_root(),
'$api_response' => $_SESSION['api_response'],
/*
@@ -97,8 +97,10 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller {
)
)
));
+
$_SESSION['success'] = '';
- return $o;
+
+ return $output;
}
function post() {
diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php
index 061296257..6063c7738 100644
--- a/Zotlabs/Module/Oauth.php
+++ b/Zotlabs/Module/Oauth.php
@@ -103,7 +103,8 @@ class Oauth extends Controller {
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth_edit.tpl");
- $o .= replace_macros($tpl, array(
+
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
'$title' => t('Add application'),
'$submit' => t('Submit'),
@@ -114,7 +115,6 @@ class Oauth extends Controller {
'$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')),
'$icon' => array('icon', t('Icon url'), '', t('Optional')),
));
- return $o;
}
if((argc() > 2) && (argv(1) === 'edit')) {
@@ -129,7 +129,7 @@ class Oauth extends Controller {
$app = $r[0];
$tpl = get_markup_template("oauth_edit.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
'$title' => t('Add application'),
'$submit' => t('Update'),
@@ -140,7 +140,6 @@ class Oauth extends Controller {
'$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''),
'$icon' => array('icon', t('Icon url'), $app['icon'], ''),
));
- return $o;
}
if((argc() > 2) && (argv(1) === 'delete')) {
@@ -163,7 +162,8 @@ class Oauth extends Controller {
$tpl = get_markup_template("oauth.tpl");
- $o .= replace_macros($tpl, array(
+
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth"),
'$baseurl' => z_root(),
'$title' => t('Connected OAuth Apps'),
@@ -175,8 +175,6 @@ class Oauth extends Controller {
'$remove' => t('Remove authorization'),
'$apps' => $r,
));
- return $o;
-
}
}
diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php
index 4b0b1991e..7aadd91bc 100644
--- a/Zotlabs/Module/Oauth2.php
+++ b/Zotlabs/Module/Oauth2.php
@@ -108,7 +108,8 @@ class Oauth2 extends Controller {
if((argc() > 1) && (argv(1) === 'add')) {
$tpl = get_markup_template("oauth2_edit.tpl");
- $o .= replace_macros($tpl, array(
+
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
'$title' => t('Add OAuth2 application'),
'$submit' => t('Submit'),
@@ -119,7 +120,6 @@ class Oauth2 extends Controller {
'$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application sepcifically requires this')),
'$scope' => array('scope', t('Authorization scope'), '', t('leave blank unless your application sepcifically requires this')),
));
- return $o;
}
if((argc() > 2) && (argv(1) === 'edit')) {
@@ -136,7 +136,7 @@ class Oauth2 extends Controller {
$app = $r[0];
$tpl = get_markup_template("oauth2_edit.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
'$title' => t('Add application'),
'$submit' => t('Update'),
@@ -147,7 +147,6 @@ class Oauth2 extends Controller {
'$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')),
'$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application specifically requires this')),
));
- return $o;
}
if((argc() > 2) && (argv(1) === 'delete')) {
@@ -184,7 +183,8 @@ class Oauth2 extends Controller {
);
$tpl = get_markup_template("oauth2.tpl");
- $o .= replace_macros($tpl, array(
+
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("oauth2"),
'$baseurl' => z_root(),
'$title' => t('Connected OAuth2 Apps'),
@@ -196,8 +196,6 @@ class Oauth2 extends Controller {
'$remove' => t('Remove authorization'),
'$apps' => $r,
));
- return $o;
-
}
}
diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php
index 85467d4f4..254b1c7d1 100644
--- a/Zotlabs/Module/Owa.php
+++ b/Zotlabs/Module/Owa.php
@@ -18,96 +18,97 @@ use Zotlabs\Web\Controller;
class Owa extends Controller {
- function init() {
+ public function init(): void
+ {
$ret = [ 'success' => false ];
- if (array_key_exists('REDIRECT_REMOTE_USER',$_SERVER) && (! array_key_exists('HTTP_AUTHORIZATION',$_SERVER))) {
- $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_REMOTE_USER'];
+ if (!$this->validateAuthorizationHeader()) {
+ $this->error('Missing or invalid authorization header.');
}
- if (array_key_exists('HTTP_AUTHORIZATION',$_SERVER) && substr(trim($_SERVER['HTTP_AUTHORIZATION']),0,9) === 'Signature') {
- $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
- if ($sigblock) {
- $keyId = $sigblock['keyId'];
- $parsed = parse_url($keyId);
- if (str_starts_with($parsed['scheme'],'http')) {
- unset($parsed['fragment']);
- unset($parsed['query']);
- $keyId = unparse_url($parsed);
- }
- else {
- $keyId = str_replace('acct:', '', $keyId);
+ $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_REMOTE_USER'];
+
+ $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
+ if ($sigblock) {
+ $keyId = $sigblock['keyId'];
+ $parsed = parse_url($keyId);
+ if (str_starts_with($parsed['scheme'],'http')) {
+ unset($parsed['fragment']);
+ unset($parsed['query']);
+ $keyId = unparse_url($parsed);
+ }
+ else {
+ $keyId = str_replace('acct:', '', $keyId);
+ }
+ if ($keyId) {
+ $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
+ AND hubloc_deleted = 0 AND xchan_pubkey != ''
+ ORDER BY hubloc_id DESC",
+ dbesc($keyId),
+ dbesc($keyId),
+ dbesc($keyId)
+ );
+ if (! $r) {
+ $found = discover_by_webbie($keyId);
+ logger('found = ' . print_r($found, true));
+ if ($found) {
+ $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
+ dbesc($keyId),
+ dbesc($keyId),
+ dbesc($keyId)
+ );
+ }
}
- if ($keyId) {
- $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
- AND hubloc_deleted = 0 AND xchan_pubkey != ''
- ORDER BY hubloc_id DESC",
- dbesc($keyId),
- dbesc($keyId),
- dbesc($keyId)
- );
- if (! $r) {
+
+ if ($r) {
+ foreach ($r as $hubloc) {
+ $verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
+ if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
+ logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
+ logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
+ $ret['success'] = true;
+ $token = random_string(32);
+ Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
+ $result = '';
+ openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
+ $ret['encrypted_token'] = base64url_encode($result);
+ break;
+ } else {
+ logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
+ }
+ }
+
+ if (!$ret['success']) {
+
+ // Possible a reinstall?
+ // In this case we probably already have an old hubloc
+ // but not the new one yet.
+
$found = discover_by_webbie($keyId);
- logger('found = ' . print_r($found, true));
+
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
- dbesc($keyId),
- dbesc($keyId),
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
+ dbesc(str_replace('acct:', '', $keyId)),
dbesc($keyId)
);
- }
- }
-
- if ($r) {
- foreach ($r as $hubloc) {
- $verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
- if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
- logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
- logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
- $ret['success'] = true;
- $token = random_string(32);
- Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
- $result = '';
- openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
- $ret['encrypted_token'] = base64url_encode($result);
- break;
- } else {
- logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
- }
- }
- if (!$ret['success']) {
-
- // Possible a reinstall?
- // In this case we probably already have an old hubloc
- // but not the new one yet.
-
- $found = discover_by_webbie($keyId);
-
- if ($found) {
- $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
- dbesc(str_replace('acct:', '', $keyId)),
- dbesc($keyId)
- );
-
- if ($r) {
- $verified = HTTPSig::verify(file_get_contents('php://input'), $r[0]['xchan_pubkey']);
- if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
- logger('OWA header: ' . print_r($verified,true), LOGGER_DATA);
- logger('OWA success: ' . $r[0]['hubloc_id_url'], LOGGER_DATA);
- $ret['success'] = true;
- $token = random_string(32);
- Verify::create('owt', 0, $token, $r[0]['hubloc_id_url']);
- $result = '';
- openssl_public_encrypt($token, $result, $r[0]['xchan_pubkey']);
- $ret['encrypted_token'] = base64url_encode($result);
- } else {
- logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
- }
+ if ($r) {
+ $verified = HTTPSig::verify(file_get_contents('php://input'), $r[0]['xchan_pubkey']);
+ if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
+ logger('OWA header: ' . print_r($verified,true), LOGGER_DATA);
+ logger('OWA success: ' . $r[0]['hubloc_id_url'], LOGGER_DATA);
+ $ret['success'] = true;
+ $token = random_string(32);
+ Verify::create('owt', 0, $token, $r[0]['hubloc_id_url']);
+ $result = '';
+ openssl_public_encrypt($token, $result, $r[0]['xchan_pubkey']);
+ $ret['encrypted_token'] = base64url_encode($result);
+ } else {
+ logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
}
}
}
@@ -118,4 +119,33 @@ class Owa extends Controller {
json_return_and_die($ret,'application/x-zot+json');
}
+
+ private function validateAuthorizationHeader(): bool
+ {
+ if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
+ $auth = trim($_SERVER['HTTP_AUTHORIZATION']);
+ } else if (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
+ $auth = trim($_SERVER['REDIRECT_REMOTE_USER']);
+ } else {
+ return false;
+ }
+
+ return strncmp($auth, 'Signature', 9) === 0;
+ }
+
+ /**
+ * Terminates the request, and return a json error response.
+ *
+ * @Note This function does not return!
+ *
+ * @param string $msg The error message for the response.
+ */
+ private function error(string $msg): void {
+ $ret = [
+ 'success' => false,
+ 'message' => $msg
+ ];
+
+ json_return_and_die($ret,'application/x-zot+json');
+ }
}
diff --git a/Zotlabs/Module/Page.php b/Zotlabs/Module/Page.php
index 8a698005a..a4ee5eaa2 100644
--- a/Zotlabs/Module/Page.php
+++ b/Zotlabs/Module/Page.php
@@ -183,9 +183,7 @@ class Page extends \Zotlabs\Web\Controller {
if($r[0]['mimetype'] === 'application/x-pdl')
\App::$page['pdl_content'] = true;
- $o .= prepare_page($r[0]);
- return $o;
-
+ return prepare_page($r[0]);
}
}
diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php
index e0bbc31d0..aa512e6da 100644
--- a/Zotlabs/Module/Pdledit.php
+++ b/Zotlabs/Module/Pdledit.php
@@ -51,7 +51,7 @@ class Pdledit extends Controller {
if(argc() > 1)
$module = 'mod_' . argv(1) . '.pdl';
else {
- $o .= '<div class="generic-content-wrapper-styled">';
+ $o = '<div class="generic-content-wrapper-styled">';
$o .= '<h1>' . t('Edit System Page Description') . '</h1>';
$edited = [];
diff --git a/Zotlabs/Module/Permcat.php b/Zotlabs/Module/Permcat.php
index 064c9cefb..0335c7bc6 100644
--- a/Zotlabs/Module/Permcat.php
+++ b/Zotlabs/Module/Permcat.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Module;
-use \Zotlabs\Lib as Zlib;
+use Zotlabs\Lib as Zlib;
class Permcat extends \Zotlabs\Web\Controller {
@@ -22,4 +22,4 @@ class Permcat extends \Zotlabs\Web\Controller {
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index 870a2cb79..e31aa9dc1 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -1122,7 +1122,7 @@ class Photos extends \Zotlabs\Web\Controller {
if(is_array($like_list) && (count($like_list) > MAX_LIKERS)) {
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
- array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ array_push($like_list_part, '<a href="#" data-bs-toggle="modal" data-bs-target="#likeModal-' . $link_item['id'] . '"><b>' . t('View all') . '</b></a>');
} else {
$like_list_part = '';
}
@@ -1134,7 +1134,7 @@ class Photos extends \Zotlabs\Web\Controller {
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
if (is_array($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
- array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ array_push($dislike_list_part, '<a href="#" data-bs-toggle="modal" data-bs-target="#dislikeModal-' . $link_item['id'] . '"><b>' . t('View all') . '</b></a>');
} else {
$dislike_list_part = '';
}
diff --git a/Zotlabs/Module/Profperm.php b/Zotlabs/Module/Profperm.php
index 842197415..4594728b1 100644
--- a/Zotlabs/Module/Profperm.php
+++ b/Zotlabs/Module/Profperm.php
@@ -55,6 +55,8 @@ class Profperm extends \Zotlabs\Web\Controller {
}
+ $o = '';
+
if((argc() > 1) && (intval(argv(1)))) {
$r = q("SELECT * FROM profile WHERE id = %d AND uid = %d AND is_default = 0 LIMIT 1",
intval(argv(1)),
diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php
index cbaa66042..f58b4adff 100644
--- a/Zotlabs/Module/Pubsites.php
+++ b/Zotlabs/Module/Pubsites.php
@@ -49,18 +49,18 @@ class Pubsites extends \Zotlabs\Web\Controller {
}
$m = parse_url($jj['url']);
$host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
- $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="fa fa-check-square-o"></i> ' . t('Rate') . '</a></td>' : '');
+ $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="bi bi-check-square"></i> ' . t('Rate') . '</a></td>' : '');
$location = '';
if(!empty($jj['location'])) {
- $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</p>';
+ $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="bi bi-globe"></i> ' . $jj['location'] . '</p>';
}
else {
$location = '<br />&nbsp;';
}
$urltext = str_replace(array('https://'), '', $jj['url']);
- $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="fa fa-link"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><!--td>' . '<a target="stats" href="https://hubchart-tarine.rhcloud.com/hub.jsp?hubFqdn=' . $m['host'] . '"><i class="fa fa-area-chart"></i></a></td--><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
+ $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="bi bi-link-45deg"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><!--td>' . '<a target="stats" href="https://hubchart-tarine.rhcloud.com/hub.jsp?hubFqdn=' . $m['host'] . '"><i class="bi bi-graph-up"></i></a></td--><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
if($rating_enabled)
- $o .= '<td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="fa fa-eye"></i> ' . t('View') . '</a></td>' . $rate_links ;
+ $o .= '<td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="bi bi-eye"></i> ' . t('View') . '</a></td>' . $rate_links ;
$o .= '</tr>';
}
}
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index 6d8edf4d8..234e73792 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -202,11 +202,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
if($mid) {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.$identifier = '%s' and item.item_private = 0
$uids $site_firehose_sql
$item_normal
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -216,11 +214,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
// Fetch a page full of parent items for this page
$r = dbq("SELECT parent AS item_id FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.item_private = 0 $thread_top
$uids $site_firehose_sql
$item_normal
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2
ORDER BY $ordering DESC $pager_sql "
@@ -231,10 +227,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
if($mid) {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.$identifier = '%s' and item.item_private = 0
$uids $site_firehose_sql $item_normal_update $simple_update
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -243,11 +237,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
else {
$r = dbq("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.item_private = 0 $thread_top
$uids $site_firehose_sql $item_normal_update
$simple_update
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2"
);
diff --git a/Zotlabs/Module/React.php b/Zotlabs/Module/React.php
index e04b9b257..e1abd242e 100644
--- a/Zotlabs/Module/React.php
+++ b/Zotlabs/Module/React.php
@@ -91,6 +91,9 @@ class React extends Controller {
if ($x['success']) {
$nid = $x['item_id'];
Master::Summon(['Notifier', 'like', $nid]);
+ if (!empty($x['approval_id'])) {
+ Master::Summon(['Notifier', 'like', $x['approval_id']]);
+ }
}
}
diff --git a/Zotlabs/Module/Removeaccount.php b/Zotlabs/Module/Removeaccount.php
index cd18b79c0..b41acb8b0 100644
--- a/Zotlabs/Module/Removeaccount.php
+++ b/Zotlabs/Module/Removeaccount.php
@@ -36,22 +36,22 @@ class Removeaccount extends \Zotlabs\Web\Controller {
return;
}
}
-
+
$global_remove = 0; //intval($_POST['global']);
-
- account_remove($account_id, 1 - $global_remove);
+
+ account_remove($account_id, 1 - $global_remove);
}
-
+
function get() {
-
+
if(! local_channel())
goaway(z_root());
-
+
$hash = random_string();
-
+
$_SESSION['remove_account_verify'] = $hash;
$tpl = get_markup_template('removeaccount.tpl');
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$basedir' => z_root(),
'$hash' => $hash,
'$title' => t('Remove This Account'),
@@ -60,9 +60,5 @@ class Removeaccount extends \Zotlabs\Web\Controller {
// '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')),
'$submit' => t('Remove Account')
));
-
- return $o;
-
}
-
}
diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php
index 4d475ead6..d71f8d4ab 100644
--- a/Zotlabs/Module/Removeme.php
+++ b/Zotlabs/Module/Removeme.php
@@ -54,7 +54,7 @@ class Removeme extends \Zotlabs\Web\Controller {
$_SESSION['remove_account_verify'] = $hash;
$tpl = get_markup_template('removeme.tpl');
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$basedir' => z_root(),
'$hash' => $hash,
'$title' => t('Remove Channel'),
@@ -63,9 +63,5 @@ class Removeme extends \Zotlabs\Web\Controller {
// '$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;
-
}
-
}
diff --git a/Zotlabs/Module/Rmagic.php b/Zotlabs/Module/Rmagic.php
index 90cf8b854..4254dd38b 100644
--- a/Zotlabs/Module/Rmagic.php
+++ b/Zotlabs/Module/Rmagic.php
@@ -29,7 +29,7 @@ class Rmagic extends \Zotlabs\Web\Controller {
if($r['hubloc_url'] === z_root())
goaway(z_root() . '/login');
$dest = bin2hex(z_root() . '/' . str_replace(['rmagic','zid='],['','zid_='],\App::$query_string));
- goaway($r['hubloc_url'] . '/magic' . '?f=&owa=1&bdest=' . $dest);
+ goaway($r['hubloc_url'] . '/magic?owa=1&bdest=' . $dest);
}
}
}
@@ -84,7 +84,7 @@ class Rmagic extends \Zotlabs\Web\Controller {
else
$dest = bin2hex(z_root() . '/' . str_replace([ 'rmagic', 'zid=' ] ,[ '', 'zid_='],\App::$query_string));
- goaway($url . '/magic' . '?f=&owa=1&bdest=' . $dest);
+ goaway($url . '/magic?owa=1&bdest=' . $dest);
}
}
}
diff --git a/Zotlabs/Module/Search_ac.php b/Zotlabs/Module/Search_ac.php
index 24b724c5d..cd0960859 100644
--- a/Zotlabs/Module/Search_ac.php
+++ b/Zotlabs/Module/Search_ac.php
@@ -90,12 +90,7 @@ class Search_ac extends \Zotlabs\Web\Controller {
'items' => $results,
);
echo json_encode($o);
-
- logger('search_ac: ' . print_r($x,true),LOGGER_DATA,LOG_INFO);
-
+
killme();
}
-
-
-
}
diff --git a/Zotlabs/Module/Settings/Account.php b/Zotlabs/Module/Settings/Account.php
index 0266cee12..7f0d11069 100644
--- a/Zotlabs/Module/Settings/Account.php
+++ b/Zotlabs/Module/Settings/Account.php
@@ -100,7 +100,7 @@ class Account {
$attremail = ((!strpos($email, '@')) ? 'disabled="disabled"' : '');
$tpl = get_markup_template("settings_account.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_account"),
'$title' => t('Account Settings'),
'$origpass' => array('origpass', t('Current Password'), ' ',''),
@@ -114,7 +114,5 @@ class Account {
'$removeaccount' => t('Remove this account including all its channels'),
'$account_settings' => $account_settings
));
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php
index 65240c635..3b15f4aa6 100644
--- a/Zotlabs/Module/Settings/Calendar.php
+++ b/Zotlabs/Module/Settings/Calendar.php
@@ -33,7 +33,7 @@ class Calendar {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Calendar {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php
index 470dbe4c3..388b70942 100644
--- a/Zotlabs/Module/Settings/Channel_home.php
+++ b/Zotlabs/Module/Settings/Channel_home.php
@@ -81,7 +81,7 @@ class Channel_home {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -90,8 +90,5 @@ 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 52a95a3d1..9d1069cf3 100644
--- a/Zotlabs/Module/Settings/Connections.php
+++ b/Zotlabs/Module/Settings/Connections.php
@@ -33,7 +33,7 @@ class Connections {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Connections {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Conversation.php b/Zotlabs/Module/Settings/Conversation.php
index aa0ff6a7e..51ee2c83a 100644
--- a/Zotlabs/Module/Settings/Conversation.php
+++ b/Zotlabs/Module/Settings/Conversation.php
@@ -11,24 +11,19 @@ class Conversation {
$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['aj']) {
- if($_POST['auto_update'] == 1)
- info(t('Settings saved.') . EOL);
- else
- info(t('Settings saved. Reload page please.') . EOL);
+ if($_POST['aj']) {
killme();
}
- else {
- return;
- }
+
+ return;
+
}
function get() {
@@ -41,14 +36,14 @@ class Conversation {
$tpl = (($aj) ? get_markup_template("settings_module_ajax.tpl") : get_markup_template("settings_module.tpl"));
- $o .= replace_macros($tpl, array(
+ $o = replace_macros($tpl, array(
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
'$title' => t('Conversation Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
if($aj) {
echo $o;
killme();
diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php
index 09ea61f60..e1957d2fa 100644
--- a/Zotlabs/Module/Settings/Directory.php
+++ b/Zotlabs/Module/Settings/Directory.php
@@ -33,7 +33,7 @@ class Directory {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Directory {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php
index 85c3e69ae..50bd2b2ad 100644
--- a/Zotlabs/Module/Settings/Editor.php
+++ b/Zotlabs/Module/Settings/Editor.php
@@ -33,7 +33,7 @@ class Editor {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Editor {
'$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 0a0e3516c..3a7faa8b4 100644
--- a/Zotlabs/Module/Settings/Events.php
+++ b/Zotlabs/Module/Settings/Events.php
@@ -33,7 +33,7 @@ class Events {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Events {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Features.php b/Zotlabs/Module/Settings/Features.php
index 553ff0836..84c868e48 100644
--- a/Zotlabs/Module/Settings/Features.php
+++ b/Zotlabs/Module/Settings/Features.php
@@ -38,17 +38,14 @@ class Features {
$arr[$fname][1][] = array('feature_' . $f[0],$f[1],((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On')));
}
}
-
+
$tpl = get_markup_template("settings_features.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_features"),
'$title' => t('Additional Features'),
'$features' => $arr,
'$baseurl' => z_root(),
'$submit' => t('Submit'),
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php
index 6fb57eafb..6e47cfcc7 100644
--- a/Zotlabs/Module/Settings/Manage.php
+++ b/Zotlabs/Module/Settings/Manage.php
@@ -34,7 +34,7 @@ class Manage {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -42,8 +42,5 @@ class Manage {
'$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 eae963a25..39c66622e 100644
--- a/Zotlabs/Module/Settings/Network.php
+++ b/Zotlabs/Module/Settings/Network.php
@@ -52,7 +52,7 @@ class Network {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -61,8 +61,5 @@ 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 f68c8847b..05c380850 100644
--- a/Zotlabs/Module/Settings/Photos.php
+++ b/Zotlabs/Module/Settings/Photos.php
@@ -33,7 +33,7 @@ class Photos {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -41,8 +41,5 @@ class Photos {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php
index 0ff2dfb6d..5052385a8 100644
--- a/Zotlabs/Module/Settings/Profiles.php
+++ b/Zotlabs/Module/Settings/Profiles.php
@@ -42,7 +42,7 @@ class Profiles {
$tpl = get_markup_template("settings_module.tpl");
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$rpath' => escape_url($rpath),
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
@@ -51,8 +51,5 @@ 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 35079e5e5..5b423f67d 100644
--- a/Zotlabs/Module/Setup.php
+++ b/Zotlabs/Module/Setup.php
@@ -263,7 +263,10 @@ class Setup extends \Zotlabs\Web\Controller {
$this->check_htaccess($checks);
- $checkspassed = array_reduce($checks, "self::check_passed", true);
+ $checkspassed = array_reduce(
+ $checks,
+ "Zotlabs\Module\Setup::check_passed",
+ true);
$tpl = get_markup_template('install_checks.tpl');
$o .= replace_macros($tpl, array(
diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php
index ea9313fa8..4fefdb4ef 100644
--- a/Zotlabs/Module/Share.php
+++ b/Zotlabs/Module/Share.php
@@ -94,6 +94,12 @@ class Share extends \Zotlabs\Web\Controller {
else
killme();
+ $object = Activity::fetch_item([ 'id' => $item['mid'] ]);
+
+ if (!$object) {
+ killme();
+ }
+
$arr['aid'] = $item['aid'];
$arr['uid'] = $item['uid'];
@@ -121,7 +127,7 @@ class Share extends \Zotlabs\Web\Controller {
$arr['owner_xchan'] = $item['author_xchan'];
$arr['source_xchan'] = '';
- $arr['obj'] = $item['obj'];
+ $arr['obj'] = $object;
$arr['obj_type'] = $item['obj_type'];
$arr['verb'] = ACTIVITY_SHARE;
@@ -130,6 +136,7 @@ class Share extends \Zotlabs\Web\Controller {
$post = item_store($arr);
$post_id = $post['item_id'];
+ $approval_id = $post['approval_id'] ?? 0;
$arr['id'] = $post_id;
@@ -137,6 +144,7 @@ class Share extends \Zotlabs\Web\Controller {
// info( t('Post repeated') . EOL);
+/*
$r = q("select * from item where id = %d",
intval($post_id)
);
@@ -145,8 +153,12 @@ class Share extends \Zotlabs\Web\Controller {
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
}
+*/
Master::Summon([ 'Notifier', 'like', $post_id ]);
+ if ($approval_id) {
+ Master::Summon(['Notifier', 'like', $approval_id]);
+ }
killme();
diff --git a/Zotlabs/Module/Snap.php b/Zotlabs/Module/Snap.php
index 89aebc097..770ba07c2 100644
--- a/Zotlabs/Module/Snap.php
+++ b/Zotlabs/Module/Snap.php
@@ -8,8 +8,8 @@ namespace Zotlabs\Module;
* Module for accessing the DAV storage area from a DAV client.
*/
-use \Sabre\DAV as SDAV;
-use \Zotlabs\Storage;
+use Sabre\DAV as SDAV;
+use Zotlabs\Storage;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
@@ -24,7 +24,7 @@ require_once('vendor/autoload.php');
class Snap extends \Zotlabs\Web\Controller {
function init() {
-
+
// workaround for HTTP-auth in CGI mode
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
@@ -43,20 +43,20 @@ class Snap extends \Zotlabs\Web\Controller {
$_SERVER['PHP_AUTH_PW'] = $password;
}
}
-
+
if (! is_dir('store'))
os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false);
-
+
$which = null;
if (argc() > 1)
$which = argv(1);
-
+
$profile = 0;
-
+
if($which)
profile_load( $which, $profile);
else
- killme();
+ killme();
if($_SERVER['PHP_AUTH_USER'] && $_SERVER['PHP_AUTH_USER'] !== $which)
killme();
@@ -68,7 +68,7 @@ class Snap extends \Zotlabs\Web\Controller {
}
if(! in_array(strtolower($_SERVER['REQUEST_METHOD']),['propfind','get','head']))
- killme();
+ killme();
$auth = new \Zotlabs\Storage\BasicAuth();
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'WebDAV');
@@ -101,5 +101,5 @@ class Snap extends \Zotlabs\Web\Controller {
killme();
}
-
+
}
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index 5baa90128..673457db1 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -19,25 +19,20 @@ class Sse extends Controller {
function init() {
+ // This is important!
+ session_write_close();
+ ignore_user_abort(true);
+
if((observer_prohibited(true))) {
killme();
}
- if(! intval(Config::Get('system','open_pubstream',1))) {
- if(! get_observer_hash()) {
- killme();
- }
- }
-
- // this is important!
- session_write_close();
-
self::$uid = local_channel();
self::$ob_hash = get_observer_hash();
self::$sse_id = false;
self::$vnotify = -1;
- if(! self::$ob_hash) {
+ if (!self::$ob_hash) {
if(session_id()) {
self::$sse_id = true;
self::$ob_hash = 'sse_id.' . session_id();
@@ -55,7 +50,7 @@ class Sse extends Controller {
self::$sse_enabled = Config::Get('system', 'sse_enabled', 0);
- if(self::$sse_enabled) {
+ if (self::$sse_enabled) {
// Server Sent Events
@@ -73,7 +68,7 @@ class Sse extends Controller {
$i = 0;
}
- if(!self::$sse_id && $i === 0) {
+ if (!self::$sse_id && $i === 0) {
// Update chat presence indication about once per minute
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
dbesc(self::$ob_hash),
@@ -82,7 +77,7 @@ class Sse extends Controller {
$basic_presence = false;
- if($r) {
+ if ($r) {
$basic_presence = true;
q("update chatpresence set cp_last = '%s' where cp_id = %d",
dbesc(datetime_convert()),
@@ -90,7 +85,7 @@ class Sse extends Controller {
);
}
- if(!$basic_presence) {
+ if (!$basic_presence) {
q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
values( '%s', '%s', '%s', '%s' ) ",
dbesc(self::$ob_hash),
@@ -101,16 +96,16 @@ class Sse extends Controller {
}
}
+ $result = [];
+
XConfig::Load(self::$ob_hash);
- $result = [];
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
if (!$lock) {
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
}
-
// 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'))) {
@@ -119,42 +114,61 @@ class Sse extends Controller {
}
}
- if($result) {
+ if ($result) {
echo "event: notifications\n";
echo 'data: ' . json_encode($result);
echo "\n\n";
-
- XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- unset($result);
+ }
+ else {
+ // if no result we will send a heartbeat to keep connected
+ echo "event: heartbeat\n";
+ echo 'data: {}';
+ echo "\n\n";
}
- // always send heartbeat to detect disconnected clients
- echo "event: heartbeat\n";
- echo 'data: {}';
- echo "\n\n";
+ if (connection_status() != CONNECTION_NORMAL || connection_aborted()) {
- if(ob_get_length() > 0)
- ob_end_flush();
+ // In case session_write_close() failed for some reason and
+ // the channel was changed we might need to reset the
+ // session to it's current stored state here.
+ // Otherwise the uid might switch back to the previous value
+ // in the background.
- flush();
+ session_reset();
- if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
- //TODO: this does not seem to be triggered
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
- break;
+ XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
+
+ if (ob_get_length() > 0) {
+ ob_end_flush();
+ }
+
+ flush();
+
+ exit;
}
- $i++;
+ if (ob_get_length() > 0) {
+ ob_flush();
+ }
+
+ flush();
usleep($sleep);
+ if ($result) {
+ XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
+ }
+
+ $i++;
+
}
}
else {
// Fallback to traditional polling
- if(! self::$sse_id) {
+ if(!self::$sse_id) {
// Update chat presence indication
@@ -163,14 +177,14 @@ class Sse extends Controller {
dbesc($_SERVER['REMOTE_ADDR'])
);
$basic_presence = false;
- if($r) {
+ 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) {
+ if (!$basic_presence) {
q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
values( '%s', '%s', '%s', '%s' ) ",
dbesc(self::$ob_hash),
@@ -181,17 +195,21 @@ class Sse extends Controller {
}
}
+ $result = [];
+
XConfig::Load(self::$ob_hash);
- $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
- if($result && !$lock) {
+ if (!$lock) {
+ $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
+ }
+
+ if ($result) {
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- json_return_and_die($result);
}
- killme();
+ json_return_and_die($result);
}
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
index 09c4ed614..8847ff242 100644
--- a/Zotlabs/Module/Sse_bs.php
+++ b/Zotlabs/Module/Sse_bs.php
@@ -22,7 +22,6 @@ class Sse_bs extends Controller {
public static $xchans;
function init() {
-
self::$uid = local_channel();
self::$ob_hash = get_observer_hash();
self::$sse_id = false;
@@ -43,8 +42,9 @@ class Sse_bs extends Controller {
self::$offset = 0;
self::$xchans = '';
- if(isset($_REQUEST['sse_rmids']))
- self::mark_read($_REQUEST['sse_rmids']);
+ if (isset($_REQUEST['sse_rmids'])) {
+ self::mark_read(explode(',', $_REQUEST['sse_rmids']));
+ }
if(!empty($_REQUEST['nquery']) && $_REQUEST['nquery'] !== '%') {
$nquery = $_REQUEST['nquery'];
@@ -502,13 +502,15 @@ class Sse_bs extends Controller {
}
}
- $r = q("SELECT id FROM item
+ $r = q("SELECT id, body FROM item
WHERE true $uids
+ AND created <= '%s'
AND created > '%s'
$item_normal
$sql_extra
$sql_extra3
AND author_xchan != '%s' LIMIT 100",
+ dbescdate($_SESSION['sse_loadtime']),
dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime']),
dbesc(self::$ob_hash)
);
@@ -600,25 +602,15 @@ class Sse_bs extends Controller {
$i = 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(self::$uid),
- 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(*) as total from item
- where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and verb != 'Announce' and item_unseen = 1 $sql_extra $item_normal",
+ where uid = %d and (owner_xchan = '%s' or author_xchan = '%s') and author_xchan != '%s' and verb != 'Announce' and item_unseen = 1 $sql_extra $item_normal",
intval(self::$uid),
dbesc($forums[$x]['xchan_hash']),
- dbesc($forums[$x]['xchan_hash'])
+ dbesc($forums[$x]['xchan_hash']),
+ dbesc(self::$ob_hash)
);
-
if($r[0]['total']) {
$forums[$x]['notify_link'] = z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id'];
diff --git a/Zotlabs/Module/Subthread.php b/Zotlabs/Module/Subthread.php
index b927ee480..baabee78f 100644
--- a/Zotlabs/Module/Subthread.php
+++ b/Zotlabs/Module/Subthread.php
@@ -159,7 +159,7 @@ class Subthread extends \Zotlabs\Web\Controller {
$arr['deny_cid'] = $item['deny_cid'];
$arr['deny_gid'] = $item['deny_gid'];
- $post = item_store($arr);
+ $post = item_store($arr, deliver: false, addAndSync: false);
$post_id = $post['item_id'];
$arr['id'] = $post_id;
diff --git a/Zotlabs/Module/Tagger.php b/Zotlabs/Module/Tagger.php
index b6067be5e..a88a3b112 100644
--- a/Zotlabs/Module/Tagger.php
+++ b/Zotlabs/Module/Tagger.php
@@ -1,6 +1,7 @@
<?php
namespace Zotlabs\Module;
+use App;
use Zotlabs\Lib\Libsync;
require_once('include/security.php');
@@ -18,6 +19,7 @@ class Tagger extends \Zotlabs\Web\Controller {
}
$sys = get_sys_channel();
+ $channel = App::get_channel();
$observer_hash = get_observer_hash();
//strip html-tags
@@ -125,10 +127,6 @@ class Tagger extends \Zotlabs\Web\Controller {
$termlink = html_entity_decode('&#x22d5;') . '[zrl=' . z_root() . '/search?tag=' . urlencode($clean_term) . ']'. $clean_term . '[/zrl]';
- $channel = \App::get_channel();
-
- $arr = array();
-
$arr['owner_xchan'] = $item['owner_xchan'];
$arr['author_xchan'] = $channel['channel_hash'];
diff --git a/Zotlabs/Module/Tagrm.php b/Zotlabs/Module/Tagrm.php
index a6dc21798..34eaf85b2 100644
--- a/Zotlabs/Module/Tagrm.php
+++ b/Zotlabs/Module/Tagrm.php
@@ -7,141 +7,141 @@ require_once('include/bbcode.php');
class Tagrm extends \Zotlabs\Web\Controller {
function post() {
-
+
if(! local_channel())
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
-
+
+
if((x($_POST,'submit')) && ($_POST['submit'] === t('Cancel')))
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
$tag = ((x($_POST,'tag')) ? trim($_POST['tag']) : '');
$item = ((x($_POST,'item')) ? intval($_POST['item']) : 0 );
-
+
$r = q("SELECT * FROM item WHERE id = %d AND uid = %d LIMIT 1",
intval($item),
intval(local_channel())
);
-
+
if(! $r)
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
$r = fetch_post_tags($r,true);
-
+
$item = $r[0];
$new_tags = array();
-
+
if($item['term']) {
for($x = 0; $x < count($item['term']); $x ++) {
if($item['term'][$x]['term'] !== hex2bin($tag))
$new_tags[] = $item['term'][$x];
}
}
-
+
if($new_tags)
$item['term'] = $new_tags;
else
unset($item['term']);
-
- item_store_update($item);
-
+
+ item_store_update($item, deliver: false, addAndSync: false);
+
info( t('Tag removed') . EOL );
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
// NOTREACHED
-
+
}
-
-
-
+
+
+
function get() {
-
+
if(! local_channel()) {
goaway(z_root() . '/' . $_SESSION['photo_return']);
// NOTREACHED
}
-
+
// remove tag on the fly if item and tag are provided
if((argc() == 4) && (argv(1) === 'drop') && intval(argv(2))) {
-
+
$item = intval(argv(2));
$tag = argv(3);
-
+
$r = q("SELECT * FROM item WHERE id = %d AND uid = %d LIMIT 1",
intval($item),
intval(local_channel())
);
-
+
if(! $r)
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
$r = fetch_post_tags($r,true);
-
+
$item = $r[0];
-
+
$new_tags = array();
-
+
if($item['term']) {
for($x = 0; $x < count($item['term']); $x ++) {
if($item['term'][$x]['term'] !== hex2bin($tag))
$new_tags[] = $item['term'][$x];
}
}
-
+
if($new_tags)
$item['term'] = $new_tags;
else
unset($item['term']);
-
- item_store_update($item);
-
+
+ item_store_update($item, deliver: false, addAndSync: false);
+
info( t('Tag removed') . EOL );
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
}
-
+
//if we got only the item print a list of tags to select
if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
-
+
$o = '';
-
+
$item = intval(argv(2));
-
+
$r = q("SELECT * FROM item WHERE id = %d AND uid = %d LIMIT 1",
intval($item),
intval(local_channel())
);
-
+
if(! $r)
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
$r = fetch_post_tags($r,true);
-
+
if(! count($r[0]['term']))
goaway(z_root() . '/' . $_SESSION['photo_return']);
-
+
$o .= '<h3>' . t('Remove Item Tag') . '</h3>';
-
+
$o .= '<p id="tag-remove-desc">' . t('Select a tag to remove: ') . '</p>';
-
+
$o .= '<form id="tagrm" action="tagrm" method="post" >';
$o .= '<input type="hidden" name="item" value="' . $item . '" />';
$o .= '<ul>';
-
-
+
+
foreach($r[0]['term'] as $x) {
$o .= '<li><input type="checkbox" name="tag" value="' . bin2hex($x['term']) . '" >' . bbcode($x['term']) . '</input></li>';
}
-
+
$o .= '</ul>';
$o .= '<input id="tagrm-submit" type="submit" name="submit" value="' . t('Remove') .'" />';
$o .= '<input id="tagrm-cancel" type="submit" name="submit" value="' . t('Cancel') .'" />';
$o .= '</form>';
-
+
return $o;
-
+
}
-
+
}
-
+
}
diff --git a/Zotlabs/Module/Thing.php b/Zotlabs/Module/Thing.php
index 2038db8c0..aef494e13 100644
--- a/Zotlabs/Module/Thing.php
+++ b/Zotlabs/Module/Thing.php
@@ -50,24 +50,31 @@ class Thing extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
- $term_hash = (($_REQUEST['term_hash']) ? $_REQUEST['term_hash'] : '');
+ $term_hash = (($_POST['term_hash']) ? $_POST['term_hash'] : '');
- $name = escape_tags($_REQUEST['term']);
- $verb = escape_tags($_REQUEST['verb']);
- $activity = intval($_REQUEST['activity']);
- $profile_guid = escape_tags($_REQUEST['profile_assign']);
- $url = $_REQUEST['url'];
- $photo = $_REQUEST['img'];
+ $name = escape_tags($_POST['term']);
+ $verb = escape_tags($_POST['verb']);
+ $activity = intval($_POST['activity']);
+ $url = $_POST['url'];
+ $photo = $_POST['img'];
+
+ $profile_guid = isset($_POST['profile_assign'])
+ ? escape_tags($_POST['profile_assign'])
+ : null;
$hash = new_uuid();
$verbs = obj_verbs();
- /**
- * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
- * We use the first person form when creating an activity, but the third person for use in activities
- * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually
- * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
+ /*
+ * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person
+ * singular, e.g. "Bill wants" We use the first person form when
+ * creating an activity, but the third person for use in activities
+ *
+ * @FIXME There is no accounting for verb gender for languages where
+ * this is significant. We may eventually require obj_verbs() to
+ * provide full conjugations and specify which form to use in the
+ * $_POST params to this module.
*/
$translated_verb = $verbs[$verb][1];
@@ -100,7 +107,7 @@ class Thing extends \Zotlabs\Web\Controller {
return;
$acl = new \Zotlabs\Access\AccessList($channel);
- $acl->set_from_array($_REQUEST);
+ $acl->set_from_array($_POST);
$x = $acl->get();
@@ -332,7 +339,7 @@ class Thing extends \Zotlabs\Web\Controller {
return '';
}
- $o .= replace_macros(get_markup_template('thing_edit.tpl'),array(
+ return replace_macros(get_markup_template('thing_edit.tpl'),array(
'$thing_hdr' => t('Edit Thing'),
'$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
'$profile_lbl' => t('Select a profile'),
@@ -356,8 +363,6 @@ class Thing extends \Zotlabs\Web\Controller {
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
-
- return $o;
}
if(argc() == 3 && argv(1) === 'drop') {
@@ -385,16 +390,16 @@ class Thing extends \Zotlabs\Web\Controller {
Libsync::build_sync_packet(0,array('obj' => $r));
- return $o;
+ return '';
}
- $o .= replace_macros(get_markup_template('thing_input.tpl'),array(
+ return replace_macros(get_markup_template('thing_input.tpl'),array(
'$thing_hdr' => t('Add Thing to your Profile'),
'$multiprof' => feature_enabled(local_channel(),'multi_profiles'),
'$profile_lbl' => t('Select a profile'),
'$profile_select' => contact_profile_assign(''),
'$verb_lbl' => $channel['channel_name'],
- '$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_REQUEST)) ? $_REQUEST['activity'] : true),t('Only sends to viewers of the applicable profile')),
+ '$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_GET)) ? $_GET['activity'] : true),t('Only sends to viewers of the applicable profile')),
'$verb_select' => obj_verb_selector(),
'$thing_lbl' => t('Name of thing e.g. something'),
'$url_lbl' => t('URL of thing (optional)'),
@@ -408,8 +413,5 @@ class Thing extends \Zotlabs\Web\Controller {
'$lockstate' => $lockstate,
'$submit' => t('Submit')
));
-
- return $o;
}
-
}
diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php
index 06c47f91f..5192e3043 100644
--- a/Zotlabs/Module/Vote.php
+++ b/Zotlabs/Module/Vote.php
@@ -107,10 +107,12 @@ class Vote extends Controller {
retain_item($fetch[0]['id']);
if($x['success']) {
- $itemid = $x['item_id'];
- Master::Summon( [ 'Notifier', 'like', $itemid ] );
+ Master::Summon(['Notifier', 'like', $x['item_id']]);
+ if (!empty($x['approval_id'])) {
+ Master::Summon(['Notifier', 'like', $x['approval_id']]);
+ }
}
-
+/*
$r = q("select * from item where id = %d",
intval($itemid)
);
@@ -119,6 +121,7 @@ class Vote extends Controller {
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
}
+*/
}
$ret['success'] = true;
diff --git a/Zotlabs/Module/Wall_attach.php b/Zotlabs/Module/Wall_attach.php
index 3c57d4b94..e354f58f1 100644
--- a/Zotlabs/Module/Wall_attach.php
+++ b/Zotlabs/Module/Wall_attach.php
@@ -111,7 +111,7 @@ class Wall_attach extends \Zotlabs\Web\Controller {
// give a wee bit of time for the background thumbnail processor to do its thing
// or else we'll never see a video poster
sleep(3);
- $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
+ $url = z_root() . '/attach/' . $r['data']['hash'];
$thumb = Linkinfo::get_video_poster($url);
if($thumb) {
$s = '[zvideo poster=\'' . $thumb . '\']' . $url . '[/zvideo]';
@@ -120,8 +120,8 @@ class Wall_attach extends \Zotlabs\Web\Controller {
$s = '[zvideo]' . $url . '[/zvideo]';
}
}
- if(strpos($r['data']['filetype'],'audio') === 0) {
- $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
+ if(strpos($r['data']['filetype'], 'audio') === 0) {
+ $url = z_root() . '/attach/' . $r['data']['hash'];
$s = '[zaudio]' . $url . '[/zaudio]';
}
if ($r['data']['filetype'] === 'image/svg+xml') {
diff --git a/Zotlabs/Module/Webfinger.php b/Zotlabs/Module/Webfinger.php
index 0dafae23c..ba0dca9e7 100644
--- a/Zotlabs/Module/Webfinger.php
+++ b/Zotlabs/Module/Webfinger.php
@@ -7,16 +7,16 @@ namespace Zotlabs\Module;
class Webfinger extends \Zotlabs\Web\Controller {
function get() {
-
-
- $o .= '<h3>Webfinger Diagnostic</h3>';
-
+
+
+ $o = '<h3>Webfinger Diagnostic</h3>';
+
$o .= '<form action="webfinger" 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 .= '<input type="submit" name="submit" value="Submit" /></form>';
+
$o .= '<br /><br />';
-
+
if(x($_GET,'addr')) {
$addr = trim($_GET['addr']);
diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php
index ffb0d94ea..ca15c0b3a 100644
--- a/Zotlabs/Module/Webpages.php
+++ b/Zotlabs/Module/Webpages.php
@@ -63,7 +63,7 @@ class Webpages extends Controller {
switch ($_SESSION['action']) {
case 'import':
$_SESSION['action'] = null;
- $o .= replace_macros(get_markup_template('webpage_import.tpl'), array(
+ return replace_macros(get_markup_template('webpage_import.tpl'), array(
'$title' => t('Import Webpage Elements'),
'$importbtn' => t('Import selected'),
'$action' => 'import',
@@ -71,7 +71,6 @@ class Webpages extends Controller {
'$layouts' => $_SESSION['layouts'],
'$blocks' => $_SESSION['blocks'],
));
- return $o;
case 'importselected':
$_SESSION['action'] = null;
@@ -87,7 +86,7 @@ class Webpages extends Controller {
$pages = get_webpage_elements($channel, 'pages');
$layouts = get_webpage_elements($channel, 'layouts');
$blocks = get_webpage_elements($channel, 'blocks');
- $o .= replace_macros(get_markup_template('webpage_export_list.tpl'), array(
+ $o = replace_macros(get_markup_template('webpage_export_list.tpl'), array(
'$title' => t('Export Webpage Elements'),
'$exportbtn' => t('Export selected'),
'$action' => $_SESSION['export'], // value should be 'zipfile' or 'cloud'
diff --git a/Zotlabs/Module/Zot_probe.php b/Zotlabs/Module/Zot_probe.php
index 3eaabdd92..cf8355ce6 100644
--- a/Zotlabs/Module/Zot_probe.php
+++ b/Zotlabs/Module/Zot_probe.php
@@ -15,13 +15,19 @@ class Zot_probe extends \Zotlabs\Web\Controller {
$o .= '<form action="zot_probe" method="get">';
$o .= 'Lookup URI: <input type="text" style="width: 250px;" name="addr" value="' . $addr .'" /><br>';
+ $o .= '<input type="checkbox" name="sign" /> Sign request <br>';
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$o .= '<br /><br />';
if($addr) {
- $x = Zotfinger::exec($addr);
+ $channel = null;
+ if ($_GET['sign']) {
+ $channel = get_sys_channel();
+ }
+
+ $x = Zotfinger::exec($addr, $channel);
$o .= '<pre>' . htmlspecialchars(print_array($x)) . '</pre>';
diff --git a/Zotlabs/Photo/PhotoGd.php b/Zotlabs/Photo/PhotoGd.php
index 4a47f97ee..a81d9cae2 100644
--- a/Zotlabs/Photo/PhotoGd.php
+++ b/Zotlabs/Photo/PhotoGd.php
@@ -160,16 +160,28 @@ class PhotoGd extends PhotoDriver {
case 'image/png':
$quality = Config::Get('system', 'png_quality');
- if((! $quality) || ($quality > 9))
+
+ if((! $quality) || ($quality > 9)) {
$quality = PNG_QUALITY;
- \imagepng($this->image, NULL, $quality);
+ }
+
+ if (function_exists('imagepng')) {
+ \imagepng($this->image, NULL, $quality);
+ }
+
break;
case 'image/webp':
$quality = Config::Get('system', 'webp_quality');
- if((! $quality) || ($quality > 100))
+
+ if((! $quality) || ($quality > 100)) {
$quality = WEBP_QUALITY;
- \imagewebp($this->image, NULL, $quality);
+ }
+
+ if (function_exists('imagewebp')) {
+ \imagewebp($this->image, NULL, $quality);
+ }
+
break;
case 'image/jpeg':
@@ -177,9 +189,15 @@ class PhotoGd extends PhotoDriver {
default:
$quality = Config::Get('system', 'jpeg_quality');
- if((! $quality) || ($quality > 100))
+
+ if((! $quality) || ($quality > 100)) {
$quality = JPEG_QUALITY;
- \imagejpeg($this->image, NULL, $quality);
+ }
+
+ if (function_exists('imagejpeg')) {
+ \imagejpeg($this->image, NULL, $quality);
+ }
+
break;
}
diff --git a/Zotlabs/Render/SmartyInterface.php b/Zotlabs/Render/SmartyInterface.php
index 64c6aa377..a319a4881 100644
--- a/Zotlabs/Render/SmartyInterface.php
+++ b/Zotlabs/Render/SmartyInterface.php
@@ -2,7 +2,7 @@
namespace Zotlabs\Render;
-use Smarty;
+use Smarty\Smarty;
use App;
class SmartyInterface extends Smarty {
@@ -26,13 +26,13 @@ class SmartyInterface extends Smarty {
$this->setTemplateDir($template_dirs);
$basecompiledir = App::$config['system']['smarty3_folder'];
-
+
$this->setCompileDir($basecompiledir.'/compiled/');
$this->setConfigDir($basecompiledir.'/config/');
$this->setCacheDir($basecompiledir.'/cache/');
- $this->left_delimiter = App::get_template_ldelim('smarty3');
- $this->right_delimiter = App::get_template_rdelim('smarty3');
+ $this->setLeftDelimiter(App::get_template_ldelim('smarty3'));
+ $this->setRightDelimiter(App::get_template_rdelim('smarty3'));
// Don't report errors so verbosely
$this->error_reporting = E_ALL & ~E_WARNING & ~E_NOTICE;
diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php
index e7f71c8c8..6a9cd61ef 100644
--- a/Zotlabs/Storage/Browser.php
+++ b/Zotlabs/Storage/Browser.php
@@ -399,7 +399,6 @@ class Browser extends DAV\Browser\Plugin {
'$allow_gid' => ((isset($channel_acl['allow_gid'])) ? acl2json($channel_acl['allow_gid']) : ''),
'$deny_cid' => ((isset($channel_acl['deny_cid'])) ? acl2json($channel_acl['deny_cid']) : ''),
'$deny_gid' => ((isset($channel_acl['deny_gid'])) ? acl2json($channel_acl['deny_gid']) : ''),
- '$is_owner' => $is_owner,
'$select_all_label' => t('Select All'),
'$bulk_actions_label' => t('Bulk Actions'),
'$adjust_permissions_label' => t('Adjust Permissions'),
diff --git a/Zotlabs/Storage/GitRepo.php b/Zotlabs/Storage/GitRepo.php
deleted file mode 100644
index 306abc0ba..000000000
--- a/Zotlabs/Storage/GitRepo.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-namespace Zotlabs\Storage;
-
-use PHPGit\Git as PHPGit;
-
-require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
-
-/**
- * Wrapper class for PHPGit class for git repositories managed by Hubzilla
- *
- * @author Andrew Manning <andrewmanning@grid.reticu.li>
- */
-class GitRepo {
-
- public $url = null;
- public $name = null;
- private $path = null;
- private $channel = null;
- public $git = null;
- private $repoBasePath = null;
-
- function __construct($channel = 'sys', $url = null, $clone = false, $name = null, $path = null) {
-
- if ($channel === 'sys' && !is_site_admin()) {
- logger('Only admin can use channel sys');
- return null;
- }
-
- $this->repoBasePath = __DIR__ . '/../../store/git';
- $this->channel = $channel;
- $this->git = new PHPGit();
-
- // Allow custom path for repo in the case of , for example
- if ($path) {
- $this->path = $path;
- } else {
- $this->path = $this->repoBasePath . "/" . $this->channel . "/" . $this->name;
- }
-
- if ($this->isValidGitRepoURL($url)) {
- $this->url = $url;
- }
-
- if ($name) {
- $this->name = $name;
- } else {
- $this->name = $this->getRepoNameFromURL($url);
- }
- if (!$this->name) {
- logger('Error creating GitRepo. No repo name found.');
- return null;
- }
-
- if (is_dir($this->path)) {
- // ignore the $url input if it exists
- // TODO: Check if the path is either empty or is a valid git repo and error if not
- $this->git->setRepository($this->path);
- // TODO: get repo metadata
- return;
- }
-
- if ($this->url) {
- // create the folder and clone the repo at url to that folder if $clone is true
- if ($clone) {
- if (mkdir($this->path, 0770, true)) {
- $this->git->setRepository($this->path);
- if (!$this->cloneRepo()) {
- // TODO: throw error
- logger('git clone failed: ' . json_encode($this->git));
- }
- } else {
- logger('git repo path could not be created: ' . json_encode($this->git));
- }
- }
- }
- }
-
- public function initRepo() {
- if(!$this->path) return false;
- try {
- return $this->git->init($this->path);
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- }
-
- public function pull() {
- try {
- $success = $this->git->pull();
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- return $success;
- }
-
- public function getRepoPath() {
- return $this->path;
- }
-
- public function setRepoPath($directory) {
- if (is_dir($directory)) {
- $this->path->$directory;
- $this->git->setRepository($directory);
- return true;
- }
- return false;
- }
-
- public function setIdentity($user_name, $user_email) {
- // setup user for commit messages
- $this->git->config->set("user.name", $user_name, ['global' => false, 'system' => false]);
- $this->git->config->set("user.email", $user_email, ['global' => false, 'system' => false]);
- }
-
- public function cloneRepo() {
- if (validate_url($this->url) && $this->isValidGitRepoURL($this->url) && is_dir($this->path)) {
- return $this->git->clone($this->url, $this->path);
- }
- }
-
- public function probeRepo() {
- $git = $this->git;
- $repo = array();
- $repo['remote'] = $git->remote();
- $repo['branches'] = $git->branch(['all' => true]);
- $repo['logs'] = $git->log(array('limit' => 50));
- return $repo;
- }
-
- // Commit changes to the repo. Default is to stage all changes and commit everything.
- public function commit($msg, $options = array()) {
- try {
- return $this->git->commit($msg, $options);
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- }
-
- public static function isValidGitRepoURL($url) {
- if (validate_url($url) && strrpos(parse_url($url, PHP_URL_PATH), '.')) {
- return true;
- } else {
- return false;
- }
- }
-
- public static function getRepoNameFromURL($url) {
- $urlpath = parse_url($url, PHP_URL_PATH);
- $lastslash = strrpos($urlpath, '/') + 1;
- $gitext = strrpos($urlpath, '.');
- if ($gitext) {
- return substr($urlpath, $lastslash, $gitext - $lastslash);
- } else {
- return null;
- }
- }
-
-}
diff --git a/Zotlabs/Thumbs/Epubthumb.php b/Zotlabs/Thumbs/Epubthumb.php
index 6ebbd8933..af372e85c 100644
--- a/Zotlabs/Thumbs/Epubthumb.php
+++ b/Zotlabs/Thumbs/Epubthumb.php
@@ -2,60 +2,197 @@
namespace Zotlabs\Thumbs;
-require_once 'library/epub-meta/epub.php';
+use DOMDocument;
+use DOMElement;
+use DOMXPath;
+use GdImage;
+use ZipArchive;
/**
- * @brief Thumbnail creation for epub files.
- *
+ * Thumbnail creation for epub files.
*/
class Epubthumb {
/**
- * @brief Match for application/epub+zip.
+ * Match for application/epub+zip.
*
* @param string $type MimeType
* @return boolean
*/
- function Match($type) {
- return(($type === 'application/epub+zip') ? true : false );
+ function Match(string $type): bool {
+ return $type === 'application/epub+zip';
}
/**
- * @brief
+ * Create the thumbnail if the Epub has a cover.
*
* @param array $attach
- * @param number $preview_style unused
- * @param number $height (optional) default 300
- * @param number $width (optional) default 300
+ * @param int $preview_style unused
+ * @param int $height (optional) default 300
+ * @param int $width (optional) default 300
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ * phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
*/
- function Thumb($attach, $preview_style, $height = 300, $width = 300) {
+ function Thumb($attach, $preview_style, $height = 300, $width = 300): void {
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
- $photo = false;
-
- $ep = new \EPub($file);
- $data = $ep->Cover();
-
- if($data['found']) {
- $photo = $data['data'];
- }
+ $image = $this->getCoverFromEpub($file);
- if($photo) {
- $image = imagecreatefromstring($photo);
- $dest = imagecreatetruecolor($width, $height);
+ if ($image) {
$srcwidth = imagesx($image);
$srcheight = imagesy($image);
+ $dest = imagecreatetruecolor($width, $height);
imagealphablending($dest, false);
imagesavealpha($dest, true);
+
imagecopyresampled($dest, $image, 0, 0, 0, 0, $width, $height, $srcwidth, $srcheight);
+
+ imagejpeg($dest, "{$file}.thumb");
+
imagedestroy($image);
- imagejpeg($dest, dbunescbin($attach['content']) . '.thumb');
+ imagedestroy($dest);
}
}
+
+ /**
+ * Fetch the cover from the epub archive, if it's present.
+ *
+ * There's a few limitations here: This will only work if the cover
+ * is a raster image of a supported format. SVG does not work, neither
+ * will other schemes sometimes used for cover/front page.
+ *
+ * @param string $filename The local filename of the epub archive.
+ *
+ * @return GdImage|false If a cover is found, it is returned as a
+ * GdImage object. Otherwise return false.
+ */
+ private function getCoverFromEpub(string $filename): GdImage|false {
+ $epub = new ZipArchive();
+ $rc = $epub->open($filename, ZipArchive::RDONLY);
+
+ if ($rc !== true) {
+ logger("Error opening file '{$filename}': rc = ${rc}.", LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $cover = false;
+ $cover_name = $this->parseEpub($epub);
+ if ($cover_name !== false) {
+ $cover = $epub->getFromName($cover_name);
+ if ($cover === false) {
+ logger("File '{$cover_name}' not found in EPUB.", LOGGER_DEBUG, LOG_DEBUG);
+ }
+ }
+
+ $epub->close();
+
+ if ($cover !== false && !empty($cover)) {
+ return imagecreatefromstring($cover);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Parse the epub to find the path of the cover image.
+ *
+ * @param ZipArchive $epub An opened epub ZipArchive.
+ *
+ * @return string|false The path to the cover image or false.
+ */
+ private function parseEpub(ZipArchive $epub): string|false {
+ $packagePath = $this->getEpubPackagePath($epub);
+ if ($packagePath !== false) {
+ $package = $epub->getFromName($packagePath);
+ if ($package === false || empty($package)) {
+ logger("Package file '${packagePath}' not found in EPUB", LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $domdoc = new DOMDocument();
+ $domdoc->loadXML($package);
+ $xpath = new DOMXPath($domdoc);
+ $xpath->registerNamespace("n", "http://www.idpf.org/2007/opf");
+ $nodes = $xpath->query('/n:package/n:manifest/n:item[@properties="cover-image"]');
+
+ if ($nodes->count() === 0) {
+ logger('No cover found in EPUB manifest.', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $node = $nodes->item(0);
+ if ($node === null) {
+ logger('No nodes in non-empty node list?', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ if (is_a($node, DOMElement::class)) {
+ // The URL's in the package file is relative to the subdirectory
+ // within the epub archive where it is located. See
+ // https://www.w3.org/TR/epub-33/#sec-parsing-urls-metainf
+ return dirname($packagePath) . '/' . $node->getAttribute('href');
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Locate the package file within the epub.
+ *
+ * The package file in an epub archive contains the manifest
+ * that again may contain a reference to the cover for the
+ * epub.
+ *
+ * @param ZipArchive $epub An opened epub archive.
+ *
+ * @return string|false The full pathname of the package file or false.
+ */
+ private function getEpubPackagePath(ZipArchive $epub): string|false {
+ //
+ // The only mandatory known file within the archive is the
+ // container file, so we fetch it to find the reference to
+ // the package file.
+ //
+ // See: https://www.w3.org/TR/epub-33/#sec-container-metainf
+ //
+ $container = $epub->getFromName('META-INF/container.xml');
+
+ if ($container === false || empty($container)) {
+ logger('No container in archive, probably not an EPUB.', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $domdoc = new DOMDocument();
+ $domdoc->loadXML($container);
+ $nodes = $domdoc->getElementsByTagName('rootfile');
+
+ if ($nodes->count() == 0) {
+ logger('EPUB rootfile not found, is this an epub?', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $packageNode = $nodes->item(0);
+ if ($packageNode === null || !is_a($packageNode, DOMElement::class)) {
+ logger('EPUB rootfile element missing or invalid.', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ $packagePath = $packageNode->getAttribute('full-path');
+ $packageMediaType = $packageNode->getAttribute('media-type');
+
+ if (empty($packagePath) || $packageMediaType !== 'application/oebps-package+xml') {
+ logger('EPUB package path missing or incorrect media type.', LOGGER_DEBUG, LOG_DEBUG);
+ return false;
+ }
+
+ return $packagePath;
+ }
}
diff --git a/Zotlabs/Update/_1007.php b/Zotlabs/Update/_1007.php
index eb52c5bc5..74e1bb310 100644
--- a/Zotlabs/Update/_1007.php
+++ b/Zotlabs/Update/_1007.php
@@ -6,10 +6,10 @@ class _1007 {
function run() {
$r = q("ALTER TABLE `channel` ADD `channel_r_storage` INT UNSIGNED NOT NULL DEFAULT '128', ADD `channel_w_storage` INT UNSIGNED NOT NULL DEFAULT '128', add index ( channel_r_storage ), add index ( channel_w_storage )");
- if($r && $r2)
+ if($r)
return UPDATE_SUCCESS;
return UPDATE_FAILED;
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Update/_1151.php b/Zotlabs/Update/_1151.php
index d14baabb1..20f3180a0 100644
--- a/Zotlabs/Update/_1151.php
+++ b/Zotlabs/Update/_1151.php
@@ -8,7 +8,7 @@ function run() {
$r3 = q("select likes.*, item.mid from likes left join item on likes.iid = item.id");
if($r3) {
foreach($r3 as $rr) {
- q("update likes set i_mid = '%s' where id = $d",
+ q("update likes set i_mid = '%s' where id = %d",
dbesc($rr['mid']),
intval($rr['id'])
);
@@ -21,4 +21,4 @@ function run() {
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Web/HttpMeta.php b/Zotlabs/Web/HttpMeta.php
index 7cf93dda9..d12037a51 100644
--- a/Zotlabs/Web/HttpMeta.php
+++ b/Zotlabs/Web/HttpMeta.php
@@ -5,16 +5,9 @@ namespace Zotlabs\Web;
class HttpMeta {
- private $vars = null;
- private $og = null;
-
- function __construct() {
-
- $this->vars = [];
- $this->og = [];
- $this->ogproperties = [];
-
- }
+ private $vars = [];
+ private $og = [];
+ private $ogproperties = [];
//Set Meta Value
// Mode:
diff --git a/Zotlabs/Web/WebServer.php b/Zotlabs/Web/WebServer.php
index 6f8a4b956..d59effc88 100644
--- a/Zotlabs/Web/WebServer.php
+++ b/Zotlabs/Web/WebServer.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Web;
+use Zotlabs\Lib\Text;
+
class WebServer {
public function run() {
@@ -59,8 +61,8 @@ class WebServer {
if (x($_GET,'zid') && $installed) {
\App::$query_string = strip_zids(\App::$query_string);
if(! local_channel()) {
- if (!isset($_SESSION['my_address']) || $_SESSION['my_address'] != $_GET['zid']) {
- $_SESSION['my_address'] = $_GET['zid'];
+ if (!isset($_SESSION['my_address'])) {
+ $_SESSION['my_address'] = Text::escape_tags($_GET['zid']);
$_SESSION['authenticated'] = 0;
}
if(!$_SESSION['authenticated']) {
diff --git a/Zotlabs/Widget/Activity.php b/Zotlabs/Widget/Activity.php
index 34e0f67dc..19f7acadb 100644
--- a/Zotlabs/Widget/Activity.php
+++ b/Zotlabs/Widget/Activity.php
@@ -17,7 +17,7 @@ class Activity {
$o = '';
if(is_array($arr) && array_key_exists('limit',$arr))
- $limit = " limit " . intval($limit) . " ";
+ $limit = " limit " . intval($arr['limit']) . " ";
else
$limit = '';
diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php
index a8a00bda6..6884963d4 100644
--- a/Zotlabs/Widget/Activity_filter.php
+++ b/Zotlabs/Widget/Activity_filter.php
@@ -42,7 +42,7 @@ class Activity_filter {
$tabs[] = [
'label' => t('Direct Messages'),
- 'icon' => 'envelope-o',
+ 'icon' => 'envelope',
'url' => z_root() . '/' . $cmd . '/?f=&dm=1',
'sel' => $dm_active,
'title' => t('Show direct (private) messages')
@@ -51,7 +51,7 @@ class Activity_filter {
if(feature_enabled(local_channel(),'events_tab')) {
$tabs[] = [
'label' => t('Events'),
- 'icon' => 'calendar',
+ 'icon' => 'calendar-date',
'url' => z_root() . '/' . $cmd . '/?verb=%2EEvent',
'sel' => $events_active,
'title' => t('Show posts that include events')
@@ -93,7 +93,7 @@ class Activity_filter {
$tabs[] = [
'id' => 'privacy_groups',
'label' => t('Privacy Groups'),
- 'icon' => 'users',
+ 'icon' => 'person',
'url' => '#',
'sel' => (($filter_active == 'group') ? true : false),
'title' => t('Show my privacy groups'),
@@ -128,7 +128,7 @@ class Activity_filter {
$tabs[] = [
'id' => 'forums',
'label' => t('Forums'),
- 'icon' => 'comments-o',
+ 'icon' => 'chat-quote',
'url' => '#',
'sel' => (($filter_active == 'forums') ? true : false),
'title' => t('Show forums'),
@@ -161,7 +161,7 @@ class Activity_filter {
$tabs[] = [
'label' => t('Personal Posts'),
- 'icon' => 'user-circle',
+ 'icon' => 'person-circle',
'url' => z_root() . '/' . $cmd . '/?f=&conv=1',
'sel' => $conv_active,
'title' => t('Show posts that mention or involve me')
@@ -233,7 +233,7 @@ class Activity_filter {
if($filter_active) {
$reset = [
'label' => '',
- 'icon' => 'remove',
+ 'icon' => 'x-lg',
'url'=> z_root() . '/' . $cmd,
'sel'=> '',
'title' => t('Remove active filter')
diff --git a/Zotlabs/Widget/Album.php b/Zotlabs/Widget/Album.php
index 003f6f49d..f1fa69182 100644
--- a/Zotlabs/Widget/Album.php
+++ b/Zotlabs/Widget/Album.php
@@ -94,7 +94,7 @@ class Album {
$tpl = get_markup_template('photo_album.tpl');
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$photos' => $photos,
'$album' => (($title) ? $title : $album),
'$album_id' => rand(),
@@ -102,11 +102,9 @@ class Album {
'$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
'$order' => false,
- '$upload_form' => $upload_form,
- '$usage' => $usage_message
+ '$upload_form' => '', // $upload_form,
+ '$usage' => '', // $usage_message
));
-
- return $o;
}
}
diff --git a/Zotlabs/Widget/Channel_activities.php b/Zotlabs/Widget/Channel_activities.php
index a799ea81e..debaf20d4 100644
--- a/Zotlabs/Widget/Channel_activities.php
+++ b/Zotlabs/Widget/Channel_activities.php
@@ -91,7 +91,7 @@ class Channel_activities {
self::$activities['photos'] = [
'label' => t('Photos'),
- 'icon' => 'photo',
+ 'icon' => 'image',
'url' => z_root() . '/photos/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -123,7 +123,7 @@ class Channel_activities {
self::$activities['files'] = [
'label' => t('Files'),
- 'icon' => 'folder-open',
+ 'icon' => 'folder',
'url' => z_root() . '/cloud/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -166,7 +166,7 @@ class Channel_activities {
self::$activities['webpages'] = [
'label' => t('Webpages'),
- 'icon' => 'newspaper-o',
+ 'icon' => 'layout-text-sidebar',
'url' => z_root() . '/webpages/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -237,7 +237,7 @@ class Channel_activities {
self::$activities['channels'] = [
'label' => t('Channels'),
- 'icon' => 'home',
+ 'icon' => 'house',
'url' => z_root() . '/manage',
'date' => datetime_convert(),
'items' => $i,
diff --git a/Zotlabs/Widget/Helpindex.php b/Zotlabs/Widget/Helpindex.php
index 5264e1947..fd9204c9e 100644
--- a/Zotlabs/Widget/Helpindex.php
+++ b/Zotlabs/Widget/Helpindex.php
@@ -22,7 +22,9 @@ class Helpindex {
$this->find_help_file('toc', $this->lang['language']);
if (! empty($this->file_name)) {
- $this->contents = file_get_contents($this->file_name);
+ $this->contents = translate_projectname(
+ file_get_contents($this->file_name)
+ );
}
$tpl = get_markup_template('widget.tpl');
diff --git a/Zotlabs/Widget/Hq_controls.php b/Zotlabs/Widget/Hq_controls.php
index 51212d145..0db492c37 100644
--- a/Zotlabs/Widget/Hq_controls.php
+++ b/Zotlabs/Widget/Hq_controls.php
@@ -34,7 +34,7 @@ class Hq_controls {
'href' => '#',
'class' => 'btn notes-toggle',
'type' => 'button',
- 'icon' => 'sticky-note-o',
+ 'icon' => 'sticky',
'extra' => 'data-toggle="button"'
];
}
@@ -44,7 +44,7 @@ class Hq_controls {
'href' => '#',
'class' => 'btn channel-activities-toggle d-none',
'type' => 'button',
- 'icon' => 'user-circle-o',
+ 'icon' => 'person-circle',
'extra' => 'data-toggle="button"'
];
diff --git a/Zotlabs/Widget/Item.php b/Zotlabs/Widget/Item.php
index 6f943ffdf..3de135cb9 100644
--- a/Zotlabs/Widget/Item.php
+++ b/Zotlabs/Widget/Item.php
@@ -34,7 +34,7 @@ class Item {
if($arr['title']) {
$r = q("select item.* from item left join iconfig on item.id = iconfig.iid
where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s'
- and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra $revision limit 1",
+ and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra limit 1",
intval($channel_id),
dbesc($arr['title']),
intval(ITEM_TYPE_WEBPAGE)
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
index 8654d8e8f..f90b4f99e 100644
--- a/Zotlabs/Widget/Messages.php
+++ b/Zotlabs/Widget/Messages.php
@@ -23,20 +23,35 @@ class Messages {
$_SESSION['messages_loadtime'] = datetime_convert();
+ $r = q("SELECT DISTINCT(term) FROM term WHERE uid = %d AND ttype = %d ORDER BY term",
+ intval(local_channel()),
+ intval(TERM_FILE)
+ );
+
+ if ($r) {
+ foreach($r as $rr) {
+ $file_tags[] = $rr['term'];
+ }
+ }
+
$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'),
+ '$feature_file' => feature_enabled(local_channel(), 'filing'),
+ '$file_tags' => $file_tags,
'$strings' => [
'messages_title' => t('Public and restricted messages'),
'direct_messages_title' => t('Direct messages'),
'starred_messages_title' => t('Starred messages'),
+ 'filed_messages_title' => t('Filed messages'),
'notice_messages_title' => t('Notices'),
'loading' => t('Loading'),
'empty' => t('No messages'),
'unseen_count' => t('Unseen'),
- 'filter' => t('Filter by name or address')
+ 'filter' => t('Filter by name or address'),
+ 'file_filter' => t('Filter by file name')
]
]);
@@ -50,6 +65,7 @@ class Messages {
$offset = $options['offset'] ?? 0;
$type = $options['type'] ?? '';
$author = $options['author'] ?? '';
+ $file = $options['file'] ?? '';
if ($offset == -1) {
return;
@@ -67,8 +83,9 @@ class Messages {
$item_normal_c = str_replace('item.', 'c.', $item_normal);
$entries = [];
$limit = 30;
+ $order_sql = 'i.created DESC';
$dummy_order_sql = '';
- $author_sql = '';
+ $filter_sql = '';
$loadtime = (($offset) ? $_SESSION['messages_loadtime'] : datetime_convert());
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify', -1);
@@ -84,43 +101,55 @@ class Messages {
$vnotify_sql_i = " AND i.verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
- if($author) {
- $author_sql = " AND (i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "') ";
+ if($type !== 'filed' && $author) {
+ $filter_sql = " AND (i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "') ";
+ }
+
+ if($type === 'filed' && $file) {
+ $filed_filter_sql = " AND (term.term = '" . protect_sprintf(dbesc($file)) . "') ";
}
switch($type) {
case 'direct':
- $type_sql = ' AND i.item_private = 2 ';
+ $type_sql = ' AND i.item_private = 2 AND i.item_thread_top = 1 ';
// $dummy_order_sql has no other meaning but to trick
// some mysql backends into using the right index.
$dummy_order_sql = ', i.received DESC ';
break;
case 'starred':
- $type_sql = ' AND i.item_starred = 1 ';
+ $type_sql = ' AND i.item_starred = 1 AND i.item_thread_top = 1 ';
+ break;
+ case 'filed':
+ $type_sql = ' AND i.id IN (SELECT term.oid FROM term WHERE term.ttype = ' . TERM_FILE . ' AND term.uid = i.uid ' . $filed_filter_sql . ')';
break;
default:
- $type_sql = ' AND i.item_private IN (0, 1) ';
+ $type_sql = ' AND i.item_private IN (0, 1) AND i.item_thread_top = 1 ';
}
$items = q("SELECT *,
(SELECT count(*) FROM item c WHERE c.uid = %d AND c.parent = i.parent AND c.item_unseen = 1 AND c.item_thread_top = 0 $item_normal_c $vnotify_sql_c) AS unseen_count
- FROM item i WHERE i.uid = %d
+ FROM item i
+ WHERE i.uid = %d
AND i.created <= '%s'
$type_sql
- AND i.item_thread_top = 1
- $author_sql
+ $filter_sql
$item_normal_i
- ORDER BY i.created DESC $dummy_order_sql
+ ORDER BY $order_sql $dummy_order_sql
LIMIT $limit OFFSET $offset",
intval(local_channel()),
intval(local_channel()),
dbescdate($loadtime)
);
+ if ($type === 'filed') {
+ $items = fetch_post_tags($items);
+ }
+
xchan_query($items, false);
$i = 0;
$entries = [];
+ $ids = [];
foreach($items as $item) {
@@ -149,6 +178,16 @@ class Messages {
$info .= t('via') . ' ' . $item['source']['xchan_name'];
}
+ if ($type == 'filed') {
+ $info = '';
+ foreach ($item['term'] as $t) {
+ if ($t['ttype'] !== TERM_FILE) {
+ continue;
+ }
+ $info .= '<span class="badge rounded-pill bg-danger me-1"><i class="bi bi-folder"></i>&nbsp;' . $t['term'] . '</span>';
+ }
+ }
+
$summary = $item['title'];
if (!$summary) {
$summary = $item['summary'];
@@ -170,10 +209,10 @@ class Messages {
switch(intval($item['item_private'])) {
case 1:
- $icon = '<i class="fa fa-lock"></i>';
+ $icon = '<i class="bi bi-lock"></i>';
break;
case 2:
- $icon = '<i class="fa fa-envelope-o"></i>';
+ $icon = '<i class="bi bi-envelope"></i>';
break;
default:
$icon = '';
@@ -293,7 +332,7 @@ class Messages {
$entries[$i]['summary'] = $summary;
$entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
$entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
- $entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="fa fa-user-plus"></i>' : '');
+ $entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="bi bi-person-plus"></i>' : '');
$i++;
}
diff --git a/Zotlabs/Widget/Notes.php b/Zotlabs/Widget/Notes.php
index 836159edd..be4ec64a6 100644
--- a/Zotlabs/Widget/Notes.php
+++ b/Zotlabs/Widget/Notes.php
@@ -16,14 +16,17 @@ use Zotlabs\Lib\Apps;
class Notes {
function widget($arr) {
- if(! local_channel())
+ if(!local_channel()) {
return EMPTY_STR;
+ }
- if(App::$profile_uid !== local_channel())
+ if (App::$profile_uid !== local_channel()) {
return EMPTY_STR;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Notes'))
+ if(!Apps::system_app_installed(local_channel(), 'Notes')) {
return EMPTY_STR;
+ }
$text = get_pconfig(local_channel(),'notes','text');
diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php
index b16303be6..225403535 100644
--- a/Zotlabs/Widget/Notifications.php
+++ b/Zotlabs/Widget/Notifications.php
@@ -18,7 +18,7 @@ class Notifications {
if(local_channel()) {
$notifications[] = [
'type' => 'network',
- 'icon' => 'th',
+ 'icon' => 'grid-3x3',
'severity' => 'secondary',
'label' => t('Network'),
'title' => t('New network activity notifications'),
@@ -38,7 +38,7 @@ class Notifications {
$notifications[] = [
'type' => 'home',
- 'icon' => 'home',
+ 'icon' => 'house',
'severity' => 'danger',
'label' => t('Home'),
'title' => t('New home activity notifications'),
@@ -76,7 +76,7 @@ class Notifications {
$notifications[] = [
'type' => 'all_events',
- 'icon' => 'calendar',
+ 'icon' => 'calendar-date',
'severity' => 'secondary',
'label' => t('Events'),
'title' => t('New events notifications'),
@@ -91,7 +91,7 @@ class Notifications {
$notifications[] = [
'type' => 'intros',
- 'icon' => 'users',
+ 'icon' => 'people',
'severity' => 'danger',
'label' => t('New Connections'),
'title' => t('New connections notifications'),
@@ -111,7 +111,7 @@ class Notifications {
$notifications[] = [
'type' => 'notify',
- 'icon' => 'exclamation',
+ 'icon' => 'exclamation-circle',
'severity' => 'danger',
'label' => t('Notices'),
'title' => t('Notices'),
@@ -126,7 +126,7 @@ class Notifications {
$notifications[] = [
'type' => 'forums',
- 'icon' => 'comments-o',
+ 'icon' => 'chat-quote',
'severity' => 'secondary',
'label' => t('Forums'),
'title' => t('Forums'),
@@ -139,7 +139,7 @@ class Notifications {
if(local_channel() && is_site_admin()) {
$notifications[] = [
'type' => 'register',
- 'icon' => 'user-o',
+ 'icon' => 'person-exclamation',
'severity' => 'danger',
'label' => t('Registrations'),
'title' => t('New registrations notifications'),
@@ -173,6 +173,8 @@ class Notifications {
'$notifications' => $notifications,
'$no_notifications' => t('Sorry, you have got no notifications at the moment'),
'$loading' => t('Loading'),
+ '$sys_only' => empty($arr['sys_only']) ? 0 : 1
+
]);
return $o;
diff --git a/Zotlabs/Widget/Permcats.php b/Zotlabs/Widget/Permcats.php
index 9bda5b8f1..f0e43b937 100644
--- a/Zotlabs/Widget/Permcats.php
+++ b/Zotlabs/Widget/Permcats.php
@@ -40,7 +40,7 @@ class Permcats {
if($active_role) {
$roles[] = [
- 'name' => '<i class="fa fa-plus"></i>&nbsp;' . t('Add new role'),
+ 'name' => '<i class="bi bi-plus-lg"></i>&nbsp;' . t('Add new role'),
'url' => z_root() . '/permcats',
'active' => ''
];
diff --git a/Zotlabs/Widget/Pinned.php b/Zotlabs/Widget/Pinned.php
index 2ba170fe8..be6b98434 100644
--- a/Zotlabs/Widget/Pinned.php
+++ b/Zotlabs/Widget/Pinned.php
@@ -112,8 +112,7 @@ class Pinned {
'mids' => json_encode([ $midb64 ]),
'isevent' => $isevent,
'attend' => $attend,
- 'consensus' => $consensus,
- 'conlabels' => ($canvote ? $conlabels : []),
+ 'conlabels' => [],
'canvote' => $canvote,
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, ($author['xchan_addr'] ? $author['xchan_addr'] : $author['xchan_url']) ),
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $owner['xchan_name'], ($owner['xchan_addr'] ? $owner['xchan_addr'] : $owner['xchan_url']) ),
diff --git a/Zotlabs/Widget/Portfolio.php b/Zotlabs/Widget/Portfolio.php
index a06f56e30..bde1c7d6a 100644
--- a/Zotlabs/Widget/Portfolio.php
+++ b/Zotlabs/Widget/Portfolio.php
@@ -103,7 +103,7 @@ class Portfolio {
$tpl = get_markup_template('photo_album_portfolio.tpl');
- $o .= replace_macros($tpl, array(
+ return replace_macros($tpl, array(
'$photos' => $photos,
'$mode' => $mode,
'$count' => $count,
@@ -113,11 +113,7 @@ class Portfolio {
'$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
'$order' => false,
- '$upload_form' => $upload_form,
- '$usage' => $usage_message
));
-
- return $o;
}
}
diff --git a/Zotlabs/Widget/Privacygroups.php b/Zotlabs/Widget/Privacygroups.php
index 62f343ea6..129c939fd 100644
--- a/Zotlabs/Widget/Privacygroups.php
+++ b/Zotlabs/Widget/Privacygroups.php
@@ -42,7 +42,7 @@ class Privacygroups {
if ($active) {
$menu_items[] = [
'href' => $z_root . '/group',
- 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new group'),
+ 'label' => '<i class="bi bi-plus-lg"></i> &nbsp;' . t('Add new group'),
'title' => '',
'active' => '',
'count' => ''
diff --git a/Zotlabs/Widget/Rating.php b/Zotlabs/Widget/Rating.php
index f8986ac93..a90052411 100644
--- a/Zotlabs/Widget/Rating.php
+++ b/Zotlabs/Widget/Rating.php
@@ -60,12 +60,12 @@ class Rating {
if((($remote) || (local_channel())) && (! $self)) {
if($remote)
- $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</a>';
+ $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="bi bi-pencil"></i> ' . t('Rate Me') . '</a>';
else
- $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</div>';
+ $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="bi bi-pencil"></i> ' . t('Rate Me') . '</div>';
}
- $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="fa fa-eye"></i> ' . t('View Ratings') . '</a>';
+ $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="bi bi-eye"></i> ' . t('View Ratings') . '</a>';
$o .= '</div>';
return $o;
diff --git a/Zotlabs/Widget/Tagcloud.php b/Zotlabs/Widget/Tagcloud.php
index 00456f24f..efd571576 100644
--- a/Zotlabs/Widget/Tagcloud.php
+++ b/Zotlabs/Widget/Tagcloud.php
@@ -18,8 +18,7 @@ class Tagcloud {
$flags = 0;
$type = TERM_HASHTAG;
- // @FIXME there exists no $authors variable
- $r = tagadelic($uid, $count, $authors, $owner, $flags, 0, $type);
+ $r = tagadelic($uid, $count, '', '', $flags, 0, $type);
// @FIXME this should use a template
diff --git a/Zotlabs/Widget/Tasklist.php b/Zotlabs/Widget/Tasklist.php
index 96b70af15..9271269cf 100644
--- a/Zotlabs/Widget/Tasklist.php
+++ b/Zotlabs/Widget/Tasklist.php
@@ -19,7 +19,7 @@ class Tasklist {
if(App::$profile_uid !== local_channel())
return EMPTY_STR;
- $o .= '<script>var tasksShowAll = 0; $(document).ready(function() { tasksFetch(); $("#tasklist-new-form").submit(function(event) { event.preventDefault(); $.post( "tasks/new", $("#tasklist-new-form").serialize(), function(data) { tasksFetch(); $("#tasklist-new-summary").val(""); } ); return false; } )});</script>';
+ $o = '<script>var tasksShowAll = 0; $(document).ready(function() { tasksFetch(); $("#tasklist-new-form").submit(function(event) { event.preventDefault(); $.post( "tasks/new", $("#tasklist-new-form").serialize(), function(data) { tasksFetch(); $("#tasklist-new-summary").val(""); } ); return false; } )});</script>';
$o .= '<script>function taskComplete(id) { $.post("tasks/complete/"+id, function(data) { tasksFetch();}); }
function tasksFetch() {
$.get("tasks/fetch" + ((tasksShowAll) ? "/all" : ""), function(data) {
diff --git a/Zotlabs/Widget/Tokens.php b/Zotlabs/Widget/Tokens.php
index 69452d628..08fe67680 100644
--- a/Zotlabs/Widget/Tokens.php
+++ b/Zotlabs/Widget/Tokens.php
@@ -38,7 +38,7 @@ class Tokens {
if ($active) {
$menu_items[] = [
'href' => $z_root . '/tokens',
- 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new guest'),
+ 'label' => '<i class="bi bi-plus-lg"></i> &nbsp;' . t('Add new guest'),
'title' => '',
'active' => ''
];
diff --git a/Zotlabs/Zot6/Zot6Handler.php b/Zotlabs/Zot6/Zot6Handler.php
index 053901205..2ef9e3b8d 100644
--- a/Zotlabs/Zot6/Zot6Handler.php
+++ b/Zotlabs/Zot6/Zot6Handler.php
@@ -34,11 +34,13 @@ class Zot6Handler implements IHandler {
logger('notify received from ' . $hub['hubloc_url']);
- $x = Libzot::fetch($data, $hub);
- $ret['delivery_report'] = $x;
+ $x = Libzot::fetch($data);
+ if ($x) {
+ $ret['delivery_report'] = $x;
+ $ret['success'] = true;
+ }
- $ret['success'] = true;
return $ret;
}