diff options
Diffstat (limited to 'Zotlabs')
-rw-r--r-- | Zotlabs/Daemon/Cron.php | 1 | ||||
-rw-r--r-- | Zotlabs/Lib/Activity.php | 291 | ||||
-rw-r--r-- | Zotlabs/Lib/Libzot.php | 35 | ||||
-rw-r--r-- | Zotlabs/Lib/NativeWiki.php | 2 | ||||
-rw-r--r-- | Zotlabs/Module/Cal.php | 435 | ||||
-rw-r--r-- | Zotlabs/Module/Channel_calendar.php | 66 | ||||
-rw-r--r-- | Zotlabs/Module/Events.php | 6 | ||||
-rw-r--r-- | Zotlabs/Module/Mail.php | 9 | ||||
-rw-r--r-- | Zotlabs/Module/Photo.php | 2 | ||||
-rw-r--r-- | Zotlabs/Photo/PhotoDriver.php | 10 |
10 files changed, 528 insertions, 329 deletions
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index 8b6b42c8a..c99892ffb 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -108,6 +108,7 @@ class Cron { $file = dbunescbin($rr['content']); if(is_file($file)) { @unlink($file); + @rmdir(dirname($file)); logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG); } } diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index d96ab95b0..f974d215b 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -1578,7 +1578,7 @@ class Activity { $s['verb'] = self::activity_decode_mapper($act->type); - if($act->type === 'Tombstone' || $act-type === 'Delete' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) { + if($act->type === 'Tombstone' || $act->type === 'Delete' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) { $s['item_deleted'] = 1; } @@ -1844,7 +1844,8 @@ class Activity { $s['item_private'] = 1; set_iconfig($s,'activitypub','recips',$act->raw_recips); - // @FIXME: $parent is not defined + + $parent = (($s['parent_mid'] && $s['parent_mid'] === $s['mid']) ? true : false); if($parent) { set_iconfig($s,'activitypub','rawmsg',$act->raw,1); } @@ -1853,6 +1854,266 @@ class Activity { } + static function store($channel,$observer_hash,$act,$item,$fetch_parents = true) { + + $is_sys_channel = is_sys_channel($channel['channel_id']); + + // Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field. + // They are hidden in the public timeline if the public inbox is listed in the 'cc' field. + // This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point. + + $pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false); + + if(! perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && ! ($is_sys_channel && $pubstream)) { + logger('no permission'); + return; + } + + if(is_array($act->obj)) { + $content = self::get_content($act->obj); + } + if(! $content) { + logger('no content'); + return; + } + + $item['aid'] = $channel['channel_account_id']; + $item['uid'] = $channel['channel_id']; + $s['uuid'] = ''; + + // Friendica sends the diaspora guid in a nonstandard field via AP + if($act->obj['diaspora:guid']) + $s['uuid'] = $act->obj['diaspora:guid']; + + if(! ( $item['author_xchan'] && $item['owner_xchan'])) { + logger('owner or author missing.'); + return; + } + + if($channel['channel_system']) { + if(! MessageFilter::evaluate($item,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) { + logger('post is filtered'); + return; + } + } + + $abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", + dbesc($observer_hash), + intval($channel['channel_id']) + ); + + if($abook) { + if(! post_is_importable($item,$abook[0])) { + logger('post is filtered'); + return; + } + } + + + if($act->obj['conversation']) { + set_iconfig($item,'ostatus','conversation',$act->obj['conversation'],1); + } + + // This isn't perfect but the best we can do for now. + + $item['comment_policy'] = 'authenticated'; + + set_iconfig($item,'activitypub','recips',$act->raw_recips); + + $parent = (($item['parent_mid'] && $item['parent_mid'] === $item['mid']) ? true : false); + + if(! $parent) { + $p = q("select parent_mid from item where mid = '%s' and uid = %d limit 1", + dbesc($item['parent_mid']), + intval($item['uid']) + ); + if(! $p) { + $a = (($fetch_parents) ? self::fetch_and_store_parents($channel,$act,$item) : false); + if($a) { + $p = q("select parent_mid from item where mid = '%s' and uid = %d limit 1", + dbesc($item['parent_mid']), + intval($item['uid']) + ); + } + else { + logger('could not fetch parents'); + return; + + // @TODO we maybe could accept these is we formatted the body correctly with share_bb() + // or at least provided a link to the object + // if(in_array($act->type,[ 'Like','Dislike' ])) { + // return; + // } + + // @TODO do we actually want that? + // if no parent was fetched, turn into a top-level post + + // turn into a top level post + // $s['parent_mid'] = $s['mid']; + // $s['thr_parent'] = $s['mid']; + } + } + if($p[0]['parent_mid'] !== $item['parent_mid']) { + $item['thr_parent'] = $item['parent_mid']; + } + else { + $item['thr_parent'] = $p[0]['parent_mid']; + } + $item['parent_mid'] = $p[0]['parent_mid']; + } + + $r = q("select id, created, edited from item where mid = '%s' and uid = %d limit 1", + dbesc($item['mid']), + intval($item['uid']) + ); + if($r) { + if($item['edited'] > $r[0]['edited']) { + $item['id'] = $r[0]['id']; + $x = item_store_update($item); + } + else { + return; + } + } + else { + $x = item_store($item); + } + + if(is_array($x) && $x['item_id']) { + if($parent) { + if($item['owner_xchan'] === $channel['channel_hash']) { + // We are the owner of this conversation, so send all received comments back downstream + Master::Summon(array('Notifier','comment-import',$x['item_id'])); + } + $r = q("select * from item where id = %d limit 1", + intval($x['item_id']) + ); + if($r) { + send_status_notifications($x['item_id'],$r[0]); + } + } + sync_an_item($channel['channel_id'],$x['item_id']); + } + + } + + static public function fetch_and_store_parents($channel,$act,$item) { + + logger('fetching parents'); + + $p = []; + + $current_act = $act; + $current_item = $item; + + while($current_item['parent_mid'] !== $current_item['mid']) { + $n = ActivityStreams::fetch($current_item['parent_mid'], $channel); + if(! $n) { + break; + } + $a = new ActivityStreams($n); + + logger($a->debug()); + + if(! $a->is_valid()) { + break; + } + + $replies = null; + if(isset($n['replies']['first']['items'])) { + $replies = $n['replies']['first']['items']; + // we already have this one + array_diff($replies, [$current_item['mid']]); + } + + $item = null; + + switch($a->type) { + case 'Create': + case 'Update': + case 'Like': + case 'Dislike': + case 'Announce': + $item = self::decode_note($a); + break; + default: + break; + + } + if(! $item) { + break; + } + + array_unshift($p,[ $a, $item, $replies]); + + if($item['parent_mid'] === $item['mid'] || count($p) > 20) { + break; + } + + $current_act = $a; + $current_item = $item; + } + + if($p) { + foreach($p as $pv) { + self::store($channel,$pv[0]->actor['id'],$pv[0],$pv[1],false); + if($pv[2]) + self::fetch_and_store_replies($channel, $pv[2]); + } + return true; + } + + return false; + } + + static public function fetch_and_store_replies($channel, $arr) { + + logger('fetching replies'); + + $p = []; + + foreach($arr as $url) { + + $n = ActivityStreams::fetch($url, $channel); + if(! $n) { + break; + } + + $a = new ActivityStreams($n); + + if(! $a->is_valid()) { + break; + } + + $item = null; + + switch($a->type) { + case 'Create': + case 'Update': + case 'Like': + case 'Dislike': + case 'Announce': + $item = self::decode_note($a); + break; + default: + break; + } + if(! $item) { + break; + } + + array_unshift($p,[ $a, $item ]); + + } + + if($p) { + foreach($p as $pv) { + self::store($channel,$pv[0]->actor['id'],$pv[0],$pv[1],false); + } + } + + } + static function announce_note($channel,$observer_hash,$act) { $s = []; @@ -1973,25 +2234,21 @@ class Activity { $x = item_store($s); } - 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 - Master::Summon(array('Notifier','comment-import',$x['item_id'])); - } - $r = q("select * from item where id = %d limit 1", - intval($x['item_id']) - ); - if($r) { - send_status_notifications($x['item_id'],$r[0]); - } + if($s['owner_xchan'] === $channel['channel_hash']) { + // We are the owner of this conversation, so send all received comments back downstream + Master::Summon(array('Notifier','comment-import',$x['item_id'])); + } + $r = q("select * from item where id = %d limit 1", + intval($x['item_id']) + ); + if($r) { + send_status_notifications($x['item_id'],$r[0]); } + sync_an_item($channel['channel_id'],$x['item_id']); } - } static function like_note($channel,$observer_hash,$act) { @@ -2261,4 +2518,4 @@ class Activity { } -}
\ No newline at end of file +} diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index de041bd6b..2a13744a3 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -2037,7 +2037,7 @@ class Libzot { $item_found = false; $post_id = 0; - $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' ) + $r = q("select * from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' ) and mid = '%s' and uid = %d limit 1", dbesc($sender), dbesc($sender), @@ -2047,10 +2047,12 @@ class Libzot { ); if($r) { - if($r[0]['author_xchan'] === $sender || $r[0]['owner_xchan'] === $sender || $r[0]['source_xchan'] === $sender) + $stored = $r[0]; + + if($stored['author_xchan'] === $sender || $stored['owner_xchan'] === $sender || $stored['source_xchan'] === $sender) $ownership_valid = true; - $post_id = $r[0]['id']; + $post_id = $stored['id']; $item_found = true; } else { @@ -2074,8 +2076,27 @@ class Libzot { return false; } + if ($stored['resource_type'] === 'event') { + $i = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1", + dbesc($stored['resource_id']), + intval($uid) + ); + if ($i) { + if ($i[0]['event_xchan'] === $sender) { + q("delete from event where event_hash = '%s' and uid = %d", + dbesc($stored['resource_id']), + intval($uid) + ); + } + else { + logger('delete linked event: not owner'); + return; + } + } + } + if($item_found) { - if(intval($r[0]['item_deleted'])) { + if(intval($stored['item_deleted'])) { logger('delete_imported_item: item was already deleted'); if(! $relay) return false; @@ -2087,10 +2108,10 @@ class Libzot { // back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing // this information from the metadata should have no other discernible impact. - if (($r[0]['id'] != $r[0]['parent']) && intval($r[0]['item_origin'])) { + if (($stored['id'] != $stored['parent']) && intval($stored['item_origin'])) { q("update item set item_origin = 0 where id = %d and uid = %d", - intval($r[0]['id']), - intval($r[0]['uid']) + intval($stored['id']), + intval($stored['uid']) ); } } diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php index e2bd07c0d..662fddad0 100644 --- a/Zotlabs/Lib/NativeWiki.php +++ b/Zotlabs/Lib/NativeWiki.php @@ -191,7 +191,7 @@ class NativeWiki { return array('item' => null, 'success' => false); } else { - $drop = drop_item($item['id'], false, DROPITEM_NORMAL, true); + $drop = drop_item($item['id'], false, DROPITEM_NORMAL); } info( t('Wiki files deleted successfully')); diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 49489f912..07bee38bd 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -1,6 +1,10 @@ <?php namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; + require_once('include/conversation.php'); require_once('include/bbcode.php'); require_once('include/datetime.php'); @@ -9,15 +13,13 @@ require_once('include/items.php'); require_once('include/html2plain.php'); -class Cal extends \Zotlabs\Web\Controller { +class Cal extends Controller { function init() { if(observer_prohibited()) { return; } - $o = ''; - if(argc() > 1) { $nick = argv(1); @@ -25,19 +27,21 @@ class Cal extends \Zotlabs\Web\Controller { $channelx = channelx_by_nick($nick); - if(! $channelx) + if(! $channelx) { + notice( t('Channel not found.') . EOL); return; + } - \App::$data['channel'] = $channelx; + App::$data['channel'] = $channelx; - $observer = \App::get_observer(); - \App::$data['observer'] = $observer; + $observer = App::get_observer(); + App::$data['observer'] = $observer; $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); - head_set_icon(\App::$data['channel']['xchan_photo_s']); + head_set_icon(App::$data['channel']['xchan_photo_s']); - \App::$page['htmlhead'] .= "<script> var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ; + App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ; } @@ -52,18 +56,8 @@ class Cal extends \Zotlabs\Web\Controller { return; } - $channel = null; - - if(argc() > 1) { - $channel = channelx_by_nick(argv(1)); - } - - - if(! $channel) { - notice( t('Channel not found.') . EOL); - return; - } - + $channel = App::$data['channel']; + // since we don't currently have an event permission - use the stream permission if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) { @@ -72,295 +66,152 @@ class Cal extends \Zotlabs\Web\Controller { } nav_set_selected('Calendar'); + + head_add_css('/library/fullcalendar/packages/core/main.min.css'); + head_add_css('/library/fullcalendar/packages/daygrid/main.min.css'); + head_add_css('cdav_calendar.css'); + + head_add_js('/library/fullcalendar/packages/core/main.min.js'); + head_add_js('/library/fullcalendar/packages/daygrid/main.min.js'); + + $sql_extra = permissions_sql($channel['channel_id'], get_observer_hash(), 'event'); + + if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends']) + $sql_extra .= " and etype != 'birthday' "; - $sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event'); - - $first_day = feature_enabled($channel['channel_id'], 'events_cal_first_day'); + $first_day = feature_enabled($channel['channel_id'], 'cal_first_day'); $first_day = (($first_day) ? $first_day : 0); - $htpl = get_markup_template('event_head.tpl'); - \App::$page['htmlhead'] .= replace_macros($htpl,array( - '$baseurl' => z_root(), - '$module_url' => '/cal/' . $channel['channel_address'], - '$modparams' => 2, - '$lang' => \App::$language, - '$timezone' => date_default_timezone_get(), - '$first_day' => $first_day - )); - - $o = ''; - - $mode = 'view'; - $y = 0; - $m = 0; - $ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : ''); - - // logger('args: ' . print_r(\App::$argv,true)); + $start = ''; + $finish = ''; + + if (argv(2) === 'json') { + if (x($_GET,'start')) $start = $_GET['start']; + if (x($_GET,'end')) $finish = $_GET['end']; + } - if(argc() > 3 && intval(argv(2)) && intval(argv(3))) { - $mode = 'view'; - $y = intval(argv(2)); - $m = intval(argv(3)); + $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 $sql_extra limit 1", + intval($channel['channel_id']), + intval($_GET['id']) + ); } - if(argc() <= 3) { - $mode = 'view'; - $event_id = argv(2); + 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 + 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' )) + $sql_extra", + intval($channel['channel_id']), + dbesc($start), + dbesc($finish), + dbesc($adjust_start), + dbesc($adjust_finish) + ); } - 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($channel['channel_id']) - ); - if(count($r)) - $orig_event = $r[0]; - } - - - // Passed parameters overrides anything found in the DB - if(!x($orig_event)) - $orig_event = array(); - - - - $tz = date_default_timezone_get(); - if(x($orig_event)) - $tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC'); - - $syear = datetime_convert('UTC', $tz, $sdt, 'Y'); - $smonth = datetime_convert('UTC', $tz, $sdt, 'm'); - $sday = datetime_convert('UTC', $tz, $sdt, 'd'); - $shour = datetime_convert('UTC', $tz, $sdt, 'H'); - $sminute = datetime_convert('UTC', $tz, $sdt, 'i'); - - $stext = datetime_convert('UTC',$tz,$sdt); - $stext = substr($stext,0,14) . "00:00"; - - $fyear = datetime_convert('UTC', $tz, $fdt, 'Y'); - $fmonth = datetime_convert('UTC', $tz, $fdt, 'm'); - $fday = datetime_convert('UTC', $tz, $fdt, 'd'); - $fhour = datetime_convert('UTC', $tz, $fdt, 'H'); - $fminute = datetime_convert('UTC', $tz, $fdt, 'i'); - - $ftext = datetime_convert('UTC',$tz,$fdt); - $ftext = substr($ftext,0,14) . "00:00"; - - $type = ((x($orig_event)) ? $orig_event['etype'] : 'event'); - - $f = get_config('system','event_input_format'); - if(! $f) - $f = 'ymd'; - - $catsenabled = feature_enabled($channel['channel_id'],'categories'); - - - $show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts'); - if(! $show_bd) { - $sql_extra .= " and event.etype != 'birthday' "; - } - - - $category = ''; - - $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); - $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); - if(! $y) - $y = intval($thisyear); - if(! $m) - $m = intval($thismonth); - - // Put some limits on dates. The PHP date functions don't seem to do so well before 1900. - // An upper limit was chosen to keep search engines from exploring links millions of years in the future. - - if($y < 1901) - $y = 1900; - if($y > 2099) - $y = 2100; - - $nextyear = $y; - $nextmonth = $m + 1; - if($nextmonth > 12) { - $nextmonth = 1; - $nextyear ++; - } - - $prevyear = $y; - if($m > 1) - $prevmonth = $m - 1; - else { - $prevmonth = 12; - $prevyear --; - } - - $dim = get_dim($y,$m); - $start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0); - $finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59); - - - if (argv(2) === '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(! perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'view_contacts')) - $sql_extra .= " and etype != 'birthday' "; + if($r) { + xchan_query($r); + $r = fetch_post_tags($r,true); + $r = sort_by_date($r); + } - 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 resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1", - intval($channel['channel_id']), - intval($_GET['id']) - ); - } - 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) - ); - - } - - $links = array(); - - if($r) { - xchan_query($r); - $r = fetch_post_tags($r,true); - - $r = sort_by_date($r); - } - - if($r) { - foreach($r as $rr) { - $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j')); - if(! x($links,$j)) - $links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j; - } - } - - $events=array(); - - $last_date = ''; - $fmt = t('l, F j'); - - if($r) { + $events = []; - foreach($r as $rr) { + if($r) { - $tz = get_iconfig($rr, 'event', 'timezone'); + foreach($r as $rr) { - if(! $tz) - $tz = 'UTC'; + $tz = get_iconfig($rr, 'event', 'timezone'); + if(! $tz) + $tz = 'UTC'; - $rr['timezone'] = $tz; + $start = (($rr['adjust']) ? datetime_convert($tz, 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($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c')); + } - $j = (($rr['adjust']) ? datetime_convert($tz,date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j')); - $d = (($rr['adjust']) ? datetime_convert($tz,date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt)); - $d = day_translate($d); - - $start = (($rr['adjust']) ? datetime_convert($tz,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($tz,date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c')); - } - - - $is_first = ($d !== $last_date); - - $last_date = $d; - - $edit = false; - - $drop = false; - - $title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8')); - if(! $title) { - list($title, $_trash) = explode("<br",bbcode($rr['desc']),2); - $title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8')); - } + $html = ''; + if (x($_GET,'id')) { + $rr['timezone'] = $tz; $html = format_event_html($rr); - $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); - $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false); - $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); - $events[] = array( - 'id'=>$rr['id'], - 'hash' => $rr['event_hash'], - 'start'=> $start, - 'end' => $end, - 'drop' => $drop, - 'allDay' => (($rr['adjust']) ? 0 : 1), - 'title' => $title, - - 'j' => $j, - 'd' => $d, - 'edit' => $edit, - 'is_first'=>$is_first, - 'item'=>$rr, - 'html'=>$html, - 'plink' => array($rr['plink'],t('Link to Source'),'',''), - ); - - } + + $events[] = array( + 'calendar_id' => 'channel_calendar', + 'rw' => true, + 'id'=>$rr['id'], + 'uri' => $rr['event_hash'], + 'timezone' => $tz, + 'start'=> $start, + 'end' => $end, + 'drop' => $drop, + 'allDay' => (($rr['adjust']) ? 0 : 1), + 'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'), + 'editable' => $edit ? true : false, + 'item' => $rr, + 'plink' => [$rr['plink'], t('Link to source')], + 'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'), + 'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'), + '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']), + 'html' => $html + ); } + } + + if (argv(2) === 'json') { + echo json_encode($events); + killme(); + } - if (argv(2) === 'json'){ - echo json_encode($events); killme(); - } - - // links: array('href', 'text', 'extra css classes', 'title') - if (x($_GET,'id')){ - $tpl = get_markup_template("event_cal.tpl"); - } - else { - $tpl = get_markup_template("events_cal-js.tpl"); - } - - $nick = $channel['channel_address']; - - $o = replace_macros($tpl, array( - '$baseurl' => z_root(), - '$new_event' => array(z_root().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''), - '$previus' => array(z_root()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''), - '$next' => array(z_root()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''), - '$export' => array(z_root()."/cal/$nick/$y/$m/export",t('Export'),'',''), - '$calendar' => cal($y,$m,$links, ' eventcal'), - '$events' => $events, - '$upload' => t('Import'), - '$submit' => t('Submit'), - '$prev' => t('Previous'), - '$next' => t('Next'), - '$today' => t('Today'), - '$form' => $form, - '$expandform' => ((x($_GET,'expandform')) ? true : false) - )); - - if (x($_GET,'id')){ echo $o; killme(); } - - return $o; + if (x($_GET,'id')) { + $o = replace_macros(get_markup_template("cal_event.tpl"), [ + '$events' => $events + ]); + echo $o; + killme(); } + + $nick = $channel['channel_address']; + + $sources = '{ + id: \'channel_calendar\', + url: \'/cal/' . $nick . '/json/\', + color: \'#3a87ad\' + }'; + + $o = replace_macros(get_markup_template("cal_calendar.tpl"), [ + '$sources' => $sources, + '$lang' => App::$language, + '$timezone' => date_default_timezone_get(), + '$first_day' => $first_day, + '$prev' => t('Previous'), + '$next' => t('Next'), + '$today' => t('Today'), + '$title' => $title, + '$dtstart' => $dtstart, + '$dtend' => $dtend, + '$nick' => $nick + ]); + + return $o; } diff --git a/Zotlabs/Module/Channel_calendar.php b/Zotlabs/Module/Channel_calendar.php index cacee57ef..109b18f37 100644 --- a/Zotlabs/Module/Channel_calendar.php +++ b/Zotlabs/Module/Channel_calendar.php @@ -381,12 +381,12 @@ class Channel_calendar extends \Zotlabs\Web\Controller { 'end' => $end, 'drop' => $drop, 'allDay' => (($rr['adjust']) ? 0 : 1), - 'title' => html_entity_decode($rr['summary'],ENT_COMPAT,'UTF-8'), + 'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'), '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), + 'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'), + 'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'), 'allow_cid' => expand_acl($rr['allow_cid']), 'allow_gid' => expand_acl($rr['allow_gid']), 'deny_cid' => expand_acl($rr['deny_cid']), @@ -422,13 +422,67 @@ class Channel_calendar extends \Zotlabs\Web\Controller { 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", + + $sync_event['event_deleted'] = 1; + build_sync_packet(0,array('event' => array($sync_event))); + + $i = q("select * from item 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))); + + if ($i) { + + $can_delete = false; + $local_delete = true; + + $ob_hash = get_observer_hash(); + if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) { + $can_delete = true; + } + + // The site admin can delete any post/item on the site. + // If the item originated on this site+channel the deletion will propagate downstream. + // Otherwise just the local copy is removed. + + if(is_site_admin()) { + $local_delete = true; + if(intval($i[0]['item_origin'])) + $can_delete = true; + } + + if($can_delete || $local_delete) { + + // if this is a different page type or it's just a local delete + // but not by the item author or owner, do a simple deletion + + $complex = false; + + if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) { + drop_item($i[0]['id']); + } + else { + // complex deletion that needs to propagate and be performed in phases + drop_item($i[0]['id'],true,DROPITEM_PHASE1); + $complex = true; + } + + $ii = q("select * from item where id = %d", + intval($i[0]['id']) + ); + if($ii) { + xchan_query($ii); + $sync_item = fetch_post_tags($ii); + build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); + } + + if($complex) { + tag_deliver($i[0]['uid'],$i[0]['id']); + } + } + } killme(); } notice( t('Failed to remove event' ) . EOL); diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index 056d0cd5a..681d6887d 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -11,6 +11,9 @@ require_once('include/html2plain.php'); class Events extends \Zotlabs\Web\Controller { function post() { + + // this module is deprecated + return; logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA); @@ -245,6 +248,9 @@ class Events extends \Zotlabs\Web\Controller { function get() { + + // this module is deprecated + return; if(argc() > 2 && argv(1) == 'ical') { $event_id = argv(2); diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php index 3202d38a5..7c344966b 100644 --- a/Zotlabs/Module/Mail.php +++ b/Zotlabs/Module/Mail.php @@ -25,6 +25,10 @@ class Mail extends \Zotlabs\Web\Controller { $expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE); $raw = ((x($_REQUEST,'raw')) ? intval($_REQUEST['raw']) : 0); $mimetype = ((x($_REQUEST,'mimetype')) ? notags(trim($_REQUEST['mimetype'])) : 'text/bbcode'); + + $sig = ((x($_REQUEST,'signature')) ? trim($_REQUEST['signature']) : ''); + if(strpos($sig,'b64.') === 0) + $sig = base64_decode(str_replace('b64.', '', $sig)); if($preview) { @@ -123,7 +127,7 @@ class Mail extends \Zotlabs\Web\Controller { // We have a local_channel, let send_message use the session channel and save a lookup - $ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw); + $ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw, $sig); if($ret['success']) { xchan_mail_query($ret['mail']); @@ -396,8 +400,9 @@ class Mail extends \Zotlabs\Web\Controller { 'can_recall' => ($channel['channel_hash'] == $message['from_xchan']), 'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''), 'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'), + 'sig' => base64_encode($message['sig']) ); - + $seen = $message['seen']; } diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 0dc6d0194..a53b00282 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -169,7 +169,7 @@ class Photo extends \Zotlabs\Web\Controller { ); call_hooks('cache_url_hook', $cache); if(! $cache['status']) { - $url = htmlspecialchars_decode($r[0]['display_path']); + $url = html_entity_decode($r[0]['display_path'], ENT_QUOTES); // SSLify if needed if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false) $url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url); diff --git a/Zotlabs/Photo/PhotoDriver.php b/Zotlabs/Photo/PhotoDriver.php index 146ef0ae4..94d2c3436 100644 --- a/Zotlabs/Photo/PhotoDriver.php +++ b/Zotlabs/Photo/PhotoDriver.php @@ -502,13 +502,17 @@ abstract class PhotoDriver { * * @param array $arr * @param scale int - * @return boolean|array + * @return boolean */ public function storeThumbnail($arr, $scale = 0) { - + + // We only process thumbnails here + if($scale == 0) + return false; + $arr['imgscale'] = $scale; - if(boolval(get_config('system','filesystem_storage_thumbnails', 0)) && $scale > 0) { + if(boolval(get_config('system','filesystem_storage_thumbnails', 0))) { $channel = channelx_by_n($arr['uid']); $arr['os_storage'] = 1; $arr['os_syspath'] = 'store/' . $channel['channel_address'] . '/' . $arr['os_path'] . '-' . $scale; |