Merge branch 'dev'

This commit is contained in:
zotlabs 2019-09-21 23:18:44 -07:00
commit 3b928db57b
14 changed files with 2771 additions and 3040 deletions

View file

@ -819,6 +819,15 @@ class Activity {
/* Add mentions only if the targets are individuals */ /* Add mentions only if the targets are individuals */
$m = self::map_acl($i,(($i['allow_gid']) ? false : true)); $m = self::map_acl($i,(($i['allow_gid']) ? false : true));
$ret['tag'] = (($ret['tag']) ? array_merge($ret['tag'],$m) : $m); $ret['tag'] = (($ret['tag']) ? array_merge($ret['tag'],$m) : $m);
$ret['to'] = [ $reply_url ];
if (is_array($m) && $m && ! $ret['to']) {
$ret['to'] = [];
foreach ($m as $ma) {
if (is_array($ma) && $ma['type'] === 'Mention') {
$ret['to'][] = $ma['href'];
}
}
}
} }
} }
else { else {
@ -874,10 +883,6 @@ class Activity {
if (! $x) if (! $x)
return; return;
$strict = (($mentions) ? true : get_config('activitypub','compliance'));
$sql_extra = (($strict) ? " and xchan_network = 'activitypub' " : '');
$details = q("select xchan_url, xchan_addr, xchan_name from xchan where xchan_hash in (" . implode(',',$x) . ") $sql_extra"); $details = q("select xchan_url, xchan_addr, xchan_name from xchan where xchan_hash in (" . implode(',',$x) . ") $sql_extra");
if ($details) { if ($details) {
@ -939,7 +944,7 @@ class Activity {
]; ];
$ret['url'] = $p['xchan_url']; $ret['url'] = $p['xchan_url'];
if ($activitypub && $feature_complete) { if ($activitypub && get_config('system','activitypub')) {
if ($c) { if ($c) {
$ret['inbox'] = z_root() . '/inbox/' . $c['channel_address']; $ret['inbox'] = z_root() . '/inbox/' . $c['channel_address'];
@ -954,6 +959,22 @@ class Activity {
'publicKeyPem' => $p['xchan_pubkey'] 'publicKeyPem' => $p['xchan_pubkey']
]; ];
// map other nomadic identities linked with this channel
$locations = [];
$locs = Libzot::encode_locations($c);
if ($locs) {
foreach ($locs as $loc) {
if ($loc['url'] !== z_root()) {
$locations[] = $loc['id_url'];
}
}
}
if ($locations) {
$ret['alsoKnownAs'] = $locations;
}
$cp = get_cover_photo($c['channel_id'],'array'); $cp = get_cover_photo($c['channel_id'],'array');
if ($cp) { if ($cp) {
$ret['image'] = [ $ret['image'] = [
@ -1286,7 +1307,6 @@ class Activity {
AccessList::member_add($channel['channel_id'],'',$ret['xchan_hash'],$g['id']); AccessList::member_add($channel['channel_id'],'',$ret['xchan_hash'],$g['id']);
} }
return; return;
} }
@ -2238,10 +2258,27 @@ class Activity {
} }
$allowed = false; $allowed = false;
$moderated = false;
if ($is_child_node) { if ($is_child_node) {
// in ActivityPub, anybody can post comments $p = q("select id from item where mid = '%s' and uid = %d and item_wall = 1",
dbesc($item['parent_mid']),
intval($channel['channel_id'])
);
if ($p) {
$allowed = perm_is_allowed($channel['channel_id'],$observer_hash,'post_comments');
if (! $allowed) {
// let the sender know we received their comment but we don't permit spam here.
self::send_rejection_activity($channel,$observer_hash,$item);
}
}
else {
$allowed = true; $allowed = true;
// reject public stream comments that weren't sent by the conversation owner
if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash) {
$allowed = false;
}
}
} }
elseif (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') || ($is_sys_channel && $pubstream)) { elseif (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') || ($is_sys_channel && $pubstream)) {
$allowed = true; $allowed = true;
@ -2918,4 +2955,35 @@ class Activity {
return $content; return $content;
} }
static function send_rejection_activity($channel,$observer_hash,$item) {
$recip = q("select * from hubloc where hubloc_hash = '%s' limit 1",
dbesc($observer_hash)
);
if (! $recip) {
return;
}
$arr = [
'id' => z_root() . '/bounces/' . new_uuid(),
'to' => [ $observer_hash ],
'type' => 'Reject',
'actor' => channel_url($channel),
'name' => 'Permission denied',
'object' => $item['message_id']
];
$msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], $arr);
$queue_id = ActivityPub::queue_message($msg,$channel,$recip[0]);
do_delivery( [ $queue_id ] );
}
} }

View file

@ -157,7 +157,6 @@ class ActivityPub {
static function queue_message($msg,$sender,$recip,$message_id = '') { static function queue_message($msg,$sender,$recip,$message_id = '') {
$dest_url = $recip['hubloc_callback']; $dest_url = $recip['hubloc_callback'];
logger('URL: ' . $dest_url, LOGGER_DEBUG); logger('URL: ' . $dest_url, LOGGER_DEBUG);

View file

@ -86,6 +86,8 @@ class Acl extends \Zotlabs\Web\Controller {
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; $sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") "; $sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
// This horrible mess is needed because position also returns 0 if nothing is found. // This horrible mess is needed because position also returns 0 if nothing is found.
// Would be MUCH easier if it instead returned a very large value // Would be MUCH easier if it instead returned a very large value
// Otherwise we could just // Otherwise we could just
@ -96,11 +98,14 @@ class Acl extends \Zotlabs\Web\Controller {
. " then POSITION('" . protect_sprintf(dbesc($search)) . " then POSITION('" . protect_sprintf(dbesc($search))
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, "; . "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR abook_alias like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) "; $sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR ( xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR abook_alias like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " )) ";
$sql_extra4 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . " OR abook_alias LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'") . ") ";
} }
else { else {
$sql_extra = $sql_extra2 = $sql_extra3 = ""; $sql_extra = $sql_extra2 = $sql_extra3 = $sql_extra4 = "";
} }
@ -217,10 +222,11 @@ class Acl extends \Zotlabs\Web\Controller {
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash FROM abook left join xchan on abook_xchan = xchan_hash
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" , WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra4 order by xchan_name asc" ,
intval(local_channel()) intval(local_channel())
); );
if($r2)
if($r && $r2)
$r = array_merge($r2,$r); $r = array_merge($r2,$r);
} }

View file

@ -77,6 +77,7 @@ class Site {
$poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0); $poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
$ap_contacts = ((x($_POST,'ap_contacts')) ? intval($_POST['ap_contacts']) : 0);
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0); $verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : ''); $imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0); $thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
@ -87,6 +88,7 @@ class Site {
$permissions_role = escape_tags(trim($_POST['permissions_role'])); $permissions_role = escape_tags(trim($_POST['permissions_role']));
set_config('system', 'feed_contacts', $feed_contacts); set_config('system', 'feed_contacts', $feed_contacts);
set_config('system', 'activitypub', $ap_contacts);
set_config('system', 'delivery_interval', $delivery_interval); set_config('system', 'delivery_interval', $delivery_interval);
set_config('system', 'delivery_batch_count', $delivery_batch_count); set_config('system', 'delivery_batch_count', $delivery_batch_count);
set_config('system', 'poll_interval', $poll_interval); set_config('system', 'poll_interval', $poll_interval);
@ -305,6 +307,7 @@ class Site {
// '$theme_mobile' => [ 'theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile ], // '$theme_mobile' => [ 'theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile ],
// '$site_channel' => [ 'site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel") ], // '$site_channel' => [ 'site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel") ],
'$feed_contacts' => [ 'feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)') ], '$feed_contacts' => [ 'feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)') ],
'$ap_contacts' => [ 'ap_contacts', t('Allow ActivityPub Connections'),get_config('system','activitypub'),t('Experimental and unsupported. ActivityPub does not fully support privacy and account mobility.') ],
'$maximagesize' => [ 'maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.") ], '$maximagesize' => [ 'maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.") ],
'$register_policy' => [ 'register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices ], '$register_policy' => [ 'register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices ],
'$invite_only' => [ 'invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. New member registration must be allowed for this to work.") ], '$invite_only' => [ 'invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. New member registration must be allowed for this to work.") ],
@ -338,7 +341,7 @@ class Site {
'$imagick_path' => [ 'imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert") ], '$imagick_path' => [ 'imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert") ],
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ], '$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
'$maxloadavg' => [ 'maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.") ], '$maxloadavg' => [ 'maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.") ],
'$default_expire_days' => [ 'default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content') ], '$default_expire_days' => [ 'default_expire_days', t('Expiration period in days for imported streams'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content') ],
'$active_expire_days' => [ 'active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), '' ], '$active_expire_days' => [ 'active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), '' ],
'$sellpage' => [ 'site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root()) ], '$sellpage' => [ 'site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root()) ],
'$first_page' => [ 'first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles') ], '$first_page' => [ 'first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles') ],

View file

@ -17,6 +17,7 @@ class Apschema extends \Zotlabs\Web\Controller {
'ostatus' => 'http://ostatus.org#', 'ostatus' => 'http://ostatus.org#',
'conversation' => 'ostatus:conversation', 'conversation' => 'ostatus:conversation',
'sensitive' => 'as:sensitive', 'sensitive' => 'as:sensitive',
'alsoKnownAs' => 'as:alsoKnownAs',
'inheritPrivacy' => 'as:inheritPrivacy', 'inheritPrivacy' => 'as:inheritPrivacy',
'commentPolicy' => 'zot:commentPolicy', 'commentPolicy' => 'zot:commentPolicy',
'topicalCollection' => 'zot:topicalCollection', 'topicalCollection' => 'zot:topicalCollection',

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Activity; use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libprofile; use Zotlabs\Lib\Libprofile;
use Zotlabs\Access\AccessControl; use Zotlabs\Access\AccessControl;
@ -12,6 +13,7 @@ use Zotlabs\Web\Controller;
*/ */
require_once('include/attach.php');
require_once('include/photo_factory.php'); require_once('include/photo_factory.php');
require_once('include/photos.php'); require_once('include/photos.php');
@ -25,14 +27,14 @@ require_once('include/photos.php');
*/ */
class Cover_photo extends \Zotlabs\Web\Controller { class Cover_photo extends Controller {
function init() { function init() {
if(! local_channel()) { if (! local_channel()) {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
Libprofile::load($channel['channel_address']); Libprofile::load($channel['channel_address']);
} }
@ -45,26 +47,26 @@ class Cover_photo extends \Zotlabs\Web\Controller {
function post() { function post() {
if(! local_channel()) { if (! local_channel()) {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo'); check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) { if ((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
// phase 2 - we have finished cropping // phase 2 - we have finished cropping
if(argc() != 2) { if (argc() != 2) {
notice( t('Image uploaded but image cropping failed.') . EOL ); notice( t('Image uploaded but image cropping failed.') . EOL );
return; return;
} }
$image_id = argv(1); $image_id = argv(1);
if(substr($image_id,-2,1) == '-') { if (substr($image_id,-2,1) == '-') {
$scale = substr($image_id,-1,1); $scale = substr($image_id,-1,1);
$image_id = substr($image_id,0,-2); $image_id = substr($image_id,0,-2);
} }
@ -79,8 +81,8 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$r = q("select gender from profile where uid = %d and is_default = 1 limit 1", $r = q("select gender from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel()) intval(local_channel())
); );
if($r) { if ($r) {
$profile = $r[0]; $profile = array_shift($r);
} }
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1", $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1",
@ -88,26 +90,26 @@ class Cover_photo extends \Zotlabs\Web\Controller {
intval(local_channel()) intval(local_channel())
); );
if($r) { if ($r) {
$max_thumb = intval(get_config('system','max_thumbnail',1600)); $max_thumb = intval(get_config('system','max_thumbnail',1600));
$iscaled = false; $iscaled = false;
if(intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) { if (intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) {
$imagick_path = get_config('system','imagick_convert_path'); $imagick_path = get_config('system','imagick_convert_path');
if($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) { if ($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) {
$fname = dbunescbin($r[0]['content']); $fname = dbunescbin($r[0]['content']);
$tmp_name = $fname . '-001'; $tmp_name = $fname . '-001';
$newsize = photo_calculate_scale(array_merge(getimagesize($fname),['max' => $max_thumb])); $newsize = photo_calculate_scale(array_merge(getimagesize($fname),['max' => $max_thumb]));
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $fname) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name); $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $fname) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name);
// logger('imagick thumbnail command: ' . $cmd); // logger('imagick thumbnail command: ' . $cmd);
for($x = 0; $x < 4; $x ++) { for ($x = 0; $x < 4; $x ++) {
exec($cmd); exec($cmd);
if(file_exists($tmp_name)) { if (file_exists($tmp_name)) {
break; break;
} }
} }
if(file_exists($tmp_name)) { if (file_exists($tmp_name)) {
$base_image = $r[0]; $base_image = $r[0];
$gis = getimagesize($tmp_name); $gis = getimagesize($tmp_name);
logger('gis: ' . print_r($gis,true)); logger('gis: ' . print_r($gis,true));
@ -119,13 +121,13 @@ logger('gis: ' . print_r($gis,true));
} }
} }
} }
if(! $iscaled) { if (! $iscaled) {
$base_image = $r[0]; $base_image = $r[0];
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); $base_image['content'] = (($base_image['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
} }
$im = photo_factory($base_image['content'], $base_image['mimetype']); $im = photo_factory($base_image['content'], $base_image['mimetype']);
if($im->is_valid()) { if ($im->is_valid()) {
// We are scaling and cropping the relative pixel locations to the original photo instead of the // We are scaling and cropping the relative pixel locations to the original photo instead of the
// scaled photo we operated on. // scaled photo we operated on.
@ -142,7 +144,7 @@ logger('gis: ' . print_r($gis,true));
$scaled_width = $g[0]['width']; $scaled_width = $g[0]['width'];
$scaled_height = $g[0]['height']; $scaled_height = $g[0]['height'];
if((! $scaled_width) || (! $scaled_height)) { if ((! $scaled_width) || (! $scaled_height)) {
logger('potential divide by zero scaling cover photo'); logger('potential divide by zero scaling cover photo');
return; return;
} }
@ -191,7 +193,7 @@ logger('gis: ' . print_r($gis,true));
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425); $r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
if($r1 === false || $r2 === false || $r3 === false) { if ($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over. // if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL ); notice( t('Image resize failed.') . EOL );
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ", $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ",
@ -201,7 +203,7 @@ logger('gis: ' . print_r($gis,true));
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
$this->send_cover_photo_activity($channel,$base_image,$profile); $this->send_cover_photo_activity($channel,$base_image,$profile);
@ -218,23 +220,21 @@ logger('gis: ' . print_r($gis,true));
$hash = photo_new_resource(); $hash = photo_new_resource();
$smallest = 0; $smallest = 0;
require_once('include/attach.php');
$matches = []; $matches = [];
$partial = false; $partial = false;
if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { if (array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches); $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
if($pm) { if ($pm) {
logger('Content-Range: ' . print_r($matches,true)); logger('Content-Range: ' . print_r($matches,true));
$partial = true; $partial = true;
} }
} }
if($partial) { if ($partial) {
$x = save_chunk($channel,$matches[1],$matches[2],$matches[3]); $x = save_chunk($channel,$matches[1],$matches[2],$matches[3]);
if($x['partial']) { if ($x['partial']) {
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0)); header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
json_return_and_die($result); json_return_and_die($result);
} }
@ -251,7 +251,7 @@ logger('gis: ' . print_r($gis,true));
} }
} }
else { else {
if(! array_key_exists('userfile',$_FILES)) { if (! array_key_exists('userfile',$_FILES)) {
$_FILES['userfile'] = [ $_FILES['userfile'] = [
'name' => $_FILES['files']['name'], 'name' => $_FILES['files']['name'],
'type' => $_FILES['files']['type'], 'type' => $_FILES['files']['type'],
@ -262,9 +262,9 @@ logger('gis: ' . print_r($gis,true));
} }
} }
$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));
logger('attach_store: ' . print_r($res,true)); logger('attach_store: ' . print_r($res,true),LOGGER_DEBUG);
json_return_and_die([ 'message' => $hash ]); json_return_and_die([ 'message' => $hash ]);
@ -272,7 +272,7 @@ logger('gis: ' . print_r($gis,true));
function send_cover_photo_activity($channel,$photo,$profile) { function send_cover_photo_activity($channel,$photo,$profile) {
$arr = array(); $arr = [];
$arr['item_thread_top'] = 1; $arr['item_thread_top'] = 1;
$arr['item_origin'] = 1; $arr['item_origin'] = 1;
$arr['item_wall'] = 1; $arr['item_wall'] = 1;
@ -281,12 +281,15 @@ logger('gis: ' . print_r($gis,true));
$arr['obj_type'] = ACTIVITY_OBJ_NOTE; $arr['obj_type'] = ACTIVITY_OBJ_NOTE;
$arr['verb'] = ACTIVITY_CREATE; $arr['verb'] = ACTIVITY_CREATE;
if($profile && stripos($profile['gender'],t('female')) !== false) if ($profile && stripos($profile['gender'],t('female')) !== false) {
$t = t('%1$s updated her %2$s'); $t = t('%1$s updated her %2$s');
elseif($profile && stripos($profile['gender'],t('male')) !== false) }
elseif ($profile && stripos($profile['gender'],t('male')) !== false) {
$t = t('%1$s updated his %2$s'); $t = t('%1$s updated his %2$s');
else }
else {
$t = t('%1$s updated their %2$s'); $t = t('%1$s updated their %2$s');
}
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]'; $ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
@ -335,19 +338,19 @@ logger('gis: ' . print_r($gis,true));
function get() { function get() {
if(! local_channel()) { if (! local_channel()) {
notice( t('Permission denied.') . EOL ); notice( t('Permission denied.') . EOL );
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
$newuser = false; $newuser = false;
if(argc() == 2 && argv(1) === 'new') if (argc() == 2 && argv(1) === 'new')
$newuser = true; $newuser = true;
if(argv(1) === 'use') { if (argv(1) === 'use') {
if (argc() < 3) { if (argc() < 3) {
notice( t('Permission denied.') . EOL ); notice( t('Permission denied.') . EOL );
return; return;
@ -361,58 +364,59 @@ logger('gis: ' . print_r($gis,true));
intval(local_channel()), intval(local_channel()),
dbesc($resource_id) dbesc($resource_id)
); );
if(! $r) { if (! $r) {
notice( t('Photo not available.') . EOL ); notice( t('Photo not available.') . EOL );
return; return;
} }
$havescale = false; $havescale = false;
foreach($r as $rr) { foreach ($r as $rr) {
if($rr['imgscale'] == 7) if ($rr['imgscale'] == 7) {
$havescale = true; $havescale = true;
} }
}
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1", $r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']), intval($r[0]['id']),
intval(local_channel()) intval(local_channel())
); );
if(! $r) { if (! $r) {
notice( t('Photo not available.') . EOL ); notice( t('Photo not available.') . EOL );
return; return;
} }
if(intval($r[0]['os_storage'])) if (intval($r[0]['os_storage'])) {
$data = @file_get_contents(dbunescbin($r[0]['content'])); $data = @file_get_contents(dbunescbin($r[0]['content']));
else }
else {
$data = dbunescbin($r[0]['content']); $data = dbunescbin($r[0]['content']);
}
$ph = photo_factory($data, $r[0]['mimetype']); $ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0; $smallest = 0;
if($ph->is_valid()) { if ($ph->is_valid()) {
// go ahead as if we have just uploaded a new photo to crop // go ahead as if we have just uploaded a new photo to crop
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0", $i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($r[0]['resource_id']), dbesc($r[0]['resource_id']),
intval(local_channel()) intval(local_channel())
); );
if($i) { if ($i) {
$hash = $i[0]['resource_id']; $hash = $i[0]['resource_id'];
foreach($i as $ii) { foreach ($i as $ii) {
$smallest = intval($ii['imgscale']); $smallest = intval($ii['imgscale']);
} }
} }
} }
$this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest); $this->cover_photo_crop_ui_head($ph, $hash, $smallest);
} }
if(! x(\App::$data,'imagecrop')) { if(! array_key_exists('imagecrop',App::$data)) {
$tpl = get_markup_template('cover_photo.tpl'); $o .= replace_macros(get_markup_template('cover_photo.tpl'), [
'$user' => App::$channel['channel_address'],
$o .= replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$info' => t('Your cover photo may be visible to anybody on the internet'), '$info' => t('Your cover photo may be visible to anybody on the internet'),
'$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850), '$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850),
'$lbl_upfile' => t('Upload File:'), '$lbl_upfile' => t('Upload File:'),
@ -433,17 +437,17 @@ logger('gis: ' . print_r($gis,true));
'$form_security_token' => get_form_security_token("cover_photo"), '$form_security_token' => get_form_security_token("cover_photo"),
'$select' => t('Select previously uploaded photo'), '$select' => t('Select previously uploaded photo'),
)); ]);
call_hooks('cover_photo_content_end', $o); call_hooks('cover_photo_content_end', $o);
return $o; return $o;
} }
else { else {
$filename = \App::$data['imagecrop'] . '-3'; $filename = App::$data['imagecrop'] . '-3';
$resolution = 3; $resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
$o .= replace_macros($tpl,array( $o .= replace_macros(get_markup_template('cropcover.tpl'), [
'$filename' => $filename, '$filename' => $filename,
'$profile' => intval($_REQUEST['profile']), '$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3', '$resource' => \App::$data['imagecrop'] . '-3',
@ -452,11 +456,9 @@ logger('gis: ' . print_r($gis,true));
'$desc' => t('Please adjust the image cropping for optimum viewing.'), '$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("cover_photo"), '$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing') '$done' => t('Done Editing')
)); ]);
return $o; return $o;
} }
return; // NOTREACHED
} }
/* @brief Generate the UI for photo-cropping /* @brief Generate the UI for photo-cropping
@ -467,27 +469,29 @@ logger('gis: ' . print_r($gis,true));
* *
*/ */
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){ function cover_photo_crop_ui_head($ph, $hash, $smallest){
$max_length = get_config('system','max_image_length'); $max_length = get_config('system','max_image_length');
if(! $max_length) if (! $max_length) {
$max_length = MAX_IMAGE_LENGTH; $max_length = MAX_IMAGE_LENGTH;
if($max_length > 0) }
if ($max_length > 0) {
$ph->scaleImage($max_length); $ph->scaleImage($max_length);
}
$width = $ph->getWidth(); $width = $ph->getWidth();
$height = $ph->getHeight(); $height = $ph->getHeight();
if($width < 300 || $height < 300) { if ($width < 300 || $height < 300) {
$ph->scaleImageUp(240); $ph->scaleImageUp(240);
$width = $ph->getWidth(); $width = $ph->getWidth();
$height = $ph->getHeight(); $height = $ph->getHeight();
} }
\App::$data['imagecrop'] = $hash; App::$data['imagecrop'] = $hash;
\App::$data['imagecrop_resolution'] = $smallest; App::$data['imagecrop_resolution'] = $smallest;
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
return; return;
} }

View file

@ -210,12 +210,12 @@ class Inbox extends Controller {
case 'emojiReaction': case 'emojiReaction':
// These require a resolvable object structure // These require a resolvable object structure
if (is_array($AS->obj)) { if (is_array($AS->obj)) {
// replies must go to the replyTo endpoint if the top level post originated here.
$item = Activity::decode_note($AS); $item = Activity::decode_note($AS);
if ($item['mid'] !== $item['parent_mid'] && stripos(z_root(), $item['parent_mid']) === 0) { // @wip replies must go to the replyTo endpoint if the top level post originated here.
$item = null; //if ($item['mid'] !== $item['parent_mid'] && stripos(z_root(), $item['parent_mid']) === 0) {
break; // $item = null;
} // break;
//}
} }
else { else {
logger('unresolved object: ' . print_r($AS->obj,true)); logger('unresolved object: ' . print_r($AS->obj,true));

View file

@ -5,6 +5,7 @@ namespace Zotlabs\Module;
use App; use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Enotify; use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\Apps;
require_once('include/bbcode.php'); require_once('include/bbcode.php');
@ -164,6 +165,10 @@ class Ping extends Controller {
$notify_pubs = ((local_channel()) ? ($vnotify & VNOTIFY_PUBS) && $discover_tab_on : $discover_tab_on); $notify_pubs = ((local_channel()) ? ($vnotify & VNOTIFY_PUBS) && $discover_tab_on : $discover_tab_on);
if ($notify_pubs && local_channel() && ! Apps::system_app_installed(local_channel(),'Public Stream')) {
$notify_pubs = false;
}
$sys = get_sys_channel(); $sys = get_sys_channel();
if ($notify_pubs) { if ($notify_pubs) {

View file

@ -48,7 +48,7 @@ require_once('include/items.php');
define ( 'STD_VERSION', '19.9.18' ); define ( 'STD_VERSION', '19.9.22' );
define ( 'ZOT_REVISION', '6.0' ); define ( 'ZOT_REVISION', '6.0' );
define ( 'DB_UPDATE_VERSION', 1236 ); define ( 'DB_UPDATE_VERSION', 1236 );
@ -470,7 +470,8 @@ define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams' ); define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams' );
define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.10' ); define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.11' );
/** /**
* activity stream defines * activity stream defines
*/ */

View file

@ -1125,8 +1125,9 @@ function bbcode($Text, $options = []) {
} }
if (strpos($Text,'[/zrl]') !== false) { if (strpos($Text,'[/zrl]') !== false) {
// $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text); // render hubzilla bookmarks as normal links
// $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
$Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\@(\!?)\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '@$1<span class="h-card"><a class="zrl u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>', $Text); $Text = preg_replace("/\@(\!?)\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '@$1<span class="h-card"><a class="zrl u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>', $Text);
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
@ -1424,6 +1425,9 @@ function bbcode($Text, $options = []) {
if($censored) { if($censored) {
$Text = separate_img_links($Text); $Text = separate_img_links($Text);
//@fixme make this work with OWA image links
$Text = preg_replace("/\<img(.*?)src=\"(.*?)\"(.*?)\>/ism",'<i class="fa fa-image"></i> <a href="#" onclick="\\$.colorbox({ \'href\': \'$2\' }); return false;">$2</a>',$Text); $Text = preg_replace("/\<img(.*?)src=\"(.*?)\"(.*?)\>/ism",'<i class="fa fa-image"></i> <a href="#" onclick="\\$.colorbox({ \'href\': \'$2\' }); return false;">$2</a>',$Text);
} }

View file

@ -1,6 +1,6 @@
<?php <?php
use \Michelf\MarkdownExtra; use Michelf\MarkdownExtra;
/** /**

View file

@ -1632,6 +1632,7 @@ function prepare_body(&$item,$attach = false,$opts = false) {
function separate_img_links($s) { function separate_img_links($s) {
$x = preg_replace('/\<a (.*?)\>\<img(.*?)\>\<\/a\>/ism', $x = preg_replace('/\<a (.*?)\>\<img(.*?)\>\<\/a\>/ism',
'<img$2><br><a $1>' . t('Link') . '</a><br>',$s); '<img$2><br><a $1>' . t('Link') . '</a><br>',$s);
return $x; return $x;
} }

File diff suppressed because it is too large Load diff

View file

@ -113,6 +113,7 @@
<div class="section-content-tools-wrapper"> <div class="section-content-tools-wrapper">
{{include file="field_checkbox.tpl" field=$verify_email}} {{include file="field_checkbox.tpl" field=$verify_email}}
{{include file="field_checkbox.tpl" field=$feed_contacts}} {{include file="field_checkbox.tpl" field=$feed_contacts}}
{{include file="field_checkbox.tpl" field=$ap_contacts}}
{{include file="field_checkbox.tpl" field=$force_publish}} {{include file="field_checkbox.tpl" field=$force_publish}}
{{include file="field_checkbox.tpl" field=$disable_discover_tab}} {{include file="field_checkbox.tpl" field=$disable_discover_tab}}
{{include file="field_checkbox.tpl" field=$site_firehose}} {{include file="field_checkbox.tpl" field=$site_firehose}}