aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
authorManuel Jiménez Friaza <mjfriaza@openmailbox.org>2019-05-19 13:25:00 +0200
committerManuel Jiménez Friaza <mjfriaza@openmailbox.org>2019-05-19 13:25:00 +0200
commit429140df97a2c273fba6974147ac2e48e7688263 (patch)
tree2e337542da1b0f4c9c383dfeb8a7d9eb63990a72 /Zotlabs
parentf92d2e3f7c6573bd7bab04223c7e28662605c6d8 (diff)
parentaf2b263bc74b16601ec7c123a58f0549613aed27 (diff)
downloadvolse-hubzilla-429140df97a2c273fba6974147ac2e48e7688263.tar.gz
volse-hubzilla-429140df97a2c273fba6974147ac2e48e7688263.tar.bz2
volse-hubzilla-429140df97a2c273fba6974147ac2e48e7688263.zip
Merge remote-tracking branch 'upstream/dev' into dev
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Daemon/Cron_daily.php1
-rw-r--r--Zotlabs/Daemon/Notifier.php8
-rw-r--r--Zotlabs/Daemon/Poller.php1
-rw-r--r--Zotlabs/Lib/Activity.php111
-rw-r--r--Zotlabs/Lib/ActivityStreams.php5
-rw-r--r--Zotlabs/Lib/Api_router.php10
-rw-r--r--Zotlabs/Lib/Apps.php7
-rw-r--r--Zotlabs/Lib/DB_Upgrade.php9
-rw-r--r--Zotlabs/Lib/DReport.php2
-rw-r--r--Zotlabs/Lib/Enotify.php24
-rw-r--r--Zotlabs/Lib/Libsync.php2
-rw-r--r--Zotlabs/Lib/Libzot.php102
-rw-r--r--Zotlabs/Lib/Libzotdir.php4
-rw-r--r--Zotlabs/Lib/MessageFilter.php16
-rw-r--r--Zotlabs/Lib/ThreadItem.php26
-rw-r--r--Zotlabs/Lib/ZotURL.php2
-rw-r--r--Zotlabs/Module/Acl.php2
-rw-r--r--Zotlabs/Module/Admin/Dbsync.php45
-rw-r--r--Zotlabs/Module/Apschema.php56
-rw-r--r--Zotlabs/Module/Cdav.php217
-rw-r--r--Zotlabs/Module/Changeaddr.php4
-rw-r--r--Zotlabs/Module/Channel.php22
-rw-r--r--Zotlabs/Module/Channel_calendar.php480
-rw-r--r--Zotlabs/Module/Connections.php20
-rw-r--r--Zotlabs/Module/Connedit.php2
-rw-r--r--Zotlabs/Module/Cover_photo.php75
-rw-r--r--Zotlabs/Module/Directory.php40
-rw-r--r--Zotlabs/Module/Dirsearch.php8
-rw-r--r--Zotlabs/Module/Display.php7
-rw-r--r--Zotlabs/Module/Dreport.php14
-rw-r--r--Zotlabs/Module/Editpost.php3
-rw-r--r--Zotlabs/Module/Embedphotos.php48
-rw-r--r--Zotlabs/Module/Getfile.php13
-rw-r--r--Zotlabs/Module/Hq.php2
-rw-r--r--Zotlabs/Module/Import.php86
-rw-r--r--Zotlabs/Module/Item.php79
-rw-r--r--Zotlabs/Module/Like.php6
-rw-r--r--Zotlabs/Module/Linkinfo.php45
-rw-r--r--Zotlabs/Module/Magic.php4
-rw-r--r--Zotlabs/Module/Network.php18
-rw-r--r--Zotlabs/Module/Oep.php2
-rw-r--r--Zotlabs/Module/Owa.php26
-rw-r--r--Zotlabs/Module/Photo.php116
-rw-r--r--Zotlabs/Module/Photos.php116
-rw-r--r--Zotlabs/Module/Ping.php2
-rw-r--r--Zotlabs/Module/Poster.php37
-rw-r--r--Zotlabs/Module/Profile_photo.php90
-rw-r--r--Zotlabs/Module/Pubstream.php6
-rw-r--r--Zotlabs/Module/React.php8
-rw-r--r--Zotlabs/Module/Register.php12
-rw-r--r--Zotlabs/Module/Settings/Calendar.php2
-rw-r--r--Zotlabs/Module/Setup.php69
-rw-r--r--Zotlabs/Module/Subthread.php2
-rw-r--r--Zotlabs/Module/Tagger.php2
-rw-r--r--Zotlabs/Module/Viewconnections.php2
-rw-r--r--Zotlabs/Module/Viewsrc.php2
-rw-r--r--Zotlabs/Module/Wall_attach.php21
-rw-r--r--Zotlabs/Module/Wfinger.php2
-rw-r--r--Zotlabs/Module/Wiki.php8
-rw-r--r--Zotlabs/Photo/PhotoDriver.php40
-rwxr-xr-xZotlabs/Render/SmartyInterface.php16
-rwxr-xr-xZotlabs/Render/SmartyTemplate.php65
-rw-r--r--Zotlabs/Update/_1231.php73
-rw-r--r--Zotlabs/Update/_1232.php47
-rw-r--r--Zotlabs/Update/_1233.php38
-rw-r--r--Zotlabs/Update/_1234.php26
-rw-r--r--Zotlabs/Widget/Cdav.php23
-rw-r--r--Zotlabs/Widget/Suggestions.php6
-rw-r--r--Zotlabs/Zot6/HTTPSig.php3
-rw-r--r--Zotlabs/Zot6/Zot6Handler.php3
70 files changed, 1933 insertions, 558 deletions
diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php
index f0351fcdd..dbfcff439 100644
--- a/Zotlabs/Daemon/Cron_daily.php
+++ b/Zotlabs/Daemon/Cron_daily.php
@@ -85,6 +85,7 @@ class Cron_daily {
Master::Summon(array('Cli_suggest'));
remove_obsolete_hublocs();
+ z6_discover();
call_hooks('cron_daily',datetime_convert());
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index df73d977d..15dc08908 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -412,6 +412,12 @@ class Notifier {
$private = false;
$recipients = collect_recipients($parent_item,$private);
+
+ if ($top_level_post) {
+ // remove clones who will receive the post via sync
+ $recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]);
+ }
+
// FIXME add any additional recipients such as mentions, etc.
// don't send deletions onward for other people's stuff
@@ -446,7 +452,7 @@ class Notifier {
$env_recips = (($private) ? array() : null);
- $details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
+ $details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
$recip_list = array();
diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php
index a8cf34ce2..84bf7e923 100644
--- a/Zotlabs/Daemon/Poller.php
+++ b/Zotlabs/Daemon/Poller.php
@@ -199,6 +199,7 @@ class Poller {
set_config('system','lastpoll',datetime_convert());
//All done - clear the lockfile
+
@unlink($lockfile);
return;
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 9aaf6d866..232d845c7 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -2,6 +2,7 @@
namespace Zotlabs\Lib;
+use Zotlabs\Daemon\Master;
use Zotlabs\Zot6\HTTPSig;
class Activity {
@@ -13,27 +14,30 @@ class Activity {
$x = json_decode($x,true);
}
- if(is_array($x) && array_key_exists('asld',$x)) {
- $x = $x['asld'];
- }
+ if(is_array($x)) {
- if($x['type'] === ACTIVITY_OBJ_PERSON) {
- return self::fetch_person($x);
- }
- if($x['type'] === ACTIVITY_OBJ_PROFILE) {
- return self::fetch_profile($x);
- }
- if(in_array($x['type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_ARTICLE ] )) {
- return self::fetch_item($x);
- }
- if($x['type'] === ACTIVITY_OBJ_THING) {
- return self::fetch_thing($x);
- }
- if($x['type'] === ACTIVITY_OBJ_EVENT) {
- return self::fetch_event($x);
- }
- if($x['type'] === ACTIVITY_OBJ_PHOTO) {
- return self::fetch_image($x);
+ if(array_key_exists('asld',$x)) {
+ return $x['asld'];
+ }
+
+ if($x['type'] === ACTIVITY_OBJ_PERSON) {
+ return self::fetch_person($x);
+ }
+ if($x['type'] === ACTIVITY_OBJ_PROFILE) {
+ return self::fetch_profile($x);
+ }
+ if(in_array($x['type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_ARTICLE ] )) {
+ return self::fetch_item($x);
+ }
+ if($x['type'] === ACTIVITY_OBJ_THING) {
+ return self::fetch_thing($x);
+ }
+ if($x['type'] === ACTIVITY_OBJ_EVENT) {
+ return self::fetch_event($x);
+ }
+ if($x['type'] === ACTIVITY_OBJ_PHOTO) {
+ return self::fetch_image($x);
+ }
}
return $x;
@@ -150,7 +154,7 @@ class Activity {
'type' => 'Image',
'id' => $x['id'],
'name' => $x['title'],
- 'content' => bbcode($x['body']),
+ 'content' => bbcode($x['body'], [ 'cache' => true ]),
'source' => [ 'mediaType' => 'text/bbcode', 'content' => $x['body'] ],
'published' => datetime_convert('UTC','UTC',$x['created'],ATOM_TIME),
'updated' => datetime_convert('UTC','UTC', $x['edited'],ATOM_TIME),
@@ -180,14 +184,24 @@ class Activity {
$y = [
'type' => 'Event',
'id' => z_root() . '/event/' . $ev['event_hash'],
- 'summary' => bbcode($ev['summary']),
+ 'summary' => bbcode($ev['summary'], [ 'cache' => true ]),
// RFC3339 Section 4.3
'startTime' => (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtstart'],'Y-m-d\\TH:i:s-00:00')),
- 'content' => bbcode($ev['description']),
- 'location' => [ 'type' => 'Place', 'content' => bbcode($ev['location']) ],
+ 'content' => bbcode($ev['description'], [ 'cache' => true ]),
+ 'location' => [ 'type' => 'Place', 'content' => bbcode($ev['location'], [ 'cache' => true ]) ],
'source' => [ 'content' => format_event_bbcode($ev), 'mediaType' => 'text/bbcode' ],
'actor' => $actor,
];
+ if(! $ev['nofinish']) {
+ $y['endTime'] = (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtend'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtend'],'Y-m-d\\TH:i:s-00:00'));
+ }
+
+ // copy attachments from the passed object - these are already formatted for ActivityStreams
+
+ if($x['attachment']) {
+ $y['attachment'] = $x['attachment'];
+ }
+
if($actor) {
return $y;
}
@@ -296,15 +310,15 @@ class Activity {
$ret['attributedTo'] = $i['author']['xchan_url'];
if($i['id'] != $i['parent']) {
- $ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
+ $ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
}
if($i['mimetype'] === 'text/bbcode') {
if($i['title'])
- $ret['name'] = bbcode($i['title']);
+ $ret['name'] = bbcode($i['title'], [ 'cache' => true ]);
if($i['summary'])
- $ret['summary'] = bbcode($i['summary']);
- $ret['content'] = bbcode($i['body']);
+ $ret['summary'] = bbcode($i['summary'], [ 'cache' => true ]);
+ $ret['content'] = bbcode($i['body'], [ 'cache' => true ]);
$ret['source'] = [ 'content' => $i['body'], 'mediaType' => 'text/bbcode' ];
}
@@ -397,7 +411,7 @@ class Activity {
$ret = [];
if($item['attach']) {
- $atts = json_decode($item['attach'],true);
+ $atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'],true));
if($atts) {
foreach($atts as $att) {
if(strpos($att['type'],'image')) {
@@ -409,7 +423,7 @@ class Activity {
}
}
}
-
+
return $ret;
}
@@ -462,14 +476,14 @@ class Activity {
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/activity/' . urlencode($i['mid']));
if($i['title'])
- $ret['name'] = html2plain(bbcode($i['title']));
+ $ret['name'] = html2plain(bbcode($i['title'], [ 'cache' => true ]));
if($i['summary'])
- $ret['summary'] = bbcode($i['summary']);
+ $ret['summary'] = bbcode($i['summary'], [ 'cache' => true ]);
if($ret['type'] === 'Announce') {
$tmp = preg_replace('/\[share(.*?)\[\/share\]/ism',EMPTY_STR, $i['body']);
- $ret['content'] = bbcode($tmp);
+ $ret['content'] = bbcode($tmp, [ 'cache' => true ]);
$ret['source'] = [
'content' => $i['body'],
'mediaType' => 'text/bbcode'
@@ -495,7 +509,7 @@ class Activity {
}
if($i['id'] != $i['parent']) {
- $ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
+ $ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
$reply = true;
if($i['item_private']) {
@@ -526,6 +540,10 @@ class Activity {
else
return [];
+ if(strpos($i['body'],'[/share]') !== false) {
+ $i['obj'] = null;
+ }
+
if($i['obj']) {
if(! is_array($i['obj'])) {
$i['obj'] = json_decode($i['obj'],true);
@@ -548,6 +566,7 @@ class Activity {
return [];
}
+
if($i['target']) {
if(! is_array($i['target'])) {
$i['target'] = json_decode($i['target'],true);
@@ -692,7 +711,7 @@ class Activity {
// Reactions will just map to normal activities
if(strpos($verb,ACTIVITY_REACT) !== false)
- return 'Create';
+ return 'emojiReaction';
if(strpos($verb,ACTIVITY_MOOD) !== false)
return 'Create';
@@ -868,7 +887,7 @@ class Activity {
// Send an Accept back to them
set_abconfig($channel['channel_id'],$person_obj['id'],'pubcrawl','their_follow_id', $their_follow_id);
- \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_accept', $contact['abook_id'] ]);
+ Master::Summon([ 'Notifier', 'permissions_accept', $contact['abook_id'] ]);
return;
case 'Accept':
@@ -969,9 +988,9 @@ class Activity {
if($my_perms && $automatic) {
// send an Accept for this Follow activity
- \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_accept', $new_connection[0]['abook_id'] ]);
+ Master::Summon([ 'Notifier', 'permissions_accept', $new_connection[0]['abook_id'] ]);
// Send back a Follow notification to them
- \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
+ Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
}
$clone = array();
@@ -1162,7 +1181,7 @@ class Activity {
$photos = import_xchan_photo($icon,$url);
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
- dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
+ dbescdate(datetime_convert('UTC','UTC',$photos[5])),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
@@ -1406,7 +1425,7 @@ class Activity {
if($parent) {
if($s['owner_xchan'] === $channel['channel_hash']) {
// We are the owner of this conversation, so send all received comments back downstream
- Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$x['item_id']));
+ Master::Summon(array('Notifier','comment-import',$x['item_id']));
}
$r = q("select * from item where id = %d limit 1",
intval($x['item_id'])
@@ -1468,7 +1487,7 @@ class Activity {
}
- if(in_array($act->type, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept' ])) {
+ if(in_array($act->type, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'emojiReaction' ])) {
$response_activity = true;
@@ -1509,6 +1528,9 @@ class Activity {
if($act->type === 'Announce') {
$content['content'] = sprintf( t('&#x1f501; Repeated %1$s\'s %2$s'), $mention, $act->obj['type']);
}
+ if ($act->type === 'emojiReaction') {
+ $content['content'] = (($act->tgt && $act->tgt['type'] === 'Image') ? '[img=32x32]' . $act->tgt['url'] . '[/img]' : '&#x' . $act->tgt['name'] . ';');
+ }
}
if(! $s['created'])
@@ -1790,7 +1812,7 @@ class Activity {
$s['item_private'] = 1;
set_iconfig($s,'activitypub','recips',$act->raw_recips);
-
+ // @FIXME: $parent is not defined
if($parent) {
set_iconfig($s,'activitypub','rawmsg',$act->raw,1);
}
@@ -1921,10 +1943,11 @@ class Activity {
if(is_array($x) && $x['item_id']) {
+ // @FIXME: $parent is not defined
if($parent) {
if($s['owner_xchan'] === $channel['channel_hash']) {
// We are the owner of this conversation, so send all received comments back downstream
- Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$x['item_id']));
+ Master::Summon(array('Notifier','comment-import',$x['item_id']));
}
$r = q("select * from item where id = %d limit 1",
intval($x['item_id'])
@@ -2060,7 +2083,7 @@ class Activity {
if($result['success']) {
// if the message isn't already being relayed, notify others
if(intval($parent_item['item_origin']))
- Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$result['item_id']));
+ Master::Summon(array('Notifier','comment-import',$result['item_id']));
sync_an_item($channel['channel_id'],$result['item_id']);
}
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index a357b6d69..006744aff 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -319,7 +319,10 @@ class ActivityStreams {
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
- $x = $this->fetch_property($x);
+ $y = $this->fetch_property($x);
+ if (is_array($y)) {
+ $x = $y;
+ }
}
// verify and unpack JSalmon signature if present
diff --git a/Zotlabs/Lib/Api_router.php b/Zotlabs/Lib/Api_router.php
index 404678bd9..6e3f231a9 100644
--- a/Zotlabs/Lib/Api_router.php
+++ b/Zotlabs/Lib/Api_router.php
@@ -12,8 +12,16 @@ class Api_router {
}
static function find($path) {
- if(array_key_exists($path,self::$routes))
+ if (array_key_exists($path,self::$routes)) {
return self::$routes[$path];
+ }
+
+ $with_params = dirname($path) . '/[id]';
+
+ if (array_key_exists($with_params,self::$routes)) {
+ return self::$routes[$with_params];
+ }
+
return null;
}
diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php
index 56283ff76..69996b49d 100644
--- a/Zotlabs/Lib/Apps.php
+++ b/Zotlabs/Lib/Apps.php
@@ -70,7 +70,7 @@ class Apps {
'Channel Home',
'View Profile',
'Photos',
- 'Events',
+ 'Calendar',
'Directory',
'Search',
'Help',
@@ -327,6 +327,8 @@ class Apps {
'Report Bug' => t('Report Bug'),
'Bookmarks' => t('Bookmarks'),
'Chatrooms' => t('Chatrooms'),
+ 'Content Filter' => t('Content Filter'),
+ 'Content Import' => t('Content Import'),
'Connections' => t('Connections'),
'Remote Diagnostics' => t('Remote Diagnostics'),
'Suggest Channels' => t('Suggest Channels'),
@@ -340,7 +342,7 @@ class Apps {
'Channel Home' => t('Channel Home'),
'View Profile' => t('View Profile'),
'Photos' => t('Photos'),
- 'Events' => t('Events'),
+ 'Calendar' => t('Calendar'),
'Directory' => t('Directory'),
'Help' => t('Help'),
'Mail' => t('Mail'),
@@ -361,7 +363,6 @@ class Apps {
'Privacy Groups' => t('Privacy Groups'),
'Notifications' => t('Notifications'),
'Order Apps' => t('Order Apps'),
- 'CalDAV' => t('CalDAV'),
'CardDAV' => t('CardDAV'),
'Channel Sources' => t('Channel Sources'),
'Guest Access' => t('Guest Access'),
diff --git a/Zotlabs/Lib/DB_Upgrade.php b/Zotlabs/Lib/DB_Upgrade.php
index 4038a2d53..b6e3f7b7b 100644
--- a/Zotlabs/Lib/DB_Upgrade.php
+++ b/Zotlabs/Lib/DB_Upgrade.php
@@ -58,10 +58,15 @@ class DB_Upgrade {
$c = new $cls();
+
$retval = $c->run();
if($retval != UPDATE_SUCCESS) {
+
+ $source = t('Source code of failed update: ') . "\n\n" . @file_get_contents('Zotlabs/Update/' . $s . '.php');
+
+
// Prevent sending hundreds of thousands of emails by creating
// a lockfile.
@@ -86,7 +91,9 @@ class DB_Upgrade {
'$sitename' => \App::$config['system']['sitename'],
'$siteurl' => z_root(),
'$update' => $x,
- '$error' => sprintf( t('Update %s failed. See error logs.'), $x)
+ '$error' => sprintf( t('Update %s failed. See error logs.'), $x),
+ '$baseurl' => z_root(),
+ '$source' => $source
]
)
]
diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php
index 18087e29f..7515d3292 100644
--- a/Zotlabs/Lib/DReport.php
+++ b/Zotlabs/Lib/DReport.php
@@ -118,7 +118,7 @@ class DReport {
// So if a remote site says they can't find us, that's no big surprise
// and just creates a lot of extra report noise
- if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
+ if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
return false;
// If you have a private post with a recipient list, every single site is going to report
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index 5e5798cac..a7082f45a 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -754,9 +754,9 @@ class Enotify {
// generate a multipart/alternative message header
$messageHeader =
$params['additionalMailHeader'] .
- "From: $fromName <{$params['fromEmail']}>\n" .
- "Reply-To: $fromName <{$params['replyTo']}>\n" .
- "MIME-Version: 1.0\n" .
+ "From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
+ "Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
+ "MIME-Version: 1.0" . PHP_EOL .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
@@ -764,15 +764,15 @@ class Enotify {
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$multipartMessageBody =
- "--" . $mimeBoundary . "\n" . // plain text section
- "Content-Type: text/plain; charset=UTF-8\n" .
- "Content-Transfer-Encoding: base64\n\n" .
- $textBody . "\n" .
- "--" . $mimeBoundary . "\n" . // text/html section
- "Content-Type: text/html; charset=UTF-8\n" .
- "Content-Transfer-Encoding: base64\n\n" .
- $htmlBody . "\n" .
- "--" . $mimeBoundary . "--\n"; // message ending
+ "--" . $mimeBoundary . PHP_EOL . // plain text section
+ "Content-Type: text/plain; charset=UTF-8" . PHP_EOL .
+ "Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
+ $textBody . PHP_EOL .
+ "--" . $mimeBoundary . PHP_EOL . // text/html section
+ "Content-Type: text/html; charset=UTF-8" . PHP_EOL .
+ "Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
+ $htmlBody . PHP_EOL .
+ "--" . $mimeBoundary . "--" . PHP_EOL; // message ending
// send the message
$res = mail(
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index d037a0058..d93270bc5 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -336,7 +336,7 @@ class Libsync {
$disallowed = array('abook_id','abook_account','abook_channel','abook_rating','abook_rating_text','abook_not_here');
- $fields = db_columns($abook);
+ $fields = db_columns('abook');
foreach($arr['abook'] as $abook) {
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index 019237568..9bf987027 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -685,9 +685,27 @@ class Libzot {
$adult_changed = 1;
if(intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
$deleted_changed = 1;
+
+ // new style 6-MAR-2019
+
+ if(array_key_exists('channel_type',$arr)) {
+ if($arr['channel_type'] === 'collection') {
+ // do nothing at this time.
+ }
+ elseif($arr['channel_type'] === 'group') {
+ $arr['public_forum'] = 1;
+ }
+ else {
+ $arr['public_forum'] = 0;
+ }
+ }
+
+ // old style
+
if(intval($r[0]['xchan_pubforum']) != intval($arr['public_forum']))
$pubforum_changed = 1;
+
if($arr['protocols']) {
$protocols = implode(',',$arr['protocols']);
if($protocols !== 'zot6') {
@@ -1107,9 +1125,14 @@ class Libzot {
logger('Activity rejected: ' . print_r($data,true));
return;
}
- $arr = Activity::decode_note($AS);
+ if (is_array($AS->obj)) {
+ $arr = Activity::decode_note($AS);
+ }
+ else {
+ $arr = [];
+ }
- logger($AS->debug());
+ logger($AS->debug(),LOGGER_DATA);
}
@@ -1174,12 +1197,14 @@ class Libzot {
//logger($AS->debug());
- $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
+ $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ",
dbesc($AS->actor['id'])
);
if($r) {
- $arr['author_xchan'] = $r[0]['hubloc_hash'];
+ // selects a zot6 hash if available, otherwise use whatever we have
+ $r = self::zot_record_preferred($r);
+ $arr['author_xchan'] = $r['hubloc_hash'];
}
@@ -1212,7 +1237,7 @@ class Libzot {
$relay = (($env['type'] === 'response') ? true : false );
- $result = self::process_delivery($env['sender'],$arr,$deliveries,$relay,false,$message_request);
+ $result = self::process_delivery($env['sender'],$AS,$arr,$deliveries,$relay,false,$message_request);
}
elseif($env['type'] === 'sync') {
// $arr = get_channelsync_elements($data);
@@ -1385,7 +1410,7 @@ class Libzot {
/**
* @brief
*
- * @param array $sender
+ * @param string $sender
* @param array $arr
* @param array $deliveries
* @param boolean $relay
@@ -1394,7 +1419,7 @@ class Libzot {
* @return array
*/
- static function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) {
+ static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false) {
$result = [];
@@ -1423,6 +1448,24 @@ class Libzot {
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+ 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.
+ // We will also need to re-parse the $item array,
+ // but preserve any values that were set during anonymous parsing.
+
+ $o = Activity::fetch($act->obj,$channel);
+ if($o) {
+ $act->obj = $o;
+ $arr = array_merge(Activity::decode_note($act),$arr);
+ }
+ else {
+ $DR->update('Incomplete or corrupt activity');
+ $result[] = $DR->get();
+ continue;
+ }
+ }
+
/**
* We need to block normal top-level message delivery from our clones, as the delivered
* message doesn't have ACL information in it as the cloned copy does. That copy
@@ -1841,7 +1884,7 @@ class Libzot {
logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_portable_id'], LOGGER_DATA, LOG_DEBUG);
- $result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_portable_id'] ],false,false,true);
+ $result = self::process_delivery($arr['owner_xchan'],$AS, $arr, [ $channel['channel_portable_id'] ],false,false,true);
if ($result) {
$ret = array_merge($ret, $result);
}
@@ -1854,8 +1897,7 @@ class Libzot {
/**
* @brief Remove community tag.
*
- * @param array $sender an associative array with
- * * \e string \b hash a xchan_hash
+ * @param string $sender
* @param array $arr an associative array
* * \e int \b verb
* * \e int \b obj_type
@@ -1928,7 +1970,7 @@ class Libzot {
*
* @see item_store_update()
*
- * @param array $sender
+ * @param string $sender
* @param array $item
* @param array $orig
* @param int $uid
@@ -1979,7 +2021,7 @@ class Libzot {
/**
* @brief Deletes an imported item.
*
- * @param array $sender
+ * @param string $sender
* * \e string \b hash a xchan_hash
* @param array $item
* @param int $uid
@@ -1997,9 +2039,9 @@ class Libzot {
$r = q("select id, author_xchan, owner_xchan, source_xchan, item_deleted from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
and mid = '%s' and uid = %d limit 1",
- dbesc($sender['hash']),
- dbesc($sender['hash']),
- dbesc($sender['hash']),
+ dbesc($sender),
+ dbesc($sender),
+ dbesc($sender),
dbesc($item['mid']),
intval($uid)
);
@@ -2154,8 +2196,7 @@ class Libzot {
*
* @see import_directory_profile()
*
- * @param array $sender an associative array
- * * \e string \b hash a xchan_hash
+ * @param string $sender
* @param array $arr
* @param array $deliveries (unused)
* @return void
@@ -2165,7 +2206,7 @@ class Libzot {
logger('process_profile_delivery', LOGGER_DEBUG);
$r = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
- dbesc($sender['hash'])
+ dbesc($sender)
);
if($r) {
Libzotdir::import_directory_profile($sender, $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0);
@@ -2176,8 +2217,7 @@ class Libzot {
/**
* @brief
*
- * @param array $sender an associative array
- * * \e string \b hash a xchan_hash
+ * @param string $sender
* @param array $arr
* @param array $deliveries (unused) deliveries is irrelevant
* @return void
@@ -3058,4 +3098,26 @@ class Libzot {
return(($x) ? true : false);
}
+
+ static public function zot_record_preferred($arr, $check = 'hubloc_network') {
+
+ if(! $arr) {
+ return $arr;
+ }
+
+ foreach($arr as $v) {
+ if($v[$check] === 'zot6') {
+ return $v;
+ }
+ }
+ foreach($arr as $v) {
+ if($v[$check] === 'zot') {
+ return $v;
+ }
+ }
+
+ return $arr[0];
+
+ }
+
}
diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php
index 91d089c86..1cb52275c 100644
--- a/Zotlabs/Lib/Libzotdir.php
+++ b/Zotlabs/Lib/Libzotdir.php
@@ -307,7 +307,7 @@ class Libzotdir {
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
$success = false;
- $href = \Zotlabs\Lib\Webfinger::zot_url(punify($url));
+ $href = \Zotlabs\Lib\Webfinger::zot_url(punify($ud['ud_addr']));
if($href) {
$zf = \Zotlabs\Lib\Zotfinger::exec($href);
}
@@ -651,4 +651,4 @@ class Libzotdir {
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Lib/MessageFilter.php b/Zotlabs/Lib/MessageFilter.php
index eb0fc3d2c..750d6d424 100644
--- a/Zotlabs/Lib/MessageFilter.php
+++ b/Zotlabs/Lib/MessageFilter.php
@@ -19,7 +19,7 @@ class MessageFilter {
$lang = null;
- if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false)) {
+ if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
$lang = detect_language($text);
}
@@ -39,10 +39,17 @@ class MessageFilter {
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
return false;
}
+ elseif(substr($word,0,1) === '$' && $tags) {
+ foreach($tags as $t)
+ if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ return false;
+ }
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
return false;
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
return false;
+ elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
+ return false;
elseif(stristr($text,$word) !== false)
return false;
}
@@ -60,10 +67,17 @@ class MessageFilter {
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
return true;
}
+ elseif(substr($word,0,1) === '$' && $tags) {
+ foreach($tags as $t)
+ if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
+ return true;
+ }
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
return true;
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
return true;
+ elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
+ return true;
elseif(stristr($text,$word) !== false)
return true;
}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 40c0fca4b..9161aa182 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -38,6 +38,7 @@ class ThreadItem {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
+ $this->threaded = get_config('system','thread_allow');
$observer = \App::get_observer();
@@ -305,6 +306,7 @@ class ThreadItem {
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"));
}
if ($shareable) {
@@ -331,7 +333,6 @@ class ThreadItem {
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$is_new = true;
-
localize_item($item);
$body = prepare_body($item,true);
@@ -347,10 +348,6 @@ class ThreadItem {
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
-
-
-
-
$children = $this->get_children();
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
@@ -373,13 +370,15 @@ class ThreadItem {
'text' => strip_tags($body['html']),
'id' => $this->get_id(),
'mid' => $item['mid'],
+ 'parent' => $item['parent'],
+ 'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
'conlabels' => $conlabels,
'canvote' => $canvote,
- 'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
- 'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
+ 'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
+ 'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url'])),
'llink' => $item['llink'],
'viewthread' => $viewthread,
'to' => t('to'),
@@ -425,9 +424,11 @@ class ThreadItem {
'has_tags' => $has_tags,
'reactions' => $this->reactions,
// Item toolbar buttons
- 'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
+ '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 : ''),
+ 'reply_to' => (((! $this->is_toplevel()) && feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
+ 'top_hint' => t("Go to previous comment"),
'share' => $share,
'embed' => $embed,
'rawmid' => $item['mid'],
@@ -440,9 +441,8 @@ class ThreadItem {
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
- 'dropdown_extras' => $dropdown_extras,
+ 'dropdown_extras' => $dropdown_extras,
// end toolbar buttons
-
'unseen_comments' => $unseen_comments,
'comment_count' => $total_children,
'comment_count_txt' => $comment_count_txt,
@@ -469,7 +469,8 @@ class ThreadItem {
'wait' => t('Please wait'),
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
'thread_level' => $thread_level,
- 'settings' => $settings
+ 'settings' => $settings,
+ 'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -814,7 +815,7 @@ class ThreadItem {
'$anonname' => [ 'anonname', t('Your full name (required)') ],
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ],
- '$auto_save_draft' => $feature_auto_save_draft,
+ '$auto_save_draft' => $feature_auto_save_draft
));
return $comment_box;
@@ -869,4 +870,3 @@ class ThreadItem {
}
-
diff --git a/Zotlabs/Lib/ZotURL.php b/Zotlabs/Lib/ZotURL.php
index d1c705fcb..bc14c516a 100644
--- a/Zotlabs/Lib/ZotURL.php
+++ b/Zotlabs/Lib/ZotURL.php
@@ -66,7 +66,7 @@ class ZotURL {
}
- static public function is_zoturl($s) {
+ static public function is_zoturl($url) {
if(strpos($url,'x-zot:') === 0) {
return true;
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php
index 738e8fbe2..82c156a9c 100644
--- a/Zotlabs/Module/Acl.php
+++ b/Zotlabs/Module/Acl.php
@@ -166,7 +166,7 @@ class Acl extends \Zotlabs\Web\Controller {
if($extra_channels) {
foreach($extra_channels as $channel) {
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) {
- if($extra_channel_sql)
+ if($extra_channels_sql)
$extra_channels_sql .= ',';
$extra_channels_sql .= intval($channel);
}
diff --git a/Zotlabs/Module/Admin/Dbsync.php b/Zotlabs/Module/Admin/Dbsync.php
index 469af2aa5..183834301 100644
--- a/Zotlabs/Module/Admin/Dbsync.php
+++ b/Zotlabs/Module/Admin/Dbsync.php
@@ -19,7 +19,47 @@ class Dbsync {
info( t('Update has been marked successful') . EOL);
goaway(z_root() . '/admin/dbsync');
}
+
+ if(argc() > 3 && intval(argv(3)) && argv(2) === 'verify') {
+
+ $s = '_' . intval(argv(3));
+ $cls = '\\Zotlabs\Update\\' . $s ;
+ if(class_exists($cls)) {
+ $c = new $cls();
+ if(method_exists($c,'verify')) {
+ $retval = $c->verify();
+ if($retval === UPDATE_FAILED) {
+ $o .= sprintf( t('Verification of update %s failed. Check system logs.'), $s);
+ }
+ elseif($retval === UPDATE_SUCCESS) {
+ $o .= sprintf( t('Update %s was successfully applied.'), $s);
+ set_config('database',$s, 'success');
+ }
+ else
+ $o .= sprintf( t('Verifying update %s did not return a status. Unknown if it succeeded.'), $s);
+ }
+ else {
+ $o .= sprintf( t('Update %s does not contain a verification function.'), $s );
+ }
+ }
+ else
+ $o .= sprintf( t('Update function %s could not be found.'), $s);
+ return $o;
+
+
+
+
+
+ // remove the old style config if it exists
+ del_config('database', 'update_r' . intval(argv(3)));
+ set_config('database', '_' . intval(argv(3)), 'success');
+ if(intval(get_config('system','db_version')) < intval(argv(3)))
+ set_config('system','db_version',intval(argv(3)));
+ info( t('Update has been marked successful') . EOL);
+ goaway(z_root() . '/admin/dbsync');
+ }
+
if(argc() > 2 && intval(argv(2))) {
$x = intval(argv(2));
$s = '_' . $x;
@@ -28,14 +68,14 @@ class Dbsync {
$c = new $cls();
$retval = $c->run();
if($retval === UPDATE_FAILED) {
- $o .= sprintf( t('Executing %s failed. Check system logs.'), $s);
+ $o .= sprintf( t('Executing update procedure %s failed. Check system logs.'), $s);
}
elseif($retval === UPDATE_SUCCESS) {
$o .= sprintf( t('Update %s was successfully applied.'), $s);
set_config('database',$s, 'success');
}
else
- $o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $s);
+ $o .= sprintf( t('Update %s did not return a status. It cannot be determined if it was successful.'), $s);
}
else
$o .= sprintf( t('Update function %s could not be found.'), $s);
@@ -59,6 +99,7 @@ class Dbsync {
'$banner' => t('Failed Updates'),
'$desc' => '',
'$mark' => t('Mark success (if update was manually applied)'),
+ '$verify' => t('Attempt to verify this update if a verification procedure exists'),
'$apply' => t('Attempt to execute this update step automatically'),
'$failed' => $failed
));
diff --git a/Zotlabs/Module/Apschema.php b/Zotlabs/Module/Apschema.php
new file mode 100644
index 000000000..5b249bfe8
--- /dev/null
+++ b/Zotlabs/Module/Apschema.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Zotlabs\Module;
+
+
+class Apschema extends \Zotlabs\Web\Controller {
+
+ function init() {
+
+ $base = z_root();
+
+ $arr = [
+ '@context' => [
+ 'zot' => z_root() . '/apschema#',
+ 'id' => '@id',
+ 'type' => '@type',
+ 'commentPolicy' => 'as:commentPolicy',
+ 'meData' => 'zot:meData',
+ 'meDataType' => 'zot:meDataType',
+ 'meEncoding' => 'zot:meEncoding',
+ 'meAlgorithm' => 'zot:meAlgorithm',
+ 'meCreator' => 'zot:meCreator',
+ 'meSignatureValue' => 'zot:meSignatureValue',
+ 'locationAddress' => 'zot:locationAddress',
+ 'locationPrimary' => 'zot:locationPrimary',
+ 'locationDeleted' => 'zot:locationDeleted',
+ 'nomadicLocation' => 'zot:nomadicLocation',
+ 'nomadicHubs' => 'zot:nomadicHubs',
+ 'emojiReaction' => 'zot:emojiReaction',
+
+ 'magicEnv' => [
+ '@id' => 'zot:magicEnv',
+ '@type' => '@id'
+ ],
+
+ 'nomadicLocations' => [
+ '@id' => 'zot:nomadicLocations',
+ '@type' => '@id'
+ ],
+
+ 'ostatus' => 'http://ostatus.org#',
+ 'conversation' => 'ostatus:conversation'
+
+ ]
+ ];
+
+ header('Content-Type: application/ld+json');
+ echo json_encode($arr,JSON_UNESCAPED_SLASHES);
+ killme();
+
+ }
+
+
+
+
+} \ No newline at end of file
diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php
index d644e48b1..6b4f57ea5 100644
--- a/Zotlabs/Module/Cdav.php
+++ b/Zotlabs/Module/Cdav.php
@@ -133,10 +133,6 @@ class Cdav extends Controller {
logger('loggedin');
- if((argv(1) == 'calendars') && (!Apps::system_app_installed(local_channel(), 'CalDAV'))) {
- killme();
- }
-
if((argv(1) == 'addressbooks') && (!Apps::system_app_installed(local_channel(), 'CardDAV'))) {
killme();
}
@@ -221,10 +217,6 @@ class Cdav extends Controller {
if(! local_channel())
return;
- if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) {
- return;
- }
-
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
return;
}
@@ -280,9 +272,12 @@ class Cdav extends Controller {
return;
$title = $_REQUEST['title'];
- $dtstart = new \DateTime($_REQUEST['dtstart']);
- if($_REQUEST['dtend'])
- $dtend = new \DateTime($_REQUEST['dtend']);
+ $start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
+ $dtstart = new \DateTime($start);
+ if($_REQUEST['dtend']) {
+ $end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
+ $dtend = new \DateTime($end);
+ }
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
@@ -306,13 +301,17 @@ class Cdav extends Controller {
'DTSTART' => $dtstart
]
]);
- if($dtend)
+ if($dtend) {
$vcalendar->VEVENT->add('DTEND', $dtend);
+ $vcalendar->VEVENT->DTEND['TZID'] = App::$timezone;
+ }
if($description)
$vcalendar->VEVENT->add('DESCRIPTION', $description);
if($location)
$vcalendar->VEVENT->add('LOCATION', $location);
+ $vcalendar->VEVENT->DTSTART['TZID'] = App::$timezone;
+
$calendarData = $vcalendar->serialize();
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
@@ -351,8 +350,12 @@ class Cdav extends Controller {
$uri = $_REQUEST['uri'];
$title = $_REQUEST['title'];
- $dtstart = new \DateTime($_REQUEST['dtstart']);
- $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
+ $start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
+ $dtstart = new \DateTime($start);
+ if($_REQUEST['dtend']) {
+ $end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
+ $dtend = new \DateTime($end);
+ }
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
@@ -404,8 +407,12 @@ class Cdav extends Controller {
return;
$uri = $_REQUEST['uri'];
- $dtstart = new \DateTime($_REQUEST['dtstart']);
- $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
+ $start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
+ $dtstart = new \DateTime($start);
+ if($_REQUEST['dtend']) {
+ $end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
+ $dtend = new \DateTime($end);
+ }
$object = $caldavBackend->getCalendarObject($id, $uri);
@@ -747,16 +754,27 @@ class Cdav extends Controller {
//Import calendar or addressbook
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) {
- $src = @file_get_contents($_FILES['userfile']['tmp_name']);
+ $src = $_FILES['userfile']['tmp_name'];
if($src) {
if($_REQUEST['c_upload']) {
+ if($_REQUEST['target'] == 'channel_calendar') {
+ $result = parse_ical_file($src,local_channel());
+ if($result)
+ info( t('Calendar entries imported.') . EOL);
+ else
+ notice( t('No calendar entries found.') . EOL);
+
+ @unlink($src);
+ return;
+ }
+
$id = explode(':', $_REQUEST['target']);
$ext = 'ics';
$table = 'calendarobjects';
$column = 'calendarid';
- $objects = new \Sabre\VObject\Splitter\ICalendar($src);
+ $objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src));
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
}
@@ -766,7 +784,7 @@ class Cdav extends Controller {
$ext = 'vcf';
$table = 'cards';
$column = 'addressbookid';
- $objects = new \Sabre\VObject\Splitter\VCard($src);
+ $objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src));
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
}
@@ -832,15 +850,6 @@ class Cdav extends Controller {
if(!local_channel())
return;
- if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
-
- $o = '<b>' . t('CalDAV App') . ' (' . t('Not Installed') . '):</b><br>';
- $o .= t('CalDAV capable calendar');
- return $o;
- }
-
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
//Do not display any associated widgets at this point
App::$pdl = '';
@@ -869,28 +878,93 @@ class Cdav extends Controller {
}
if(argv(1) === 'calendar') {
- nav_set_selected('CalDAV');
+ nav_set_selected('Calendar');
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
$calendars = $caldavBackend->getCalendarsForUser($principalUri);
}
//Display calendar(s) here
- if(argc() == 2 && argv(1) === 'calendar') {
+ if(argc() <= 3 && argv(1) === 'calendar') {
- head_add_css('/library/fullcalendar/fullcalendar.css');
+ head_add_css('/library/fullcalendar/packages/core/main.min.css');
+ head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
+ head_add_css('/library/fullcalendar/packages/timegrid/main.min.css');
+ head_add_css('/library/fullcalendar/packages/list/main.min.css');
head_add_css('cdav_calendar.css');
- head_add_js('/library/moment/moment.min.js', 1);
- head_add_js('/library/fullcalendar/fullcalendar.min.js', 1);
- head_add_js('/library/fullcalendar/locale-all.js', 1);
+ head_add_js('/library/fullcalendar/packages/core/main.min.js');
+ head_add_js('/library/fullcalendar/packages/interaction/main.min.js');
+ head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
+ head_add_js('/library/fullcalendar/packages/timegrid/main.min.js');
+ head_add_js('/library/fullcalendar/packages/list/main.min.js');
+
+ $sources = '';
+ $resource_id = '';
+ $resource = null;
+
+ if(argc() == 3)
+ $resource_id = argv(2);
+
+ if($resource_id) {
+ $r = q("SELECT event.*, item.author_xchan, item.owner_xchan, item.plink, item.id as item_id FROM event LEFT JOIN item ON event.event_hash = item.resource_id
+ WHERE event.uid = %d AND event.event_hash = '%s' LIMIT 1",
+ intval(local_channel()),
+ dbesc($resource_id)
+ );
+ if($r) {
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+
+ $r[0]['dtstart'] = (($r[0]['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$r[0]['dtstart'], 'c') : datetime_convert('UTC','UTC',$r[0]['dtstart'],'c'));
+ $r[0]['dtend'] = (($r[0]['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$r[0]['dtend'], 'c') : datetime_convert('UTC','UTC',$r[0]['dtend'],'c'));
+
+ $r[0]['plink'] = [$r[0]['plink'], t('Link to source')];
+
+ $resource = $r[0];
+
+ $catsenabled = feature_enabled(local_channel(),'categories');
+ $categories = '';
+ if($catsenabled){
+ if($r[0]['term']) {
+ $cats = get_terms_oftype($r[0]['term'], TERM_CATEGORY);
+ foreach ($cats as $cat) {
+ if(strlen($categories))
+ $categories .= ', ';
+ $categories .= $cat['term'];
+ }
+ }
+ }
+
+ if($r[0]['dismissed'] == 0) {
+ q("UPDATE event SET dismissed = 1 WHERE event.uid = %d AND event.event_hash = '%s'",
+ intval(local_channel()),
+ dbesc($resource_id)
+ );
+ }
+ }
+ }
+
+ if(get_pconfig(local_channel(), 'cdav_calendar', 'channel_calendar')) {
+ $sources .= '{
+ id: \'channel_calendar\',
+ url: \'/channel_calendar/json/\',
+ color: \'#3a87ad\'
+ }, ';
+ }
+
+ $channel_calendars[] = [
+ 'displayname' => $channel['channel_name'],
+ 'id' => 'channel_calendar'
+ ];
foreach($calendars as $calendar) {
$editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
- $color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad');
+ $color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#6cad39');
$sharer = (($calendar['share-access'] == 3) ? $calendar['{urn:ietf:params:xml:ns:caldav}calendar-description'] : '');
$switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]);
if($switch) {
$sources .= '{
+ id: ' . $calendar['id'][0] . ',
url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\',
color: \'' . $color . '\'
}, ';
@@ -911,15 +985,29 @@ class Cdav extends Controller {
$first_day = (($first_day) ? $first_day : 0);
$title = ['title', t('Event title')];
- $dtstart = ['dtstart', t('Start date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
- $dtend = ['dtend', t('End date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
+ $dtstart = ['dtstart', t('Start date and time')];
+ $dtend = ['dtend', t('End date and time')];
$description = ['description', t('Description')];
$location = ['location', t('Location')];
+ $catsenabled = feature_enabled(local_channel(), 'categories');
+
+ require_once('include/acl_selectors.php');
+
+ $accesslist = new \Zotlabs\Access\AccessList($channel);
+ $perm_defaults = $accesslist->get();
+
+ //$acl = (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream')));
+ $acl = populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'));
+
+ //$permissions = ((x($orig_event)) ? $orig_event : $perm_defaults);
+ $permissions = $perm_defaults;
+
$o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [
'$sources' => $sources,
'$color' => $color,
'$lang' => App::$language,
+ '$timezone' => App::$timezone,
'$first_day' => $first_day,
'$prev' => t('Previous'),
'$next' => t('Next'),
@@ -931,6 +1019,7 @@ class Cdav extends Controller {
'$list_week' => t('List week'),
'$list_day' => t('List day'),
'$title' => $title,
+ '$channel_calendars' => $channel_calendars,
'$writable_calendars' => $writable_calendars,
'$dtstart' => $dtstart,
'$dtend' => $dtend,
@@ -938,11 +1027,27 @@ class Cdav extends Controller {
'$location' => $location,
'$more' => t('More'),
'$less' => t('Less'),
+ '$update' => t('Update'),
'$calendar_select_label' => t('Select calendar'),
+ '$calendar_optiopns_label' => [t('Channel Calendars'), t('CalDAV Calendars')],
'$delete' => t('Delete'),
'$delete_all' => t('Delete all'),
'$cancel' => t('Cancel'),
- '$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.')
+ '$create' => t('Create'),
+ '$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'),
+
+ '$channel_hash' => $channel['channel_hash'],
+ '$acl' => $acl,
+ '$lockstate' => (($accesslist->is_private()) ? 'lock' : 'unlock'),
+ '$allow_cid' => acl2json($permissions['allow_cid']),
+ '$allow_gid' => acl2json($permissions['allow_gid']),
+ '$deny_cid' => acl2json($permissions['deny_cid']),
+ '$deny_gid' => acl2json($permissions['deny_gid']),
+ '$catsenabled' => $catsenabled,
+ '$categories_label' => t('Categories'),
+
+ '$resource' => json_encode($resource),
+ '$categories' => $categories
]);
return $o;
@@ -952,10 +1057,12 @@ class Cdav extends Controller {
//Provide json data for calendar
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) {
+ $events = [];
+
$id = [argv(3), argv(4)];
if(! cdav_perms($id[0],$calendars))
- killme();
+ json_return_and_die($events);
if (x($_GET,'start'))
$start = new \DateTime($_GET['start']);
@@ -969,16 +1076,19 @@ class Cdav extends Controller {
$filters['comp-filters'][0]['time-range']['end'] = $end;
$uris = $caldavBackend->calendarQuery($id, $filters);
- if($uris) {
+ if($uris) {
$objects = $caldavBackend->getMultipleCalendarObjects($id, $uris);
-
foreach($objects as $object) {
$vcalendar = \Sabre\VObject\Reader::read($object['calendardata']);
- if(isset($vcalendar->VEVENT->RRULE))
+ if(isset($vcalendar->VEVENT->RRULE)) {
+ // expanding recurrent events seems to loose timezone info
+ // save it here so we can add it later
+ $recurrent_timezone = (string)$vcalendar->VEVENT->DTSTART['TZID'];
$vcalendar = $vcalendar->expand($start, $end);
+ }
foreach($vcalendar->VEVENT as $vevent) {
$title = (string)$vevent->SUMMARY;
@@ -986,14 +1096,15 @@ class Cdav extends Controller {
$dtend = (string)$vevent->DTEND;
$description = (string)$vevent->DESCRIPTION;
$location = (string)$vevent->LOCATION;
-
+ $timezone = (string)$vevent->DTSTART['TZID'];
$rw = ((cdav_perms($id[0],$calendars,true)) ? true : false);
- $recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
-
$editable = $rw ? true : false;
+ $recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
- if($recurrent)
+ if($recurrent) {
$editable = false;
+ $timezone = $recurrent_timezone;
+ }
$allDay = false;
@@ -1007,8 +1118,8 @@ class Cdav extends Controller {
'calendar_id' => $id,
'uri' => $object['uri'],
'title' => $title,
- 'start' => $dtstart,
- 'end' => $dtend,
+ 'start' => datetime_convert($timezone, $timezone, $dtstart, 'c'),
+ 'end' => (($dtend) ? datetime_convert($timezone, $timezone, $dtend, 'c') : ''),
'description' => $description,
'location' => $location,
'allDay' => $allDay,
@@ -1018,15 +1129,12 @@ class Cdav extends Controller {
];
}
}
- json_return_and_die($events);
- }
- else {
- killme();
}
+ json_return_and_die($events);
}
//enable/disable calendars
- if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && intval(argv(3)) && (argv(4) == 1 || argv(4) == 0)) {
+ if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && argv(3) && (argv(4) == 1 || argv(4) == 0)) {
$id = argv(3);
if(! cdav_perms($id,$calendars))
@@ -1285,12 +1393,13 @@ class Cdav extends Controller {
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
$properties = [
'{DAV:}displayname' => t('Default Calendar'),
- '{http://apple.com/ns/ical/}calendar-color' => '#3a87ad',
+ '{http://apple.com/ns/ical/}calendar-color' => '#6cad39',
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']
];
$id = $caldavBackend->createCalendar($uri, 'default', $properties);
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
+ set_pconfig(local_channel(), 'cdav_calendar' , 'channel_calendar', 1);
//create default addressbook
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
diff --git a/Zotlabs/Module/Changeaddr.php b/Zotlabs/Module/Changeaddr.php
index 5cd236394..ed139c9f9 100644
--- a/Zotlabs/Module/Changeaddr.php
+++ b/Zotlabs/Module/Changeaddr.php
@@ -31,7 +31,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
if($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
- if($account['account_password_changed'] > d1) {
+ if($account['account_password_changed'] > $d1) {
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
return;
}
@@ -49,7 +49,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
if(check_webbie(array($new_address)) !== $new_address) {
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
- return $ret;
+ return;
}
channel_change_address($channel,$new_address);
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 5fdefd805..144c2472a 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -46,14 +46,14 @@ class Channel extends Controller {
$channel = App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
- $which = $channel['channel_address'];
- $profile = argv(1);
- }
+ $which = $channel['channel_address'];
+ $profile = argv(1);
+ }
$channel = channelx_by_nick($which);
- if(! $channel) {
- http_status_exit(404, 'Not found');
- }
+ if(! $channel) {
+ http_status_exit(404, 'Not found');
+ }
// handle zot6 channel discovery
@@ -310,10 +310,6 @@ class Channel extends Controller {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
- if($datequery || $datequery2) {
- $sql_extra2 .= " and item.item_thread_top != 0 ";
- }
-
if($order === 'post')
$ordering = "created";
else
@@ -342,7 +338,7 @@ class Channel extends Controller {
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
AND item.item_wall = 1 AND item.item_thread_top = 1
$sql_extra $sql_extra2
- ORDER BY $ordering DESC $pager_sql ",
+ ORDER BY $ordering DESC, item_id $pager_sql ",
intval(App::$profile['profile_uid'])
);
}
@@ -414,12 +410,12 @@ class Channel extends Controller {
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => $search,
'$xchan' => '',
- '$order' => $order,
+ '$order' => (($order) ? urlencode($order) : ''),
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$file' => '',
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
- '$mid' => $mid,
+ '$mid' => (($mid) ? urlencode($mid) : ''),
'$verb' => '',
'$net' => '',
'$dend' => $datequery,
diff --git a/Zotlabs/Module/Channel_calendar.php b/Zotlabs/Module/Channel_calendar.php
new file mode 100644
index 000000000..9229e6eb2
--- /dev/null
+++ b/Zotlabs/Module/Channel_calendar.php
@@ -0,0 +1,480 @@
+<?php
+namespace Zotlabs\Module;
+
+require_once('include/conversation.php');
+require_once('include/bbcode.php');
+require_once('include/datetime.php');
+require_once('include/event.php');
+require_once('include/items.php');
+require_once('include/html2plain.php');
+
+class Channel_calendar extends \Zotlabs\Web\Controller {
+
+ function post() {
+
+ logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
+
+ if(! local_channel())
+ return;
+
+ $event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
+ $event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
+
+ $xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
+ $uid = local_channel();
+
+ $start_text = escape_tags($_REQUEST['dtstart']);
+ $finish_text = escape_tags($_REQUEST['dtend']);
+
+ $adjust = intval($_POST['adjust']);
+ $nofinish = intval($_POST['nofinish']);
+
+ $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
+
+ $tz = (($timezone) ? $timezone : date_default_timezone_get());
+
+ $categories = escape_tags(trim($_POST['categories']));
+
+ // only allow editing your own events.
+
+ if(($xchan) && ($xchan !== get_observer_hash()))
+ return;
+
+ if($start_text) {
+ $start = $start_text;
+ }
+ else {
+ $start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute);
+ }
+
+ if($finish_text) {
+ $finish = $finish_text;
+ }
+ else {
+ $finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute);
+ }
+
+ if($nofinish) {
+ $finish = NULL_DATE;
+ }
+
+ if($adjust) {
+ $start = datetime_convert($tz,'UTC',$start);
+ if(! $nofinish)
+ $finish = datetime_convert($tz,'UTC',$finish);
+ }
+ else {
+ $start = datetime_convert('UTC','UTC',$start);
+ if(! $nofinish)
+ $finish = datetime_convert('UTC','UTC',$finish);
+ }
+
+ $summary = escape_tags(trim($_POST['summary']));
+ $desc = escape_tags(trim($_POST['desc']));
+ $location = escape_tags(trim($_POST['location']));
+ $type = escape_tags(trim($_POST['type']));
+
+ // Don't allow the event to finish before it begins.
+ // It won't hurt anything, but somebody will file a bug report
+ // and we'll waste a bunch of time responding to it. Time that
+ // could've been spent doing something else.
+
+ if(strcmp($finish,$start) < 0 && !$nofinish) {
+ notice( t('Event can not end before it has started.') . EOL);
+ if(intval($_REQUEST['preview'])) {
+ echo( t('Unable to generate preview.'));
+ }
+ killme();
+ }
+
+ if((! $summary) || (! $start)) {
+ notice( t('Event title and start time are required.') . EOL);
+ if(intval($_REQUEST['preview'])) {
+ echo( t('Unable to generate preview.'));
+ }
+ killme();
+ }
+
+ $channel = \App::get_channel();
+
+ $acl = new \Zotlabs\Access\AccessList(false);
+
+ if($event_id) {
+ $x = q("select * from event where id = %d and uid = %d limit 1",
+ intval($event_id),
+ intval(local_channel())
+ );
+ if(! $x) {
+ notice( t('Event not found.') . EOL);
+ if(intval($_REQUEST['preview'])) {
+ echo( t('Unable to generate preview.'));
+ killme();
+ }
+ return;
+ }
+
+ $acl->set($x[0]);
+
+ $created = $x[0]['created'];
+ $edited = datetime_convert();
+ }
+ else {
+ $created = $edited = datetime_convert();
+ $acl->set_from_array($_POST);
+ }
+
+ $post_tags = array();
+ $channel = \App::get_channel();
+ $ac = $acl->get();
+
+ $str_contact_allow = $ac['allow_cid'];
+ $str_group_allow = $ac['allow_gid'];
+ $str_contact_deny = $ac['deny_cid'];
+ $str_group_deny = $ac['deny_gid'];
+
+ $private = $acl->is_private();
+
+ require_once('include/text.php');
+ $results = linkify_tags($desc, local_channel());
+
+ if($results) {
+ // Set permissions based on tag replacements
+ set_linkified_perms($results, $str_contact_allow, $str_group_allow, local_channel(), false, $private);
+
+ foreach($results as $result) {
+ $success = $result['success'];
+ if($success['replaced']) {
+ $post_tags[] = array(
+ 'uid' => local_channel(),
+ 'ttype' => $success['termtype'],
+ 'otype' => TERM_OBJ_POST,
+ 'term' => $success['term'],
+ 'url' => $success['url']
+ );
+ }
+ }
+ }
+
+ if(strlen($categories)) {
+ $cats = explode(',',$categories);
+ foreach($cats as $cat) {
+ $post_tags[] = array(
+ 'uid' => local_channel(),
+ 'ttype' => TERM_CATEGORY,
+ 'otype' => TERM_OBJ_POST,
+ 'term' => trim($cat),
+ 'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
+ );
+ }
+ }
+
+ $datarray = array();
+ $datarray['dtstart'] = $start;
+ $datarray['dtend'] = $finish;
+ $datarray['summary'] = $summary;
+ $datarray['description'] = $desc;
+ $datarray['location'] = $location;
+ $datarray['etype'] = $type;
+ $datarray['adjust'] = $adjust;
+ $datarray['nofinish'] = $nofinish;
+ $datarray['uid'] = local_channel();
+ $datarray['account'] = get_account_id();
+ $datarray['event_xchan'] = $channel['channel_hash'];
+ $datarray['allow_cid'] = $str_contact_allow;
+ $datarray['allow_gid'] = $str_group_allow;
+ $datarray['deny_cid'] = $str_contact_deny;
+ $datarray['deny_gid'] = $str_group_deny;
+ $datarray['private'] = intval($private);
+ $datarray['id'] = $event_id;
+ $datarray['created'] = $created;
+ $datarray['edited'] = $edited;
+
+ if(intval($_REQUEST['preview'])) {
+ $html = format_event_html($datarray);
+ echo $html;
+ killme();
+ }
+
+ $event = event_store_event($datarray);
+
+ if($post_tags)
+ $datarray['term'] = $post_tags;
+
+ $item_id = event_store_item($datarray,$event);
+
+ if($item_id) {
+ $r = q("select * from item where id = %d",
+ intval($item_id)
+ );
+ if($r) {
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ $z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
+ dbesc($r[0]['resource_id']),
+ intval($channel['channel_id'])
+ );
+ if($z) {
+ build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
+ }
+ }
+ }
+
+ \Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
+
+ killme();
+
+ }
+
+
+
+ function get() {
+
+ if(argc() > 2 && argv(1) == 'ical') {
+ $event_id = argv(2);
+
+ require_once('include/security.php');
+ $sql_extra = permissions_sql(local_channel());
+
+ $r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
+ dbesc($event_id)
+ );
+ if($r) {
+ header('Content-type: text/calendar');
+ header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
+ echo ical_wrapper($r);
+ killme();
+ }
+ else {
+ notice( t('Event not found.') . EOL );
+ return;
+ }
+ }
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL);
+ return;
+ }
+
+ if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
+ $r = q("update event set dismissed = 1 where id = %d and uid = %d",
+ intval(argv(2)),
+ intval(local_channel())
+ );
+ }
+
+ if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
+ $r = q("update event set dismissed = 0 where id = %d and uid = %d",
+ intval(argv(2)),
+ intval(local_channel())
+ );
+ }
+
+ $channel = \App::get_channel();
+
+ $mode = 'view';
+ $export = false;
+ $ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
+
+ if(argc() > 1) {
+ if(argc() > 2 && argv(1) === 'add') {
+ $mode = 'add';
+ $item_id = intval(argv(2));
+ }
+ if(argc() > 2 && argv(1) === 'drop') {
+ $mode = 'drop';
+ $event_id = argv(2);
+ }
+ if(argc() <= 2 && argv(1) === 'export') {
+ $export = true;
+ }
+ if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
+ $mode = 'view';
+ }
+ if(argc() <= 2) {
+ $mode = 'view';
+ $event_id = argv(1);
+ }
+ }
+
+ if($mode === 'add') {
+ event_addtocal($item_id,local_channel());
+ killme();
+ }
+
+ if($mode == 'view') {
+
+ /* edit/create form */
+ if($event_id) {
+ $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
+ dbesc($event_id),
+ intval(local_channel())
+ );
+ if(count($r))
+ $orig_event = $r[0];
+ }
+
+ $channel = \App::get_channel();
+
+ if (argv(1) === 'json'){
+ if (x($_GET,'start')) $start = $_GET['start'];
+ if (x($_GET,'end')) $finish = $_GET['end'];
+ }
+
+ $start = datetime_convert('UTC','UTC',$start);
+ $finish = datetime_convert('UTC','UTC',$finish);
+
+ $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
+ $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
+
+ if (x($_GET,'id')){
+ $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
+ from event left join item on item.resource_id = event.event_hash
+ where item.resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
+ intval(local_channel()),
+ intval($_GET['id'])
+ );
+ }
+ elseif($export) {
+ $r = q("SELECT * from event where uid = %d and dtstart > '%s' and dtend > dtstart",
+ intval(local_channel()),
+ dbesc(NULL_DATE)
+ );
+ }
+ else {
+ // fixed an issue with "nofinish" events not showing up in the calendar.
+ // There's still an issue if the finish date crosses the end of month.
+ // Noting this for now - it will need to be fixed here and in Friendica.
+ // Ultimately the finish date shouldn't be involved in the query.
+
+ $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
+ from event left join item on event.event_hash = item.resource_id
+ where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
+ AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
+ OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) ",
+ intval(local_channel()),
+ dbesc($start),
+ dbesc($finish),
+ dbesc($adjust_start),
+ dbesc($adjust_finish)
+ );
+
+ }
+
+ if($r && ! $export) {
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+
+ $r = sort_by_date($r);
+ }
+
+ $events = [];
+
+ if($r) {
+
+ foreach($r as $rr) {
+
+ $start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
+ if ($rr['nofinish']){
+ $end = null;
+ } else {
+ $end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
+
+ // give a fake end to birthdays so they get crammed into a
+ // single day on the calendar
+
+ if($rr['etype'] === 'birthday')
+ $end = null;
+ }
+
+ $catsenabled = feature_enabled(local_channel(),'categories');
+ $categories = '';
+ if($catsenabled){
+ if($rr['term']) {
+ $cats = get_terms_oftype($rr['term'], TERM_CATEGORY);
+ foreach ($cats as $cat) {
+ if(strlen($categories))
+ $categories .= ', ';
+ $categories .= $cat['term'];
+ }
+ }
+ }
+
+ $allDay = false;
+
+ // allDay event rules
+ if(!strpos($start, 'T') && !strpos($end, 'T'))
+ $allDay = true;
+ if(strpos($start, 'T00:00:00') && strpos($end, 'T00:00:00'))
+ $allDay = true;
+
+ $edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
+
+ $drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
+
+ $events[] = array(
+ 'calendar_id' => 'channel_calendar',
+ 'rw' => true,
+ 'id'=>$rr['id'],
+ 'uri' => $rr['event_hash'],
+ 'start'=> $start,
+ 'end' => $end,
+ 'drop' => $drop,
+ 'allDay' => $allDay,
+ 'title' => htmlentities($rr['summary'], ENT_COMPAT, 'UTF-8', false),
+ 'editable' => $edit ? true : false,
+ 'item'=>$rr,
+ 'plink' => [$rr['plink'], t('Link to source')],
+ 'description' => htmlentities($rr['description'], ENT_COMPAT, 'UTF-8', false),
+ 'location' => htmlentities($rr['location'], ENT_COMPAT, 'UTF-8', false),
+ 'allow_cid' => expand_acl($rr['allow_cid']),
+ 'allow_gid' => expand_acl($rr['allow_gid']),
+ 'deny_cid' => expand_acl($rr['deny_cid']),
+ 'deny_gid' => expand_acl($rr['deny_gid']),
+ 'categories' => $categories
+ );
+ }
+ }
+
+ if($export) {
+ header('Content-type: text/calendar');
+ header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
+ echo ical_wrapper($r);
+ killme();
+ }
+
+ if (\App::$argv[1] === 'json'){
+ json_return_and_die($events);
+ }
+ }
+
+
+ if($mode === 'drop' && $event_id) {
+ $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
+ dbesc($event_id),
+ intval(local_channel())
+ );
+
+ $sync_event = $r[0];
+
+ if($r) {
+ $r = q("delete from event where event_hash = '%s' and uid = %d",
+ dbesc($event_id),
+ intval(local_channel())
+ );
+ if($r) {
+ $r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d",
+ dbesc($event_id),
+ intval(local_channel())
+ );
+ $sync_event['event_deleted'] = 1;
+ build_sync_packet(0,array('event' => array($sync_event)));
+ killme();
+ }
+ notice( t('Failed to remove event' ) . EOL);
+ killme();
+ }
+ }
+
+ }
+
+}
diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php
index 967e9521d..7c8d71210 100644
--- a/Zotlabs/Module/Connections.php
+++ b/Zotlabs/Module/Connections.php
@@ -127,6 +127,20 @@ class Connections extends \Zotlabs\Web\Controller {
$unblocked = true;
}
+ switch($_REQUEST['order']) {
+ case 'name_desc':
+ $sql_order = 'xchan_name DESC';
+ break;
+ case 'connected':
+ $sql_order = 'abook_created';
+ break;
+ case 'connected_desc':
+ $sql_order = 'abook_created DESC';
+ break;
+ default:
+ $sql_order = 'xchan_name';
+ }
+
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$tabs = array(
@@ -233,7 +247,7 @@ class Connections extends \Zotlabs\Web\Controller {
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
- WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
+ WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY $sql_order LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(App::$pager['itemspage']),
intval(App::$pager['start'])
@@ -307,7 +321,7 @@ class Connections extends \Zotlabs\Web\Controller {
'ignore_hover' => t('Ignore connection'),
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
'recent_label' => t('Recent activity'),
- 'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']),
+ 'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
'oneway' => $oneway
);
}
@@ -329,7 +343,7 @@ class Connections extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$o .= replace_macros(get_markup_template('connections.tpl'),array(
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php
index a587324df..acd7cb769 100644
--- a/Zotlabs/Module/Connedit.php
+++ b/Zotlabs/Module/Connedit.php
@@ -848,7 +848,7 @@ class Connedit extends \Zotlabs\Web\Controller {
$locstr = unpunify($contact['xchan_url']);
$clone_warn = '';
- $clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false);
+ $clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
if(! $clonable) {
$clone_warn = '<strong>';
$clone_warn .= ((intval($contact['abook_not_here']))
diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php
index b911ac991..d97014f9c 100644
--- a/Zotlabs/Module/Cover_photo.php
+++ b/Zotlabs/Module/Cover_photo.php
@@ -48,6 +48,32 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
+
+ // Remove cover photo
+ if(isset($_POST['remove'])) {
+
+ $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
+ intval(PHOTO_COVER),
+ intval(local_channel())
+ );
+
+ if($r) {
+ q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_COVER),
+ intval(local_channel())
+ );
+
+ $sync = attach_export_data($channel,$r[0]['resource_id']);
+ if($sync)
+ build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ }
+
+ // Update directory in background
+ \Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
+
+ goaway(z_root() . '/cover_photo');
+ }
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
@@ -106,7 +132,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if(file_exists($tmp_name)) {
$base_image = $r[0];
$gis = getimagesize($tmp_name);
-logger('gis: ' . print_r($gis,true));
+ logger('gis: ' . print_r($gis,true), LOGGER_DEBUG);
$base_image['width'] = $gis[0];
$base_image['height'] = $gis[1];
$base_image['content'] = @file_get_contents($tmp_name);
@@ -167,25 +193,18 @@ logger('gis: ' . print_r($gis,true));
'filename' => $base_image['filename'],
'album' => t('Cover Photos'),
'os_path' => $base_image['os_path'],
- 'display_path' => $base_image['display_path']
+ 'display_path' => $base_image['display_path'],
+ 'photo_usage' => PHOTO_COVER
];
-
- $p['imgscale'] = 7;
- $p['photo_usage'] = PHOTO_COVER;
-
- $r1 = $im->save($p);
+
+ $r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
$im->doScaleImage(850,310);
- $p['imgscale'] = 8;
-
- $r2 = $im->save($p);
-
+ $r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
$im->doScaleImage(425,160);
- $p['imgscale'] = 9;
-
- $r3 = $im->save($p);
-
+ $r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
+
if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL );
@@ -193,13 +212,28 @@ logger('gis: ' . print_r($gis,true));
dbesc($base_image['resource_id']),
local_channel()
);
+
+ $x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale >= 7",
+ dbesc($base_image['resource_id']),
+ local_channel()
+ );
+ if($x) {
+ foreach($x as $xx) {
+ @unlink(dbunescbin($xx['content']));
+ }
+ }
+
return;
}
-
- $channel = \App::get_channel();
+
$this->send_cover_photo_activity($channel,$base_image,$profile);
-
-
+
+ $sync = attach_export_data($channel,$base_image['resource_id']);
+ if($sync)
+ build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+
+ // Update directory in background
+ \Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
}
else
notice( t('Unable to process image') . EOL);
@@ -215,7 +249,7 @@ logger('gis: ' . print_r($gis,true));
require_once('include/attach.php');
- $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
+ $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
logger('attach_store: ' . print_r($res,true));
@@ -393,6 +427,7 @@ logger('gis: ' . print_r($gis,true));
'$lbl_profiles' => t('Select a profile:'),
'$title' => t('Change Cover Photo'),
'$submit' => t('Upload'),
+ '$remove' => t('Remove'),
'$profiles' => $profiles,
'$embedPhotos' => t('Use a photo from your albums'),
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php
index c29fa8326..8f5db6635 100644
--- a/Zotlabs/Module/Directory.php
+++ b/Zotlabs/Module/Directory.php
@@ -103,8 +103,14 @@ class Directory extends \Zotlabs\Web\Controller {
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
if($suggest) {
-
- $r = suggestion_query(local_channel(),get_observer_hash());
+
+ // the directory options have no effect in suggestion mode
+
+ $globaldir = 1;
+ $safe_mode = 1;
+ $type = 0;
+
+ $r = suggestion_query(local_channel(),get_observer_hash(),0,60);
if(! $r) {
notice( t('No default suggestions were found.') . EOL);
@@ -212,12 +218,17 @@ class Directory extends \Zotlabs\Web\Controller {
if($j) {
if($j['results']) {
-
+
+ $results = $j['results'];
+ if($suggest) {
+ $results = self::reorder_results($results,$addresses);
+ }
+
$entries = array();
$photo = 'thumb';
- foreach($j['results'] as $rr) {
+ foreach($results as $rr) {
$profile_link = chanlink_url($rr['url']);
@@ -399,7 +410,7 @@ class Directory extends \Zotlabs\Web\Controller {
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
- $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
+ $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array(
'$search' => $search,
'$desc' => t('Find'),
@@ -438,5 +449,22 @@ class Directory extends \Zotlabs\Web\Controller {
return $o;
}
-
+ static public function reorder_results($results,$suggests) {
+
+ if(! $suggests)
+ return $results;
+
+ $out = [];
+ foreach($suggests as $k => $v) {
+ foreach($results as $rv) {
+ if($k == $rv['address']) {
+ $out[intval($v)] = $rv;
+ break;
+ }
+ }
+ }
+
+ return $out;
+ }
+
}
diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php
index 81942860f..26cb82044 100644
--- a/Zotlabs/Module/Dirsearch.php
+++ b/Zotlabs/Module/Dirsearch.php
@@ -116,12 +116,12 @@ class Dirsearch extends \Zotlabs\Web\Controller {
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
if($address)
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
- if($city)
- $sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$city);
+ if($locale)
+ $sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$locale);
if($region)
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
- if($post)
- $sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$post);
+ if($postcode)
+ $sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$postcode);
if($country)
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
if($gender)
diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php
index 04e5f9fce..5983578b3 100644
--- a/Zotlabs/Module/Display.php
+++ b/Zotlabs/Module/Display.php
@@ -175,6 +175,11 @@ class Display extends \Zotlabs\Web\Controller {
return '';
}
}
+ if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
+ call_hooks('item_custom_display',$target_item);
+ notice( t('Page not found.') . EOL);
+ return '';
+ }
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
@@ -233,7 +238,7 @@ class Display extends \Zotlabs\Web\Controller {
'$dbegin' => '',
'$verb' => '',
'$net' => '',
- '$mid' => $mid
+ '$mid' => (($mid) ? urlencode($mid) : '')
));
head_add_link([
diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php
index 2c125b7a9..0fc36dc29 100644
--- a/Zotlabs/Module/Dreport.php
+++ b/Zotlabs/Module/Dreport.php
@@ -16,17 +16,20 @@ class Dreport extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
$mid = ((argc() > 1) ? argv(1) : '');
+ $encoded_mid = '';
- if(strpos($mid,'b64.') === 0)
+ if(strpos($mid,'b64.') === 0) {
+ $encoded_mid = $mid;
$mid = @base64url_decode(substr($mid,4));
-
-
+ }
if($mid === 'push') {
$table = 'push';
$mid = ((argc() > 2) ? argv(2) : '');
- if(strpos($mid,'b64.') === 0)
+ if(strpos($mid,'b64.') === 0) {
+ $encoded_mid = $mid;
$mid = @base64url_decode(substr($mid,4));
+ }
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 )) ",
@@ -40,7 +43,7 @@ class Dreport extends \Zotlabs\Web\Controller {
}
}
sleep(3);
- goaway(z_root() . '/dreport/' . urlencode($mid));
+ goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid));
}
if($mid === 'mail') {
@@ -159,6 +162,7 @@ class Dreport extends \Zotlabs\Web\Controller {
'$title' => sprintf( t('Delivery report for %1$s'),basename($mid)) . '...',
'$table' => $table,
'$mid' => urlencode($mid),
+ '$safe_mid' => urlencode(gen_link_id($mid)),
'$options' => t('Options'),
'$push' => t('Redeliver'),
'$entries' => $entries
diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php
index 1c9068e07..49b2892e8 100644
--- a/Zotlabs/Module/Editpost.php
+++ b/Zotlabs/Module/Editpost.php
@@ -45,7 +45,8 @@ class Editpost extends \Zotlabs\Web\Controller {
}
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
- goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
+ goaway(z_root() . '/cdav/calendar/' . $itm[0]['resource_id']);
+ //goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
}
$owner_uid = $itm[0]['uid'];
diff --git a/Zotlabs/Module/Embedphotos.php b/Zotlabs/Module/Embedphotos.php
index 2df14c239..8b0421457 100644
--- a/Zotlabs/Module/Embedphotos.php
+++ b/Zotlabs/Module/Embedphotos.php
@@ -41,24 +41,44 @@ class Embedphotos extends \Zotlabs\Web\Controller {
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
}
$resource_id = array_pop(explode('/', $href));
- $r = q("SELECT obj from item where resource_type = 'photo' and resource_id = '%s' limit 1",
- dbesc($resource_id)
+ $x = self::photolink($resource_id);
+ if($x)
+ json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));
+ json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
+ }
+ }
+
+
+ protected static function photolink($resource) {
+ $channel = \App::get_channel();
+ $output = EMPTY_STR;
+ if($channel) {
+ $resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 2 : 3);
+ $r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
+ dbesc($resource),
+ intval($resolution),
+ intval($channel['channel_id'])
);
- if (!$r) {
- json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
- }
- $obj = json_decode($r[0]['obj'], true);
- if (x($obj, 'body')) {
- $photolink = $obj['body'];
- } elseif (x($obj, 'bbcode')) {
- $photolink = $obj['bbcode'];
- } else {
- json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
- }
- json_return_and_die(array('status' => true, 'photolink' => $photolink, 'resource_id' => $resource_id));
+ if(! $r)
+ return $output;
+
+ if($r[0]['mimetype'] === 'image/jpeg')
+ $ext = '.jpg';
+ elseif($r[0]['mimetype'] === 'image/png')
+ $ext = '.png';
+ elseif($r[0]['mimetype'] === 'image/gif')
+ $ext = '.gif';
+ else
+ $ext = EMPTY_STR;
+
+ $output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' .
+ '[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]';
+
+ return $output;
}
}
+
/**
* @brief Get photos from an album.
*
diff --git a/Zotlabs/Module/Getfile.php b/Zotlabs/Module/Getfile.php
index abc9f50d9..583cf38f0 100644
--- a/Zotlabs/Module/Getfile.php
+++ b/Zotlabs/Module/Getfile.php
@@ -35,7 +35,6 @@ class Getfile extends \Zotlabs\Web\Controller {
$sig = $_POST['signature'];
$resource = $_POST['resource'];
$revision = intval($_POST['revision']);
- $resolution = (-1);
if(! $hash)
killme();
@@ -81,9 +80,14 @@ class Getfile extends \Zotlabs\Web\Controller {
killme();
}
- if(substr($resource,-2,1) == '-') {
+ if(isset($_POST['resolution']))
+ $resolution = intval($_POST['resolution']);
+ elseif(substr($resource,-2,1) == '-') {
$resolution = intval(substr($resource,-1,1));
$resource = substr($resource,0,-2);
+ }
+ else {
+ $resolution = (-1);
}
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
@@ -106,9 +110,10 @@ class Getfile extends \Zotlabs\Web\Controller {
}
if($resolution > 0) {
- $r = q("select * from photo where resource_id = '%s' and uid = %d limit 1",
+ $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1",
dbesc($resource),
- intval($channel['channel_id'])
+ intval($channel['channel_id']),
+ $resolution
);
if($r) {
header('Content-type: ' . $r[0]['mimetype']);
diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php
index 3535ac71a..848fe3e25 100644
--- a/Zotlabs/Module/Hq.php
+++ b/Zotlabs/Module/Hq.php
@@ -194,7 +194,7 @@ class Hq extends \Zotlabs\Web\Controller {
'$dbegin' => '',
'$verb' => '',
'$net' => '',
- '$mid' => $mid
+ '$mid' => (($mid) ? urlencode($mid) : '')
]);
}
diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php
index 0daf28aa9..18cb5560e 100644
--- a/Zotlabs/Module/Import.php
+++ b/Zotlabs/Module/Import.php
@@ -8,6 +8,8 @@ require_once('include/import.php');
require_once('include/perm_upgrade.php');
require_once('library/urlify/URLify.php');
+use Zotlabs\Lib\Libzot;
+
/**
* @brief Module for channel import.
@@ -228,13 +230,45 @@ class Import extends \Zotlabs\Web\Controller {
);
// reset the original primary hubloc if it is being seized
-
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
);
}
+
+ // create a new zot6 hubloc if we have got a channel_portable_id
+ if($channel['channel_portable_id']) {
+ $r = hubloc_store_lowlevel(
+ [
+ 'hubloc_guid' => $channel['channel_guid'],
+ 'hubloc_guid_sig' => 'sha256.' . $channel['channel_guid_sig'],
+ 'hubloc_hash' => $channel['channel_portable_id'],
+ 'hubloc_addr' => channel_reddress($channel),
+ 'hubloc_network' => 'zot6',
+ 'hubloc_primary' => (($seize) ? 1 : 0),
+ 'hubloc_url' => z_root(),
+ 'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
+ 'hubloc_host' => \App::get_hostname(),
+ 'hubloc_callback' => z_root() . '/zot',
+ 'hubloc_sitekey' => get_config('system','pubkey'),
+ 'hubloc_updated' => datetime_convert(),
+ 'hubloc_id_url' => channel_url($channel),
+ 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
+
+ ]
+ );
+
+ // reset the original primary hubloc if it is being seized
+ if($seize) {
+ $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
+ dbesc($channel['channel_portable_id']),
+ dbesc(z_root())
+ );
+ }
+
+ }
+
}
logger('import step 5');
@@ -246,8 +280,9 @@ class Import extends \Zotlabs\Web\Controller {
// replace any existing xchan we may have on this site if we're seizing control
- $r = q("delete from xchan where xchan_hash = '%s'",
- dbesc($channel['channel_hash'])
+ $r = q("delete from xchan where ( xchan_hash = '%s' or xchan_hash = '%s' ) ",
+ dbesc($channel['channel_hash']),
+ dbesc($channel['channel_portable_id'])
);
$r = xchan_store_lowlevel(
@@ -269,6 +304,30 @@ class Import extends \Zotlabs\Web\Controller {
'xchan_name_date' => datetime_convert()
]
);
+
+ if($channel['channel_portable_id']) {
+ $r = xchan_store_lowlevel(
+ [
+ 'xchan_hash' => \Zotlabs\Lib\Libzot::make_xchan_hash($channel['channel_guid'],$channel['channel_pubkey']),
+ 'xchan_guid' => $channel['channel_guid'],
+ 'xchan_guid_sig' => 'sha256.' . $channel['channel_guid_sig'],
+ 'xchan_pubkey' => $channel['channel_pubkey'],
+ 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'],
+ 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'],
+ 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'],
+ 'xchan_addr' => channel_reddress($channel),
+ 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'],
+ 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
+ 'xchan_follow' => z_root() . '/follow?f=&url=%s',
+ 'xchan_name' => $channel['channel_name'],
+ 'xchan_network' => 'zot6',
+ 'xchan_photo_date' => datetime_convert(),
+ 'xchan_name_date' => datetime_convert()
+ ]
+ );
+ }
+
+
}
logger('import step 6');
@@ -278,10 +337,20 @@ class Import extends \Zotlabs\Web\Controller {
if($xchans) {
foreach($xchans as $xchan) {
- $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
- if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
- logger('forged xchan: ' . print_r($xchan,true));
- continue;
+ if($xchan['xchan_network'] === 'zot') {
+ $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']);
+ if($hash !== $xchan['xchan_hash']) {
+ logger('forged xchan: ' . print_r($xchan,true));
+ continue;
+ }
+ }
+
+ if($xchan['xchan_network'] === 'zot6') {
+ $zhash = \Zotlabs\Lib\Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']);
+ if($zhash !== $xchan['xchan_hash']) {
+ logger('forged xchan: ' . print_r($xchan,true));
+ continue;
+ }
}
if(! array_key_exists('xchan_hidden',$xchan)) {
@@ -472,6 +541,9 @@ class Import extends \Zotlabs\Web\Controller {
if(is_array($data['app']))
import_apps($channel,$data['app']);
+ if(is_array($data['sysapp']))
+ import_sysapps($channel,$data['sysapp']);
+
if(is_array($data['chatroom']))
import_chatrooms($channel,$data['chatroom']);
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index ebcf632ef..6bc8c645f 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -40,56 +40,78 @@ class Item extends Controller {
function init() {
- if(Libzot::is_zot_request()) {
+ if (Libzot::is_zot_request()) {
$conversation = false;
$item_id = argv(1);
- if(! $item_id)
+ if (! $item_id)
http_status_exit(404, 'Not found');
-
$portable_id = EMPTY_STR;
- $sigdata = HTTPSig::verify(EMPTY_STR);
- if($sigdata['portable_id'] && $sigdata['header_valid']) {
- $portable_id = $sigdata['portable_id'];
- }
-
$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 ";
- $sql_extra = item_permissions_sql(0);
+ $i = null;
+
+ // do we have the item (at all)?
- $r = q("select * from item where mid = '%s' $item_normal $sql_extra limit 1",
+ $r = q("select * from item where mid = '%s' $item_normal limit 1",
dbesc(z_root() . '/item/' . $item_id)
);
- if(! $r) {
+ 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'];
+ observer_auth($portable_id);
+
+ // first see if we have a copy of this item's parent owned by the current signer
+ // include xchans for all zot-like networks - these will have the same guid and public key
- $r = q("select * from item where mid = '%s' $item_normal limit 1",
- dbesc(z_root() . '/item/' . $item_id)
+ $x = q("select * from xchan where xchan_hash = '%s'",
+ dbesc($sigdata['portable_id'])
);
- if($r) {
- http_status_exit(403, 'Forbidden');
+
+ if ($x) {
+ $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
+ dbesc($sigdata['portable_id']),
+ dbesc($x[0]['xchan_guid']),
+ dbesc($x[0]['xchan_pubkey'])
+ );
+
+ if ($xchans) {
+ $hashes = ids_to_querystr($xchans,'xchan_hash',true);
+ $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
+ }
}
- http_status_exit(404, 'Not found');
}
+ // 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
- $items = q("select parent as item_id from item where mid = '%s' and uid = %d $item_normal $sql_extra ",
- dbesc($r[0]['parent_mid']),
- intval($r[0]['uid'])
- );
- if(! $items) {
- http_status_exit(404, 'Not found');
+ $sql_extra = item_permissions_sql(0);
+
+ if (! $i) {
+ $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
}
- $r = $items;
+ if(! $i) {
+ http_status_exit(403,'Forbidden');
+ }
- $parents_str = ids_to_querystr($r,'item_id');
+ $parents_str = ids_to_querystr($i,'item_id');
- $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal $sql_extra ",
+ $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
dbesc($parents_str)
);
@@ -97,9 +119,8 @@ class Item extends Controller {
http_status_exit(404, 'Not found');
}
- $r = $items;
- xchan_query($r,true);
- $items = fetch_post_tags($r,true);
+ xchan_query($items,true);
+ $items = fetch_post_tags($items,true);
$observer = App::get_observer();
$parent = $items[0];
@@ -145,7 +166,7 @@ class Item extends Controller {
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
http_status_exit(403, 'Forbidden');
- $i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection',( defined('NOMADIC') ? false : true));
+ $i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
if($portable_id) {
ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id);
}
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
index 3d1f503b6..052d51d43 100644
--- a/Zotlabs/Module/Like.php
+++ b/Zotlabs/Module/Like.php
@@ -491,7 +491,7 @@ class Like extends \Zotlabs\Web\Controller {
$arr['item_flags'] = $item_flags;
$arr['item_wall'] = $item_wall;
- $arr['parent_mid'] = (($extended_like) ? $mid : $item['mid']);
+ $arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
@@ -546,7 +546,7 @@ class Like extends \Zotlabs\Web\Controller {
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
intval($post_id),
- dbesc($mid),
+ dbesc($arr['mid']),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id),
@@ -555,7 +555,7 @@ class Like extends \Zotlabs\Web\Controller {
$r = q("select * from likes where liker = '%s' and likee = '%s' and i_mid = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' ",
dbesc($observer['xchan_hash']),
dbesc($ch[0]['channel_hash']),
- dbesc($mid),
+ dbesc($arr['mid']),
dbesc($activity),
dbesc(($tgttype)? $tgttype : $objtype),
dbesc($obj_id)
diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php
index 32b4c0281..b9f90deec 100644
--- a/Zotlabs/Module/Linkinfo.php
+++ b/Zotlabs/Module/Linkinfo.php
@@ -69,6 +69,14 @@ class Linkinfo extends \Zotlabs\Web\Controller {
killme();
}
if(stripos($type,'video/') !== false) {
+ $thumb = self::get_video_poster($url);
+ if($thumb) {
+ if ($zrl)
+ echo $br . '[zvideo poster=\'' . $thumb . '\']' . $url . '[/zvideo]' . $br;
+ else
+ echo $br . '[video poster=\'' . $thumb . '\']' . $url . '[/video]' . $br;
+ killme();
+ }
if($zrl)
echo $br . '[zvideo]' . $url . '[/zvideo]' . $br;
else
@@ -216,7 +224,42 @@ class Linkinfo extends \Zotlabs\Web\Controller {
return($complete);
}
-
+
+ public static function get_video_poster($url) {
+
+ if(strpos($url,z_root() . '/cloud/') === false) {
+ return EMPTY_STR;
+ }
+ $m = parse_url($url,PHP_URL_PATH);
+ if($m) {
+ // strip leading '/cloud/'
+ $m = substr($m,7);
+ }
+ $nick = substr($m,0,strpos($m,'/'));
+ $p = substr($m,strpos($m,'/')+1);
+
+ // get the channel to check permissions
+
+ $u = channelx_by_nick($nick);
+
+ if($u && $p) {
+
+ $sql_extra = permissions_sql(intval($u['channel_id']));
+
+ $r = q("select hash, content from attach where display_path = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1",
+ dbesc($p),
+ intval($u['channel_id'])
+ );
+ if($r) {
+ $path = dbunescbin($r[0]['content']);
+ if($path && @file_exists($path . '.thumb')) {
+ return z_root() . '/poster/' . $nick . '/' . $r[0]['hash'];
+ }
+ }
+ }
+ return EMPTY_STR;
+ }
+
public static function parseurl_getsiteinfo($url) {
$siteinfo = array();
diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php
index 71737eef8..e8e960574 100644
--- a/Zotlabs/Module/Magic.php
+++ b/Zotlabs/Module/Magic.php
@@ -169,8 +169,8 @@ class Magic extends \Zotlabs\Web\Controller {
$token = $j['token'];
}
- $x = strpbrk($dest,'?&');
- $args = (($x) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
+ $strp = strpbrk($dest,'?&');
+ $args = (($strp) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : '');
goaway($dest . $args);
}
}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index 2019082ed..1c16e34ef 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -368,19 +368,19 @@ class Network extends \Zotlabs\Web\Controller {
'$static' => $static,
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
- '$search' => (($search) ? $search : ''),
- '$xchan' => $xchan,
+ '$search' => (($search) ? urlencode($search) : ''),
+ '$xchan' => (($xchan) ? urlencode($xchan) : ''),
'$order' => $order,
- '$file' => $file,
- '$cats' => urlencode($category),
- '$tags' => urlencode($hashtags),
+ '$file' => (($file) ? urlencode($file) : ''),
+ '$cats' => (($category) ? urlencode($category) : ''),
+ '$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$dend' => $datequery,
'$mid' => '',
- '$verb' => $verb,
- '$net' => $net,
+ '$verb' => (($verb) ? urlencode($verb) : ''),
+ '$net' => (($net) ? urlencode($net) : ''),
'$dbegin' => $datequery2,
- '$pf' => (($pf) ? $pf : '0'),
- '$unseen' => $unseen
+ '$pf' => (($pf) ? intval($pf) : 0),
+ '$unseen' => (($unseen) ? urlencode($unseen) : '')
));
}
diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php
index c0d8e15e5..3977ac8dd 100644
--- a/Zotlabs/Module/Oep.php
+++ b/Zotlabs/Module/Oep.php
@@ -456,7 +456,7 @@ class Oep extends \Zotlabs\Web\Controller {
if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) {
$chn = $matches[3];
- $res = hex2bin(basename($url));
+ $res = basename($url);
}
if(! ($chn && $res))
diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php
index ad57f883c..cf116a96c 100644
--- a/Zotlabs/Module/Owa.php
+++ b/Zotlabs/Module/Owa.php
@@ -30,12 +30,29 @@ class Owa extends \Zotlabs\Web\Controller {
$keyId = $sigblock['keyId'];
if($keyId) {
+
+ // Hubzilla connections can have both zot and zot6 hublocs
+ // The connections will usually be zot so match those first
+
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
- where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
+ where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) and hubloc_network = 'zot' ",
dbesc(str_replace('acct:','',$keyId)),
dbesc($keyId)
);
- if(! $r) {
+
+ // If nothing was found, try searching on any network
+
+ if (! $r) {
+ $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
+ where ( hubloc_addr = '%s' or hubloc_id_url = '%s' )",
+ dbesc(str_replace('acct:','',$keyId)),
+ dbesc($keyId)
+ );
+ }
+
+ // If nothing was found on any network, use network discovery and create a new record
+
+ if (! $r) {
$found = discover_by_webbie(str_replace('acct:','',$keyId));
if($found) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
@@ -45,7 +62,8 @@ class Owa extends \Zotlabs\Web\Controller {
);
}
}
- if($r) {
+
+ if ($r) {
foreach($r as $hubloc) {
$verified = \Zotlabs\Web\HTTPSig::verify(file_get_contents('php://input'),$hubloc['xchan_pubkey']);
if($verified && $verified['header_signed'] && $verified['header_valid']) {
@@ -53,7 +71,7 @@ class Owa extends \Zotlabs\Web\Controller {
logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA);
$ret['success'] = true;
$token = random_string(32);
- \Zotlabs\Lib\Verify::create('owt',0,$token,$hubloc['hubloc_addr']);
+ \Zotlabs\Lib\Verify::create('owt',0,$token,$hubloc['hubloc_network'] . ',' . $hubloc['hubloc_addr']);
$result = '';
openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
$ret['encrypted_token'] = base64url_encode($result);
diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php
index 96a4e1f40..0dc6d0194 100644
--- a/Zotlabs/Module/Photo.php
+++ b/Zotlabs/Module/Photo.php
@@ -40,7 +40,7 @@ class Photo extends \Zotlabs\Web\Controller {
call_hooks('cache_mode_hook', $cache_mode);
$observer_xchan = get_observer_hash();
- $ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
+ $cachecontrol = '';
if(isset($type)) {
@@ -68,39 +68,44 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
- $modified = filemtime($default);
- $default = z_root() . '/' . $default;
$uid = $person;
+
+ $data = '';
- $d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
- call_hooks('get_profile_photo',$d);
-
- $resolution = $d['imgscale'];
- $uid = $d['channel_id'];
- $default = $d['default'];
- $data = $d['data'];
- $mimetype = $d['mimetype'];
-
+ $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
+ intval($resolution),
+ intval($uid),
+ intval(PHOTO_PROFILE)
+ );
+ if($r) {
+ $modified = strtotime($r[0]['edited'] . "Z");
+ $mimetype = $r[0]['mimetype'];
+ if(intval($r[0]['os_storage']))
+ $data = file_get_contents(dbunescbin($r[0]['content']));
+ else
+ $data = dbunescbin($r[0]['content']);
+ }
+
if(! $data) {
- $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
- intval($resolution),
- intval($uid),
- intval(PHOTO_PROFILE)
- );
- if($r) {
- $modified = strtotime($r[0]['edited'] . "Z");
- $data = dbunescbin($r[0]['content']);
- $mimetype = $r[0]['mimetype'];
- }
- if(intval($r[0]['os_storage']))
- $data = file_get_contents($data);
+ $d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
+ call_hooks('get_profile_photo',$d);
+
+ $resolution = $d['imgscale'];
+ $uid = $d['channel_id'];
+ $default = $d['default'];
+ $data = $d['data'];
+ $mimetype = $d['mimetype'];
+ $modified = 0;
}
if(! $data) {
- $x = z_fetch_url($default,true,0,[ 'novalidate' => true ]);
+ $x = z_fetch_url(z_root() . '/' . $default, true, 0, [ 'novalidate' => true ]);
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
$mimetype = 'image/png';
+ $modified = filemtime($default);
}
+
+ $cachecontrol = ', must-revalidate';
}
else {
@@ -157,18 +162,19 @@ class Photo extends \Zotlabs\Web\Controller {
$allowed = (-1);
if($u === PHOTO_CACHE) {
// Validate cache
- $cache = array(
- 'resid' => $photo,
- 'status' => false
- );
- if($cache_mode['on'])
+ if($cache_mode['on']) {
+ $cache = array(
+ 'resid' => $photo,
+ 'status' => false
+ );
call_hooks('cache_url_hook', $cache);
- if(! $cache['status']) {
- $url = htmlspecialchars_decode($r[0]['display_path']);
- if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false)
- $url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
- header("Location: " . $url);
- killme();
+ if(! $cache['status']) {
+ $url = htmlspecialchars_decode($r[0]['display_path']);
+ // SSLify if needed
+ if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false)
+ $url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
+ goaway($url);
+ }
}
}
}
@@ -213,38 +219,23 @@ class Photo extends \Zotlabs\Web\Controller {
http_status_exit(404,'not found');
}
+ if(! $data)
+ killme();
+
+ $etag = md5($data . $modified);
+
+ if($modified == 0)
+ $modified = time();
+
header_remove('Pragma');
- if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
+ if($_SERVER['HTTP_IF_NONE_MATCH'] === $etag || $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
header_remove('Expires');
header_remove('Cache-Control');
header_remove('Set-Cookie');
http_status_exit(304,'not modified');
- }
-
- if(! isset($data)) {
- if(isset($resolution)) {
- switch($resolution) {
- case 4:
- $default = get_default_profile_photo();
- break;
- case 5:
- $default = get_default_profile_photo(80);
- break;
- case 6:
- $default = get_default_profile_photo(48);
- break;
- default:
- killme();
- // NOTREACHED
- break;
- }
- $x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]);
- $data = ($x['success'] ? $x['body'] : EMPTY_STR);
- $mimetype = 'image/png';
- }
}
-
+
if(isset($res) && intval($res) && $res < 500) {
$ph = photo_factory($data, $mimetype);
if($ph->is_valid()) {
@@ -281,12 +272,13 @@ class Photo extends \Zotlabs\Web\Controller {
$maxage = $expires - time();
header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
- header("Cache-Control: max-age=" . $maxage);
+ header("Cache-Control: max-age=" . $maxage . $cachecontrol);
}
header("Content-type: " . $mimetype);
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT");
+ header("ETag: " . $etag);
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
// If it's a file resource, stream it.
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index a761dbd14..13ec64ab9 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -239,95 +239,53 @@ class Photos extends \Zotlabs\Web\Controller {
intval($page_owner_uid)
);
if(count($r)) {
- $d = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($r[0]['content'])) : dbunescbin($r[0]['content']));
- $ph = photo_factory($d, $r[0]['mimetype']);
+
+ $ph = photo_factory(@file_get_contents(dbunescbin($r[0]['content'])), $r[0]['mimetype']);
if($ph->is_valid()) {
$rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
$ph->rotate($rotate_deg);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
-
- if(intval($r[0]['os_storage'])) {
- @file_put_contents($r[0]['content'],$ph->imageString());
- $data = $r[0]['content'];
- $fsize = @filesize($r[0]['content']);
- q("update attach set filesize = %d where hash = '%s' and uid = %d",
- intval($fsize),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
- }
- else {
- $data = $ph->imageString();
- $fsize = strlen($data);
- }
-
- $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
- dbesc(datetime_convert()),
- dbescbin($data),
- intval($fsize),
- intval($height),
- intval($width),
+
+ $edited = datetime_convert();
+
+ q("update attach set filesize = %d, edited = '%s' where hash = '%s' and uid = %d",
+ strlen($ph->imageString()),
+ dbescdate($edited),
dbesc($resource_id),
intval($page_owner_uid)
);
-
+
+ $ph->saveImage(dbunescbin($r[0]['content']));
+
+ $arr = [
+ 'aid' => get_account_id(),
+ 'uid' => intval($page_owner_uid),
+ 'resource_id' => dbesc($resource_id),
+ 'filename' => $r[0]['filename'],
+ 'imgscale' => 0,
+ 'album' => $r[0]['album'],
+ 'os_path' => $r[0]['os_path'],
+ 'os_storage' => 1,
+ 'os_syspath' => dbunescbin($r[0]['content']),
+ 'display_path' => $r[0]['display_path'],
+ 'photo_usage' => PHOTO_NORMAL,
+ 'edited' => dbescdate($edited)
+ ];
+
+ $ph->save($arr);
+
+ unset($arr['os_syspath']);
+
if($width > 1024 || $height > 1024)
$ph->scaleImage(1024);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
- $data = $ph->imageString();
- $fsize = strlen($data);
-
- $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
- dbesc(datetime_convert()),
- dbescbin($data),
- intval($fsize),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
-
+ $ph->storeThumbnail($arr, PHOTO_RES_1024);
+
if($width > 640 || $height > 640)
$ph->scaleImage(640);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
- $data = $ph->imageString();
- $fsize = strlen($data);
-
- $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
- dbesc(datetime_convert()),
- dbescbin($data),
- intval($fsize),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
-
-
+ $ph->storeThumbnail($arr, PHOTO_RES_640);
+
if($width > 320 || $height > 320)
$ph->scaleImage(320);
-
- $width = $ph->getWidth();
- $height = $ph->getHeight();
- $data = $ph->imageString();
- $fsize = strlen($data);
-
- $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
- dbesc(datetime_convert()),
- dbescbin($data),
- intval($fsize),
- intval($height),
- intval($width),
- dbesc($resource_id),
- intval($page_owner_uid)
- );
+ $ph->storeThumbnail($arr, PHOTO_RES_320);
}
}
}
@@ -848,7 +806,7 @@ class Photos extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template('photo_album.tpl');
$o .= replace_macros($tpl, array(
'$photos' => $photos,
@@ -1396,7 +1354,7 @@ class Photos extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template('photos_recent.tpl');
$o .= replace_macros($tpl, array(
'$title' => t('Recent Photos'),
diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php
index a367b1062..3dabe0f7b 100644
--- a/Zotlabs/Module/Ping.php
+++ b/Zotlabs/Module/Ping.php
@@ -447,7 +447,7 @@ class Ping extends \Zotlabs\Web\Controller {
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
$result[] = array(
- 'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
+ 'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
diff --git a/Zotlabs/Module/Poster.php b/Zotlabs/Module/Poster.php
new file mode 100644
index 000000000..10317ee61
--- /dev/null
+++ b/Zotlabs/Module/Poster.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use Zotlabs\Web\Controller;
+
+require_once('include/security.php');
+
+class Poster extends Controller {
+
+ function init() {
+
+ $nick = argv(1);
+ $hash = argv(2);
+
+ if(! ($nick && $hash)) {
+ return;
+ }
+
+ $u = channelx_by_nick($nick);
+
+ $sql_extra = permissions_sql(intval($u['channel_id']));
+
+ $r = q("select content from attach where hash = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1",
+ dbesc($hash),
+ intval($u['channel_id'])
+ );
+ if($r) {
+ $path = dbunescbin($r[0]['content']);
+ if($path && @file_exists($path . '.thumb')) {
+ header('Content-Type: image/jpeg');
+ echo file_get_contents($path . '.thumb');
+ killme();
+ }
+ }
+ }
+}
diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php
index 751c4338f..a812ca210 100644
--- a/Zotlabs/Module/Profile_photo.php
+++ b/Zotlabs/Module/Profile_photo.php
@@ -52,14 +52,39 @@ class Profile_photo extends \Zotlabs\Web\Controller {
return;
}
+ $channel = \App::get_channel();
+
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
+
+ // Remove cover photo
+ if(isset($_POST['remove'])) {
+
+ $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
+ intval(PHOTO_PROFILE),
+ intval(local_channel())
+ );
+
+ if($r) {
+ q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
+ intval(PHOTO_NORMAL),
+ intval(PHOTO_PROFILE),
+ intval(local_channel())
+ );
+
+ $sync = attach_export_data($channel,$r[0]['resource_id']);
+ if($sync)
+ build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ }
+
+ $_SESSION['reload_avatar'] = true;
+
+ goaway(z_root() . '/profiles');
+ }
if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
// logger('crop: ' . print_r($_POST,true));
-
-
// phase 2 - we have finished cropping
if(argc() != 2) {
@@ -119,39 +144,48 @@ class Profile_photo extends \Zotlabs\Web\Controller {
'filename' => $base_image['filename'],
'album' => t('Profile Photos'),
'os_path' => $base_image['os_path'],
- 'display_path' => $base_image['display_path']
+ 'display_path' => $base_image['display_path'],
+ 'photo_usage' => PHOTO_PROFILE,
+ 'edited' => dbescdate($base_image['edited'])
];
- $p['imgscale'] = PHOTO_RES_PROFILE_300;
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
- $r1 = $im->save($p);
+ $r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
$im->scaleImage(80);
- $p['imgscale'] = PHOTO_RES_PROFILE_80;
-
- $r2 = $im->save($p);
+ $r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
$im->scaleImage(48);
- $p['imgscale'] = PHOTO_RES_PROFILE_48;
-
- $r3 = $im->save($p);
-
+ $r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
+
if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL );
- $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d ) ",
+ $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
+ dbesc($base_image['resource_id']),
+ local_channel(),
+ intval(PHOTO_RES_PROFILE_300),
+ intval(PHOTO_RES_PROFILE_80),
+ intval(PHOTO_RES_PROFILE_48)
+ );
+
+ $x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale IN ( %d, %d, %d )",
dbesc($base_image['resource_id']),
local_channel(),
intval(PHOTO_RES_PROFILE_300),
intval(PHOTO_RES_PROFILE_80),
intval(PHOTO_RES_PROFILE_48)
);
+ if($x) {
+ foreach($x as $xx) {
+ @unlink(dbunescbin($xx['content']));
+ }
+ }
+
return;
}
- $channel = \App::get_channel();
-
// If setting for the default profile, unset the profile photo flag from any other photos I own
if($is_default_profile) {
@@ -198,7 +232,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
$r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
where xchan_hash = '%s'",
dbesc($im->getType()),
- dbesc(datetime_convert()),
+ dbescdate($base_image['edited']),
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']),
@@ -245,7 +279,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
else {
require_once('include/attach.php');
- $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash));
+ $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true));
logger('attach_store: ' . print_r($res,true));
}
@@ -353,20 +387,23 @@ class Profile_photo extends \Zotlabs\Web\Controller {
if($havescale) {
// unset any existing profile photos
- $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
+ $x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE),
- intval(local_channel()));
-
- $r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
+ intval(local_channel())
+ );
+
+ $edited = datetime_convert();
+
+ $x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
intval(PHOTO_PROFILE),
+ dbescdate($edited),
intval(local_channel()),
dbesc($resource_id)
- );
+ );
- $r = q("UPDATE xchan set xchan_photo_date = '%s'
- where xchan_hash = '%s'",
- dbesc(datetime_convert()),
+ $x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
+ dbescdate($edited),
dbesc($channel['xchan_hash'])
);
@@ -376,8 +413,10 @@ class Profile_photo extends \Zotlabs\Web\Controller {
if($sync)
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
+ $_SESSION['reload_avatar'] = true;
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
+
goaway(z_root() . '/profiles');
}
@@ -457,6 +496,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
'$lbl_profiles' => t('Select a profile:'),
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
'$submit' => (($importing) ? t('Use') : t('Upload')),
+ '$remove' => t('Remove'),
'$profiles' => $profiles,
'$single' => ((count($profiles) == 1) ? true : false),
'$profile0' => $profiles[0],
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index 94df29984..84ac42f72 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -149,11 +149,11 @@ class Pubstream extends \Zotlabs\Web\Controller {
'$order' => 'comment',
'$file' => '',
'$cats' => '',
- '$tags' => $hashtags,
+ '$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$dend' => '',
- '$mid' => $mid,
+ '$mid' => (($mid) ? urlencode($mid) : ''),
'$verb' => '',
- '$net' => $net,
+ '$net' => (($net) ? urlencode($net) : ''),
'$dbegin' => ''
));
}
diff --git a/Zotlabs/Module/React.php b/Zotlabs/Module/React.php
index 3920301f5..f80b04a3f 100644
--- a/Zotlabs/Module/React.php
+++ b/Zotlabs/Module/React.php
@@ -59,6 +59,14 @@ class React extends \Zotlabs\Web\Controller {
$n['body'] = "\n\n[zmg=32x32]" . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]' . "\n\n";
$n['author_xchan'] = $channel['channel_hash'];
+ $n['tgt_type'] = 'Image';
+ $n['target'] = [
+ 'type' => 'Image',
+ 'name' => $emoji,
+ 'url' => z_root() . '/images/emoji/' . $emoji . '.png'
+ ];
+
+
$x = item_store($n);
retain_item($postid);
diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php
index f9d81be0c..bc813f8e1 100644
--- a/Zotlabs/Module/Register.php
+++ b/Zotlabs/Module/Register.php
@@ -1,10 +1,11 @@
<?php
namespace Zotlabs\Module;
-require_once('include/channel.php');
+use Zotlabs\Web\Controller;
+require_once('include/security.php');
-class Register extends \Zotlabs\Web\Controller {
+class Register extends Controller {
function init() {
@@ -39,7 +40,9 @@ class Register extends \Zotlabs\Web\Controller {
function post() {
-
+
+ check_form_security_token_redirectOnErr('/register', 'register');
+
$max_dailies = intval(get_config('system','max_daily_registrations'));
if($max_dailies) {
$r = q("select count(account_id) as total from account where account_created > %s - INTERVAL %s",
@@ -269,7 +272,8 @@ class Register extends \Zotlabs\Web\Controller {
require_once('include/bbcode.php');
$o = replace_macros(get_markup_template('register.tpl'), array(
-
+
+ '$form_security_token' => get_form_security_token("register"),
'$title' => t('Registration'),
'$reg_is' => $registration_is,
'$registertext' => bbcode(get_config('system','register_text')),
diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php
index a27bf0fa5..0298b412e 100644
--- a/Zotlabs/Module/Settings/Calendar.php
+++ b/Zotlabs/Module/Settings/Calendar.php
@@ -36,7 +36,7 @@ class Calendar {
'$rpath' => $rpath,
'$action_url' => 'settings/' . $module,
'$form_security_token' => get_form_security_token('settings_' . $module),
- '$title' => t('CalDAV Settings'),
+ '$title' => t('Calendar Settings'),
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php
index 370b7b9f8..541e4fa21 100644
--- a/Zotlabs/Module/Setup.php
+++ b/Zotlabs/Module/Setup.php
@@ -39,12 +39,12 @@ class Setup extends \Zotlabs\Web\Controller {
ini_set('display_errors', '1');
// $baseurl/setup/testrewrite to test if rewrite in .htaccess is working
- if (argc() == 2 && argv(1) == "testrewrite") {
+ if(argc() == 2 && argv(1) == 'testrewrite') {
echo 'ok';
killme();
}
- if (x($_POST, 'pass')) {
+ if(x($_POST, 'pass')) {
$this->install_wizard_pass = intval($_POST['pass']);
} else {
$this->install_wizard_pass = 1;
@@ -63,7 +63,6 @@ class Setup extends \Zotlabs\Web\Controller {
return;
// implied break;
case 3:
- $urlpath = \App::get_path();
$dbhost = trim($_POST['dbhost']);
$dbport = intval(trim($_POST['dbport']));
$dbuser = trim($_POST['dbuser']);
@@ -89,7 +88,6 @@ class Setup extends \Zotlabs\Web\Controller {
return;
// implied break;
case 4:
- $urlpath = \App::get_path();
$dbhost = trim($_POST['dbhost']);
$dbport = intval(trim($_POST['dbport']));
$dbuser = trim($_POST['dbuser']);
@@ -162,7 +160,6 @@ class Setup extends \Zotlabs\Web\Controller {
*
* @return string parsed HTML output
*/
-
function get() {
$o = '';
@@ -213,10 +210,10 @@ class Setup extends \Zotlabs\Web\Controller {
}
if(x(\App::$data, 'txt') && strlen(\App::$data['txt'])) {
- $db_return_text .= $this->manual_config($a);
+ $db_return_text .= $this->manual_config();
}
- if ($db_return_text != "") {
+ if($db_return_text != '') {
$tpl = get_markup_template('install.tpl');
return replace_macros($tpl, array(
'$title' => $install_title,
@@ -242,7 +239,7 @@ class Setup extends \Zotlabs\Web\Controller {
$this->check_keys($checks);
- if (x($_POST, 'phpath'))
+ if(x($_POST, 'phpath'))
$phpath = notags(trim($_POST['phpath']));
$this->check_php($phpath, $checks);
@@ -278,7 +275,6 @@ class Setup extends \Zotlabs\Web\Controller {
$dbtype = intval(trim($_POST['dbtype']));
$phpath = trim($_POST['phpath']);
$adminmail = trim($_POST['adminmail']);
- $siteurl = trim($_POST['siteurl']);
$tpl = get_markup_template('install_db.tpl');
$o .= replace_macros($tpl, array(
@@ -320,7 +316,6 @@ class Setup extends \Zotlabs\Web\Controller {
$phpath = trim($_POST['phpath']);
$adminmail = trim($_POST['adminmail']);
- $siteurl = trim($_POST['siteurl']);
$timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
@@ -363,12 +358,12 @@ class Setup extends \Zotlabs\Web\Controller {
* @param string $help optional help string
*/
function check_add(&$checks, $title, $status, $required, $help = '') {
- $checks[] = array(
+ $checks[] = [
'title' => $title,
'status' => $status,
'required' => $required,
'help' => $help
- );
+ ];
}
/**
@@ -380,12 +375,12 @@ class Setup extends \Zotlabs\Web\Controller {
function check_php(&$phpath, &$checks) {
$help = '';
- if(version_compare(PHP_VERSION, '5.5') < 0) {
- $help .= t('PHP version 5.5 or greater is required.');
- $this->check_add($checks, t('PHP version'), false, false, $help);
+ if(version_compare(PHP_VERSION, '7.1') < 0) {
+ $help .= t('PHP version 7.1 or greater is required.');
+ $this->check_add($checks, t('PHP version'), false, true, $help);
}
- if (strlen($phpath)) {
+ if(strlen($phpath)) {
$passed = file_exists($phpath);
}
elseif(function_exists('shell_exec')) {
@@ -419,6 +414,7 @@ class Setup extends \Zotlabs\Web\Controller {
$result = trim(shell_exec($cmd));
else
$help .= t('Unable to check command line PHP, as shell_exec() is disabled. This is required.') . EOL;
+
$passed2 = (($result == $str) ? true : false);
if(!$passed2) {
$help .= t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL;
@@ -445,14 +441,14 @@ class Setup extends \Zotlabs\Web\Controller {
$result = getPhpiniUploadLimits();
if($result['post_max_size'] < 4194304 || $result['max_upload_filesize'] < 4194304) {
- $mem_warning = '<strong>' .t('This is not sufficient to upload larger images or files. You should be able to upload at least 4 MB at once.') . '</strong>';
- }
+ $mem_warning = '<strong>' .t('This is not sufficient to upload larger images or files. You should be able to upload at least 4 MB at once.') . '</strong>';
+ }
$help = sprintf(t('Your max allowed total upload size is set to %s. Maximum size of one file to upload is set to %s. You are allowed to upload up to %d files at once.'),
userReadableSize($result['post_max_size']),
userReadableSize($result['max_upload_filesize']),
$result['max_file_uploads']
);
- $help .= $mem_warning;
+ $help .= $mem_warning;
$help .= '<br><br>' . t('You can adjust these settings in the server php.ini file.');
$this->check_add($checks, t('PHP upload limits'), true, false, $help);
@@ -467,7 +463,7 @@ class Setup extends \Zotlabs\Web\Controller {
$help = '';
$res = false;
- if (function_exists('openssl_pkey_new')) {
+ if(function_exists('openssl_pkey_new')) {
$res = openssl_pkey_new(array(
'digest_alg' => 'sha1',
'private_key_bits' => 4096,
@@ -477,7 +473,7 @@ class Setup extends \Zotlabs\Web\Controller {
// Get private key
- if (! $res) {
+ if(! $res) {
$help .= t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL;
$help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
}
@@ -508,7 +504,7 @@ class Setup extends \Zotlabs\Web\Controller {
$this->check_add($ck_funcs, t('zip PHP module'), true, true);
if(function_exists('apache_get_modules')){
- if (! in_array('mod_rewrite', apache_get_modules())) {
+ if(! in_array('mod_rewrite', apache_get_modules())) {
$this->check_add($ck_funcs, t('Apache mod_rewrite module'), false, true, t('Error: Apache webserver mod-rewrite module is required but not installed.'));
} else {
$this->check_add($ck_funcs, t('Apache mod_rewrite module'), true, true);
@@ -577,7 +573,7 @@ class Setup extends \Zotlabs\Web\Controller {
$fname = '.htconfig.php';
- if((file_exists($fname) && is_writable($fname)) ||
+ if((file_exists($fname) && is_writable($fname)) ||
(! (file_exists($fname) && is_writable('.')))) {
$this->check_add($checks, t('.htconfig.php is writable'), $status, true, $help);
return;
@@ -643,7 +639,7 @@ class Setup extends \Zotlabs\Web\Controller {
$url = z_root() . '/setup/testrewrite';
- if (function_exists('curl_init')){
+ if(function_exists('curl_init')){
$test = z_fetch_url($url);
if(! $test['success']) {
if(strstr($url,'https://')) {
@@ -666,14 +662,13 @@ class Setup extends \Zotlabs\Web\Controller {
$help .= t('If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues.') . EOL;
$help .= t('This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement.') .EOL;
$help .= t('Providers are available that issue free certificates which are browser-valid.'). EOL;
-
$help .= t('If you are confident that the certificate is valid and signed by a trusted authority, check to see if you have failed to install an intermediate cert. These are not normally required by browsers, but are required for server-to-server communications.') . EOL;
$this->check_add($checks, t('SSL certificate validation'), false, true, $help);
}
}
- if ((! $test['success']) || ($test['body'] != "ok")) {
+ if((! $test['success']) || ($test['body'] != "ok")) {
$status = false;
$help = t('Url rewrite in .htaccess is not working. Check your server configuration.'.'Test: '.var_export($test,true));
}
@@ -687,10 +682,9 @@ class Setup extends \Zotlabs\Web\Controller {
/**
* @brief
*
- * @param App &$a
* @return string with paresed HTML
*/
- function manual_config(&$a) {
+ function manual_config() {
$data = htmlspecialchars(\App::$data['txt'], ENT_COMPAT, 'UTF-8');
$o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
$o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
@@ -700,14 +694,19 @@ class Setup extends \Zotlabs\Web\Controller {
function load_database_rem($v, $i){
$l = trim($i);
- if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
+ if(strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
return $v;
} else {
return $v."\n".$i;
}
}
-
+ /**
+ * @brief Executes the SQL install script and create database tables.
+ *
+ * @param dba_driver $db (unused)
+ * @return boolean|string false on success or error message as string
+ */
function load_database($db) {
$str = file_get_contents(\DBA::$dba->get_install_script());
$arr = explode(';', $str);
@@ -733,6 +732,12 @@ class Setup extends \Zotlabs\Web\Controller {
// install the standard theme
set_config('system', 'allowed_themes', 'redbasic');
+ // if imagick converter is installed, use it
+ if(@is_executable('/usr/bin/convert')) {
+ set_config('system','imagick_convert_path','/usr/bin/convert');
+ }
+
+
// Set a lenient list of ciphers if using openssl. Other ssl engines
// (e.g. NSS used in RedHat) require different syntax, so hopefully
// the default curl cipher list will work for most sites. If not,
@@ -767,12 +772,12 @@ class Setup extends \Zotlabs\Web\Controller {
/**
* @brief
*
- * @param unknown $v
+ * @param array $v
* @param array $c
* @return array
*/
static private function check_passed($v, $c) {
- if ($c['required'])
+ if($c['required'])
$v = $v && $c['status'];
return $v;
diff --git a/Zotlabs/Module/Subthread.php b/Zotlabs/Module/Subthread.php
index 54343fdfa..30e57197d 100644
--- a/Zotlabs/Module/Subthread.php
+++ b/Zotlabs/Module/Subthread.php
@@ -33,7 +33,7 @@ class Subthread extends \Zotlabs\Web\Controller {
if(! $i) {
$i = q("select * from item where id = %d and uid = %d",
- intval($postid),
+ intval($item_id),
intval($sys['channel_id'])
);
diff --git a/Zotlabs/Module/Tagger.php b/Zotlabs/Module/Tagger.php
index 24adf1bde..e6e80dce3 100644
--- a/Zotlabs/Module/Tagger.php
+++ b/Zotlabs/Module/Tagger.php
@@ -69,7 +69,7 @@ class Tagger extends \Zotlabs\Web\Controller {
$post_type = t('photo');
break;
case 'event':
- $targgettype = ACTIVITY_OBJ_EVENT;
+ $targettype = ACTIVITY_OBJ_EVENT;
$post_type = t('event');
break;
default:
diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php
index 0a5e86907..30df0b9e4 100644
--- a/Zotlabs/Module/Viewconnections.php
+++ b/Zotlabs/Module/Viewconnections.php
@@ -107,7 +107,7 @@ class Viewconnections extends \Zotlabs\Web\Controller {
killme();
}
else {
- $o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
+ $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template("viewcontact_template.tpl");
$o .= replace_macros($tpl, array(
'$title' => t('View Connections'),
diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php
index b73d81283..3e49b9db4 100644
--- a/Zotlabs/Module/Viewsrc.php
+++ b/Zotlabs/Module/Viewsrc.php
@@ -25,7 +25,7 @@ class Viewsrc extends \Zotlabs\Web\Controller {
notice( t('Item not found.') . EOL);
}
- $item_normal = item_normal();
+ $item_normal = item_normal_search();
if(local_channel() && $item_id) {
$r = q("select id, mid, item_flags, mimetype, item_obscured, body, llink, plink from item where uid in (%d , %d) and id = %d $item_normal limit 1",
diff --git a/Zotlabs/Module/Wall_attach.php b/Zotlabs/Module/Wall_attach.php
index 2250e6e44..0ede3ad90 100644
--- a/Zotlabs/Module/Wall_attach.php
+++ b/Zotlabs/Module/Wall_attach.php
@@ -96,9 +96,26 @@ class Wall_attach extends \Zotlabs\Web\Controller {
$s = "\n\n" . $r['body'] . "\n\n";
}
else {
- $s = "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
+ if(strpos($r['data']['filetype'],'video') === 0) {
+ // 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'];
+ $thumb = Linkinfo::get_video_poster($url);
+ if($thumb) {
+ $s = "\n\n" . '[zvideo poster=\'' . $thumb . '\']' . $url . '[/zvideo]' . "\n\n";
+ }
+ else {
+ $s = "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n";
+ }
+ }
+ if(strpos($r['data']['filetype'],'audio') === 0) {
+ $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
+ echo "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n";
+ }
+
+ $s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
}
-
$sync = attach_export_data($channel,$r['data']['hash']);
if($sync) {
diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php
index 03275abbc..a19bdbedc 100644
--- a/Zotlabs/Module/Wfinger.php
+++ b/Zotlabs/Module/Wfinger.php
@@ -128,7 +128,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
'http://webfinger.net/ns/name' => $r[0]['channel_name'],
'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name'],
'https://w3id.org/security/v1#publicKeyPem' => $r[0]['xchan_pubkey'],
- 'http://purl.org/zot/federation' => 'zot'
+ 'http://purl.org/zot/federation' => 'zot,zot6'
];
foreach($aliases as $alias)
diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php
index 502f96a62..169dc6de1 100644
--- a/Zotlabs/Module/Wiki.php
+++ b/Zotlabs/Module/Wiki.php
@@ -293,9 +293,9 @@ class Wiki extends Controller {
}
//$wikiheaderName = urldecode($wikiUrlName);
- $wikiheaderName = NativeWiki::name_decode($wikiUrlName);
+ $wikiheaderName = escape_tags(NativeWiki::name_decode($wikiUrlName));
//$wikiheaderPage = urldecode($pageUrlName);
- $wikiheaderPage = NativeWiki::name_decode($pageUrlName);
+ $wikiheaderPage = escape_tags(NativeWiki::name_decode($pageUrlName));
$renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page'));
$sharePage = t('Share');
@@ -373,13 +373,13 @@ class Wiki extends Controller {
$placeholder = t('Short description of your changes (optional)');
- $zrl = urlencode( z_root() . '/wiki/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . NativeWiki::name_encode($pageUrlName) );
+ $zrl = z_root() . '/wiki/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . NativeWiki::name_encode($pageUrlName);
$o .= replace_macros(get_markup_template('wiki.tpl'),array(
'$wikiheaderName' => $wikiheaderName,
'$wikiheaderPage' => $wikiheaderPage,
'$renamePage' => $renamePage,
'$sharePage' => $sharePage,
- '$shareLink' => '#^[zrl=' . $zrl . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]',
+ '$shareLink' => urlencode('#^[zrl=' . $zrl . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]'),
'$showPageControls' => $showPageControls,
'$editOrSourceLabel' => (($showPageControls) ? t('Edit') : t('Source')),
'$tools_label' => 'Page Tools',
diff --git a/Zotlabs/Photo/PhotoDriver.php b/Zotlabs/Photo/PhotoDriver.php
index c47a7c3b2..bacf926ff 100644
--- a/Zotlabs/Photo/PhotoDriver.php
+++ b/Zotlabs/Photo/PhotoDriver.php
@@ -448,6 +448,7 @@ abstract class PhotoDriver {
$p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth());
$p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight());
$p['expires'] = (($arr['expires']) ? $arr['expires'] : gmdate('Y-m-d H:i:s', time() + get_config('system', 'photo_cache_time', 86400)));
+ $p['profile'] = ((array_key_exists('profile', $arr)) ? intval($arr['profile']) : 0);
if(! intval($p['imgscale']))
logger('save: ' . print_r($arr, true), LOGGER_DATA);
@@ -481,18 +482,49 @@ abstract class PhotoDriver {
allow_gid = '%s',
deny_cid = '%s',
deny_gid = '%s',
- expires = '%s'
+ expires = '%s',
+ profile = %d
where id = %d",
- intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($x[0]['id']));
+ intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']), intval($x[0]['id']));
} else {
$p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']);
$r = q("INSERT INTO photo
- ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires )
- VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']));
+ ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires, profile )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']));
}
logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r));
return $r;
}
+
+ /**
+ * @brief Stores thumbnail to database or filesystem.
+ *
+ * @param array $arr
+ * @param scale int
+ * @return boolean|array
+ */
+ public function storeThumbnail($arr, $scale = 0) {
+
+ $arr['imgscale'] = $scale;
+
+ if(boolval(get_config('system','filesystem_storage_thumbnails', 0)) && $scale > 0) {
+ $channel = \App::get_channel();
+ $arr['os_storage'] = 1;
+ $arr['os_syspath'] = 'store/' . $channel['channel_address'] . '/' . $arr['os_path'] . '-' . $scale;
+ if(! $this->saveImage($arr['os_syspath']))
+ return false;
+ }
+ else
+ $arr['os_storage'] = 0;
+
+ if(! $this->save($arr)) {
+ if(array_key_exists('os_syspath', $arr))
+ @unlink($arr['os_syspath']);
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/Zotlabs/Render/SmartyInterface.php b/Zotlabs/Render/SmartyInterface.php
index 9c9a501c0..a40effecf 100755
--- a/Zotlabs/Render/SmartyInterface.php
+++ b/Zotlabs/Render/SmartyInterface.php
@@ -2,7 +2,10 @@
namespace Zotlabs\Render;
-class SmartyInterface extends \Smarty {
+use Smarty;
+use App;
+
+class SmartyInterface extends Smarty {
public $filename;
@@ -16,26 +19,27 @@ class SmartyInterface extends \Smarty {
// The order is thus very important here
$template_dirs = array('theme' => "view/theme/$thname/tpl/");
- if( x(\App::$theme_info,"extends") )
+ if ( x(App::$theme_info,"extends") ) {
$template_dirs = $template_dirs + array('extends' => "view/theme/" . \App::$theme_info["extends"] . "/tpl/");
+ }
$template_dirs = $template_dirs + array('base' => 'view/tpl/');
$this->setTemplateDir($template_dirs);
- $basecompiledir = \App::$config['system']['smarty3_folder'];
+ $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->left_delimiter = App::get_template_ldelim('smarty3');
+ $this->right_delimiter = App::get_template_rdelim('smarty3');
// Don't report errors so verbosely
$this->error_reporting = E_ALL & (~E_NOTICE);
}
function parsed($template = '') {
- if($template) {
+ if ($template) {
return $this->fetch('string:' . $template);
}
return $this->fetch('file:' . $this->filename);
diff --git a/Zotlabs/Render/SmartyTemplate.php b/Zotlabs/Render/SmartyTemplate.php
index f14d63064..61fb72f8a 100755
--- a/Zotlabs/Render/SmartyTemplate.php
+++ b/Zotlabs/Render/SmartyTemplate.php
@@ -2,28 +2,33 @@
namespace Zotlabs\Render;
+use App;
+
+
class SmartyTemplate implements TemplateEngine {
static $name ="smarty3";
- public function __construct(){
+ public function __construct() {
// Cannot use get_config() here because it is called during installation when there is no DB.
// FIXME: this may leak private information such as system pathnames.
- $basecompiledir = ((array_key_exists('smarty3_folder',\App::$config['system']))
- ? \App::$config['system']['smarty3_folder'] : '');
- if (!$basecompiledir) $basecompiledir = str_replace('Zotlabs','',dirname(__dir__)) . "/" . TEMPLATE_BUILD_PATH;
- if (!is_dir($basecompiledir)) {
+ $basecompiledir = ((array_key_exists('smarty3_folder', App::$config['system']))
+ ? App::$config['system']['smarty3_folder'] : '');
+ if (! $basecompiledir) {
+ $basecompiledir = str_replace('Zotlabs','',dirname(__dir__)) . "/" . TEMPLATE_BUILD_PATH;
+ }
+ if (! is_dir($basecompiledir)) {
@os_mkdir(TEMPLATE_BUILD_PATH, STORAGE_DEFAULT_PERMISSIONS, true);
- if (!is_dir($basecompiledir)) {
+ if (! is_dir($basecompiledir)) {
echo "<b>ERROR:</b> folder <tt>$basecompiledir</tt> does not exist."; killme();
}
}
- if(!is_writable($basecompiledir)){
+ if (! is_writable($basecompiledir)) {
echo "<b>ERROR:</b> folder <tt>$basecompiledir</tt> must be writable by webserver."; killme();
}
- \App::$config['system']['smarty3_folder'] = $basecompiledir;
+ App::$config['system']['smarty3_folder'] = $basecompiledir;
}
// TemplateEngine interface
@@ -31,18 +36,18 @@ class SmartyTemplate implements TemplateEngine {
public function replace_macros($s, $r) {
$template = '';
- // these are available for use in all templates
+ // macro or macros available for use in all templates
$r['$z_baseurl'] = z_root();
$r['$z_server_role'] = \Zotlabs\Lib\System::get_server_role();
$r['$z_techlevel'] = get_account_techlevel();
- if(gettype($s) === 'string') {
+ if (gettype($s) === 'string') {
$template = $s;
$s = new SmartyInterface();
}
- foreach($r as $key=>$value) {
- if($key[0] === '$') {
+ foreach ($r as $key=>$value) {
+ if ($key[0] === '$') {
$key = substr($key, 1);
}
$s->assign($key, $value);
@@ -50,32 +55,32 @@ class SmartyTemplate implements TemplateEngine {
return $s->parsed($template);
}
- public function get_markup_template($file, $root=''){
+ public function get_markup_template($file, $root = '') {
$template_file = theme_include($file, $root);
- if($template_file) {
+ if ($template_file) {
$template = new SmartyInterface();
$template->filename = $template_file;
return $template;
}
- return "";
+ return EMPTY_STR;
}
- public function get_intltext_template($file, $root='') {
-
- $lang = \App::$language;
- if ($root != '' && substr($root,-1) != '/' ) {
- $root .= '/';
- }
- foreach (Array(
- $root."view/$lang/$file",
- $root."view/en/$file",
- ''
- ) as $template_file) {
- if (is_file($template_file)) { break; }
- }
- if ($template_file=='') {$template_file = theme_include($file,$root);}
- if($template_file) {
+ public function get_intltext_template($file, $root = '') {
+
+ $lang = App::$language;
+ if ($root != '' && substr($root,-1) != '/' ) {
+ $root .= '/';
+ }
+ foreach ( [ $root . "view/$lang/$file", $root . "view/en/$file", '' ] as $template_file) {
+ if (is_file($template_file)) {
+ break;
+ }
+ }
+ if ($template_file == '') {
+ $template_file = theme_include($file,$root);
+ }
+ if ($template_file) {
$template = new SmartyInterface();
$template->filename = $template_file;
return $template;
diff --git a/Zotlabs/Update/_1231.php b/Zotlabs/Update/_1231.php
new file mode 100644
index 000000000..a685c5b28
--- /dev/null
+++ b/Zotlabs/Update/_1231.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1231 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = q("DROP INDEX item_uid");
+ $r2 = q("DROP INDEX item_aid");
+ $r3 = q("DROP INDEX item_restrict");
+ $r4 = q("DROP INDEX item_flags");
+ $r5 = q("DROP INDEX item_private");
+ $r6 = q("DROP INDEX item_starred");
+ $r7 = q("DROP INDEX item_thread_top");
+ $r8 = q("DROP INDEX item_retained");
+ $r9 = q("DROP INDEX item_deleted");
+ $r10 = q("DROP INDEX item_type");
+ $r11 = q("DROP INDEX item_hidden");
+ $r12 = q("DROP INDEX item_unpublished");
+ $r13 = q("DROP INDEX item_delayed");
+ $r14 = q("DROP INDEX item_pending_remove");
+ $r15 = q("DROP INDEX item_blocked");
+ $r16 = q("DROP INDEX item_unseen");
+ $r17 = q("DROP INDEX item_relay");
+ $r18 = q("DROP INDEX item_verified");
+ $r19 = q("DROP INDEX item_notshown");
+
+ $r20 = q("create index item_uid_item_type on item (uid, item_type)");
+ $r21 = q("create index item_uid_item_thread_top on item (uid, item_thread_top)");
+ $r22 = q("create index item_uid_item_blocked on item (uid, item_blocked)");
+ $r23 = q("create index item_uid_item_wall on item (uid, item_wall)");
+ $r24 = q("create index item_uid_item_starred on item (uid, item_starred)");
+ $r25 = q("create index item_uid_item_retained on item (uid, item_retained)");
+ $r26 = q("create index item_uid_item_private on item (uid, item_private)");
+ $r27 = q("create index item_uid_resource_type on item (uid, resource_type)");
+ $r28 = q("create index item_item_deleted_item_pending_remove_changed on item (item_deleted, item_pending_remove, changed)");
+ $r29 = q("create index item_item_pending_remove_changed on item (item_pending_remove, changed)");
+
+ $r30 = q("create index item_thr_parent on item (thr_parent)");
+
+ $r = (
+ $r1 && $r2 && $r3 && $r4 && $r5 && $r6 && $r7 && $r8 && $r9 && $r10 && $r11 && $r12 && $r13 && $r14
+ && $r15 && $r16 && $r17 && $r18 && $r19 && $r20 && $r21 && $r22 && $r23 && $r24 && $r25 && $r26
+ && $r27 && $r28 && $r29 && $r30
+ );
+ }
+ else {
+
+ $r1 = q("ALTER TABLE item DROP INDEX item_unseen");
+ $r2 = q("ALTER TABLE item DROP INDEX item_relay");
+ $r3 = q("ALTER TABLE item DROP INDEX item_verified");
+ $r4 = q("ALTER TABLE item DROP INDEX item_notshown");
+
+ $r5 = q("ALTER TABLE item ADD INDEX thr_parent (thr_parent)");
+
+ $r = ($r1 && $r2 && $r3 && $r4 && $r5);
+ }
+
+ if($r) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1232.php b/Zotlabs/Update/_1232.php
new file mode 100644
index 000000000..d1e3d75b5
--- /dev/null
+++ b/Zotlabs/Update/_1232.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1232 {
+
+ function run() {
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ return UPDATE_SUCCESS;
+ }
+ else {
+ q("START TRANSACTION");
+
+ $r = q("ALTER TABLE channel
+ DROP channel_r_stream,
+ DROP channel_r_profile,
+ DROP channel_r_photos,
+ DROP channel_r_abook,
+ DROP channel_w_stream,
+ DROP channel_w_wall,
+ DROP channel_w_tagwall,
+ DROP channel_w_comment,
+ DROP channel_w_mail,
+ DROP channel_w_photos,
+ DROP channel_w_chat,
+ DROP channel_a_delegate,
+ DROP channel_r_storage,
+ DROP channel_w_storage,
+ DROP channel_r_pages,
+ DROP channel_w_pages,
+ DROP channel_a_republish,
+ DROP channel_w_like"
+ );
+ }
+
+ if($r) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1233.php b/Zotlabs/Update/_1233.php
new file mode 100644
index 000000000..bd85aa379
--- /dev/null
+++ b/Zotlabs/Update/_1233.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1233 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = q("DROP INDEX item_uid_mid");
+
+ $r2 = q("create index item_uid_mid on item (uid, mid)");
+ $r3 = q("create index xchan_photo_m on xchan (xchan_photo_m)");
+
+ $r = ($r1 && $r2 && $r3);
+ }
+ else {
+ $r1 = q("ALTER TABLE item DROP INDEX uid_mid");
+
+ $r2 = q("ALTER TABLE item ADD INDEX uid_mid (uid, mid)");
+ $r3 = q("ALTER TABLE xchan ADD INDEX xchan_photo_m (xchan_photo_m)");
+
+ $r = ($r1 && $r2 && $r3);
+ }
+
+ if($r) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1234.php b/Zotlabs/Update/_1234.php
new file mode 100644
index 000000000..b1b3b0c4e
--- /dev/null
+++ b/Zotlabs/Update/_1234.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1234 {
+
+ function run() {
+
+ q("START TRANSACTION");
+
+ $r = q("DELETE FROM app WHERE app_name = '%s' OR app_name = '%s'",
+ dbesc('Events'),
+ dbesc('CalDAV')
+ );
+
+ if($r) {
+ q("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Widget/Cdav.php b/Zotlabs/Widget/Cdav.php
index 589f915c5..ce716b455 100644
--- a/Zotlabs/Widget/Cdav.php
+++ b/Zotlabs/Widget/Cdav.php
@@ -22,7 +22,7 @@ class Cdav {
$o = '';
- if(argc() == 2 && argv(1) === 'calendar') {
+ if(argc() <= 3 && argv(1) === 'calendar') {
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
@@ -57,7 +57,7 @@ class Cdav {
$switch = get_pconfig(local_channel(), 'cdav_calendar', $sabrecal['id'][0]);
- $color = (($sabrecal['{http://apple.com/ns/ical/}calendar-color']) ? $sabrecal['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad');
+ $color = (($sabrecal['{http://apple.com/ns/ical/}calendar-color']) ? $sabrecal['{http://apple.com/ns/ical/}calendar-color'] : '#6cad39');
$editable = (($sabrecal['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
@@ -113,10 +113,22 @@ class Cdav {
}
}
+ $channel_calendars[] = [
+ 'ownernick' => $channel['channel_address'],
+ 'displayname' => $channel['channel_name'],
+ 'calendarid' => 'channel_calendar',
+ 'json_source' => '/channel_calendar/json',
+ 'color' => '#3a87ad',
+ 'editable' => true,
+ 'switch' => get_pconfig(local_channel(), 'cdav_calendar', 'channel_calendar')
+ ];
+
$o .= replace_macros(get_markup_template('cdav_widget_calendar.tpl'), [
- '$my_calendars_label' => t('My Calendars'),
+ '$channel_calendars_label' => t('Channel Calendar'),
+ '$channel_calendars' => $channel_calendars,
+ '$my_calendars_label' => t('CalDAV Calendars'),
'$my_calendars' => $my_calendars,
- '$shared_calendars_label' => t('Shared Calendars'),
+ '$shared_calendars_label' => t('Shared CalDAV Calendars'),
'$shared_calendars' => $shared_calendars,
'$sharee_options' => $sharee_options,
'$access_options' => $access_options,
@@ -124,10 +136,11 @@ class Cdav {
'$share' => t('Share'),
'$edit_label' => t('Calendar name and color'),
'$edit' => t('Edit'),
- '$create_label' => t('Create new calendar'),
+ '$create_label' => t('Create new CalDAV calendar'),
'$create' => t('Create'),
'$create_placeholder' => t('Calendar Name'),
'$tools_label' => t('Calendar Tools'),
+ '$tools_options_label' => [t('Channel Calendars'), t('CalDAV Calendars')],
'$import_label' => t('Import calendar'),
'$import_placeholder' => t('Select a calendar to import to'),
'$upload' => t('Upload'),
diff --git a/Zotlabs/Widget/Suggestions.php b/Zotlabs/Widget/Suggestions.php
index 5fb3d3e8b..b4f384e9d 100644
--- a/Zotlabs/Widget/Suggestions.php
+++ b/Zotlabs/Widget/Suggestions.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Widget;
+use Zotlabs\Lib\Apps;
+
require_once('include/socgraph.php');
@@ -9,9 +11,9 @@ class Suggestions {
function widget($arr) {
- if((! local_channel()) || (! feature_enabled(local_channel(),'suggest')))
- return '';
+ if((! local_channel()) || (! Apps::system_app_installed(local_channel(), 'Suggest Channels')))
+ return EMPTY_STR;
$r = suggestion_query(local_channel(),get_observer_hash(),0,20);
diff --git a/Zotlabs/Zot6/HTTPSig.php b/Zotlabs/Zot6/HTTPSig.php
index 72785b1e9..d3a09b858 100644
--- a/Zotlabs/Zot6/HTTPSig.php
+++ b/Zotlabs/Zot6/HTTPSig.php
@@ -5,6 +5,7 @@ namespace Zotlabs\Zot6;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Webfinger;
use Zotlabs\Web\HTTPHeaders;
+use Zotlabs\Lib\Libzot;
/**
* @brief Implements HTTP Signatures per draft-cavage-http-signatures-10.
@@ -324,7 +325,7 @@ class HTTPSig {
if($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href',$l) && $l['href'] !== EMPTY_STR) {
$z = \Zotlabs\Lib\Zotfinger::exec($l['href']);
if($z) {
- $i = Zotlabs\Lib\Libzot::import_xchan($z['data']);
+ $i = Libzot::import_xchan($z['data']);
if($i['success']) {
$key['portable_id'] = $i['hash'];
diff --git a/Zotlabs/Zot6/Zot6Handler.php b/Zotlabs/Zot6/Zot6Handler.php
index 8f8957037..37ce11980 100644
--- a/Zotlabs/Zot6/Zot6Handler.php
+++ b/Zotlabs/Zot6/Zot6Handler.php
@@ -151,8 +151,7 @@ class Zot6Handler implements IHandler {
/*
* fetch the requested conversation
*/
- /// @FIXME $sender_hash is undefined
- $messages = zot_feed($c[0]['channel_id'],$sender_hash, [ 'message_id' => $data['message_id'], 'encoding' => 'activitystreams' ]);
+ $messages = zot_feed($c[0]['channel_id'], $sender, [ 'message_id' => $data['message_id'], 'encoding' => 'activitystreams' ]);
return (($messages) ? : [] );
}